Annotation of sys/arch/m88k/m88k/subr.S, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: subr.S,v 1.14 2006/11/18 22:48:44 miod Exp $ */
2: /*
3: * Mach Operating System
4: * Copyright (c) 1993-1992 Carnegie Mellon University
5: * Copyright (c) 1991 OMRON Corporation
6: * Copyright (c) 1996 Nivas Madhur
7: * Copyright (c) 1998 Steve Murphree, Jr.
8: * All Rights Reserved.
9: *
10: * Permission to use, copy, modify and distribute this software and its
11: * documentation is hereby granted, provided that both the copyright
12: * notice and this permission notice appear in all copies of the
13: * software, derivative works or modified versions, and any portions
14: * thereof, and that both notices appear in supporting documentation.
15: *
16: * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
17: * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
18: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19: *
20: * Carnegie Mellon requests users of this software to return to
21: *
22: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
23: * School of Computer Science
24: * Carnegie Mellon University
25: * Pittsburgh PA 15213-3890
26: *
27: * any improvements or extensions that they make and grant Carnegie the
28: * rights to redistribute these changes.
29: */
30:
31: #include "assym.h"
32:
33: #include <sys/errno.h>
34:
35: #include <machine/asm.h>
36: #include <machine/trap.h>
37:
38: #ifdef M88100
39:
40: /*
41: * DO_LOAD_ADDRESS
42: *
43: * unsigned int do_load_word(address, supervisor_mode)
44: * vaddr_t address; \\ in r2
45: * boolean_t supervisor_mode; \\ in r3
46: *
47: * Return the word at ADDRESS (from user space if SUPERVISOR_MODE is zero,
48: * supervisor space if non-zero).
49: *
50: */
51:
52: ENTRY(do_load_word) /* do_load_word(address, supervisor) */
53: bcnd ne0,r3,1f
54: #ifdef ERRATA__XXX_USR
55: NOP
56: ld.usr r2,r2,r0
57: NOP
58: NOP
59: NOP
60: jmp r1
61: #else
62: jmp.n r1
63: ld.usr r2,r2,r0
64: #endif
65: 1: jmp.n r1
66: ld r2,r2,r0
67:
68: ENTRY(do_load_half) /* do_load_half(address, supervisor) */
69: bcnd ne0,r3,1f
70: #ifdef ERRATA__XXX_USR
71: NOP
72: ld.h.usr r2,r2,r0
73: NOP
74: NOP
75: NOP
76: jmp r1
77: #else
78: jmp.n r1
79: ld.h.usr r2,r2,r0
80: #endif
81: 1: jmp.n r1
82: ld.h r2,r2,r0
83:
84: ENTRY(do_load_byte) /* do_load_byte(address, supervisor) */
85: bcnd ne0,r3,1f
86: #ifdef ERRATA__XXX_USR
87: NOP
88: ld.b.usr r2,r2,r0
89: NOP
90: NOP
91: NOP
92: jmp r1
93: #else
94: jmp.n r1
95: ld.b.usr r2,r2,r0
96: #endif
97: 1: jmp.n r1
98: ld.b r2,r2,r0
99:
100: ENTRY(do_store_word) /* do_store_word(address, data, supervisor) */
101: bcnd ne0,r4,1f
102: #ifdef ERRATA__XXX_USR
103: NOP
104: st.usr r3,r2,r0
105: NOP
106: NOP
107: NOP
108: jmp r1
109: #else
110: jmp.n r1
111: st.usr r3,r2,r0
112: #endif
113: 1: jmp.n r1
114: st r3,r2,r0
115:
116: ENTRY(do_store_half) /* do_store_half(address, data, supervisor) */
117: bcnd ne0,r4,1f
118: #ifdef ERRATA__XXX_USR
119: NOP
120: st.h.usr r3,r2,r0
121: NOP
122: NOP
123: NOP
124: jmp r1
125: #else
126: jmp.n r1
127: st.h.usr r3,r2,r0
128: #endif
129: 1: jmp.n r1
130: st.h r3,r2,r0
131:
132: ENTRY(do_store_byte) /* do_store_byte(address, data, supervisor) */
133: bcnd ne0,r4,1f
134: #ifdef ERRATA__XXX_USR
135: NOP
136: st.b.usr r3,r2,r0
137: NOP
138: NOP
139: NOP
140: jmp r1
141: #else
142: jmp.n r1
143: st.b.usr r3,r2,r0
144: #endif
145: 1: jmp.n r1
146: st.b r3,r2,r0
147:
148: ENTRY(do_xmem_word) /* do_xmem_word(address, data, supervisor) */
149: bcnd ne0,r4,1f
150: #ifdef ERRATA__XXX_USR
151: NOP
152: xmem.usr r3,r2,r0
153: NOP
154: NOP
155: NOP
156: jmp r1
157: #else
158: jmp.n r1
159: xmem.usr r3,r2,r0
160: #endif
161: 1: jmp.n r1
162: xmem r3,r2,r0
163:
164: ENTRY(do_xmem_byte) /* do_xmem_byte(address, data, supervisor) */
165: bcnd ne0,r4,1f
166: #ifdef ERRATA__XXX_USR
167: NOP
168: xmem.bu.usr r3,r2,r0
169: NOP
170: NOP
171: NOP
172: jmp r1
173: #else
174: jmp.n r1
175: xmem.bu.usr r3,r2,r0
176: #endif
177: 1: jmp.n r1
178: xmem.bu r3,r2,r0
179:
180: #endif /* M88100 */
181:
182: /*
183: * Copy specified amount of data from user space into the kernel
184: * copyin(from, to, len)
185: * r2 == from (user source address)
186: * r3 == to (kernel destination address)
187: * r4 == length
188: * (r1=return addr)
189: */
190:
191: #define SRC r2
192: #define DEST r3
193: #define LEN r4
194:
195: ENTRY(copyin)
196: /* set up fault handler */
197: ldcr r5, CPU
198: ld r6, r5, CI_CURPCB
199: or.u r5, r0, hi16(_ASM_LABEL(Lciflt))
200: or r5, r5, lo16(_ASM_LABEL(Lciflt))
201: st r5, r6, PCB_ONFAULT /* pcb_onfault = Lciflt */
202:
203: /*
204: * If it's a small length (less than 8), then do byte-by-byte.
205: * Despite not being optimal if len is 4, and from and to
206: * are word-aligned, this is still faster than doing more tests
207: * to save an hyperthetical fraction of cycle.
208: */
209: cmp r9, LEN, 8
210: bb1 lt, r9, _ASM_LABEL(copyin_byte_only)
211:
212: /* If they're not aligned similarly, use byte only... */
213: xor r9, SRC, DEST
214: mask r8, r9, 0x3
215: bcnd ne0, r8, _ASM_LABEL(copyin_byte_only)
216:
217: /*
218: * At this point, we don't know if they're word aligned or not,
219: * but we know that what needs to be done to one to align
220: * it is what's needed for the other.
221: */
222: bb1 0, SRC, _ASM_LABEL(copyin_left_align_to_halfword)
223: ASLOCAL(copyin_left_aligned_to_halfword)
224: bb1 1, SRC, _ASM_LABEL(copyin_left_align_to_word)
225: ASLOCAL(copyin_left_aligned_to_word)
226: bb1 0, LEN, _ASM_LABEL(copyin_right_align_to_halfword)
227: ASLOCAL(copyin_right_aligned_to_halfword)
228: bb1 1, LEN, _ASM_LABEL(copyin_right_align_to_word)
229: ASLOCAL(copyin_right_aligned_to_word)
230:
231: /*
232: * At this point, both SRC and DEST are aligned to a word
233: * boundary, and LEN is a multiple of 4. We want it an even
234: * multiple of 4.
235: */
236: bb1.n 2, LEN, _ASM_LABEL(copyin_right_align_to_doubleword)
237: or r7, r0, 4
238:
239: ASLOCAL(copyin_right_aligned_to_doubleword)
240: #ifdef ERRATA__XXX_USR
241: NOP
242: ld.usr r5, SRC, r0
243: NOP
244: NOP
245: NOP
246: ld.usr r6, SRC, r7
247: NOP
248: NOP
249: NOP
250: #else
251: ld.usr r5, SRC, r0
252: ld.usr r6, SRC, r7
253: #endif
254: subu LEN, LEN, 8
255: st r5, DEST, r0
256: addu SRC, SRC, 8
257: st r6, DEST, r7
258: bcnd.n ne0, LEN, _ASM_LABEL(copyin_right_aligned_to_doubleword)
259: addu DEST, DEST, 8
260: br.n _ASM_LABEL(Lcidone)
261: or r2, r0, r0 /* successful return */
262:
263: ASLOCAL(copyin_left_align_to_halfword)
264: #ifdef ERRATA__XXX_USR
265: NOP
266: ld.b.usr r5, SRC, r0
267: NOP
268: NOP
269: NOP
270: #else
271: ld.b.usr r5, SRC, r0
272: #endif
273: subu LEN, LEN, 1
274: st.b r5, DEST, r0
275: addu SRC, SRC, 1
276: br.n _ASM_LABEL(copyin_left_aligned_to_halfword)
277: addu DEST, DEST, 1
278:
279: ASLOCAL(copyin_left_align_to_word)
280: #ifdef ERRATA__XXX_USR
281: NOP
282: ld.h.usr r5, SRC, r0
283: NOP
284: NOP
285: NOP
286: #else
287: ld.h.usr r5, SRC, r0
288: #endif
289: subu LEN, LEN, 2
290: st.h r5, DEST, r0
291: addu SRC, SRC, 2
292: br.n _ASM_LABEL(copyin_left_aligned_to_word)
293: addu DEST, DEST, 2
294:
295: ASLOCAL(copyin_right_align_to_halfword)
296: subu LEN, LEN, 1
297: #ifdef ERRATA__XXX_USR
298: NOP
299: ld.b.usr r5, SRC, LEN
300: NOP
301: NOP
302: NOP
303: #else
304: ld.b.usr r5, SRC, LEN
305: #endif
306: br.n _ASM_LABEL(copyin_right_aligned_to_halfword)
307: st.b r5, DEST, LEN
308:
309: ASLOCAL(copyin_right_align_to_word)
310: subu LEN, LEN, 2
311: #ifdef ERRATA__XXX_USR
312: NOP
313: ld.h.usr r5, SRC, LEN
314: NOP
315: NOP
316: NOP
317: #else
318: ld.h.usr r5, SRC, LEN
319: #endif
320: br.n _ASM_LABEL(copyin_right_aligned_to_word)
321: st.h r5, DEST, LEN
322:
323: ASLOCAL(copyin_right_align_to_doubleword)
324: subu LEN, LEN, 4
325: #ifdef ERRATA__XXX_USR
326: NOP
327: ld.usr r5, SRC, LEN
328: NOP
329: NOP
330: NOP
331: #else
332: ld.usr r5, SRC, LEN
333: #endif
334: bcnd.n ne0, LEN, _ASM_LABEL(copyin_right_aligned_to_doubleword)
335: st r5, DEST, LEN
336: br.n _ASM_LABEL(Lcidone)
337: or r2, r0, r0 /* successful return */
338:
339: ASLOCAL(copyin_byte_only)
340: bcnd eq0, LEN, 2f
341: 1:
342: subu LEN, LEN, 1
343: #ifdef ERRATA__XXX_USR
344: NOP
345: ld.b.usr r5, SRC, LEN
346: NOP
347: NOP
348: NOP
349: #else
350: ld.b.usr r5, SRC, LEN
351: #endif
352: bcnd.n ne0, LEN, 1b
353: st.b r5, DEST, LEN
354: 2:
355: or r2, r0, r0 /* successful return */
356: /* FALLTHROUGH */
357:
358: ASLOCAL(Lcidone)
359: ldcr r5, CPU
360: ld r6, r5, CI_CURPCB
361: jmp.n r1
362: st r0,r6,PCB_ONFAULT
363:
364: ASLOCAL(Lciflt)
365: br.n _ASM_LABEL(Lcidone)
366: or r2, r0, EFAULT /* return fault */
367:
368: #undef SRC
369: #undef DEST
370: #undef LEN
371:
372: /*######################################################################*/
373: /*######################################################################*/
374:
375: /*
376: * Copy a null terminated string from the user space to the kernel
377: * address space.
378: *
379: * copyinstr(from, to, maxlen, &lencopied)
380: * r2 == from
381: * r3 == to
382: * r4 == maxlen
383: * r5 == len actually transferred (includes the terminating NUL!!!)
384: * r6 & r7 - used as temporaries
385: */
386: #define SRC r2
387: #define DEST r3
388: #define CNT r4
389: #define LEN r5
390:
391: ENTRY(copyinstr)
392:
393: /* setup fault handler */
394: ldcr r6, CPU
395: ld r7, r6, CI_CURPCB
396: or.u r6, r0, hi16(_ASM_LABEL(Lcisflt))
397: or r6, r6, lo16(_ASM_LABEL(Lcisflt))
398: st r6, r7, PCB_ONFAULT
399: or r6, r0, 0
400: bcnd lt0, CNT, _ASM_LABEL(Lcisflt)
401: bcnd eq0, CNT, _ASM_LABEL(Lcistoolong)
402: 1:
403: #ifdef ERRATA__XXX_USR
404: NOP
405: ld.bu.usr r7, SRC, r6
406: NOP
407: NOP
408: NOP
409: #else
410: ld.bu.usr r7, SRC, r6
411: #endif
412: st.b r7, DEST, r6
413: bcnd.n eq0, r7, 2f /* all done */
414: addu r6, r6, 1
415: cmp r7, r6, CNT
416: bb1 lt, r7, 1b
417:
418: ASLOCAL(Lcistoolong)
419: or r2, r0, ENAMETOOLONG /* overflow */
420:
421: ASLOCAL(Lcisnull)
422: bcnd eq0,r6, _ASM_LABEL(Lcisdone) /* do not attempt to clear last byte */
423: /* if we did not write to the string */
424: subu r6, r6, 1
425: st.b r0, DEST, r6 /* clear last byte */
426: br.n _ASM_LABEL(Lcisdone)
427: addu r6, r6, 1
428: 2: /* all done */
429: or r2, r0, 0
430:
431: ASLOCAL(Lcisdone)
432: bcnd eq0, LEN, 3f
433: st r6, r0, LEN
434: 3:
435: ldcr r5, CPU
436: ld r6, r5, CI_CURPCB
437: jmp.n r1
438: st r0,r6,PCB_ONFAULT /* clear the handler */
439:
440: ASLOCAL(Lcisflt)
441: br.n _ASM_LABEL(Lcisnull)
442: or r2, r0, EFAULT /* return fault */
443:
444: #undef SRC
445: #undef DEST
446: #undef CNT
447: #undef LEN
448:
449: /*
450: * Copy specified amount of data from kernel to the user space
451: * Copyout(from, to, len)
452: * r2 == from (kernel source address)
453: * r3 == to (user destination address)
454: * r4 == length
455: */
456:
457: #define SRC r2
458: #define DEST r3
459: #define LEN r4
460:
461: ENTRY(copyout)
462: /* setup fault handler */
463: ldcr r5, CPU
464: ld r6, r5, CI_CURPCB
465: or.u r5, r0, hi16(_ASM_LABEL(Lcoflt))
466: or r5, r5, lo16(_ASM_LABEL(Lcoflt))
467: st r5, r6, PCB_ONFAULT /* pcb_onfault = Lcoflt */
468:
469: /*
470: * If it's a small length (less than 8), then do byte-by-byte.
471: * Despite not being optimal if len is 4, and from and to
472: * are word-aligned, this is still faster than doing more tests
473: * to save an hyperthetical fraction of cycle.
474: */
475: cmp r9, LEN, 8
476: bb1 lt, r9, _ASM_LABEL(copyout_byte_only)
477:
478: /* If they're not aligned similarly, use byte only... */
479: xor r9, SRC, DEST
480: mask r8, r9, 0x3
481: bcnd ne0, r8, _ASM_LABEL(copyout_byte_only)
482:
483: /*
484: * At this point, we don't know if they're word aligned or not,
485: * but we know that what needs to be done to one to align
486: * it is what's needed for the other.
487: */
488: bb1 0, SRC, _ASM_LABEL(copyout_left_align_to_halfword)
489: ASLOCAL(copyout_left_aligned_to_halfword)
490: bb1 1, SRC, _ASM_LABEL(copyout_left_align_to_word)
491: ASLOCAL(copyout_left_aligned_to_word)
492: bb1 0, LEN, _ASM_LABEL(copyout_right_align_to_halfword)
493: ASLOCAL(copyout_right_aligned_to_halfword)
494: bb1 1, LEN, _ASM_LABEL(copyout_right_align_to_word)
495: ASLOCAL(copyout_right_aligned_to_word)
496:
497: /*
498: * At this point, both SRC and DEST are aligned to a word
499: * boundary, and LEN is a multiple of 4. We want it an even
500: * multiple of 4.
501: */
502: bb1.n 2, LEN, _ASM_LABEL(copyout_right_align_to_doubleword)
503: or r7, r0, 4
504:
505: ASLOCAL(copyout_right_aligned_to_doubleword)
506: ld r5, SRC, r0
507: ld r6, SRC, r7
508: subu LEN, LEN, 8
509: #ifdef ERRATA__XXX_USR
510: NOP
511: st.usr r5, DEST, r0
512: NOP
513: NOP
514: NOP
515: #else
516: st.usr r5, DEST, r0
517: #endif
518: addu SRC, SRC, 8
519: #ifdef ERRATA__XXX_USR
520: NOP
521: st.usr r6, DEST, r7
522: NOP
523: NOP
524: NOP
525: #else
526: st.usr r6, DEST, r7
527: #endif
528: bcnd.n ne0, LEN, _ASM_LABEL(copyout_right_aligned_to_doubleword)
529: addu DEST, DEST, 8
530: or r2, r0, r0 /* successful return */
531: br _ASM_LABEL(Lcodone)
532:
533: /***************************************************/
534: ASLOCAL(copyout_left_align_to_halfword)
535: ld.b r5, SRC, r0
536: subu LEN, LEN, 1
537: #ifdef ERRATA__XXX_USR
538: NOP
539: st.b.usr r5, DEST, r0
540: NOP
541: NOP
542: NOP
543: #else
544: st.b.usr r5, DEST, r0
545: #endif
546: addu SRC, SRC, 1
547: br.n _ASM_LABEL(copyout_left_aligned_to_halfword)
548: addu DEST, DEST, 1
549:
550: ASLOCAL(copyout_left_align_to_word)
551: ld.h r5, SRC, r0
552: subu LEN, LEN, 2
553: #ifdef ERRATA__XXX_USR
554: NOP
555: st.h.usr r5, DEST, r0
556: NOP
557: NOP
558: NOP
559: #else
560: st.h.usr r5, DEST, r0
561: #endif
562: addu SRC, SRC, 2
563: br.n _ASM_LABEL(copyout_left_aligned_to_word)
564: addu DEST, DEST, 2
565:
566: ASLOCAL(copyout_right_align_to_halfword)
567: subu LEN, LEN, 1
568: ld.b r5, SRC, LEN
569: #ifdef ERRATA__XXX_USR
570: NOP
571: st.b.usr r5, DEST, LEN
572: NOP
573: NOP
574: NOP
575: br _ASM_LABEL(copyout_right_aligned_to_halfword)
576: #else
577: br.n _ASM_LABEL(copyout_right_aligned_to_halfword)
578: st.b.usr r5, DEST, LEN
579: #endif
580:
581: ASLOCAL(copyout_right_align_to_word)
582: subu LEN, LEN, 2
583: ld.h r5, SRC, LEN
584: #ifdef ERRATA__XXX_USR
585: NOP
586: st.h.usr r5, DEST, LEN
587: NOP
588: NOP
589: NOP
590: br _ASM_LABEL(copyout_right_aligned_to_word)
591: #else
592: br.n _ASM_LABEL(copyout_right_aligned_to_word)
593: st.h.usr r5, DEST, LEN
594: #endif
595:
596: ASLOCAL(copyout_right_align_to_doubleword)
597: subu LEN, LEN, 4
598: ld r5, SRC, LEN
599: #ifdef ERRATA__XXX_USR
600: NOP
601: st.usr r5, DEST, LEN
602: NOP
603: NOP
604: NOP
605: bcnd ne0, LEN, _ASM_LABEL(copyout_right_aligned_to_doubleword)
606: #else
607: bcnd.n ne0, LEN, _ASM_LABEL(copyout_right_aligned_to_doubleword)
608: st.usr r5, DEST, LEN
609: #endif
610: br.n _ASM_LABEL(Lcodone)
611: or r2, r0, r0 /* successful return */
612:
613: ASLOCAL(copyout_byte_only)
614: bcnd eq0, LEN, 2f
615: 1:
616: subu LEN, LEN, 1
617: ld.b r5, SRC, LEN
618: #ifdef ERRATA__XXX_USR
619: NOP
620: st.b.usr r5, DEST, LEN
621: NOP
622: NOP
623: NOP
624: bcnd ne0, LEN, 1b
625: #else
626: bcnd.n ne0, LEN, 1b
627: st.b.usr r5, DEST, LEN
628: #endif
629:
630: 2:
631: or r2, r0, r0 /* successful return */
632: /* FALLTHROUGH */
633:
634: ASLOCAL(Lcodone)
635: ldcr r5, CPU
636: ld r6, r5, CI_CURPCB
637: jmp.n r1
638: st r0,r6,PCB_ONFAULT /* clear the handler */
639:
640: ASLOCAL(Lcoflt)
641: br.n _ASM_LABEL(Lcodone)
642: or r2, r0, EFAULT /* return fault */
643:
644: #undef SRC
645: #undef DEST
646: #undef LEN
647:
648: /*
649: * Copy a null terminated string from the kernel space to the user
650: * address space.
651: *
652: * copyoutstr(from, to, maxlen, &lencopied)
653: * r2 == from
654: * r3 == to
655: * r4 == maxlen that can be copied
656: * r5 == len actually copied (including the terminating NUL!!!)
657: */
658:
659: #define SRC r2
660: #define DEST r3
661: #define CNT r4
662: #define LEN r5
663:
664: ENTRY(copyoutstr)
665: /* setup fault handler */
666: ldcr r6, CPU
667: ld r7, r6, CI_CURPCB
668: or.u r6, r0, hi16(_ASM_LABEL(Lcosflt))
669: or r6, r6, lo16(_ASM_LABEL(Lcosflt))
670: st r6, r7, PCB_ONFAULT
671: bcnd lt0, CNT, _ASM_LABEL(Lcosflt)
672: bcnd eq0, CNT, _ASM_LABEL(Lcosdone)
673: or r6, r0, 0
674: 1:
675: ld.bu r7, SRC, r6
676: #ifdef ERRATA__XXX_USR
677: NOP
678: st.b.usr r7, DEST, r6
679: NOP
680: NOP
681: NOP
682: #else
683: st.b.usr r7, DEST, r6
684: #endif
685: bcnd.n eq0, r7, 2f /* all done */
686: addu r6, r6, 1
687: cmp r7, r6, CNT
688: bb1 lt, r7, 1b
689: br.n _ASM_LABEL(Lcosdone)
690: or r2, r0, ENAMETOOLONG
691: 2:
692: br.n _ASM_LABEL(Lcosdone)
693: or r2, r0, 0
694:
695: ASLOCAL(Lcosflt)
696: br.n _ASM_LABEL(Lcosdone)
697: or r2, r0, EFAULT
698:
699: ASLOCAL(Lcosdone)
700: bcnd eq0, LEN, 3f
701: st r6, r0, LEN
702: 3:
703: ldcr r5, CPU
704: ld r6, r5, CI_CURPCB
705: jmp.n r1
706: st r0,r6,PCB_ONFAULT /* clear the handler */
707:
708: #undef SRC
709: #undef DEST
710: #undef CNT
711: #undef LEN
712:
713: /*######################################################################*/
714:
715: /*
716: * kcopy(const void *src, void *dst, size_t len);
717: *
718: * Copy len bytes from src to dst, aborting if we encounter a page fault.
719: */
720: ENTRY(kcopy)
721: ldcr r5, CPU
722: ld r6, r5, CI_CURPCB
723: or.u r5, r0, hi16(_ASM_LABEL(kcopy_fault))
724: or r5, r5, lo16(_ASM_LABEL(kcopy_fault))
725: st r5, r6, PCB_ONFAULT /* pcb_onfault = kcopy_fault */
726: bcnd le0,r4,_ASM_LABEL(kcopy_out) /* nothing to do if <= 0 */
727: /*
728: * check position of source and destination data
729: */
730: cmp r9,r2,r3 /* compare source address to destination */
731: bb1 eq,r9,_ASM_LABEL(kcopy_out) /* nothing to do if equal */
732: bb1 lo,r9,_ASM_LABEL(kcopy_reverse) /* reverse copy if src < dest */
733: /*
734: * source address is greater than destination address, copy forward
735: */
736: cmp r9,r4,16 /* see if we have at least 16 bytes */
737: bb1 lt,r9,_ASM_LABEL(kf_byte_copy) /* copy bytes for small length */
738: /*
739: * determine copy strategy based on alignment of source and destination
740: */
741: mask r6,r2,3 /* get 2 low order bits of source address */
742: mask r7,r3,3 /* get 2 low order bits of destintation addr */
743: mak r6,r6,0<4> /* convert source bits to table offset */
744: mak r7,r7,0<2> /* convert destination bits to table offset */
745: or.u r12,r0,hi16(_ASM_LABEL(kf_strat))
746: or r12,r12,lo16(_ASM_LABEL(kf_strat))
747: addu r6,r6,r7 /* compute final table offset for strategy */
748: ld r12,r12,r6 /* load the strategy routine */
749: jmp r12 /* branch to strategy routine */
750:
751: /*
752: * Copy three bytes from src to destination then copy words
753: */
754: ASLOCAL(kf_3byte_word_copy)
755: ld.bu r6,r2,0 /* load byte from source */
756: ld.bu r7,r2,1 /* load byte from source */
757: ld.bu r8,r2,2 /* load byte from source */
758: st.b r6,r3,0 /* store byte to destination */
759: st.b r7,r3,1 /* store byte to destination */
760: st.b r8,r3,2 /* store byte to destination */
761: addu r2,r2,3 /* increment source pointer */
762: addu r3,r3,3 /* increment destination pointer */
763: br.n _ASM_LABEL(kf_word_copy) /* copy full words */
764: subu r4,r4,3 /* decrement length */
765:
766: /*
767: * Copy 1 halfword from src to destination then copy words
768: */
769: ASLOCAL(kf_1half_word_copy)
770: ld.hu r6,r2,0 /* load half-word from source */
771: st.h r6,r3,0 /* store half-word to destination */
772: addu r2,r2,2 /* increment source pointer */
773: addu r3,r3,2 /* increment destination pointer */
774: br.n _ASM_LABEL(kf_word_copy) /* copy full words */
775: subu r4,r4,2 /* decrement remaining length */
776:
777: /*
778: * Copy 1 byte from src to destination then copy words
779: */
780: ASLOCAL(kf_1byte_word_copy)
781: ld.bu r6,r2,0 /* load 1 byte from source */
782: st.b r6,r3,0 /* store 1 byte to destination */
783: addu r2,r2,1 /* increment source pointer */
784: addu r3,r3,1 /* increment destination pointer */
785: subu r4,r4,1 /* decrement remaining length */
786: /* fall through to word copy */
787: /*
788: * Copy as many full words as possible, 4 words per loop
789: */
790: ASLOCAL(kf_word_copy)
791: cmp r10,r4,16 /* see if we have 16 bytes remaining */
792: bb1 lo,r10,_ASM_LABEL(kf_byte_copy) /* not enough left, copy bytes */
793: ld r6,r2,0 /* load first word */
794: ld r7,r2,4 /* load second word */
795: ld r8,r2,8 /* load third word */
796: ld r9,r2,12 /* load fourth word */
797: st r6,r3,0 /* store first word */
798: st r7,r3,4 /* store second word */
799: st r8,r3,8 /* store third word */
800: st r9,r3,12 /* store fourth word */
801: addu r2,r2,16 /* increment source pointer */
802: addu r3,r3,16 /* increment destination pointer */
803: br.n _ASM_LABEL(kf_word_copy) /* copy another block */
804: subu r4,r4,16 /* decrement remaining length */
805:
806: ASLOCAL(kf_1byte_half_copy)
807: ld.bu r6,r2,0 /* load 1 byte from source */
808: st.b r6,r3,0 /* store 1 byte to destination */
809: addu r2,r2,1 /* increment source pointer */
810: addu r3,r3,1 /* increment destination pointer */
811: subu r4,r4,1 /* decrement remaining length */
812: /* fall through to half copy */
813:
814: ASLOCAL(kf_half_copy)
815: cmp r10,r4,16 /* see if we have 16 bytes remaining */
816: bb1 lo,r10,_ASM_LABEL(kf_byte_copy) /* not enough left, copy bytes */
817: ld.hu r6,r2,0 /* load first half-word */
818: ld.hu r7,r2,2 /* load second half-word */
819: ld.hu r8,r2,4 /* load third half-word */
820: ld.hu r9,r2,6 /* load fourth half-word */
821: ld.hu r10,r2,8 /* load fifth half-word */
822: ld.hu r11,r2,10 /* load sixth half-word */
823: ld.hu r12,r2,12 /* load seventh half-word */
824: ld.hu r13,r2,14 /* load eighth half-word */
825: st.h r6,r3,0 /* store first half-word */
826: st.h r7,r3,2 /* store second half-word */
827: st.h r8,r3,4 /* store third half-word */
828: st.h r9,r3,6 /* store fourth half-word */
829: st.h r10,r3,8 /* store fifth half-word */
830: st.h r11,r3,10 /* store sixth half-word */
831: st.h r12,r3,12 /* store seventh half-word */
832: st.h r13,r3,14 /* store eighth half-word */
833: addu r2,r2,16 /* increment source pointer */
834: addu r3,r3,16 /* increment destination pointer */
835: br.n _ASM_LABEL(kf_half_copy) /* copy another block */
836: subu r4,r4,16 /* decrement remaining length */
837:
838: ASLOCAL(kf_byte_copy)
839: bcnd eq0,r4,_ASM_LABEL(kcopy_out) /* branch if nothing left to copy */
840: ld.bu r6,r2,0 /* load byte from source */
841: st.b r6,r3,0 /* store byte in destination */
842: addu r2,r2,1 /* increment source pointer */
843: addu r3,r3,1 /* increment destination pointer */
844: br.n _ASM_LABEL(kf_byte_copy) /* branch for next byte */
845: subu r4,r4,1 /* decrement remaining length */
846:
847: /*
848: * source address is less than destination address, copy in reverse
849: */
850: ASLOCAL(kcopy_reverse)
851: /*
852: * start copy pointers at end of data
853: */
854: addu r2,r2,r4 /* start source at end of data */
855: addu r3,r3,r4 /* start destination at end of data */
856: /*
857: * check for short data
858: */
859: cmp r9,r4,16 /* see if we have at least 16 bytes */
860: bb1 lt,r9,_ASM_LABEL(kr_byte_copy) /* copy bytes for small data length */
861: /*
862: * determine copy strategy based on alignment of source and destination
863: */
864: mask r6,r2,3 /* get 2 low order bits of source address */
865: mask r7,r3,3 /* get 2 low order bits of destintation addr */
866: mak r6,r6,0<4> /* convert source bits to table offset */
867: mak r7,r7,0<2> /* convert destination bits to table offset */
868: or.u r12,r0,hi16(_ASM_LABEL(kr_strat))
869: or r12,r12,lo16(_ASM_LABEL(kr_strat))
870: addu r6,r6,r7 /* compute final table offset for strategy */
871: ld r12,r12,r6 /* load the strategy routine */
872: jmp r12 /* branch to strategy routine */
873:
874: /*
875: * Copy three bytes from src to destination then copy words
876: */
877: ASLOCAL(kr_3byte_word_copy)
878: subu r2,r2,3 /* decrement source pointer */
879: subu r3,r3,3 /* decrement destination pointer */
880: ld.bu r6,r2,0 /* load byte from source */
881: ld.bu r7,r2,1 /* load byte from source */
882: ld.bu r8,r2,2 /* load byte from source */
883: st.b r6,r3,0 /* store byte to destination */
884: st.b r7,r3,1 /* store byte to destination */
885: st.b r8,r3,2 /* store byte to destination */
886: br.n _ASM_LABEL(kr_word_copy) /* copy full words */
887: subu r4,r4,3 /* decrement length */
888:
889: /*
890: * Copy 1 halfword from src to destination then copy words
891: */
892: ASLOCAL(kr_1half_word_copy)
893: subu r2,r2,2 /* decrement source pointer */
894: subu r3,r3,2 /* decrement destination pointer */
895: ld.hu r6,r2,0 /* load half-word from source */
896: st.h r6,r3,0 /* store half-word to destination */
897: br.n _ASM_LABEL(kr_word_copy) /* copy full words */
898: subu r4,r4,2 /* decrement remaining length */
899:
900: /*
901: * Copy 1 byte from src to destination then copy words
902: */
903: ASLOCAL(kr_1byte_word_copy)
904: subu r2,r2,1 /* decrement source pointer */
905: subu r3,r3,1 /* decrement destination pointer */
906: ld.bu r6,r2,0 /* load 1 byte from source */
907: st.b r6,r3,0 /* store 1 byte to destination */
908: subu r4,r4,1 /* decrement remaining length */
909: /* fall through to word copy */
910: /*
911: * Copy as many full words as possible, 4 words per loop
912: */
913: ASLOCAL(kr_word_copy)
914: cmp r10,r4,16 /* see if we have 16 bytes remaining */
915: bb1 lo,r10,_ASM_LABEL(kr_byte_copy) /* not enough left, copy bytes */
916: subu r2,r2,16 /* decrement source pointer */
917: subu r3,r3,16 /* decrement destination pointer */
918: ld r6,r2,0 /* load first word */
919: ld r7,r2,4 /* load second word */
920: ld r8,r2,8 /* load third word */
921: ld r9,r2,12 /* load fourth word */
922: st r6,r3,0 /* store first word */
923: st r7,r3,4 /* store second word */
924: st r8,r3,8 /* store third word */
925: st r9,r3,12 /* store fourth word */
926: br.n _ASM_LABEL(kr_word_copy) /* copy another block */
927: subu r4,r4,16 /* decrement remaining length */
928:
929: ASLOCAL(kr_1byte_half_copy)
930: subu r2,r2,1 /* decrement source pointer */
931: subu r3,r3,1 /* decrement destination pointer */
932: ld.bu r6,r2,0 /* load 1 byte from source */
933: st.b r6,r3,0 /* store 1 byte to destination */
934: subu r4,r4,1 /* decrement remaining length */
935: /* fall through to half copy */
936:
937: ASLOCAL(kr_half_copy)
938: cmp r10,r4,16 /* see if we have 16 bytes remaining */
939: bb1 lo,r10,_ASM_LABEL(kr_byte_copy) /* not enough left, copy bytes */
940: subu r2,r2,16 /* decrement source pointer */
941: subu r3,r3,16 /* decrement destination pointer */
942: ld.hu r6,r2,0 /* load first half-word */
943: ld.hu r7,r2,2 /* load second half-word */
944: ld.hu r8,r2,4 /* load third half-word */
945: ld.hu r9,r2,6 /* load fourth half-word */
946: ld.hu r10,r2,8 /* load fifth half-word */
947: ld.hu r11,r2,10 /* load sixth half-word */
948: ld.hu r12,r2,12 /* load seventh half-word */
949: ld.hu r13,r2,14 /* load eighth half-word */
950: st.h r6,r3,0 /* store first half-word */
951: st.h r7,r3,2 /* store second half-word */
952: st.h r8,r3,4 /* store third half-word */
953: st.h r9,r3,6 /* store fourth half-word */
954: st.h r10,r3,8 /* store fifth half-word */
955: st.h r11,r3,10 /* store sixth half-word */
956: st.h r12,r3,12 /* store seventh half-word */
957: st.h r13,r3,14 /* store eighth half-word */
958: br.n _ASM_LABEL(kr_half_copy) /* copy another block */
959: subu r4,r4,16 /* decrement remaining length */
960:
961: ASLOCAL(kr_byte_copy)
962: bcnd eq0,r4,_ASM_LABEL(kcopy_out) /* branch if nothing left to copy */
963: subu r2,r2,1 /* decrement source pointer */
964: subu r3,r3,1 /* decrement destination pointer */
965: ld.bu r6,r2,0 /* load byte from source */
966: st.b r6,r3,0 /* store byte in destination */
967: br.n _ASM_LABEL(kr_byte_copy) /* branch for next byte */
968: subu r4,r4,1 /* decrement remaining length */
969:
970: ASLOCAL(kcopy_out)
971: or r2, r0, 0 /* return success */
972: ASLOCAL(kcopy_out_fault)
973: ldcr r5, CPU
974: ld r6, r5, CI_CURPCB
975: jmp.n r1 /* all done, return to caller */
976: st r0, r6, PCB_ONFAULT /* clear the handler */
977:
978: ASLOCAL(kcopy_fault)
979: br.n _ASM_LABEL(kcopy_out_fault)
980: or r2, r0, EFAULT /* return fault */
981:
982: data
983: align 4
984: ASLOCAL(kf_strat)
985: word _ASM_LABEL(kf_word_copy)
986: word _ASM_LABEL(kf_byte_copy)
987: word _ASM_LABEL(kf_half_copy)
988: word _ASM_LABEL(kf_byte_copy)
989: word _ASM_LABEL(kf_byte_copy)
990: word _ASM_LABEL(kf_3byte_word_copy)
991: word _ASM_LABEL(kf_byte_copy)
992: word _ASM_LABEL(kf_1byte_half_copy)
993: word _ASM_LABEL(kf_half_copy)
994: word _ASM_LABEL(kf_byte_copy)
995: word _ASM_LABEL(kf_1half_word_copy)
996: word _ASM_LABEL(kf_byte_copy)
997: word _ASM_LABEL(kf_byte_copy)
998: word _ASM_LABEL(kf_1byte_half_copy)
999: word _ASM_LABEL(kf_byte_copy)
1000: word _ASM_LABEL(kf_1byte_word_copy)
1001:
1002: ASLOCAL(kr_strat)
1003: word _ASM_LABEL(kr_word_copy)
1004: word _ASM_LABEL(kr_byte_copy)
1005: word _ASM_LABEL(kr_half_copy)
1006: word _ASM_LABEL(kr_byte_copy)
1007: word _ASM_LABEL(kr_byte_copy)
1008: word _ASM_LABEL(kr_1byte_word_copy)
1009: word _ASM_LABEL(kr_byte_copy)
1010: word _ASM_LABEL(kr_1byte_half_copy)
1011: word _ASM_LABEL(kr_half_copy)
1012: word _ASM_LABEL(kr_byte_copy)
1013: word _ASM_LABEL(kr_1half_word_copy)
1014: word _ASM_LABEL(kr_byte_copy)
1015: word _ASM_LABEL(kr_byte_copy)
1016: word _ASM_LABEL(kr_1byte_half_copy)
1017: word _ASM_LABEL(kr_byte_copy)
1018: word _ASM_LABEL(kr_3byte_word_copy)
1019:
1020: /*
1021: * non-local goto
1022: * int setjmp(label_t *);
1023: * void longjmp(label_t*);
1024: */
1025: ENTRY(setjmp)
1026: st r1,r2,0
1027: st r14,r2,4
1028: st r15,r2,2*4
1029: st r16,r2,3*4
1030: st r17,r2,4*4
1031: st r18,r2,5*4
1032: st r19,r2,6*4
1033: st r20,r2,7*4
1034: st r21,r2,8*4
1035: st r22,r2,9*4
1036: st r23,r2,10*4
1037: st r24,r2,11*4
1038: st r25,r2,12*4
1039: st r26,r2,13*4
1040: st r27,r2,14*4
1041: st r28,r2,15*4
1042: st r29,r2,16*4
1043: st r30,r2,17*4
1044: st r31,r2,18*4
1045: jmp.n r1
1046: or r2,r0,r0
1047:
1048: ENTRY(longjmp)
1049: ld r1,r2,0
1050: ld r14,r2,4
1051: ld r15,r2,2*4
1052: ld r16,r2,3*4
1053: ld r17,r2,4*4
1054: ld r18,r2,5*4
1055: ld r19,r2,6*4
1056: ld r20,r2,7*4
1057: ld r21,r2,8*4
1058: ld r22,r2,9*4
1059: ld r23,r2,10*4
1060: ld r24,r2,11*4
1061: ld r25,r2,12*4
1062: ld r26,r2,13*4
1063: ld r27,r2,14*4
1064: ld r28,r2,15*4
1065: ld r29,r2,16*4
1066: ld r30,r2,17*4
1067: ld r31,r2,18*4
1068: jmp.n r1
1069: or r2,r0,1
1070:
1071: /*
1072: * Signal trampoline code.
1073: * The kernel arranges for the handler to be invoked directly, and return
1074: * here.
1075: */
1076: GLOBAL(sigcode) /* r31 points to sigframe */
1077: ld r2, r31, 0 /* pick sigcontext* */
1078: or r13, r0, SYS_sigreturn
1079: tb0 0, r0, 128 /* syscall trap, calling sigreturn */
1080: NOP | failure return
1081: #ifdef dontbother /* sigreturn will not return unless it fails */
1082: NOP | success return
1083: #endif
1084: or r13, r0, SYS_exit
1085: tb0 0, r0, 128 /* syscall trap, exit */
1086: /*
1087: * this never returns, but we need to provide fetchable instructions
1088: * for the 88100 pipeline.
1089: */
1090: NOP
1091: NOP
1092: GLOBAL(esigcode)
CVSweb