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$
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 KDSEL 0x10 /* kernel data selector */
46 #define KCSEL 0x8 /* kernel code selector */
47 #define IDXSHIFT 10
48
49 .data
50 .globl _bcopy_vector
51 _bcopy_vector:
52 .long _generic_bcopy
53 .globl _bzero
54 _bzero:
55 .long _generic_bzero
56 .globl _copyin_vector
57 _copyin_vector:
58 .long _generic_copyin
59 .globl _copyout_vector
60 _copyout_vector:
61 .long _generic_copyout
62 .globl _ovbcopy_vector
63 _ovbcopy_vector:
64 .long _generic_bcopy
65 #if defined(I586_CPU) && NNPX > 0
66 kernel_fpu_lock:
67 .byte 0xfe
68 .space 3
69 #endif
70
71 .text
72
73 /*
74 * bcopy family
75 * void bzero(void *buf, u_int len)
76 */
77
78 ENTRY(generic_bzero)
79 pushl %edi
80 movl 8(%esp),%edi
81 movl 12(%esp),%ecx
82 xorl %eax,%eax
83 shrl $2,%ecx
84 cld
85 rep
86 stosl
87 movl 12(%esp),%ecx
88 andl $3,%ecx
89 rep
90 stosb
91 popl %edi
92 ret
93
94 #if defined(I486_CPU)
95 ENTRY(i486_bzero)
96 movl 4(%esp),%edx
97 movl 8(%esp),%ecx
98 xorl %eax,%eax
99 /*
100 * do 64 byte chunks first
101 *
102 * XXX this is probably over-unrolled at least for DX2's
103 */
104 2:
105 cmpl $64,%ecx
106 jb 3f
107 movl %eax,(%edx)
108 movl %eax,4(%edx)
109 movl %eax,8(%edx)
110 movl %eax,12(%edx)
111 movl %eax,16(%edx)
112 movl %eax,20(%edx)
113 movl %eax,24(%edx)
114 movl %eax,28(%edx)
115 movl %eax,32(%edx)
116 movl %eax,36(%edx)
117 movl %eax,40(%edx)
118 movl %eax,44(%edx)
119 movl %eax,48(%edx)
120 movl %eax,52(%edx)
121 movl %eax,56(%edx)
122 movl %eax,60(%edx)
123 addl $64,%edx
124 subl $64,%ecx
125 jnz 2b
126 ret
127
128 /*
129 * do 16 byte chunks
130 */
131 SUPERALIGN_TEXT
132 3:
133 cmpl $16,%ecx
134 jb 4f
135 movl %eax,(%edx)
136 movl %eax,4(%edx)
137 movl %eax,8(%edx)
138 movl %eax,12(%edx)
139 addl $16,%edx
140 subl $16,%ecx
141 jnz 3b
142 ret
143
144 /*
145 * do 4 byte chunks
146 */
147 SUPERALIGN_TEXT
148 4:
149 cmpl $4,%ecx
150 jb 5f
151 movl %eax,(%edx)
152 addl $4,%edx
153 subl $4,%ecx
154 jnz 4b
155 ret
156
157 /*
158 * do 1 byte chunks
159 * a jump table seems to be faster than a loop or more range reductions
160 *
161 * XXX need a const section for non-text
162 */
163 .data
164 jtab:
165 .long do0
166 .long do1
167 .long do2
168 .long do3
169
170 .text
171 SUPERALIGN_TEXT
172 5:
173 jmp jtab(,%ecx,4)
174
175 SUPERALIGN_TEXT
176 do3:
177 movw %ax,(%edx)
178 movb %al,2(%edx)
179 ret
180
181 SUPERALIGN_TEXT
182 do2:
183 movw %ax,(%edx)
184 ret
185
186 SUPERALIGN_TEXT
187 do1:
188 movb %al,(%edx)
189 ret
190
191 SUPERALIGN_TEXT
192 do0:
193 ret
194 #endif
195
196 #if defined(I586_CPU) && NNPX > 0
197 ENTRY(i586_bzero)
198 movl 4(%esp),%edx
199 movl 8(%esp),%ecx
200
201 /*
202 * The FPU register method is twice as fast as the integer register
203 * method unless the target is in the L1 cache and we pre-allocate a
204 * cache line for it (then the integer register method is 4-5 times
205 * faster). However, we never pre-allocate cache lines, since that
206 * would make the integer method 25% or more slower for the common
207 * case when the target isn't in either the L1 cache or the L2 cache.
208 * Thus we normally use the FPU register method unless the overhead
209 * would be too large.
210 */
211 cmpl $256,%ecx /* empirical; clts, fninit, smsw cost a lot */
212 jb intreg_i586_bzero
213
214 /*
215 * The FPU registers may belong to an application or to fastmove()
216 * or to another invocation of bcopy() or ourself in a higher level
217 * interrupt or trap handler. Preserving the registers is
218 * complicated since we avoid it if possible at all levels. We
219 * want to localize the complications even when that increases them.
220 * Here the extra work involves preserving CR0_TS in TS.
221 * `npxproc != NULL' is supposed to be the condition that all the
222 * FPU resources belong to an application, but npxproc and CR0_TS
223 * aren't set atomically enough for this condition to work in
224 * interrupt handlers.
225 *
226 * Case 1: FPU registers belong to the application: we must preserve
227 * the registers if we use them, so we only use the FPU register
228 * method if the target size is large enough to amortize the extra
229 * overhead for preserving them. CR0_TS must be preserved although
230 * it is very likely to end up as set.
231 *
232 * Case 2: FPU registers belong to fastmove(): fastmove() currently
233 * makes the registers look like they belong to an application so
234 * that cpu_switch() and savectx() don't have to know about it, so
235 * this case reduces to case 1.
236 *
237 * Case 3: FPU registers belong to the kernel: don't use the FPU
238 * register method. This case is unlikely, and supporting it would
239 * be more complicated and might take too much stack.
240 *
241 * Case 4: FPU registers don't belong to anyone: the FPU registers
242 * don't need to be preserved, so we always use the FPU register
243 * method. CR0_TS must be preserved although it is very likely to
244 * always end up as clear.
245 */
246 cmpl $0,_npxproc
247 je i586_bz1
248 cmpl $256+184,%ecx /* empirical; not quite 2*108 more */
249 jb intreg_i586_bzero
250 sarb $1,kernel_fpu_lock
251 jc intreg_i586_bzero
252 smsw %ax
253 clts
254 subl $108,%esp
255 fnsave 0(%esp)
256 jmp i586_bz2
257
258 i586_bz1:
259 sarb $1,kernel_fpu_lock
260 jc intreg_i586_bzero
261 smsw %ax
262 clts
263 fninit /* XXX should avoid needing this */
264 i586_bz2:
265 fldz
266
267 /*
268 * Align to an 8 byte boundary (misalignment in the main loop would
269 * cost a factor of >= 2). Avoid jumps (at little cost if it is
270 * already aligned) by always zeroing 8 bytes and using the part up
271 * to the _next_ alignment position.
272 */
273 fstl 0(%edx)
274 addl %edx,%ecx /* part of %ecx -= new_%edx - %edx */
275 addl $8,%edx
276 andl $~7,%edx
277 subl %edx,%ecx
278
279 /*
280 * Similarly align `len' to a multiple of 8.
281 */
282 fstl -8(%edx,%ecx)
283 decl %ecx
284 andl $~7,%ecx
285
286 /*
287 * This wouldn't be any faster if it were unrolled, since the loop
288 * control instructions are much faster than the fstl and/or done
289 * in parallel with it so their overhead is insignificant.
290 */
291 fpureg_i586_bzero_loop:
292 fstl 0(%edx)
293 addl $8,%edx
294 subl $8,%ecx
295 cmpl $8,%ecx
296 jae fpureg_i586_bzero_loop
297
298 cmpl $0,_npxproc
299 je i586_bz3
300 frstor 0(%esp)
301 addl $108,%esp
302 lmsw %ax
303 movb $0xfe,kernel_fpu_lock
304 ret
305
306 i586_bz3:
307 fstpl %st(0)
308 lmsw %ax
309 movb $0xfe,kernel_fpu_lock
310 ret
311
312 intreg_i586_bzero:
313 /*
314 * `rep stos' seems to be the best method in practice for small
315 * counts. Fancy methods usually take too long to start up due
316 * to cache and BTB misses.
317 */
318 pushl %edi
319 movl %edx,%edi
320 xorl %eax,%eax
321 shrl $2,%ecx
322 cld
323 rep
324 stosl
325 movl 12(%esp),%ecx
326 andl $3,%ecx
327 jne 1f
328 popl %edi
329 ret
330
331 1:
332 rep
333 stosb
334 popl %edi
335 ret
336 #endif /* I586_CPU && NNPX > 0 */
337
338 ENTRY(i686_pagezero)
339 pushl %edi
340 pushl %ebx
341
342 movl 12(%esp), %edi
343 movl $1024, %ecx
344 cld
345
346 ALIGN_TEXT
347 1:
348 xorl %eax, %eax
349 repe
350 scasl
351 jnz 2f
352
353 popl %ebx
354 popl %edi
355 ret
356
357 ALIGN_TEXT
358
359 2:
360 incl %ecx
361 subl $4, %edi
362
363 movl %ecx, %edx
364 cmpl $16, %ecx
365
366 jge 3f
367
368 movl %edi, %ebx
369 andl $0x3f, %ebx
370 shrl %ebx
371 shrl %ebx
372 movl $16, %ecx
373 subl %ebx, %ecx
374
375 3:
376 subl %ecx, %edx
377 rep
378 stosl
379
380 movl %edx, %ecx
381 testl %edx, %edx
382 jnz 1b
383
384 popl %ebx
385 popl %edi
386 ret
387
388 /* fillw(pat, base, cnt) */
389 ENTRY(fillw)
390 pushl %edi
391 movl 8(%esp),%eax
392 movl 12(%esp),%edi
393 movl 16(%esp),%ecx
394 cld
395 rep
396 stosw
397 popl %edi
398 ret
399
400 ENTRY(bcopyb)
401 pushl %esi
402 pushl %edi
403 movl 12(%esp),%esi
404 movl 16(%esp),%edi
405 movl 20(%esp),%ecx
406 movl %edi,%eax
407 subl %esi,%eax
408 cmpl %ecx,%eax /* overlapping && src < dst? */
409 jb 1f
410 cld /* nope, copy forwards */
411 rep
412 movsb
413 popl %edi
414 popl %esi
415 ret
416
417 ALIGN_TEXT
418 1:
419 addl %ecx,%edi /* copy backwards. */
420 addl %ecx,%esi
421 decl %edi
422 decl %esi
423 std
424 rep
425 movsb
426 popl %edi
427 popl %esi
428 cld
429 ret
430
431 ENTRY(bcopy)
432 MEXITCOUNT
433 jmp *_bcopy_vector
434
435 ENTRY(ovbcopy)
436 MEXITCOUNT
437 jmp *_ovbcopy_vector
438
439 /*
440 * generic_bcopy(src, dst, cnt)
441 * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
442 */
443 ENTRY(generic_bcopy)
444 pushl %esi
445 pushl %edi
446 movl 12(%esp),%esi
447 movl 16(%esp),%edi
448 movl 20(%esp),%ecx
449
450 movl %edi,%eax
451 subl %esi,%eax
452 cmpl %ecx,%eax /* overlapping && src < dst? */
453 jb 1f
454
455 shrl $2,%ecx /* copy by 32-bit words */
456 cld /* nope, copy forwards */
457 rep
458 movsl
459 movl 20(%esp),%ecx
460 andl $3,%ecx /* any bytes left? */
461 rep
462 movsb
463 popl %edi
464 popl %esi
465 ret
466
467 ALIGN_TEXT
468 1:
469 addl %ecx,%edi /* copy backwards */
470 addl %ecx,%esi
471 decl %edi
472 decl %esi
473 andl $3,%ecx /* any fractional bytes? */
474 std
475 rep
476 movsb
477 movl 20(%esp),%ecx /* copy remainder by 32-bit words */
478 shrl $2,%ecx
479 subl $3,%esi
480 subl $3,%edi
481 rep
482 movsl
483 popl %edi
484 popl %esi
485 cld
486 ret
487
488 #if defined(I586_CPU) && NNPX > 0
489 ENTRY(i586_bcopy)
490 pushl %esi
491 pushl %edi
492 movl 12(%esp),%esi
493 movl 16(%esp),%edi
494 movl 20(%esp),%ecx
495
496 movl %edi,%eax
497 subl %esi,%eax
498 cmpl %ecx,%eax /* overlapping && src < dst? */
499 jb 1f
500
501 cmpl $1024,%ecx
502 jb small_i586_bcopy
503
504 sarb $1,kernel_fpu_lock
505 jc small_i586_bcopy
506 cmpl $0,_npxproc
507 je i586_bc1
508 smsw %dx
509 clts
510 subl $108,%esp
511 fnsave 0(%esp)
512 jmp 4f
513
514 i586_bc1:
515 smsw %dx
516 clts
517 fninit /* XXX should avoid needing this */
518
519 ALIGN_TEXT
520 4:
521 pushl %ecx
522 #define DCACHE_SIZE 8192
523 cmpl $(DCACHE_SIZE-512)/2,%ecx
524 jbe 2f
525 movl $(DCACHE_SIZE-512)/2,%ecx
526 2:
527 subl %ecx,0(%esp)
528 cmpl $256,%ecx
529 jb 5f /* XXX should prefetch if %ecx >= 32 */
530 pushl %esi
531 pushl %ecx
532 ALIGN_TEXT
533 3:
534 movl 0(%esi),%eax
535 movl 32(%esi),%eax
536 movl 64(%esi),%eax
537 movl 96(%esi),%eax
538 movl 128(%esi),%eax
539 movl 160(%esi),%eax
540 movl 192(%esi),%eax
541 movl 224(%esi),%eax
542 addl $256,%esi
543 subl $256,%ecx
544 cmpl $256,%ecx
545 jae 3b
546 popl %ecx
547 popl %esi
548 5:
549 ALIGN_TEXT
550 large_i586_bcopy_loop:
551 fildq 0(%esi)
552 fildq 8(%esi)
553 fildq 16(%esi)
554 fildq 24(%esi)
555 fildq 32(%esi)
556 fildq 40(%esi)
557 fildq 48(%esi)
558 fildq 56(%esi)
559 fistpq 56(%edi)
560 fistpq 48(%edi)
561 fistpq 40(%edi)
562 fistpq 32(%edi)
563 fistpq 24(%edi)
564 fistpq 16(%edi)
565 fistpq 8(%edi)
566 fistpq 0(%edi)
567 addl $64,%esi
568 addl $64,%edi
569 subl $64,%ecx
570 cmpl $64,%ecx
571 jae large_i586_bcopy_loop
572 popl %eax
573 addl %eax,%ecx
574 cmpl $64,%ecx
575 jae 4b
576
577 cmpl $0,_npxproc
578 je i586_bc2
579 frstor 0(%esp)
580 addl $108,%esp
581 i586_bc2:
582 lmsw %dx
583 movb $0xfe,kernel_fpu_lock
584
585 /*
586 * This is a duplicate of the main part of generic_bcopy. See the comments
587 * there. Jumping into generic_bcopy would cost a whole 0-1 cycles and
588 * would mess up high resolution profiling.
589 */
590 ALIGN_TEXT
591 small_i586_bcopy:
592 shrl $2,%ecx
593 cld
594 rep
595 movsl
596 movl 20(%esp),%ecx
597 andl $3,%ecx
598 rep
599 movsb
600 popl %edi
601 popl %esi
602 ret
603
604 ALIGN_TEXT
605 1:
606 addl %ecx,%edi
607 addl %ecx,%esi
608 decl %edi
609 decl %esi
610 andl $3,%ecx
611 std
612 rep
613 movsb
614 movl 20(%esp),%ecx
615 shrl $2,%ecx
616 subl $3,%esi
617 subl $3,%edi
618 rep
619 movsl
620 popl %edi
621 popl %esi
622 cld
623 ret
624 #endif /* I586_CPU && NNPX > 0 */
625
626 /*
627 * Note: memcpy does not support overlapping copies
628 */
629 ENTRY(memcpy)
630 pushl %edi
631 pushl %esi
632 movl 12(%esp),%edi
633 movl 16(%esp),%esi
634 movl 20(%esp),%ecx
635 movl %edi,%eax
636 shrl $2,%ecx /* copy by 32-bit words */
637 cld /* nope, copy forwards */
638 rep
639 movsl
640 movl 20(%esp),%ecx
641 andl $3,%ecx /* any bytes left? */
642 rep
643 movsb
644 popl %esi
645 popl %edi
646 ret
647
648
649 /*****************************************************************************/
650 /* copyout and fubyte family */
651 /*****************************************************************************/
652 /*
653 * Access user memory from inside the kernel. These routines and possibly
654 * the math- and DOS emulators should be the only places that do this.
655 *
656 * We have to access the memory with user's permissions, so use a segment
657 * selector with RPL 3. For writes to user space we have to additionally
658 * check the PTE for write permission, because the 386 does not check
659 * write permissions when we are executing with EPL 0. The 486 does check
660 * this if the WP bit is set in CR0, so we can use a simpler version here.
661 *
662 * These routines set curpcb->onfault for the time they execute. When a
663 * protection violation occurs inside the functions, the trap handler
664 * returns to *curpcb->onfault instead of the function.
665 */
666
667 /* copyout(from_kernel, to_user, len) */
668 ENTRY(copyout)
669 MEXITCOUNT
670 jmp *_copyout_vector
671
672 ENTRY(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
730 1:
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
742 4:
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
756 2:
757 addl $4,%edx
758 decl %ecx
759 jnz 1b /* check next page */
760 #endif /* I386_CPU */
761
762 /* bcopy(%esi, %edi, %ebx) */
763 3:
764 movl %ebx,%ecx
765
766 #if defined(I586_CPU) && NNPX > 0
767 ALIGN_TEXT
768 slow_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
779 done_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
789 copyout_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
799 ENTRY(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) */
837 3:
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 /* copyin(from_user, to_kernel, len) */
853 ENTRY(copyin)
854 MEXITCOUNT
855 jmp *_copyin_vector
856
857 ENTRY(generic_copyin)
858 movl _curpcb,%eax
859 movl $copyin_fault,PCB_ONFAULT(%eax)
860 pushl %esi
861 pushl %edi
862 movl 12(%esp),%esi /* caddr_t from */
863 movl 16(%esp),%edi /* caddr_t to */
864 movl 20(%esp),%ecx /* size_t len */
865
866 /*
867 * make sure address is valid
868 */
869 movl %esi,%edx
870 addl %ecx,%edx
871 jc copyin_fault
872 cmpl $VM_MAXUSER_ADDRESS,%edx
873 ja copyin_fault
874
875 #if defined(I586_CPU) && NNPX > 0
876 ALIGN_TEXT
877 slow_copyin:
878 #endif
879 movb %cl,%al
880 shrl $2,%ecx /* copy longword-wise */
881 cld
882 rep
883 movsl
884 movb %al,%cl
885 andb $3,%cl /* copy remaining bytes */
886 rep
887 movsb
888
889 #if defined(I586_CPU) && NNPX > 0
890 ALIGN_TEXT
891 done_copyin:
892 #endif
893 popl %edi
894 popl %esi
895 xorl %eax,%eax
896 movl _curpcb,%edx
897 movl %eax,PCB_ONFAULT(%edx)
898 ret
899
900 ALIGN_TEXT
901 copyin_fault:
902 popl %edi
903 popl %esi
904 movl _curpcb,%edx
905 movl $0,PCB_ONFAULT(%edx)
906 movl $EFAULT,%eax
907 ret
908
909 #if defined(I586_CPU) && NNPX > 0
910 ENTRY(i586_copyin)
911 /*
912 * Duplicated from generic_copyin. Could be done a bit better.
913 */
914 movl _curpcb,%eax
915 movl $copyin_fault,PCB_ONFAULT(%eax)
916 pushl %esi
917 pushl %edi
918 movl 12(%esp),%esi /* caddr_t from */
919 movl 16(%esp),%edi /* caddr_t to */
920 movl 20(%esp),%ecx /* size_t len */
921
922 /*
923 * make sure address is valid
924 */
925 movl %esi,%edx
926 addl %ecx,%edx
927 jc copyin_fault
928 cmpl $VM_MAXUSER_ADDRESS,%edx
929 ja copyin_fault
930 /*
931 * End of duplicated code.
932 */
933
934 cmpl $1024,%ecx
935 jb slow_copyin
936
937 pushl %ebx /* XXX prepare for fastmove_fault */
938 pushl %ecx
939 call _fastmove
940 addl $8,%esp
941 jmp done_copyin
942 #endif /* I586_CPU && NNPX > 0 */
943
944 #if defined(I586_CPU) && NNPX > 0
945 /* fastmove(src, dst, len)
946 src in %esi
947 dst in %edi
948 len in %ecx XXX changed to on stack for profiling
949 uses %eax and %edx for tmp. storage
950 */
951 /* XXX use ENTRY() to get profiling. fastmove() is actually a non-entry. */
952 ENTRY(fastmove)
953 pushl %ebp
954 movl %esp,%ebp
955 subl $PCB_SAVEFPU_SIZE+3*4,%esp
956
957 movl 8(%ebp),%ecx
958 cmpl $63,%ecx
959 jbe fastmove_tail
960
961 testl $7,%esi /* check if src addr is multiple of 8 */
962 jnz fastmove_tail
963
964 testl $7,%edi /* check if dst addr is multiple of 8 */
965 jnz fastmove_tail
966
967 /* if (npxproc != NULL) { */
968 cmpl $0,_npxproc
969 je 6f
970 /* fnsave(&curpcb->pcb_savefpu); */
971 movl _curpcb,%eax
972 fnsave PCB_SAVEFPU(%eax)
973 /* npxproc = NULL; */
974 movl $0,_npxproc
975 /* } */
976 6:
977 /* now we own the FPU. */
978
979 /*
980 * The process' FP state is saved in the pcb, but if we get
981 * switched, the cpu_switch() will store our FP state in the
982 * pcb. It should be possible to avoid all the copying for
983 * this, e.g., by setting a flag to tell cpu_switch() to
984 * save the state somewhere else.
985 */
986 /* tmp = curpcb->pcb_savefpu; */
987 movl %ecx,-12(%ebp)
988 movl %esi,-8(%ebp)
989 movl %edi,-4(%ebp)
990 movl %esp,%edi
991 movl _curpcb,%esi
992 addl $PCB_SAVEFPU,%esi
993 cld
994 movl $PCB_SAVEFPU_SIZE>>2,%ecx
995 rep
996 movsl
997 movl -12(%ebp),%ecx
998 movl -8(%ebp),%esi
999 movl -4(%ebp),%edi
1000 /* stop_emulating(); */
1001 clts
1002 /* npxproc = curproc; */
1003 movl _curproc,%eax
1004 movl %eax,_npxproc
1005 movl _curpcb,%eax
1006 movl $fastmove_fault,PCB_ONFAULT(%eax)
1007 4:
1008 movl %ecx,-12(%ebp)
1009 cmpl $1792,%ecx
1010 jbe 2f
1011 movl $1792,%ecx
1012 2:
1013 subl %ecx,-12(%ebp)
1014 cmpl $256,%ecx
1015 jb 5f
1016 movl %ecx,-8(%ebp)
1017 movl %esi,-4(%ebp)
1018 ALIGN_TEXT
1019 3:
1020 movl 0(%esi),%eax
1021 movl 32(%esi),%eax
1022 movl 64(%esi),%eax
1023 movl 96(%esi),%eax
1024 movl 128(%esi),%eax
1025 movl 160(%esi),%eax
1026 movl 192(%esi),%eax
1027 movl 224(%esi),%eax
1028 addl $256,%esi
1029 subl $256,%ecx
1030 cmpl $256,%ecx
1031 jae 3b
1032 movl -8(%ebp),%ecx
1033 movl -4(%ebp),%esi
1034 5:
1035 ALIGN_TEXT
1036 fastmove_loop:
1037 fildq 0(%esi)
1038 fildq 8(%esi)
1039 fildq 16(%esi)
1040 fildq 24(%esi)
1041 fildq 32(%esi)
1042 fildq 40(%esi)
1043 fildq 48(%esi)
1044 fildq 56(%esi)
1045 fistpq 56(%edi)
1046 fistpq 48(%edi)
1047 fistpq 40(%edi)
1048 fistpq 32(%edi)
1049 fistpq 24(%edi)
1050 fistpq 16(%edi)
1051 fistpq 8(%edi)
1052 fistpq 0(%edi)
1053 addl $-64,%ecx
1054 addl $64,%esi
1055 addl $64,%edi
1056 cmpl $63,%ecx
1057 ja fastmove_loop
1058 movl -12(%ebp),%eax
1059 addl %eax,%ecx
1060 cmpl $64,%ecx
1061 jae 4b
1062
1063 /* curpcb->pcb_savefpu = tmp; */
1064 movl %ecx,-12(%ebp)
1065 movl %esi,-8(%ebp)
1066 movl %edi,-4(%ebp)
1067 movl _curpcb,%edi
1068 addl $PCB_SAVEFPU,%edi
1069 movl %esp,%esi
1070 cld
1071 movl $PCB_SAVEFPU_SIZE>>2,%ecx
1072 rep
1073 movsl
1074 movl -12(%ebp),%ecx
1075 movl -8(%ebp),%esi
1076 movl -4(%ebp),%edi
1077
1078 /* start_emulating(); */
1079 smsw %ax
1080 orb $CR0_TS,%al
1081 lmsw %ax
1082 /* npxproc = NULL; */
1083 movl $0,_npxproc
1084
1085 ALIGN_TEXT
1086 fastmove_tail:
1087 movl _curpcb,%eax
1088 movl $fastmove_tail_fault,PCB_ONFAULT(%eax)
1089
1090 movb %cl,%al
1091 shrl $2,%ecx /* copy longword-wise */
1092 cld
1093 rep
1094 movsl
1095 movb %al,%cl
1096 andb $3,%cl /* copy remaining bytes */
1097 rep
1098 movsb
1099
1100 movl %ebp,%esp
1101 popl %ebp
1102 ret
1103
1104 ALIGN_TEXT
1105 fastmove_fault:
1106 movl _curpcb,%edi
1107 addl $PCB_SAVEFPU,%edi
1108 movl %esp,%esi
1109 cld
1110 movl $PCB_SAVEFPU_SIZE>>2,%ecx
1111 rep
1112 movsl
1113
1114 smsw %ax
1115 orb $CR0_TS,%al
1116 lmsw %ax
1117 movl $0,_npxproc
1118
1119 fastmove_tail_fault:
1120 movl %ebp,%esp
1121 popl %ebp
1122 addl $8,%esp
1123 popl %ebx
1124 popl %edi
1125 popl %esi
1126 movl _curpcb,%edx
1127 movl $0,PCB_ONFAULT(%edx)
1128 movl $EFAULT,%eax
1129 ret
1130 #endif /* I586_CPU && NNPX > 0 */
1131
1132 /*
1133 * fu{byte,sword,word} : fetch a byte (sword, word) from user memory
1134 */
1135 ENTRY(fuword)
1136 movl _curpcb,%ecx
1137 movl $fusufault,PCB_ONFAULT(%ecx)
1138 movl 4(%esp),%edx /* from */
1139
1140 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */
1141 ja fusufault
1142
1143 movl (%edx),%eax
1144 movl $0,PCB_ONFAULT(%ecx)
1145 ret
1146
1147 /*
1148 * These two routines are called from the profiling code, potentially
1149 * at interrupt time. If they fail, that's okay, good things will
1150 * happen later. Fail all the time for now - until the trap code is
1151 * able to deal with this.
1152 */
1153 ALTENTRY(suswintr)
1154 ENTRY(fuswintr)
1155 movl $-1,%eax
1156 ret
1157
1158 ENTRY(fusword)
1159 movl _curpcb,%ecx
1160 movl $fusufault,PCB_ONFAULT(%ecx)
1161 movl 4(%esp),%edx
1162
1163 cmpl $VM_MAXUSER_ADDRESS-2,%edx
1164 ja fusufault
1165
1166 movzwl (%edx),%eax
1167 movl $0,PCB_ONFAULT(%ecx)
1168 ret
1169
1170 ENTRY(fubyte)
1171 movl _curpcb,%ecx
1172 movl $fusufault,PCB_ONFAULT(%ecx)
1173 movl 4(%esp),%edx
1174
1175 cmpl $VM_MAXUSER_ADDRESS-1,%edx
1176 ja fusufault
1177
1178 movzbl (%edx),%eax
1179 movl $0,PCB_ONFAULT(%ecx)
1180 ret
1181
1182 ALIGN_TEXT
1183 fusufault:
1184 movl _curpcb,%ecx
1185 xorl %eax,%eax
1186 movl %eax,PCB_ONFAULT(%ecx)
1187 decl %eax
1188 ret
1189
1190 /*
1191 * su{byte,sword,word}: write a byte (word, longword) to user memory
1192 */
1193 ENTRY(suword)
1194 movl _curpcb,%ecx
1195 movl $fusufault,PCB_ONFAULT(%ecx)
1196 movl 4(%esp),%edx
1197
1198 #if defined(I386_CPU)
1199
1200 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
1201 cmpl $CPUCLASS_386,_cpu_class
1202 jne 2f /* we only have to set the right segment selector */
1203 #endif /* I486_CPU || I586_CPU || I686_CPU */
1204
1205 /* XXX - page boundary crossing is still not handled */
1206 movl %edx,%eax
1207 shrl $IDXSHIFT,%edx
1208 andb $0xfc,%dl
1209
1210 leal _PTmap(%edx),%ecx
1211 shrl $IDXSHIFT,%ecx
1212 andb $0xfc,%cl
1213 testb $PG_V,_PTmap(%ecx) /* PTE page must be valid */
1214 je 4f
1215 movb _PTmap(%edx),%dl
1216 andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */
1217 cmpb $PG_V|PG_RW|PG_U,%dl
1218 je 1f
1219
1220 4:
1221 /* simulate a trap */
1222 pushl %eax
1223 call _trapwrite
1224 popl %edx /* remove junk parameter from stack */
1225 testl %eax,%eax
1226 jnz fusufault
1227 1:
1228 movl 4(%esp),%edx
1229 #endif
1230
1231 2:
1232 cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address validity */
1233 ja fusufault
1234
1235 movl 8(%esp),%eax
1236 movl %eax,(%edx)
1237 xorl %eax,%eax
1238 movl _curpcb,%ecx
1239 movl %eax,PCB_ONFAULT(%ecx)
1240 ret
1241
1242 ENTRY(susword)
1243 movl _curpcb,%ecx
1244 movl $fusufault,PCB_ONFAULT(%ecx)
1245 movl 4(%esp),%edx
1246
1247 #if defined(I386_CPU)
1248
1249 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
1250 cmpl $CPUCLASS_386,_cpu_class
1251 jne 2f
1252 #endif /* I486_CPU || I586_CPU || I686_CPU */
1253
1254 /* XXX - page boundary crossing is still not handled */
1255 movl %edx,%eax
1256 shrl $IDXSHIFT,%edx
1257 andb $0xfc,%dl
1258
1259 leal _PTmap(%edx),%ecx
1260 shrl $IDXSHIFT,%ecx
1261 andb $0xfc,%cl
1262 testb $PG_V,_PTmap(%ecx) /* PTE page must be valid */
1263 je 4f
1264 movb _PTmap(%edx),%dl
1265 andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */
1266 cmpb $PG_V|PG_RW|PG_U,%dl
1267 je 1f
1268
1269 4:
1270 /* simulate a trap */
1271 pushl %eax
1272 call _trapwrite
1273 popl %edx /* remove junk parameter from stack */
1274 testl %eax,%eax
1275 jnz fusufault
1276 1:
1277 movl 4(%esp),%edx
1278 #endif
1279
1280 2:
1281 cmpl $VM_MAXUSER_ADDRESS-2,%edx /* verify address validity */
1282 ja fusufault
1283
1284 movw 8(%esp),%ax
1285 movw %ax,(%edx)
1286 xorl %eax,%eax
1287 movl _curpcb,%ecx /* restore trashed register */
1288 movl %eax,PCB_ONFAULT(%ecx)
1289 ret
1290
1291 ALTENTRY(suibyte)
1292 ENTRY(subyte)
1293 movl _curpcb,%ecx
1294 movl $fusufault,PCB_ONFAULT(%ecx)
1295 movl 4(%esp),%edx
1296
1297 #if defined(I386_CPU)
1298
1299 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
1300 cmpl $CPUCLASS_386,_cpu_class
1301 jne 2f
1302 #endif /* I486_CPU || I586_CPU || I686_CPU */
1303
1304 movl %edx,%eax
1305 shrl $IDXSHIFT,%edx
1306 andb $0xfc,%dl
1307
1308 leal _PTmap(%edx),%ecx
1309 shrl $IDXSHIFT,%ecx
1310 andb $0xfc,%cl
1311 testb $PG_V,_PTmap(%ecx) /* PTE page must be valid */
1312 je 4f
1313 movb _PTmap(%edx),%dl
1314 andb $PG_V|PG_RW|PG_U,%dl /* page must be valid and user writable */
1315 cmpb $PG_V|PG_RW|PG_U,%dl
1316 je 1f
1317
1318 4:
1319 /* simulate a trap */
1320 pushl %eax
1321 call _trapwrite
1322 popl %edx /* remove junk parameter from stack */
1323 testl %eax,%eax
1324 jnz fusufault
1325 1:
1326 movl 4(%esp),%edx
1327 #endif
1328
1329 2:
1330 cmpl $VM_MAXUSER_ADDRESS-1,%edx /* verify address validity */
1331 ja fusufault
1332
1333 movb 8(%esp),%al
1334 movb %al,(%edx)
1335 xorl %eax,%eax
1336 movl _curpcb,%ecx /* restore trashed register */
1337 movl %eax,PCB_ONFAULT(%ecx)
1338 ret
1339
1340 /*
1341 * copyinstr(from, to, maxlen, int *lencopied)
1342 * copy a string from from to to, stop when a 0 character is reached.
1343 * return ENAMETOOLONG if string is longer than maxlen, and
1344 * EFAULT on protection violations. If lencopied is non-zero,
1345 * return the actual length in *lencopied.
1346 */
1347 ENTRY(copyinstr)
1348 pushl %esi
1349 pushl %edi
1350 movl _curpcb,%ecx
1351 movl $cpystrflt,PCB_ONFAULT(%ecx)
1352
1353 movl 12(%esp),%esi /* %esi = from */
1354 movl 16(%esp),%edi /* %edi = to */
1355 movl 20(%esp),%edx /* %edx = maxlen */
1356
1357 movl $VM_MAXUSER_ADDRESS,%eax
1358
1359 /* make sure 'from' is within bounds */
1360 subl %esi,%eax
1361 jbe cpystrflt
1362
1363 /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */
1364 cmpl %edx,%eax
1365 jae 1f
1366 movl %eax,%edx
1367 movl %eax,20(%esp)
1368 1:
1369 incl %edx
1370 cld
1371
1372 2:
1373 decl %edx
1374 jz 3f
1375
1376 lodsb
1377 stosb
1378 orb %al,%al
1379 jnz 2b
1380
1381 /* Success -- 0 byte reached */
1382 decl %edx
1383 xorl %eax,%eax
1384 jmp cpystrflt_x
1385 3:
1386 /* edx is zero - return ENAMETOOLONG or EFAULT */
1387 cmpl $VM_MAXUSER_ADDRESS,%esi
1388 jae cpystrflt
1389 4:
1390 movl $ENAMETOOLONG,%eax
1391 jmp cpystrflt_x
1392
1393 cpystrflt:
1394 movl $EFAULT,%eax
1395
1396 cpystrflt_x:
1397 /* set *lencopied and return %eax */
1398 movl _curpcb,%ecx
1399 movl $0,PCB_ONFAULT(%ecx)
1400 movl 20(%esp),%ecx
1401 subl %edx,%ecx
1402 movl 24(%esp),%edx
1403 testl %edx,%edx
1404 jz 1f
1405 movl %ecx,(%edx)
1406 1:
1407 popl %edi
1408 popl %esi
1409 ret
1410
1411
1412 /*
1413 * copystr(from, to, maxlen, int *lencopied)
1414 */
1415 ENTRY(copystr)
1416 pushl %esi
1417 pushl %edi
1418
1419 movl 12(%esp),%esi /* %esi = from */
1420 movl 16(%esp),%edi /* %edi = to */
1421 movl 20(%esp),%edx /* %edx = maxlen */
1422 incl %edx
1423 cld
1424 1:
1425 decl %edx
1426 jz 4f
1427 lodsb
1428 stosb
1429 orb %al,%al
1430 jnz 1b
1431
1432 /* Success -- 0 byte reached */
1433 decl %edx
1434 xorl %eax,%eax
1435 jmp 6f
1436 4:
1437 /* edx is zero -- return ENAMETOOLONG */
1438 movl $ENAMETOOLONG,%eax
1439
1440 6:
1441 /* set *lencopied and return %eax */
1442 movl 20(%esp),%ecx
1443 subl %edx,%ecx
1444 movl 24(%esp),%edx
1445 testl %edx,%edx
1446 jz 7f
1447 movl %ecx,(%edx)
1448 7:
1449 popl %edi
1450 popl %esi
1451 ret
1452
1453 ENTRY(bcmp)
1454 pushl %edi
1455 pushl %esi
1456 movl 12(%esp),%edi
1457 movl 16(%esp),%esi
1458 movl 20(%esp),%edx
1459 xorl %eax,%eax
1460
1461 movl %edx,%ecx
1462 shrl $2,%ecx
1463 cld /* compare forwards */
1464 repe
1465 cmpsl
1466 jne 1f
1467
1468 movl %edx,%ecx
1469 andl $3,%ecx
1470 repe
1471 cmpsb
1472 je 2f
1473 1:
1474 incl %eax
1475 2:
1476 popl %esi
1477 popl %edi
1478 ret
1479
1480
1481 /*
1482 * Handling of special 386 registers and descriptor tables etc
1483 */
1484 /* void lgdt(struct region_descriptor *rdp); */
1485 ENTRY(lgdt)
1486 /* reload the descriptor table */
1487 movl 4(%esp),%eax
1488 lgdt (%eax)
1489
1490 /* flush the prefetch q */
1491 jmp 1f
1492 nop
1493 1:
1494 /* reload "stale" selectors */
1495 movl $KDSEL,%eax
1496 movl %ax,%ds
1497 movl %ax,%es
1498 movl %ax,%fs
1499 movl %ax,%gs
1500 movl %ax,%ss
1501
1502 /* reload code selector by turning return into intersegmental return */
1503 movl (%esp),%eax
1504 pushl %eax
1505 movl $KCSEL,4(%esp)
1506 lret
1507
1508 /*
1509 * void lidt(struct region_descriptor *rdp);
1510 */
1511 ENTRY(lidt)
1512 movl 4(%esp),%eax
1513 lidt (%eax)
1514 ret
1515
1516 /*
1517 * void lldt(u_short sel)
1518 */
1519 ENTRY(lldt)
1520 lldt 4(%esp)
1521 ret
1522
1523 /*
1524 * void ltr(u_short sel)
1525 */
1526 ENTRY(ltr)
1527 ltr 4(%esp)
1528 ret
1529
1530 /* ssdtosd(*ssdp,*sdp) */
1531 ENTRY(ssdtosd)
1532 pushl %ebx
1533 movl 8(%esp),%ecx
1534 movl 8(%ecx),%ebx
1535 shll $16,%ebx
1536 movl (%ecx),%edx
1537 roll $16,%edx
1538 movb %dh,%bl
1539 movb %dl,%bh
1540 rorl $8,%ebx
1541 movl 4(%ecx),%eax
1542 movw %ax,%dx
1543 andl $0xf0000,%eax
1544 orl %eax,%ebx
1545 movl 12(%esp),%ecx
1546 movl %edx,(%ecx)
1547 movl %ebx,4(%ecx)
1548 popl %ebx
1549 ret
1550
1551 /* load_cr0(cr0) */
1552 ENTRY(load_cr0)
1553 movl 4(%esp),%eax
1554 movl %eax,%cr0
1555 ret
1556
1557 /* rcr0() */
1558 ENTRY(rcr0)
1559 movl %cr0,%eax
1560 ret
1561
1562 /* rcr3() */
1563 ENTRY(rcr3)
1564 movl %cr3,%eax
1565 ret
1566
1567 /* void load_cr3(caddr_t cr3) */
1568 ENTRY(load_cr3)
1569 #if defined(SWTCH_OPTIM_STATS)
1570 incl _tlb_flush_count
1571 #endif
1572 movl 4(%esp),%eax
1573 movl %eax,%cr3
1574 ret
1575
1576 /* rcr4() */
1577 ENTRY(rcr4)
1578 movl %cr4,%eax
1579 ret
1580
1581 /* void load_cr4(caddr_t cr4) */
1582 ENTRY(load_cr4)
1583 movl 4(%esp),%eax
1584 movl %eax,%cr4
1585 ret
1586
1587 /*****************************************************************************/
1588 /* setjump, longjump */
1589 /*****************************************************************************/
1590
1591 ENTRY(setjmp)
1592 movl 4(%esp),%eax
1593 movl %ebx,(%eax) /* save ebx */
1594 movl %esp,4(%eax) /* save esp */
1595 movl %ebp,8(%eax) /* save ebp */
1596 movl %esi,12(%eax) /* save esi */
1597 movl %edi,16(%eax) /* save edi */
1598 movl (%esp),%edx /* get rta */
1599 movl %edx,20(%eax) /* save eip */
1600 xorl %eax,%eax /* return(0); */
1601 ret
1602
1603 ENTRY(longjmp)
1604 movl 4(%esp),%eax
1605 movl (%eax),%ebx /* restore ebx */
1606 movl 4(%eax),%esp /* restore esp */
1607 movl 8(%eax),%ebp /* restore ebp */
1608 movl 12(%eax),%esi /* restore esi */
1609 movl 16(%eax),%edi /* restore edi */
1610 movl 20(%eax),%edx /* get rta */
1611 movl %edx,(%esp) /* put in return frame */
1612 xorl %eax,%eax /* return(1); */
1613 incl %eax
1614 ret
1615
1616 /*
1617 * Here for doing BB-profiling (gcc -a).
1618 * We rely on the "bbset" instead, but need a dummy function.
1619 */
1620 NON_GPROF_ENTRY(__bb_init_func)
1621 movl 4(%esp),%eax
1622 movl $1,(%eax)
1623 .byte 0xc3 /* avoid macro for `ret' */
Cache object: 7fe6b844481cbfa1ef67db08e6af7c7f
|