Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / platform / pc32 / i386 / support.s
CommitLineData
984263bc
MD
1/*-
2 * Copyright (c) 1993 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * $FreeBSD: src/sys/i386/i386/support.s,v 1.67.2.5 2001/08/15 01:23:50 peter Exp $
34 */
35
36#include "npx.h"
37
38#include <machine/asmacros.h>
39#include <machine/cputypes.h>
40#include <machine/pmap.h>
41#include <machine/specialreg.h>
42
43#include "assym.s"
44
45#define IDXSHIFT 10
46
47 .data
48 .globl _bcopy_vector
49_bcopy_vector:
50 .long _generic_bcopy
51 .globl _bzero
52_bzero:
53 .long _generic_bzero
54 .globl _copyin_vector
55_copyin_vector:
56 .long _generic_copyin
57 .globl _copyout_vector
58_copyout_vector:
59 .long _generic_copyout
60 .globl _ovbcopy_vector
61_ovbcopy_vector:
62 .long _generic_bcopy
63#if defined(I586_CPU) && NNPX > 0
64kernel_fpu_lock:
65 .byte 0xfe
66 .space 3
67#endif
68
69 .text
70
71/*
72 * bcopy family
73 * void bzero(void *buf, u_int len)
74 */
75
76ENTRY(generic_bzero)
77 pushl %edi
78 movl 8(%esp),%edi
79 movl 12(%esp),%ecx
80 xorl %eax,%eax
81 shrl $2,%ecx
82 cld
83 rep
84 stosl
85 movl 12(%esp),%ecx
86 andl $3,%ecx
87 rep
88 stosb
89 popl %edi
90 ret
91
92#if defined(I486_CPU)
93ENTRY(i486_bzero)
94 movl 4(%esp),%edx
95 movl 8(%esp),%ecx
96 xorl %eax,%eax
97/*
98 * do 64 byte chunks first
99 *
100 * XXX this is probably over-unrolled at least for DX2's
101 */
1022:
103 cmpl $64,%ecx
104 jb 3f
105 movl %eax,(%edx)
106 movl %eax,4(%edx)
107 movl %eax,8(%edx)
108 movl %eax,12(%edx)
109 movl %eax,16(%edx)
110 movl %eax,20(%edx)
111 movl %eax,24(%edx)
112 movl %eax,28(%edx)
113 movl %eax,32(%edx)
114 movl %eax,36(%edx)
115 movl %eax,40(%edx)
116 movl %eax,44(%edx)
117 movl %eax,48(%edx)
118 movl %eax,52(%edx)
119 movl %eax,56(%edx)
120 movl %eax,60(%edx)
121 addl $64,%edx
122 subl $64,%ecx
123 jnz 2b
124 ret
125
126/*
127 * do 16 byte chunks
128 */
129 SUPERALIGN_TEXT
1303:
131 cmpl $16,%ecx
132 jb 4f
133 movl %eax,(%edx)
134 movl %eax,4(%edx)
135 movl %eax,8(%edx)
136 movl %eax,12(%edx)
137 addl $16,%edx
138 subl $16,%ecx
139 jnz 3b
140 ret
141
142/*
143 * do 4 byte chunks
144 */
145 SUPERALIGN_TEXT
1464:
147 cmpl $4,%ecx
148 jb 5f
149 movl %eax,(%edx)
150 addl $4,%edx
151 subl $4,%ecx
152 jnz 4b
153 ret
154
155/*
156 * do 1 byte chunks
157 * a jump table seems to be faster than a loop or more range reductions
158 *
159 * XXX need a const section for non-text
160 */
161 .data
162jtab:
163 .long do0
164 .long do1
165 .long do2
166 .long do3
167
168 .text
169 SUPERALIGN_TEXT
1705:
171 jmp *jtab(,%ecx,4)
172
173 SUPERALIGN_TEXT
174do3:
175 movw %ax,(%edx)
176 movb %al,2(%edx)
177 ret
178
179 SUPERALIGN_TEXT
180do2:
181 movw %ax,(%edx)
182 ret
183
184 SUPERALIGN_TEXT
185do1:
186 movb %al,(%edx)
187 ret
188
189 SUPERALIGN_TEXT
190do0:
191 ret
192#endif
193
194#if defined(I586_CPU) && NNPX > 0
195ENTRY(i586_bzero)
196 movl 4(%esp),%edx
197 movl 8(%esp),%ecx
198
199 /*
200 * The FPU register method is twice as fast as the integer register
201 * method unless the target is in the L1 cache and we pre-allocate a
202 * cache line for it (then the integer register method is 4-5 times
203 * faster). However, we never pre-allocate cache lines, since that
204 * would make the integer method 25% or more slower for the common
205 * case when the target isn't in either the L1 cache or the L2 cache.
206 * Thus we normally use the FPU register method unless the overhead
207 * would be too large.
208 */
209 cmpl $256,%ecx /* empirical; clts, fninit, smsw cost a lot */
210 jb intreg_i586_bzero
211
212 /*
213 * The FPU registers may belong to an application or to fastmove()
214 * or to another invocation of bcopy() or ourself in a higher level
215 * interrupt or trap handler. Preserving the registers is
216 * complicated since we avoid it if possible at all levels. We
217 * want to localize the complications even when that increases them.
218 * Here the extra work involves preserving CR0_TS in TS.
219 * `npxproc != NULL' is supposed to be the condition that all the
220 * FPU resources belong to an application, but npxproc and CR0_TS
221 * aren't set atomically enough for this condition to work in
222 * interrupt handlers.
223 *
224 * Case 1: FPU registers belong to the application: we must preserve
225 * the registers if we use them, so we only use the FPU register
226 * method if the target size is large enough to amortize the extra
227 * overhead for preserving them. CR0_TS must be preserved although
228 * it is very likely to end up as set.
229 *
230 * Case 2: FPU registers belong to fastmove(): fastmove() currently
231 * makes the registers look like they belong to an application so
232 * that cpu_switch() and savectx() don't have to know about it, so
233 * this case reduces to case 1.
234 *
235 * Case 3: FPU registers belong to the kernel: don't use the FPU
236 * register method. This case is unlikely, and supporting it would
237 * be more complicated and might take too much stack.
238 *
239 * Case 4: FPU registers don't belong to anyone: the FPU registers
240 * don't need to be preserved, so we always use the FPU register
241 * method. CR0_TS must be preserved although it is very likely to
242 * always end up as clear.
243 */
244 cmpl $0,_npxproc
245 je i586_bz1
246 cmpl $256+184,%ecx /* empirical; not quite 2*108 more */
247 jb intreg_i586_bzero
248 sarb $1,kernel_fpu_lock
249 jc intreg_i586_bzero
250 smsw %ax
251 clts
252 subl $108,%esp
253 fnsave 0(%esp)
254 jmp i586_bz2
255
256i586_bz1:
257 sarb $1,kernel_fpu_lock
258 jc intreg_i586_bzero
259 smsw %ax
260 clts
261 fninit /* XXX should avoid needing this */
262i586_bz2:
263 fldz
264
265 /*
266 * Align to an 8 byte boundary (misalignment in the main loop would
267 * cost a factor of >= 2). Avoid jumps (at little cost if it is
268 * already aligned) by always zeroing 8 bytes and using the part up
269 * to the _next_ alignment position.
270 */
271 fstl 0(%edx)
272 addl %edx,%ecx /* part of %ecx -= new_%edx - %edx */
273 addl $8,%edx
274 andl $~7,%edx
275 subl %edx,%ecx
276
277 /*
278 * Similarly align `len' to a multiple of 8.
279 */
280 fstl -8(%edx,%ecx)
281 decl %ecx
282 andl $~7,%ecx
283
284 /*
285 * This wouldn't be any faster if it were unrolled, since the loop
286 * control instructions are much faster than the fstl and/or done
287 * in parallel with it so their overhead is insignificant.
288 */
289fpureg_i586_bzero_loop:
290 fstl 0(%edx)
291 addl $8,%edx
292 subl $8,%ecx
293 cmpl $8,%ecx
294 jae fpureg_i586_bzero_loop
295
296 cmpl $0,_npxproc
297 je i586_bz3
298 frstor 0(%esp)
299 addl $108,%esp
300 lmsw %ax
301 movb $0xfe,kernel_fpu_lock
302 ret
303
304i586_bz3:
305 fstp %st(0)
306 lmsw %ax
307 movb $0xfe,kernel_fpu_lock
308 ret
309
310intreg_i586_bzero:
311 /*
312 * `rep stos' seems to be the best method in practice for small
313 * counts. Fancy methods usually take too long to start up due
314 * to cache and BTB misses.
315 */
316 pushl %edi
317 movl %edx,%edi
318 xorl %eax,%eax
319 shrl $2,%ecx
320 cld
321 rep
322 stosl
323 movl 12(%esp),%ecx
324 andl $3,%ecx
325 jne 1f
326 popl %edi
327 ret
328
3291:
330 rep
331 stosb
332 popl %edi
333 ret
334#endif /* I586_CPU && NNPX > 0 */
335
336ENTRY(i686_pagezero)
337 pushl %edi
338 pushl %ebx
339
340 movl 12(%esp), %edi
341 movl $1024, %ecx
342 cld
343
344 ALIGN_TEXT
3451:
346 xorl %eax, %eax
347 repe
348 scasl
349 jnz 2f
350
351 popl %ebx
352 popl %edi
353 ret
354
355 ALIGN_TEXT
356
3572:
358 incl %ecx
359 subl $4, %edi
360
361 movl %ecx, %edx
362 cmpl $16, %ecx
363
364 jge 3f
365
366 movl %edi, %ebx
367 andl $0x3f, %ebx
368 shrl %ebx
369 shrl %ebx
370 movl $16, %ecx
371 subl %ebx, %ecx
372
3733:
374 subl %ecx, %edx
375 rep
376 stosl
377
378 movl %edx, %ecx
379 testl %edx, %edx
380 jnz 1b
381
382 popl %ebx
383 popl %edi
384 ret
385
386/* fillw(pat, base, cnt) */
387ENTRY(fillw)
388 pushl %edi
389 movl 8(%esp),%eax
390 movl 12(%esp),%edi
391 movl 16(%esp),%ecx
392 cld
393 rep
394 stosw
395 popl %edi
396 ret
397
398ENTRY(bcopyb)
399 pushl %esi
400 pushl %edi
401 movl 12(%esp),%esi
402 movl 16(%esp),%edi
403 movl 20(%esp),%ecx
404 movl %edi,%eax
405 subl %esi,%eax
406 cmpl %ecx,%eax /* overlapping && src < dst? */
407 jb 1f
408 cld /* nope, copy forwards */
409 rep
410 movsb
411 popl %edi
412 popl %esi
413 ret
414
415 ALIGN_TEXT
4161:
417 addl %ecx,%edi /* copy backwards. */
418 addl %ecx,%esi
419 decl %edi
420 decl %esi
421 std
422 rep
423 movsb
424 popl %edi
425 popl %esi
426 cld
427 ret
428
429ENTRY(bcopy)
430 MEXITCOUNT
431 jmp *_bcopy_vector
432
433ENTRY(ovbcopy)
434 MEXITCOUNT
435 jmp *_ovbcopy_vector
436
437/*
438 * generic_bcopy(src, dst, cnt)
439 * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
440 */
441ENTRY(generic_bcopy)
442 pushl %esi
443 pushl %edi
444 movl 12(%esp),%esi
445 movl 16(%esp),%edi
446 movl 20(%esp),%ecx
447
448 movl %edi,%eax
449 subl %esi,%eax
450 cmpl %ecx,%eax /* overlapping && src < dst? */
451 jb 1f
452
453 shrl $2,%ecx /* copy by 32-bit words */
454 cld /* nope, copy forwards */
455 rep
456 movsl
457 movl 20(%esp),%ecx
458 andl $3,%ecx /* any bytes left? */
459 rep
460 movsb
461 popl %edi
462 popl %esi
463 ret
464
465 ALIGN_TEXT
4661:
467 addl %ecx,%edi /* copy backwards */
468 addl %ecx,%esi
469 decl %edi
470 decl %esi
471 andl $3,%ecx /* any fractional bytes? */
472 std
473 rep
474 movsb
475 movl 20(%esp),%ecx /* copy remainder by 32-bit words */
476 shrl $2,%ecx
477 subl $3,%esi
478 subl $3,%edi
479 rep
480 movsl
481 popl %edi
482 popl %esi
483 cld
484 ret
485
486#if defined(I586_CPU) && NNPX > 0
487ENTRY(i586_bcopy)
488 pushl %esi
489 pushl %edi
490 movl 12(%esp),%esi
491 movl 16(%esp),%edi
492 movl 20(%esp),%ecx
493
494 movl %edi,%eax
495 subl %esi,%eax
496 cmpl %ecx,%eax /* overlapping && src < dst? */
497 jb 1f
498
499 cmpl $1024,%ecx
500 jb small_i586_bcopy
501
502 sarb $1,kernel_fpu_lock
503 jc small_i586_bcopy
504 cmpl $0,_npxproc
505 je i586_bc1
506 smsw %dx
507 clts
508 subl $108,%esp
509 fnsave 0(%esp)
510 jmp 4f
511
512i586_bc1:
513 smsw %dx
514 clts
515 fninit /* XXX should avoid needing this */
516
517 ALIGN_TEXT
5184:
519 pushl %ecx
520#define DCACHE_SIZE 8192
521 cmpl $(DCACHE_SIZE-512)/2,%ecx
522 jbe 2f
523 movl $(DCACHE_SIZE-512)/2,%ecx
5242:
525 subl %ecx,0(%esp)
526 cmpl $256,%ecx
527 jb 5f /* XXX should prefetch if %ecx >= 32 */
528 pushl %esi
529 pushl %ecx
530 ALIGN_TEXT
5313:
532 movl 0(%esi),%eax
533 movl 32(%esi),%eax
534 movl 64(%esi),%eax
535 movl 96(%esi),%eax
536 movl 128(%esi),%eax
537 movl 160(%esi),%eax
538 movl 192(%esi),%eax
539 movl 224(%esi),%eax
540 addl $256,%esi
541 subl $256,%ecx
542 cmpl $256,%ecx
543 jae 3b
544 popl %ecx
545 popl %esi
5465:
547 ALIGN_TEXT
548large_i586_bcopy_loop:
549 fildq 0(%esi)
550 fildq 8(%esi)
551 fildq 16(%esi)
552 fildq 24(%esi)
553 fildq 32(%esi)
554 fildq 40(%esi)
555 fildq 48(%esi)
556 fildq 56(%esi)
557 fistpq 56(%edi)
558 fistpq 48(%edi)
559 fistpq 40(%edi)
560 fistpq 32(%edi)
561 fistpq 24(%edi)
562 fistpq 16(%edi)
563 fistpq 8(%edi)
564 fistpq 0(%edi)
565 addl $64,%esi
566 addl $64,%edi
567 subl $64,%ecx
568 cmpl $64,%ecx
569 jae large_i586_bcopy_loop
570 popl %eax
571 addl %eax,%ecx
572 cmpl $64,%ecx
573 jae 4b
574
575 cmpl $0,_npxproc
576 je i586_bc2
577 frstor 0(%esp)
578 addl $108,%esp
579i586_bc2:
580 lmsw %dx
581 movb $0xfe,kernel_fpu_lock
582
583/*
584 * This is a duplicate of the main part of generic_bcopy. See the comments
585 * there. Jumping into generic_bcopy would cost a whole 0-1 cycles and
586 * would mess up high resolution profiling.
587 */
588 ALIGN_TEXT
589small_i586_bcopy:
590 shrl $2,%ecx
591 cld
592 rep
593 movsl
594 movl 20(%esp),%ecx
595 andl $3,%ecx
596 rep
597 movsb
598 popl %edi
599 popl %esi
600 ret
601
602 ALIGN_TEXT
6031:
604 addl %ecx,%edi
605 addl %ecx,%esi
606 decl %edi
607 decl %esi
608 andl $3,%ecx
609 std
610 rep
611 movsb
612 movl 20(%esp),%ecx
613 shrl $2,%ecx
614 subl $3,%esi
615 subl $3,%edi
616 rep
617 movsl
618 popl %edi
619 popl %esi
620 cld
621 ret
622#endif /* I586_CPU && NNPX > 0 */
623
624/*
625 * Note: memcpy does not support overlapping copies
626 */
627ENTRY(memcpy)
628 pushl %edi
629 pushl %esi
630 movl 12(%esp),%edi
631 movl 16(%esp),%esi
632 movl 20(%esp),%ecx
633 movl %edi,%eax
634 shrl $2,%ecx /* copy by 32-bit words */
635 cld /* nope, copy forwards */
636 rep
637 movsl
638 movl 20(%esp),%ecx
639 andl $3,%ecx /* any bytes left? */
640 rep
641 movsb
642 popl %esi
643 popl %edi
644 ret
645
646
647/*****************************************************************************/
648/* copyout and fubyte family */
649/*****************************************************************************/
650/*
651 * Access user memory from inside the kernel. These routines and possibly
652 * the math- and DOS emulators should be the only places that do this.
653 *
654 * We have to access the memory with user's permissions, so use a segment
655 * selector with RPL 3. For writes to user space we have to additionally
656 * check the PTE for write permission, because the 386 does not check
657 * write permissions when we are executing with EPL 0. The 486 does check
658 * this if the WP bit is set in CR0, so we can use a simpler version here.
659 *
660 * These routines set curpcb->onfault for the time they execute. When a
661 * protection violation occurs inside the functions, the trap handler
662 * returns to *curpcb->onfault instead of the function.
663 */
664
665/*
666 * copyout(from_kernel, to_user, len) - MP SAFE (if not I386_CPU)
667 */
668ENTRY(copyout)
669 MEXITCOUNT
670 jmp *_copyout_vector
671
672ENTRY(generic_copyout)
673 movl _curpcb,%eax
674 movl $copyout_fault,PCB_ONFAULT(%eax)
675 pushl %esi
676 pushl %edi
677 pushl %ebx
678 movl 16(%esp),%esi
679 movl 20(%esp),%edi
680 movl 24(%esp),%ebx
681 testl %ebx,%ebx /* anything to do? */
682 jz done_copyout
683
684 /*
685 * Check explicitly for non-user addresses. If 486 write protection
686 * is being used, this check is essential because we are in kernel
687 * mode so the h/w does not provide any protection against writing
688 * kernel addresses.
689 */
690
691 /*
692 * First, prevent address wrapping.
693 */
694 movl %edi,%eax
695 addl %ebx,%eax
696 jc copyout_fault
697/*
698 * XXX STOP USING VM_MAXUSER_ADDRESS.
699 * It is an end address, not a max, so every time it is used correctly it
700 * looks like there is an off by one error, and of course it caused an off
701 * by one error in several places.
702 */
703 cmpl $VM_MAXUSER_ADDRESS,%eax
704 ja copyout_fault
705
706#if defined(I386_CPU)
707
708#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
709 cmpl $CPUCLASS_386,_cpu_class
710 jne 3f
711#endif
712/*
713 * We have to check each PTE for user write permission.
714 * The checking may cause a page fault, so it is important to set
715 * up everything for return via copyout_fault before here.
716 */
717 /* compute number of pages */
718 movl %edi,%ecx
719 andl $PAGE_MASK,%ecx
720 addl %ebx,%ecx
721 decl %ecx
722 shrl $IDXSHIFT+2,%ecx
723 incl %ecx
724
725 /* compute PTE offset for start address */
726 movl %edi,%edx
727 shrl $IDXSHIFT,%edx
728 andb $0xfc,%dl
729
7301:
731 /* check PTE for each page */
732 leal _PTmap(%edx),%eax
733 shrl $IDXSHIFT,%eax
734 andb $0xfc,%al
735 testb $PG_V,_PTmap(%eax) /* PTE page must be valid */
736 je 4f
737 movb _PTmap(%edx),%al
738 andb $PG_V|PG_RW|PG_U,%al /* page must be valid and user writable */
739 cmpb $PG_V|PG_RW|PG_U,%al
740 je 2f
741
7424:
743 /* simulate a trap */
744 pushl %edx
745 pushl %ecx
746 shll $IDXSHIFT,%edx
747 pushl %edx
748 call _trapwrite /* trapwrite(addr) */
749 popl %edx
750 popl %ecx
751 popl %edx
752
753 testl %eax,%eax /* if not ok, return EFAULT */
754 jnz copyout_fault
755
7562:
757 addl $4,%edx
758 decl %ecx
759 jnz 1b /* check next page */
760#endif /* I386_CPU */
761
762 /* bcopy(%esi, %edi, %ebx) */
7633:
764 movl %ebx,%ecx
765
766#if defined(I586_CPU) && NNPX > 0
767 ALIGN_TEXT
768slow_copyout:
769#endif
770 shrl $2,%ecx
771 cld
772 rep
773 movsl
774 movb %bl,%cl
775 andb $3,%cl
776 rep
777 movsb
778
779done_copyout:
780 popl %ebx
781 popl %edi
782 popl %esi
783 xorl %eax,%eax
784 movl _curpcb,%edx
785 movl %eax,PCB_ONFAULT(%edx)
786 ret
787
788 ALIGN_TEXT
789copyout_fault:
790 popl %ebx
791 popl %edi
792 popl %esi
793 movl _curpcb,%edx
794 movl $0,PCB_ONFAULT(%edx)
795 movl $EFAULT,%eax
796 ret
797
798#if defined(I586_CPU) && NNPX > 0
799ENTRY(i586_copyout)
800 /*
801 * Duplicated from generic_copyout. Could be done a bit better.
802 */
803 movl _curpcb,%eax
804 movl $copyout_fault,PCB_ONFAULT(%eax)
805 pushl %esi
806 pushl %edi
807 pushl %ebx
808 movl 16(%esp),%esi
809 movl 20(%esp),%edi
810 movl 24(%esp),%ebx
811 testl %ebx,%ebx /* anything to do? */
812 jz done_copyout
813
814 /*
815 * Check explicitly for non-user addresses. If 486 write protection
816 * is being used, this check is essential because we are in kernel
817 * mode so the h/w does not provide any protection against writing
818 * kernel addresses.
819 */
820
821 /*
822 * First, prevent address wrapping.
823 */
824 movl %edi,%eax
825 addl %ebx,%eax
826 jc copyout_fault
827/*
828 * XXX STOP USING VM_MAXUSER_ADDRESS.
829 * It is an end address, not a max, so every time it is used correctly it
830 * looks like there is an off by one error, and of course it caused an off
831 * by one error in several places.
832 */
833 cmpl $VM_MAXUSER_ADDRESS,%eax
834 ja copyout_fault
835
836 /* bcopy(%esi, %edi, %ebx) */
8373:
838 movl %ebx,%ecx
839 /*
840 * End of duplicated code.
841 */
842
843 cmpl $1024,%ecx
844 jb slow_copyout
845
846 pushl %ecx
847 call _fastmove
848 addl $4,%esp
849 jmp done_copyout
850#endif /* I586_CPU && NNPX > 0 */
851
852/*
853 * copyin(from_user, to_kernel, len) - MP SAFE
854 */
855ENTRY(copyin)
856 MEXITCOUNT
857 jmp *_copyin_vector
858
859ENTRY(generic_copyin)
860 movl _curpcb,%eax
861 movl $copyin_fault,PCB_ONFAULT(%eax)
862 pushl %esi
863 pushl %edi
864 movl 12(%esp),%esi /* caddr_t from */
865 movl 16(%esp),%edi /* caddr_t to */
866 movl 20(%esp),%ecx /* size_t len */
867
868 /*
869 * make sure address is valid
870 */
871 movl %esi,%edx
872 addl %ecx,%edx
873 jc copyin_fault
874 cmpl $VM_MAXUSER_ADDRESS,%edx
875 ja copyin_fault
876
877#if defined(I586_CPU) && NNPX > 0
878 ALIGN_TEXT
879slow_copyin:
880#endif
881 movb %cl,%al
882 shrl $2,%ecx /* copy longword-wise */
883 cld
884 rep
885 movsl
886 movb %al,%cl
887 andb $3,%cl /* copy remaining bytes */
888 rep
889 movsb
890
891#if defined(I586_CPU) && NNPX > 0
892 ALIGN_TEXT
893done_copyin:
894#endif
895 popl %edi
896 popl %esi
897 xorl %eax,%eax
898 movl _curpcb,%edx
899 movl %eax,PCB_ONFAULT(%edx)
900 ret
901
902 ALIGN_TEXT
903copyin_fault:
904 popl %edi
905 popl %esi
906 movl _curpcb,%edx
907 movl $0,PCB_ONFAULT(%edx)
908 movl $EFAULT,%eax
909 ret
910
911#if defined(I586_CPU) && NNPX > 0
912ENTRY(i586_copyin)
913 /*
914 * Duplicated from generic_copyin. Could be done a bit better.
915 */
916 movl _curpcb,%eax
917 movl $copyin_fault,PCB_ONFAULT(%eax)
918 pushl %esi
919 pushl %edi
920 movl 12(%esp),%esi /* caddr_t from */
921 movl 16(%esp),%edi /* caddr_t to */
922 movl 20(%esp),%ecx /* size_t len */
923
924 /*
925 * make sure address is valid
926 */
927 movl %esi,%edx
928 addl %ecx,%edx
929 jc copyin_fault
930 cmpl $VM_MAXUSER_ADDRESS,%edx
931 ja copyin_fault
932 /*
933 * End of duplicated code.
934 */
935
936 cmpl $1024,%ecx
937 jb slow_copyin
938
939 pushl %ebx /* XXX prepare for fastmove_fault */
940 pushl %ecx
941 call _fastmove
942 addl $8,%esp
943 jmp done_copyin
944#endif /* I586_CPU && NNPX > 0 */
945
946#if defined(I586_CPU) && NNPX > 0
947/* fastmove(src, dst, len)
948 src in %esi
949 dst in %edi
950 len in %ecx XXX changed to on stack for profiling
951 uses %eax and %edx for tmp. storage
952 */
953/* XXX use ENTRY() to get profiling. fastmove() is actually a non-entry. */
954ENTRY(fastmove)
955 pushl %ebp
956 movl %esp,%ebp
957 subl $PCB_SAVE87_SIZE+3*4,%esp
958
959 movl 8(%ebp),%ecx
960 cmpl $63,%ecx
961 jbe fastmove_tail
962
963 testl $7,%esi /* check if src addr is multiple of 8 */
964 jnz fastmove_tail
965
966 testl $7,%edi /* check if dst addr is multiple of 8 */
967 jnz fastmove_tail
968
969/* if (npxproc != NULL) { */
970 cmpl $0,_npxproc
971 je 6f
972/* fnsave(&curpcb->pcb_savefpu); */
973 movl _curpcb,%eax
974 fnsave PCB_SAVEFPU(%eax)
975/* npxproc = NULL; */
976 movl $0,_npxproc
977/* } */
9786:
979/* now we own the FPU. */
980
981/*
982 * The process' FP state is saved in the pcb, but if we get
983 * switched, the cpu_switch() will store our FP state in the
984 * pcb. It should be possible to avoid all the copying for
985 * this, e.g., by setting a flag to tell cpu_switch() to
986 * save the state somewhere else.
987 */
988/* tmp = curpcb->pcb_savefpu; */
989 movl %ecx,-12(%ebp)
990 movl %esi,-8(%ebp)
991 movl %edi,-4(%ebp)
992 movl %esp,%edi
993 movl _curpcb,%esi
994 addl $PCB_SAVEFPU,%esi
995 cld
996 movl $PCB_SAVE87_SIZE>>2,%ecx
997 rep
998 movsl
999 movl -12(%ebp),%ecx
1000 movl -8(%ebp),%esi
1001 movl -4(%ebp),%edi
1002/* stop_emulating(); */
1003 clts
1004/* npxproc = curproc; */
1005 movl _curproc,%eax
1006 movl %eax,_npxproc
1007 movl _curpcb,%eax
1008 movl $fastmove_fault,PCB_ONFAULT(%eax)
10094:
1010 movl %ecx,-12(%ebp)
1011 cmpl $1792,%ecx
1012 jbe 2f
1013 movl $1792,%ecx
10142:
1015 subl %ecx,-12(%ebp)
1016 cmpl $256,%ecx
1017 jb 5f
1018 movl %ecx,-8(%ebp)
1019 movl %esi,-4(%ebp)
1020 ALIGN_TEXT
10213:
1022 movl 0(%esi),%eax
1023 movl 32(%esi),%eax
1024 movl 64(%esi),%eax
1025 movl 96(%esi),%eax
1026 movl 128(%esi),%eax
1027 movl 160(%esi),%eax
1028 movl 192(%esi),%eax
1029 movl 224(%esi),%eax
1030 addl $256,%esi
1031 subl $256,%ecx
1032 cmpl $256,%ecx
1033 jae 3b
1034 movl -8(%ebp),%ecx
1035 movl -4(%ebp),%esi
10365:
1037 ALIGN_TEXT
1038fastmove_loop:
1039 fildq 0(%esi)
1040 fildq 8(%esi)
1041 fildq 16(%esi)
1042 fildq 24(%esi)
1043 fildq 32(%esi)
1044 fildq 40(%esi)
1045 fildq 48(%esi)
1046 fildq 56(%esi)
1047 fistpq 56(%edi)
1048 fistpq 48(%edi)
1049 fistpq 40(%edi)
1050 fistpq 32(%edi)
1051 fistpq 24(%edi)
1052 fistpq 16(%edi)
1053 fistpq 8(%edi)
1054 fistpq 0(%edi)
1055 addl $-64,%ecx
1056 addl $64,%esi
1057 addl $64,%edi
1058 cmpl $63,%ecx
1059 ja fastmove_loop
1060 movl -12(%ebp),%eax
1061 addl %eax,%ecx
1062 cmpl $64,%ecx
1063 jae 4b
1064
1065/* curpcb->pcb_savefpu = tmp; */
1066 movl %ecx,-12(%ebp)
1067 movl %esi,-8(%ebp)
1068 movl %edi,-4(%ebp)
1069 movl _curpcb,%edi
1070 addl $PCB_SAVEFPU,%edi
1071 movl %esp,%esi
1072 cld
1073 movl $PCB_SAVE87_SIZE>>2,%ecx
1074 rep
1075 movsl
1076 movl -12(%ebp),%ecx
1077 movl -8(%ebp),%esi
1078 movl -4(%ebp),%edi
1079
1080/* start_emulating(); */
1081 smsw %ax
1082 orb $CR0_TS,%al
1083 lmsw %ax
1084/* npxproc = NULL; */
1085 movl $0,_npxproc
1086
1087 ALIGN_TEXT
1088fastmove_tail:
1089 movl _curpcb,%eax
1090 movl $fastmove_tail_fault,PCB_ONFAULT(%eax)
1091
1092 movb %cl,%al
1093 shrl $2,%ecx /* copy longword-wise */
1094 cld
1095 rep
1096 movsl
1097 movb %al,%cl
1098 andb $3,%cl /* copy remaining bytes */
1099 rep
1100 movsb
1101
1102 movl %ebp,%esp
1103 popl %ebp
1104 ret
1105
1106 ALIGN_TEXT
1107fastmove_fault:
1108 movl _curpcb,%edi
1109 addl $PCB_SAVEFPU,%edi
1110 movl %esp,%esi
1111 cld
1112 movl $PCB_SAVE87_SIZE>>2,%ecx
1113 rep
1114 movsl
1115
1116 smsw %ax
1117 orb $CR0_TS,%al
1118 lmsw %ax
1119 movl $0,_npxproc
1120
1121fastmove_tail_fault:
1122 movl %ebp,%esp
1123 popl %ebp
1124 addl $8,%esp
1125 popl %ebx
1126 popl %edi
1127 popl %esi
1128 movl _curpcb,%edx
1129 movl $0,PCB_ONFAULT(%edx)
1130 movl $EFAULT,%eax
1131 ret
1132#endif /* I586_CPU && NNPX > 0 */
1133
1134/*
1135 * fu{byte,sword,word} - MP SAFE
1136 *
1137 * Fetch a byte (sword, word) from user memory
1138 */
1139ENTRY(fuword)
1140 movl _curpcb,%ecx
1141 movl $fusufault,PCB_ONFAULT(%ecx)
1142 movl 4(%esp),%edx /* from */
1143
1144 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */
1145 ja fusufault
1146
1147 movl (%edx),%eax
1148 movl $0,PCB_ONFAULT(%ecx)
1149 ret
1150
1151/*
1152 * These two routines are called from the profiling code, potentially
1153 * at interrupt time. If they fail, that's okay, good things will
1154 * happen later. Fail all the time for now - until the trap code is
1155 * able to deal with this.
1156 */
1157ALTENTRY(suswintr)
1158ENTRY(fuswintr)
1159 movl $-1,%eax
1160 ret
1161
1162/*
1163 * fusword - MP SAFE
1164 */
1165ENTRY(fusword)
1166 movl _curpcb,%ecx
1167 movl $fusufault,PCB_ONFAULT(%ecx)
1168 movl 4(%esp),%edx
1169
1170 cmpl $VM_MAXUSER_ADDRESS-2,%edx
1171 ja fusufault
1172
1173 movzwl (%edx),%eax
1174 movl $0,PCB_ONFAULT(%ecx)
1175 ret
1176
1177/*
1178 * fubyte - MP SAFE
1179 */
1180ENTRY(fubyte)
1181 movl _curpcb,%ecx
1182 movl $fusufault,PCB_ONFAULT(%ecx)
1183 movl 4(%esp),%edx
1184
1185 cmpl $VM_MAXUSER_ADDRESS-1,%edx
1186 ja fusufault
1187
1188 movzbl (%edx),%eax
1189 movl $0,PCB_ONFAULT(%ecx)
1190 ret
1191
1192 ALIGN_TEXT
1193fusufault:
1194 movl _curpcb,%ecx
1195 xorl %eax,%eax
1196 movl %eax,PCB_ONFAULT(%ecx)
1197 decl %eax
1198 ret
1199
1200/*
1201 * su{byte,sword,word} - MP SAFE (if not I386_CPU)
1202 *
1203 * Write a byte (word, longword) to user memory
1204 */
1205ENTRY(suword)
1206 movl _curpcb,%ecx
1207 movl $fusufault,PCB_ONFAULT(%ecx)
1208 movl 4(%esp),%edx
1209
1210#if defined(I386_CPU)
1211
1212#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
1213 cmpl $CPUCLASS_386,_cpu_class
1214 jne 2f /* we only have to set the right segment selector */
1215#endif /* I486_CPU || I586_CPU || I686_CPU */
1216
1217 /* XXX - page boundary crossing is still not handled */
1218 movl %edx,%eax
1219 shrl $IDXSHIFT,%edx
1220 andb $0xfc,%dl
1221
1222 leal _PTmap(%edx),%ecx
1223 shrl $IDXSHIFT,%ecx
1224 andb $0xfc,%cl
1225 testb $PG_V,_PTmap(%ecx) /* PTE page must be valid */
1226 je 4f
1227 movb _PTmap(%edx),%dl
1228 andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */
1229 cmpb $PG_V|PG_RW|PG_U,%dl
1230 je 1f
1231
12324:
1233 /* simulate a trap */
1234 pushl %eax
1235 call _trapwrite
1236 popl %edx /* remove junk parameter from stack */
1237 testl %eax,%eax
1238 jnz fusufault
12391:
1240 movl 4(%esp),%edx
1241#endif
1242
12432:
1244 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address validity */
1245 ja fusufault
1246
1247 movl 8(%esp),%eax
1248 movl %eax,(%edx)
1249 xorl %eax,%eax
1250 movl _curpcb,%ecx
1251 movl %eax,PCB_ONFAULT(%ecx)
1252 ret
1253
1254/*
1255 * susword - MP SAFE (if not I386_CPU)
1256 */
1257ENTRY(susword)
1258 movl _curpcb,%ecx
1259 movl $fusufault,PCB_ONFAULT(%ecx)
1260 movl 4(%esp),%edx
1261
1262#if defined(I386_CPU)
1263
1264#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
1265 cmpl $CPUCLASS_386,_cpu_class
1266 jne 2f
1267#endif /* I486_CPU || I586_CPU || I686_CPU */
1268
1269 /* XXX - page boundary crossing is still not handled */
1270 movl %edx,%eax
1271 shrl $IDXSHIFT,%edx
1272 andb $0xfc,%dl
1273
1274 leal _PTmap(%edx),%ecx
1275 shrl $IDXSHIFT,%ecx
1276 andb $0xfc,%cl
1277 testb $PG_V,_PTmap(%ecx) /* PTE page must be valid */
1278 je 4f
1279 movb _PTmap(%edx),%dl
1280 andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */
1281 cmpb $PG_V|PG_RW|PG_U,%dl
1282 je 1f
1283
12844:
1285 /* simulate a trap */
1286 pushl %eax
1287 call _trapwrite
1288 popl %edx /* remove junk parameter from stack */
1289 testl %eax,%eax
1290 jnz fusufault
12911:
1292 movl 4(%esp),%edx
1293#endif
1294
12952:
1296 cmpl $VM_MAXUSER_ADDRESS-2,%edx /* verify address validity */
1297 ja fusufault
1298
1299 movw 8(%esp),%ax
1300 movw %ax,(%edx)
1301 xorl %eax,%eax
1302 movl _curpcb,%ecx /* restore trashed register */
1303 movl %eax,PCB_ONFAULT(%ecx)
1304 ret
1305
1306/*
1307 * su[i]byte - MP SAFE (if not I386_CPU)
1308 */
1309ALTENTRY(suibyte)
1310ENTRY(subyte)
1311 movl _curpcb,%ecx
1312 movl $fusufault,PCB_ONFAULT(%ecx)
1313 movl 4(%esp),%edx
1314
1315#if defined(I386_CPU)
1316
1317#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
1318 cmpl $CPUCLASS_386,_cpu_class
1319 jne 2f
1320#endif /* I486_CPU || I586_CPU || I686_CPU */
1321
1322 movl %edx,%eax
1323 shrl $IDXSHIFT,%edx
1324 andb $0xfc,%dl
1325
1326 leal _PTmap(%edx),%ecx
1327 shrl $IDXSHIFT,%ecx
1328 andb $0xfc,%cl
1329 testb $PG_V,_PTmap(%ecx) /* PTE page must be valid */
1330 je 4f
1331 movb _PTmap(%edx),%dl
1332 andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */
1333 cmpb $PG_V|PG_RW|PG_U,%dl
1334 je 1f
1335
13364:
1337 /* simulate a trap */
1338 pushl %eax
1339 call _trapwrite
1340 popl %edx /* remove junk parameter from stack */
1341 testl %eax,%eax
1342 jnz fusufault
13431:
1344 movl 4(%esp),%edx
1345#endif
1346
13472:
1348 cmpl $VM_MAXUSER_ADDRESS-1,%edx /* verify address validity */
1349 ja fusufault
1350
1351 movb 8(%esp),%al
1352 movb %al,(%edx)
1353 xorl %eax,%eax
1354 movl _curpcb,%ecx /* restore trashed register */
1355 movl %eax,PCB_ONFAULT(%ecx)
1356 ret
1357
1358/*
1359 * copyinstr(from, to, maxlen, int *lencopied) - MP SAFE
1360 *
1361 * copy a string from from to to, stop when a 0 character is reached.
1362 * return ENAMETOOLONG if string is longer than maxlen, and
1363 * EFAULT on protection violations. If lencopied is non-zero,
1364 * return the actual length in *lencopied.
1365 */
1366ENTRY(copyinstr)
1367 pushl %esi
1368 pushl %edi
1369 movl _curpcb,%ecx
1370 movl $cpystrflt,PCB_ONFAULT(%ecx)
1371
1372 movl 12(%esp),%esi /* %esi = from */
1373 movl 16(%esp),%edi /* %edi = to */
1374 movl 20(%esp),%edx /* %edx = maxlen */
1375
1376 movl $VM_MAXUSER_ADDRESS,%eax
1377
1378 /* make sure 'from' is within bounds */
1379 subl %esi,%eax
1380 jbe cpystrflt
1381
1382 /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */
1383 cmpl %edx,%eax
1384 jae 1f
1385 movl %eax,%edx
1386 movl %eax,20(%esp)
13871:
1388 incl %edx
1389 cld
1390
13912:
1392 decl %edx
1393 jz 3f
1394
1395 lodsb
1396 stosb
1397 orb %al,%al
1398 jnz 2b
1399
1400 /* Success -- 0 byte reached */
1401 decl %edx
1402 xorl %eax,%eax
1403 jmp cpystrflt_x
14043:
1405 /* edx is zero - return ENAMETOOLONG or EFAULT */
1406 cmpl $VM_MAXUSER_ADDRESS,%esi
1407 jae cpystrflt
14084:
1409 movl $ENAMETOOLONG,%eax
1410 jmp cpystrflt_x
1411
1412cpystrflt:
1413 movl $EFAULT,%eax
1414
1415cpystrflt_x:
1416 /* set *lencopied and return %eax */
1417 movl _curpcb,%ecx
1418 movl $0,PCB_ONFAULT(%ecx)
1419 movl 20(%esp),%ecx
1420 subl %edx,%ecx
1421 movl 24(%esp),%edx
1422 testl %edx,%edx
1423 jz 1f
1424 movl %ecx,(%edx)
14251:
1426 popl %edi
1427 popl %esi
1428 ret
1429
1430
1431/*
1432 * copystr(from, to, maxlen, int *lencopied) - MP SAFE
1433 */
1434ENTRY(copystr)
1435 pushl %esi
1436 pushl %edi
1437
1438 movl 12(%esp),%esi /* %esi = from */
1439 movl 16(%esp),%edi /* %edi = to */
1440 movl 20(%esp),%edx /* %edx = maxlen */
1441 incl %edx
1442 cld
14431:
1444 decl %edx
1445 jz 4f
1446 lodsb
1447 stosb
1448 orb %al,%al
1449 jnz 1b
1450
1451 /* Success -- 0 byte reached */
1452 decl %edx
1453 xorl %eax,%eax
1454 jmp 6f
14554:
1456 /* edx is zero -- return ENAMETOOLONG */
1457 movl $ENAMETOOLONG,%eax
1458
14596:
1460 /* set *lencopied and return %eax */
1461 movl 20(%esp),%ecx
1462 subl %edx,%ecx
1463 movl 24(%esp),%edx
1464 testl %edx,%edx
1465 jz 7f
1466 movl %ecx,(%edx)
14677:
1468 popl %edi
1469 popl %esi
1470 ret
1471
1472ENTRY(bcmp)
1473 pushl %edi
1474 pushl %esi
1475 movl 12(%esp),%edi
1476 movl 16(%esp),%esi
1477 movl 20(%esp),%edx
1478 xorl %eax,%eax
1479
1480 movl %edx,%ecx
1481 shrl $2,%ecx
1482 cld /* compare forwards */
1483 repe
1484 cmpsl
1485 jne 1f
1486
1487 movl %edx,%ecx
1488 andl $3,%ecx
1489 repe
1490 cmpsb
1491 je 2f
14921:
1493 incl %eax
14942:
1495 popl %esi
1496 popl %edi
1497 ret
1498
1499
1500/*
1501 * Handling of special 386 registers and descriptor tables etc
1502 */
1503/* void lgdt(struct region_descriptor *rdp); */
1504ENTRY(lgdt)
1505 /* reload the descriptor table */
1506 movl 4(%esp),%eax
1507 lgdt (%eax)
1508
1509 /* flush the prefetch q */
1510 jmp 1f
1511 nop
15121:
1513 /* reload "stale" selectors */
1514 movl $KDSEL,%eax
1515 mov %ax,%ds
1516 mov %ax,%es
1517 mov %ax,%gs
1518 mov %ax,%ss
1519#ifdef SMP
1520 movl $KPSEL,%eax
1521#endif
1522 mov %ax,%fs
1523
1524 /* reload code selector by turning return into intersegmental return */
1525 movl (%esp),%eax
1526 pushl %eax
1527 movl $KCSEL,4(%esp)
1528 lret
1529
1530/*
1531 * void lidt(struct region_descriptor *rdp);
1532 */
1533ENTRY(lidt)
1534 movl 4(%esp),%eax
1535 lidt (%eax)
1536 ret
1537
1538/*
1539 * void lldt(u_short sel)
1540 */
1541ENTRY(lldt)
1542 lldt 4(%esp)
1543 ret
1544
1545/*
1546 * void ltr(u_short sel)
1547 */
1548ENTRY(ltr)
1549 ltr 4(%esp)
1550 ret
1551
1552/* ssdtosd(*ssdp,*sdp) */
1553ENTRY(ssdtosd)
1554 pushl %ebx
1555 movl 8(%esp),%ecx
1556 movl 8(%ecx),%ebx
1557 shll $16,%ebx
1558 movl (%ecx),%edx
1559 roll $16,%edx
1560 movb %dh,%bl
1561 movb %dl,%bh
1562 rorl $8,%ebx
1563 movl 4(%ecx),%eax
1564 movw %ax,%dx
1565 andl $0xf0000,%eax
1566 orl %eax,%ebx
1567 movl 12(%esp),%ecx
1568 movl %edx,(%ecx)
1569 movl %ebx,4(%ecx)
1570 popl %ebx
1571 ret
1572
1573/* load_cr0(cr0) */
1574ENTRY(load_cr0)
1575 movl 4(%esp),%eax
1576 movl %eax,%cr0
1577 ret
1578
1579/* rcr0() */
1580ENTRY(rcr0)
1581 movl %cr0,%eax
1582 ret
1583
1584/* rcr3() */
1585ENTRY(rcr3)
1586 movl %cr3,%eax
1587 ret
1588
1589/* void load_cr3(caddr_t cr3) */
1590ENTRY(load_cr3)
1591#if defined(SWTCH_OPTIM_STATS)
1592 incl _tlb_flush_count
1593#endif
1594 movl 4(%esp),%eax
1595 movl %eax,%cr3
1596 ret
1597
1598/* rcr4() */
1599ENTRY(rcr4)
1600 movl %cr4,%eax
1601 ret
1602
1603/* void load_cr4(caddr_t cr4) */
1604ENTRY(load_cr4)
1605 movl 4(%esp),%eax
1606 movl %eax,%cr4
1607 ret
1608
1609/* void reset_dbregs() */
1610ENTRY(reset_dbregs)
1611 movl $0,%eax
1612 movl %eax,%dr7 /* disable all breapoints first */
1613 movl %eax,%dr0
1614 movl %eax,%dr1
1615 movl %eax,%dr2
1616 movl %eax,%dr3
1617 movl %eax,%dr6
1618 ret
1619
1620/*****************************************************************************/
1621/* setjump, longjump */
1622/*****************************************************************************/
1623
1624ENTRY(setjmp)
1625 movl 4(%esp),%eax
1626 movl %ebx,(%eax) /* save ebx */
1627 movl %esp,4(%eax) /* save esp */
1628 movl %ebp,8(%eax) /* save ebp */
1629 movl %esi,12(%eax) /* save esi */
1630 movl %edi,16(%eax) /* save edi */
1631 movl (%esp),%edx /* get rta */
1632 movl %edx,20(%eax) /* save eip */
1633 xorl %eax,%eax /* return(0); */
1634 ret
1635
1636ENTRY(longjmp)
1637 movl 4(%esp),%eax
1638 movl (%eax),%ebx /* restore ebx */
1639 movl 4(%eax),%esp /* restore esp */
1640 movl 8(%eax),%ebp /* restore ebp */
1641 movl 12(%eax),%esi /* restore esi */
1642 movl 16(%eax),%edi /* restore edi */
1643 movl 20(%eax),%edx /* get rta */
1644 movl %edx,(%esp) /* put in return frame */
1645 xorl %eax,%eax /* return(1); */
1646 incl %eax
1647 ret
1648
1649/*
1650 * Support for BB-profiling (gcc -a). The kernbb program will extract
1651 * the data from the kernel.
1652 */
1653
1654 .data
1655 ALIGN_DATA
1656 .globl bbhead
1657bbhead:
1658 .long 0
1659
1660 .text
1661NON_GPROF_ENTRY(__bb_init_func)
1662 movl 4(%esp),%eax
1663 movl $1,(%eax)
1664 movl bbhead,%edx
1665 movl %edx,16(%eax)
1666 movl %eax,bbhead
1667 .byte 0xc3 /* avoid macro for `ret' */