]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - sys/ia64/ia64/support.S
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / sys / ia64 / ia64 / support.S
1 /*-
2  * Copyright (c) 1998 Doug Rabson
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  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28 /*-
29  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
30  * All rights reserved.
31  *
32  * Author: Chris G. Demetriou
33  *
34  * Permission to use, copy, modify and distribute this software and
35  * its documentation is hereby granted, provided that both the copyright
36  * notice and this permission notice appear in all copies of the
37  * software, derivative works or modified versions, and any portions
38  * thereof, and that both notices appear in supporting documentation.
39  *
40  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
41  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
42  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
43  *
44  * Carnegie Mellon requests users of this software to return to
45  *
46  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
47  *  School of Computer Science
48  *  Carnegie Mellon University
49  *  Pittsburgh PA 15213-3890
50  *
51  * any improvements or extensions that they make and grant Carnegie the
52  * rights to redistribute these changes.
53  */
54
55 #include <machine/asm.h>
56 #include <machine/ia64_cpu.h>
57 #include <assym.s>
58
59         .text
60
61 ENTRY(fusufault, 0)
62 {       .mib
63         st8.rel         [r15]=r0                // Clear onfault.
64         add             ret0=-1,r0
65         br.ret.sptk     rp
66         ;;
67 }
68 END(fusufault)
69
70 /*
71  * casuword(u_long *p, u_long old, u_long new)
72  *      Perform a compare-exchange in user space.
73  */
74 ENTRY(casuword, 3)
75 {       .mlx
76         add             r15=PC_CURTHREAD,r13
77         movl            r14=VM_MAXUSER_ADDRESS
78         ;;
79 }
80 {       .mib
81         ld8             r15=[r15]               // r15 = curthread
82         cmp.geu         p6,p0=in0,r14
83 (p6)    br.dpnt.few     1f
84         ;;
85 }
86 {       .mlx
87         add             r15=TD_PCB,r15
88         movl            r14=fusufault
89         ;;
90 }
91 {       .mmi
92         ld8             r15=[r15]               // r15 = PCB
93         ;;
94         mov             ar.ccv=in1
95         add             r15=PCB_ONFAULT,r15
96         ;;
97 }
98 {       .mmi
99         st8             [r15]=r14               // Set onfault
100         ;;
101         cmpxchg8.rel    ret0=[in0],in2,ar.ccv
102         nop             0
103         ;;
104 }
105 {       .mib
106         st8.rel         [r15]=r0                // Clear onfault
107         nop             0
108         br.ret.sptk     rp
109         ;;
110 }
111 1:
112 {       .mib
113         add             ret0=-1,r0
114         nop             0
115         br.ret.sptk     rp
116         ;;
117 }
118 END(casuword)
119
120 /*
121  * casuword32(uint32_t *p, uint32_t old, uint32_t new)
122  *      Perform a 32-bit compare-exchange in user space.
123  */
124 ENTRY(casuword32, 3)
125 {       .mlx
126         add             r15=PC_CURTHREAD,r13
127         movl            r14=VM_MAXUSER_ADDRESS
128         ;;
129 }
130 {       .mib
131         ld8             r15=[r15]               // r15 = curthread
132         cmp.geu         p6,p0=in0,r14
133 (p6)    br.dpnt.few     1f
134         ;;
135 }
136 {       .mlx
137         add             r15=TD_PCB,r15
138         movl            r14=fusufault
139         ;;
140 }
141 {       .mmi
142         ld8             r15=[r15]               // r15 = PCB
143         ;;
144         mov             ar.ccv=in1
145         add             r15=PCB_ONFAULT,r15
146         ;;
147 }
148 {       .mmi
149         st8             [r15]=r14               // Set onfault
150         ;;
151         cmpxchg4.rel    ret0=[in0],in2,ar.ccv
152         nop             0
153         ;;
154 }
155 {       .mib
156         st8.rel         [r15]=r0                // Clear onfault
157         nop             0
158         br.ret.sptk     rp
159         ;;
160 }
161 1:
162 {       .mib
163         add             ret0=-1,r0
164         nop             0
165         br.ret.sptk     rp
166         ;;
167 }
168 END(casuword32)
169
170 /*
171  * subyte(void *addr, int byte)
172  * suword16(void *addr, int word)
173  * suword32(void *addr, int word)
174  * suword64|suword(void *addr, long word)
175  *      Store in user space
176  */
177
178 ENTRY(subyte, 2)
179 {       .mlx
180         add             r15=PC_CURTHREAD,r13
181         movl            r14=VM_MAXUSER_ADDRESS
182         ;;
183 }
184 {       .mib
185         ld8             r15=[r15]               // r15 = curthread
186         cmp.geu         p6,p0=in0,r14
187 (p6)    br.dpnt.few     1f
188         ;;
189 }
190 {       .mlx
191         add             r15=TD_PCB,r15
192         movl            r14=fusufault
193         ;;
194 }
195 {       .mmi
196         ld8             r15=[r15]               // r15 = PCB
197         ;;
198         nop             0
199         add             r15=PCB_ONFAULT,r15
200         ;;
201 }
202 {       .mmi
203         st8             [r15]=r14               // Set onfault
204         ;;
205         st1.rel         [in0]=in1
206         nop             0
207         ;;
208 }
209 {       .mib
210         st8.rel         [r15]=r0                // Clear onfault
211         mov             ret0=r0
212         br.ret.sptk     rp
213         ;;
214 }
215 1:
216 {       .mib
217         add             ret0=-1,r0
218         nop             0
219         br.ret.sptk     rp
220         ;;
221 }
222 END(subyte)
223
224 ENTRY(suword16, 2)
225 {       .mlx
226         add             r15=PC_CURTHREAD,r13
227         movl            r14=VM_MAXUSER_ADDRESS
228         ;;
229 }
230 {       .mib
231         ld8             r15=[r15]               // r15 = curthread
232         cmp.geu         p6,p0=in0,r14
233 (p6)    br.dpnt.few     1f
234         ;;
235 }
236 {       .mlx
237         add             r15=TD_PCB,r15
238         movl            r14=fusufault
239         ;;
240 }
241 {       .mmi
242         ld8             r15=[r15]               // r15 = PCB
243         ;;
244         nop             0
245         add             r15=PCB_ONFAULT,r15
246         ;;
247 }
248 {       .mmi
249         st8             [r15]=r14               // Set onfault
250         ;;
251         st2.rel         [in0]=in1
252         nop             0
253         ;;
254 }
255 {       .mib
256         st8.rel         [r15]=r0                // Clear onfault
257         mov             ret0=r0
258         br.ret.sptk     rp
259         ;;
260 }
261 1:
262 {       .mib
263         add             ret0=-1,r0
264         nop             0
265         br.ret.sptk     rp
266         ;;
267 }
268 END(suword16)
269
270 ENTRY(suword32, 2)
271 {       .mlx
272         add             r15=PC_CURTHREAD,r13
273         movl            r14=VM_MAXUSER_ADDRESS
274         ;;
275 }
276 {       .mib
277         ld8             r15=[r15]               // r15 = curthread
278         cmp.geu         p6,p0=in0,r14
279 (p6)    br.dpnt.few     1f
280         ;;
281 }
282 {       .mlx
283         add             r15=TD_PCB,r15
284         movl            r14=fusufault
285         ;;
286 }
287 {       .mmi
288         ld8             r15=[r15]               // r15 = PCB
289         ;;
290         nop             0
291         add             r15=PCB_ONFAULT,r15
292         ;;
293 }
294 {       .mmi
295         st8             [r15]=r14               // Set onfault
296         ;;
297         st4.rel         [in0]=in1
298         nop             0
299         ;;
300 }
301 {       .mib
302         st8.rel         [r15]=r0                // Clear onfault
303         mov             ret0=r0
304         br.ret.sptk     rp
305         ;;
306 }
307 1:
308 {       .mib
309         add             ret0=-1,r0
310         nop             0
311         br.ret.sptk     rp
312         ;;
313 }
314 END(suword32)
315
316 ENTRY(suword64, 2)
317 XENTRY(suword)
318 {       .mlx
319         add             r15=PC_CURTHREAD,r13
320         movl            r14=VM_MAXUSER_ADDRESS
321         ;;
322 }
323 {       .mib
324         ld8             r15=[r15]               // r15 = curthread
325         cmp.geu         p6,p0=in0,r14
326 (p6)    br.dpnt.few     1f
327         ;;
328 }
329 {       .mlx
330         add             r15=TD_PCB,r15
331         movl            r14=fusufault
332         ;;
333 }
334 {       .mmi
335         ld8             r15=[r15]               // r15 = PCB
336         ;;
337         nop             0
338         add             r15=PCB_ONFAULT,r15
339         ;;
340 }
341 {       .mmi
342         st8             [r15]=r14               // Set onfault
343         ;;
344         st8.rel         [in0]=in1
345         nop             0
346         ;;
347 }
348 {       .mib
349         st8.rel         [r15]=r0                // Clear onfault
350         mov             ret0=r0
351         br.ret.sptk     rp
352         ;;
353 }
354 1:
355 {       .mib
356         add             ret0=-1,r0
357         nop             0
358         br.ret.sptk     rp
359         ;;
360 }
361 END(suword64)
362
363 /*
364  * fubyte(void *addr, int byte)
365  * fuword16(void *addr, int word)
366  * fuword32(void *addr, int word)
367  * fuword64|fuword(void *addr, long word)
368  *      Fetch from user space
369  */
370
371 ENTRY(fubyte, 1)
372 {       .mlx
373         add             r15=PC_CURTHREAD,r13
374         movl            r14=VM_MAXUSER_ADDRESS
375         ;;
376 }
377 {       .mib
378         ld8             r15=[r15]               // r15 = curthread
379         cmp.geu         p6,p0=in0,r14
380 (p6)    br.dpnt.few     1f
381         ;;
382 }
383 {       .mlx
384         add             r15=TD_PCB,r15
385         movl            r14=fusufault
386         ;;
387 }
388 {       .mmi
389         ld8             r15=[r15]               // r15 = PCB
390         ;;
391         nop             0
392         add             r15=PCB_ONFAULT,r15
393         ;;
394 }
395 {       .mmi
396         st8             [r15]=r14               // Set onfault
397         ;;
398         mf
399         nop             0
400         ;;
401 }
402 {       .mmb
403         ld1             ret0=[in0]
404         st8.rel         [r15]=r0                // Clear onfault
405         br.ret.sptk     rp
406         ;;
407 }
408 1:
409 {       .mib
410         add             ret0=-1,r0
411         nop             0
412         br.ret.sptk     rp
413         ;;
414 }
415 END(fubyte)
416
417 ENTRY(fuword16, 2)
418 {       .mlx
419         add             r15=PC_CURTHREAD,r13
420         movl            r14=VM_MAXUSER_ADDRESS
421         ;;
422 }
423 {       .mib
424         ld8             r15=[r15]               // r15 = curthread
425         cmp.geu         p6,p0=in0,r14
426 (p6)    br.dpnt.few     1f
427         ;;
428 }
429 {       .mlx
430         add             r15=TD_PCB,r15
431         movl            r14=fusufault
432         ;;
433 }
434 {       .mmi
435         ld8             r15=[r15]               // r15 = PCB
436         ;;
437         nop             0
438         add             r15=PCB_ONFAULT,r15
439         ;;
440 }
441 {       .mmi
442         st8             [r15]=r14               // Set onfault
443         ;;
444         mf
445         nop             0
446         ;;
447 }
448 {       .mmb
449         ld2             ret0=[in0]
450         st8.rel         [r15]=r0                // Clear onfault
451         br.ret.sptk     rp
452         ;;
453 }
454 1:
455 {       .mib
456         add             ret0=-1,r0
457         nop             0
458         br.ret.sptk     rp
459         ;;
460 }
461 END(fuword16)
462
463 ENTRY(fuword32, 2)
464 {       .mlx
465         add             r15=PC_CURTHREAD,r13
466         movl            r14=VM_MAXUSER_ADDRESS
467         ;;
468 }
469 {       .mib
470         ld8             r15=[r15]               // r15 = curthread
471         cmp.geu         p6,p0=in0,r14
472 (p6)    br.dpnt.few     1f
473         ;;
474 }
475 {       .mlx
476         add             r15=TD_PCB,r15
477         movl            r14=fusufault
478         ;;
479 }
480 {       .mmi
481         ld8             r15=[r15]               // r15 = PCB
482         ;;
483         nop             0
484         add             r15=PCB_ONFAULT,r15
485         ;;
486 }
487 {       .mmi
488         st8             [r15]=r14               // Set onfault
489         ;;
490         mf
491         nop             0
492         ;;
493 }
494 {       .mmb
495         ld4             ret0=[in0]
496         st8.rel         [r15]=r0                // Clear onfault
497         br.ret.sptk     rp
498         ;;
499 }
500 1:
501 {       .mib
502         add             ret0=-1,r0
503         nop             0
504         br.ret.sptk     rp
505         ;;
506 }
507 END(fuword32)
508
509 ENTRY(fuword64, 2)
510 XENTRY(fuword)
511 {       .mlx
512         add             r15=PC_CURTHREAD,r13
513         movl            r14=VM_MAXUSER_ADDRESS
514         ;;
515 }
516 {       .mib
517         ld8             r15=[r15]               // r15 = curthread
518         cmp.geu         p6,p0=in0,r14
519 (p6)    br.dpnt.few     1f
520         ;;
521 }
522 {       .mlx
523         add             r15=TD_PCB,r15
524         movl            r14=fusufault
525         ;;
526 }
527 {       .mmi
528         ld8             r15=[r15]               // r15 = PCB
529         ;;
530         nop             0
531         add             r15=PCB_ONFAULT,r15
532         ;;
533 }
534 {       .mmi
535         st8             [r15]=r14               // Set onfault
536         ;;
537         mf
538         nop             0
539         ;;
540 }
541 {       .mmb
542         ld8             ret0=[in0]
543         st8.rel         [r15]=r0                // Clear onfault
544         br.ret.sptk     rp
545         ;;
546 }
547 1:
548 {       .mib
549         add             ret0=-1,r0
550         nop             0
551         br.ret.sptk     rp
552         ;;
553 }
554 END(fuword64)
555
556 /*
557  * fuswintr(void *addr)
558  * suswintr(void *addr)
559  */
560
561 ENTRY(fuswintr, 1)
562 {       .mib
563         add             ret0=-1,r0
564         nop             0
565         br.ret.sptk     rp
566         ;;
567 }
568 END(fuswintr)
569
570 ENTRY(suswintr, 0)
571 {       .mib
572         add             ret0=-1,r0
573         nop             0
574         br.ret.sptk     rp
575         ;;
576 }
577 END(suswintr)
578
579 /**************************************************************************/
580
581 /*
582  * Copy a null-terminated string within the kernel's address space.
583  * If lenp is not NULL, store the number of chars copied in *lenp
584  *
585  * int copystr(char *from, char *to, size_t len, size_t *lenp);
586  */
587 ENTRY(copystr, 4)
588         mov     r14=in2                 // r14 = i = len
589         cmp.eq  p6,p0=r0,in2
590 (p6)    br.cond.spnt.few 2f             // if (len == 0), bail out
591
592 1:      ld1     r15=[in0],1             // read one byte
593         ;;
594         st1     [in1]=r15,1             // write that byte
595         add     in2=-1,in2              // len--
596         ;;
597         cmp.eq  p6,p0=r0,r15
598         cmp.ne  p7,p0=r0,in2
599         ;; 
600 (p6)    br.cond.spnt.few 2f             // if (*from == 0), bail out
601 (p7)    br.cond.sptk.few 1b             // if (len != 0) copy more
602
603 2:      cmp.eq  p6,p0=r0,in3
604 (p6)    br.cond.dpnt.few 3f             // if (lenp != NULL)
605         sub     r14=r14,in2             // *lenp = (i - len)
606         ;;
607         st8     [in3]=r14
608         
609 3:      cmp.eq  p6,p0=r0,r15
610 (p6)    br.cond.spnt.few 4f             // *from == '\0'; leave quietly
611
612         mov     ret0=ENAMETOOLONG       // *from != '\0'; error.
613         br.ret.sptk.few rp
614
615 4:      mov     ret0=0                  // return 0.
616         br.ret.sptk.few rp
617 END(copystr)
618
619 ENTRY(copyinstr, 4)
620         .prologue
621         .regstk 4, 3, 4, 0
622         .save   ar.pfs,loc0
623         alloc   loc0=ar.pfs,4,3,4,0
624         .save   rp,loc1
625         mov     loc1=rp
626         .body
627
628         movl    loc2=VM_MAXUSER_ADDRESS         // make sure that src addr
629         ;; 
630         cmp.geu p6,p0=in0,loc2                  // is in user space.
631         ;; 
632 (p6)    br.cond.spnt.few copyerr                // if it's not, error out.
633         movl    r14=copyerr                     // set up fault handler.
634         add     r15=PC_CURTHREAD,r13            // find curthread
635         ;;
636         ld8     r15=[r15]
637         ;;
638         add     r15=TD_PCB,r15                  // find pcb
639         ;;
640         ld8     r15=[r15]
641         ;;
642         add     loc2=PCB_ONFAULT,r15
643         ;;
644         st8     [loc2]=r14
645         ;;
646         mov     out0=in0
647         mov     out1=in1
648         mov     out2=in2
649         mov     out3=in3
650         ;;
651         br.call.sptk.few rp=copystr             // do the copy.
652         st8     [loc2]=r0                       // kill the fault handler.
653         mov     ar.pfs=loc0                     // restore ar.pfs
654         mov     rp=loc1                         // restore ra.
655         br.ret.sptk.few rp                      // ret0 left over from copystr
656 END(copyinstr)
657
658 /*
659  * Not the fastest bcopy in the world.
660  */
661 ENTRY(bcopy, 3)
662         mov     ret0=r0                         // return zero for copy{in,out}
663         ;; 
664         cmp.le  p6,p0=in2,r0                    // bail if len <= 0
665 (p6)    br.ret.spnt.few rp
666
667         sub     r14=in1,in0 ;;                  // check for overlap
668         cmp.ltu p6,p0=r14,in2                   // dst-src < len
669 (p6)    br.cond.spnt.few 5f
670
671         extr.u  r14=in0,0,3                     // src & 7
672         extr.u  r15=in1,0,3 ;;                  // dst & 7
673         cmp.eq  p6,p0=r14,r15                   // different alignment?
674 (p6)    br.cond.spnt.few 2f                     // branch if same alignment
675
676 1:      ld1     r14=[in0],1 ;;                  // copy bytewise
677         st1     [in1]=r14,1
678         add     in2=-1,in2 ;;                   // len--
679         cmp.ne  p6,p0=r0,in2
680 (p6)    br.cond.dptk.few 1b                     // loop
681         br.ret.sptk.few rp                      // done
682
683 2:      cmp.eq  p6,p0=r14,r0                    // aligned?
684 (p6)    br.cond.sptk.few 4f
685
686 3:      ld1     r14=[in0],1 ;;                  // copy bytewise
687         st1     [in1]=r14,1
688         extr.u  r15=in0,0,3                     // src & 7
689         add     in2=-1,in2 ;;                   // len--
690         cmp.eq  p6,p0=r0,in2                    // done?
691         cmp.eq  p7,p0=r0,r15 ;;                 // aligned now?
692 (p6)    br.ret.spnt.few rp                      // return if done
693 (p7)    br.cond.spnt.few 4f                     // go to main copy
694         br.cond.sptk.few 3b                     // more bytes to copy
695
696         // At this point, in2 is non-zero
697
698 4:      mov     r14=8 ;;
699         cmp.ltu p6,p0=in2,r14 ;;                // len < 8?
700 (p6)    br.cond.spnt.few 1b                     // byte copy the end
701         ld8     r15=[in0],8 ;;                  // copy word
702         st8     [in1]=r15,8
703         add     in2=-8,in2 ;;                   // len -= 8
704         cmp.ne  p6,p0=r0,in2                    // done?
705 (p6)    br.cond.spnt.few 4b                     // again
706
707         br.ret.sptk.few rp                      // return
708
709         // Don't bother optimising overlap case
710
711 5:      add     in0=in0,in2
712         add     in1=in1,in2 ;;
713         add     in0=-1,in0
714         add     in1=-1,in1 ;;
715
716 6:      ld1     r14=[in0],-1 ;;
717         st1     [in1]=r14,-1
718         add     in2=-1,in2 ;;
719         cmp.ne  p6,p0=r0,in2
720 (p6)    br.cond.spnt.few 6b
721
722         br.ret.sptk.few rp
723 END(bcopy)
724
725 ENTRY(memcpy,3)
726         mov     r14=in0 ;;
727         mov     in0=in1 ;;
728         mov     in1=r14
729         br.cond.sptk.few bcopy
730 END(memcpy)
731         
732 ENTRY(copyin, 3)
733         .prologue
734         .regstk 3, 3, 3, 0
735         .save   ar.pfs,loc0
736         alloc   loc0=ar.pfs,3,3,3,0
737         .save   rp,loc1
738         mov     loc1=rp
739         .body
740
741         movl    loc2=VM_MAXUSER_ADDRESS         // make sure that src addr
742         ;; 
743         cmp.geu p6,p0=in0,loc2                  // is in user space.
744         ;; 
745 (p6)    br.cond.spnt.few copyerr                // if it's not, error out.
746         movl    r14=copyerr                     // set up fault handler.
747         add     r15=PC_CURTHREAD,r13            // find curthread
748         ;;
749         ld8     r15=[r15]
750         ;;
751         add     r15=TD_PCB,r15                  // find pcb
752         ;;
753         ld8     r15=[r15]
754         ;;
755         add     loc2=PCB_ONFAULT,r15
756         ;;
757         st8     [loc2]=r14
758         ;;
759         mov     out0=in0
760         mov     out1=in1
761         mov     out2=in2
762         ;;
763         br.call.sptk.few rp=bcopy               // do the copy.
764         st8     [loc2]=r0                       // kill the fault handler.
765         mov     ar.pfs=loc0                     // restore ar.pfs
766         mov     rp=loc1                         // restore ra.
767         br.ret.sptk.few rp                      // ret0 left over from bcopy
768 END(copyin)
769
770 ENTRY(copyout, 3)
771         .prologue
772         .regstk 3, 3, 3, 0
773         .save   ar.pfs,loc0
774         alloc   loc0=ar.pfs,3,3,3,0
775         .save   rp,loc1
776         mov     loc1=rp
777         .body
778
779         movl    loc2=VM_MAXUSER_ADDRESS         // make sure that dest addr
780         ;; 
781         cmp.geu p6,p0=in1,loc2                  // is in user space.
782         ;; 
783 (p6)    br.cond.spnt.few copyerr                // if it's not, error out.
784         movl    r14=copyerr                     // set up fault handler.
785         add     r15=PC_CURTHREAD,r13            // find curthread
786         ;;
787         ld8     r15=[r15]
788         ;;
789         add     r15=TD_PCB,r15                  // find pcb
790         ;;
791         ld8     r15=[r15]
792         ;;
793         add     loc2=PCB_ONFAULT,r15
794         ;;
795         st8     [loc2]=r14
796         ;;
797         mov     out0=in0
798         mov     out1=in1
799         mov     out2=in2
800         ;;
801         br.call.sptk.few rp=bcopy               // do the copy.
802         st8     [loc2]=r0                       // kill the fault handler.
803         mov     ar.pfs=loc0                     // restore ar.pfs
804         mov     rp=loc1                         // restore ra.
805         br.ret.sptk.few rp                      // ret0 left over from bcopy
806 END(copyout)
807
808 ENTRY(copyerr, 0)
809         add     r14=PC_CURTHREAD,r13 ;;         // find curthread
810         ld8     r14=[r14] ;;
811         add     r14=TD_PCB,r14 ;;               // curthread->td_addr
812         ld8     r14=[r14] ;;
813         add     r14=PCB_ONFAULT,r14 ;;          // &curthread->td_pcb->pcb_onfault
814         st8     [r14]=r0                        // reset fault handler
815         
816         mov     ret0=EFAULT                     // return EFAULT
817         br.ret.sptk.few rp
818 END(copyerr)
819
820 #if defined(GPROF)
821 /*
822  * Important registers:
823  *      r8      structure return address
824  *      rp      our return address
825  *      in0     caller's ar.pfs
826  *      in1     caller's gp
827  *      in2     caller's rp
828  *      in3     GOT entry
829  *      ar.pfs  our pfs
830  */
831 ENTRY_NOPROFILE(_mcount, 4)
832         alloc           loc0 = ar.pfs, 4, 3, 2, 0
833         mov             loc1 = r8
834         mov             loc2 = rp
835         ;;
836         mov             out0 = in2
837         mov             out1 = rp
838         br.call.sptk    rp = __mcount
839         ;;
840 1:
841         mov             gp = in1
842         mov             r14 = ip
843         mov             b7 = loc2
844         ;;
845         add             r14 = 2f - 1b, r14
846         mov             ar.pfs = loc0
847         mov             rp = in2
848         ;;
849         mov             b7 = r14
850         mov             b6 = loc2
851         mov             r8 = loc1
852         mov             r14 = in0
853         br.ret.sptk     b7
854         ;;
855 2:
856         mov             ar.pfs = r14
857         br.sptk         b6
858         ;;
859 END(_mcount)
860 #endif