ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / parisc / kernel / entry.S
1 /*
2  * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3  *
4  * kernel entry points (interruptions, system call wrappers)
5  *  Copyright (C) 1999,2000 Philipp Rumpf 
6  *  Copyright (C) 1999 SuSE GmbH Nuernberg 
7  *  Copyright (C) 2000 Hewlett-Packard (John Marvin)
8  *  Copyright (C) 1999 Hewlett-Packard (Frank Rowand)
9  *
10  *    This program is free software; you can redistribute it and/or modify
11  *    it under the terms of the GNU General Public License as published by
12  *    the Free Software Foundation; either version 2, or (at your option)
13  *    any later version.
14  *
15  *    This program is distributed in the hope that it will be useful,
16  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *    GNU General Public License for more details.
19  *
20  *    You should have received a copy of the GNU General Public License
21  *    along with this program; if not, write to the Free Software
22  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25 #include <linux/config.h>
26 #include <asm/offsets.h>
27
28 /* we have the following possibilities to act on an interruption:
29  *  - handle in assembly and use shadowed registers only
30  *  - save registers to kernel stack and handle in assembly or C */
31
32
33 #include <asm/assembly.h>       /* for LDREG/STREG defines */
34 #include <asm/pgtable.h>
35 #include <asm/psw.h>
36 #include <asm/signal.h>
37 #include <asm/unistd.h>
38 #include <asm/thread_info.h>
39
40 #ifdef __LP64__
41 #define CMPIB           cmpib,*
42 #define CMPB            cmpb,*
43
44         .level 2.0w
45 #else
46 #define CMPIB           cmpib,
47 #define CMPB            cmpb,
48
49         .level 2.0
50 #endif
51
52         .import         pa_dbit_lock,data
53
54         /* space_to_prot macro creates a prot id from a space id */
55
56 #if (SPACEID_SHIFT) == 0
57         .macro  space_to_prot spc prot
58         depd,z  \spc,62,31,\prot
59         .endm
60 #else
61         .macro  space_to_prot spc prot
62         extrd,u \spc,(64 - (SPACEID_SHIFT)),32,\prot
63         .endm
64 #endif
65
66         /* Switch to virtual mapping, trashing only %r1 */
67         .macro  virt_map
68         rsm     PSW_SM_Q,%r0
69         tovirt_r1 %r29
70         mfsp    %sr7, %r1
71         or,=    %r0,%r1,%r0 /* Only save sr7 in sr3 if sr7 != 0 */
72         mtsp    %r1, %sr3
73         mtsp    %r0, %sr4
74         mtsp    %r0, %sr5
75         mtsp    %r0, %sr6
76         mtsp    %r0, %sr7
77         ldil    L%KERNEL_PSW, %r1
78         ldo     R%KERNEL_PSW(%r1), %r1
79         mtctl   %r1, %cr22
80         mtctl   %r0, %cr17      /* Clear IIASQ tail */
81         mtctl   %r0, %cr17      /* Clear IIASQ head */
82         ldil    L%4f, %r1
83         ldo     R%4f(%r1), %r1
84         mtctl   %r1, %cr18      /* Set IIAOQ tail */
85         ldo     4(%r1), %r1
86         mtctl   %r1, %cr18      /* Set IIAOQ head */
87         rfir
88         nop
89 4:
90         .endm
91
92         /*
93          * The "get_stack" macros are responsible for determining the
94          * kernel stack value.
95          *
96          * For Faults:
97          *      If sr7 == 0
98          *          Already using a kernel stack, so call the
99          *          get_stack_use_r30 macro to push a pt_regs structure
100          *          on the stack, and store registers there.
101          *      else
102          *          Need to set up a kernel stack, so call the
103          *          get_stack_use_cr30 macro to set up a pointer
104          *          to the pt_regs structure contained within the
105          *          task pointer pointed to by cr30. Set the stack
106          *          pointer to point to the end of the task structure.
107          *
108          * For Interrupts:
109          *      If sr7 == 0
110          *          Already using a kernel stack, check to see if r30
111          *          is already pointing to the per processor interrupt
112          *          stack. If it is, call the get_stack_use_r30 macro
113          *          to push a pt_regs structure on the stack, and store
114          *          registers there. Otherwise, call get_stack_use_cr31
115          *          to get a pointer to the base of the interrupt stack
116          *          and push a pt_regs structure on that stack.
117          *      else
118          *          Need to set up a kernel stack, so call the
119          *          get_stack_use_cr30 macro to set up a pointer
120          *          to the pt_regs structure contained within the
121          *          task pointer pointed to by cr30. Set the stack
122          *          pointer to point to the end of the task structure.
123          *          N.B: We don't use the interrupt stack for the
124          *          first interrupt from userland, because signals/
125          *          resched's are processed when returning to userland,
126          *          and we can sleep in those cases.
127          *
128          * Note that we use shadowed registers for temps until
129          * we can save %r26 and %r29. %r26 is used to preserve
130          * %r8 (a shadowed register) which temporarily contained
131          * either the fault type ("code") or the eirr. We need
132          * to use a non-shadowed register to carry the value over
133          * the rfir in virt_map. We use %r26 since this value winds
134          * up being passed as the argument to either do_cpu_irq_mask
135          * or handle_interruption. %r29 is used to hold a pointer
136          * the register save area, and once again, it needs to
137          * be a non-shadowed register so that it survives the rfir.
138          *
139          * N.B. TASK_SZ_ALGN and PT_SZ_ALGN include space for a stack frame.
140          */
141
142         .macro  get_stack_use_cr30
143
144         /* we save the registers in the task struct */
145
146         mfctl   %cr30, %r1
147         tophys  %r1,%r9
148         LDREG   TI_TASK(%r9), %r1       /* thread_info -> task_struct */
149         tophys  %r1,%r9
150         ldo     TASK_REGS(%r9),%r9
151         STREG   %r30, PT_GR30(%r9)
152         STREG   %r29,PT_GR29(%r9)
153         STREG   %r26,PT_GR26(%r9)
154         copy    %r9,%r29
155         mfctl   %cr30, %r1
156         ldo     THREAD_SZ_ALGN(%r1), %r30
157         .endm
158
159         .macro  get_stack_use_r30
160
161         /* we put a struct pt_regs on the stack and save the registers there */
162
163         tophys  %r30,%r9
164         STREG   %r30,PT_GR30(%r9)
165         ldo     PT_SZ_ALGN(%r30),%r30
166         STREG   %r29,PT_GR29(%r9)
167         STREG   %r26,PT_GR26(%r9)
168         copy    %r9,%r29
169         .endm
170
171         .macro  rest_stack
172         LDREG   PT_GR1(%r29), %r1
173         LDREG   PT_GR30(%r29),%r30
174         LDREG   PT_GR29(%r29),%r29
175         .endm
176
177         /* default interruption handler
178          * (calls traps.c:handle_interruption) */
179         .macro  def code
180         b       intr_save
181         ldi     \code, %r8
182         .align  32
183         .endm
184
185         /* Interrupt interruption handler
186          * (calls irq.c:do_cpu_irq_mask) */
187         .macro  extint code
188         b       intr_extint
189         mfsp    %sr7,%r16
190         .align  32
191         .endm   
192
193         .import os_hpmc, code
194
195         /* HPMC handler */
196         .macro  hpmc code
197         nop                     /* must be a NOP, will be patched later */
198         ldil    L%PA(os_hpmc), %r3
199         ldo     R%PA(os_hpmc)(%r3), %r3
200         bv,n    0(%r3)
201         nop
202         .word   0               /* checksum (will be patched) */
203         .word   PA(os_hpmc)     /* address of handler */
204         .word   0               /* length of handler */
205         .endm
206
207         /*
208          * Performance Note: Instructions will be moved up into
209          * this part of the code later on, once we are sure
210          * that the tlb miss handlers are close to final form.
211          */
212
213         /* Register definitions for tlb miss handler macros */
214
215         va  = r8        /* virtual address for which the trap occured */
216         spc = r24       /* space for which the trap occured */
217
218 #ifndef __LP64__
219
220         /*
221          * itlb miss interruption handler (parisc 1.1 - 32 bit)
222          */
223
224         .macro  itlb_11 code
225
226         mfctl   %pcsq, spc
227         b       itlb_miss_11
228         mfctl   %pcoq, va
229
230         .align          32
231         .endm
232 #endif
233         
234         /*
235          * itlb miss interruption handler (parisc 2.0)
236          */
237
238         .macro  itlb_20 code
239         mfctl   %pcsq, spc
240 #ifdef __LP64__
241         b       itlb_miss_20w
242 #else
243         b       itlb_miss_20
244 #endif
245         mfctl   %pcoq, va
246
247         .align          32
248         .endm
249         
250 #ifndef __LP64__
251         /*
252          * naitlb miss interruption handler (parisc 1.1 - 32 bit)
253          *
254          * Note: naitlb misses will be treated
255          * as an ordinary itlb miss for now.
256          * However, note that naitlb misses
257          * have the faulting address in the
258          * IOR/ISR.
259          */
260
261         .macro  naitlb_11 code
262
263         mfctl   %isr,spc
264         b       itlb_miss_11
265         mfctl   %ior,va
266         /* FIXME: If user causes a naitlb miss, the priv level may not be in
267          * lower bits of va, where the itlb miss handler is expecting them
268          */
269
270         .align          32
271         .endm
272 #endif
273         
274         /*
275          * naitlb miss interruption handler (parisc 2.0)
276          *
277          * Note: naitlb misses will be treated
278          * as an ordinary itlb miss for now.
279          * However, note that naitlb misses
280          * have the faulting address in the
281          * IOR/ISR.
282          */
283
284         .macro  naitlb_20 code
285
286         mfctl   %isr,spc
287 #ifdef __LP64__
288         b       itlb_miss_20w
289 #else
290         b       itlb_miss_20
291 #endif
292         mfctl   %ior,va
293         /* FIXME: If user causes a naitlb miss, the priv level may not be in
294          * lower bits of va, where the itlb miss handler is expecting them
295          */
296
297         .align          32
298         .endm
299         
300 #ifndef __LP64__
301         /*
302          * dtlb miss interruption handler (parisc 1.1 - 32 bit)
303          */
304
305         .macro  dtlb_11 code
306
307         mfctl   %isr, spc
308         b       dtlb_miss_11
309         mfctl   %ior, va
310
311         .align          32
312         .endm
313 #endif
314
315         /*
316          * dtlb miss interruption handler (parisc 2.0)
317          */
318
319         .macro  dtlb_20 code
320
321         mfctl   %isr, spc
322 #ifdef __LP64__
323         b       dtlb_miss_20w
324 #else
325         b       dtlb_miss_20
326 #endif
327         mfctl   %ior, va
328
329         .align          32
330         .endm
331         
332 #ifndef __LP64__
333         /* nadtlb miss interruption handler (parisc 1.1 - 32 bit) */
334
335         .macro  nadtlb_11 code
336
337         mfctl   %isr,spc
338         b       nadtlb_miss_11
339         mfctl   %ior,va
340
341         .align          32
342         .endm
343 #endif
344         
345         /* nadtlb miss interruption handler (parisc 2.0) */
346
347         .macro  nadtlb_20 code
348
349         mfctl   %isr,spc
350 #ifdef __LP64__
351         b       nadtlb_miss_20w
352 #else
353         b       nadtlb_miss_20
354 #endif
355         mfctl   %ior,va
356
357         .align          32
358         .endm
359         
360 #ifndef __LP64__
361         /*
362          * dirty bit trap interruption handler (parisc 1.1 - 32 bit)
363          */
364
365         .macro  dbit_11 code
366
367         mfctl   %isr,spc
368         b       dbit_trap_11
369         mfctl   %ior,va
370
371         .align          32
372         .endm
373 #endif
374
375         /*
376          * dirty bit trap interruption handler (parisc 2.0)
377          */
378
379         .macro  dbit_20 code
380
381         mfctl   %isr,spc
382 #ifdef __LP64__
383         b       dbit_trap_20w
384 #else
385         b       dbit_trap_20
386 #endif
387         mfctl   %ior,va
388
389         .align          32
390         .endm
391
392         /*
393          * Align fault_vector_20 on 4K boundary so that both
394          * fault_vector_11 and fault_vector_20 are on the
395          * same page. This is only necessary as long as we
396          * write protect the kernel text, which we may stop
397          * doing once we use large page translations to cover
398          * the static part of the kernel address space.
399          */
400
401         .export fault_vector_20
402
403         .text
404
405         .align 4096
406
407 fault_vector_20:
408         /* First vector is invalid (0) */
409         .ascii  "cows can fly"
410         .byte 0
411         .align 32
412
413         hpmc             1
414         def              2
415         def              3
416         extint           4
417         def              5
418         itlb_20          6
419         def              7
420         def              8
421         def              9
422         def             10
423         def             11
424         def             12
425         def             13
426         def             14
427         dtlb_20         15
428 #if 0
429         naitlb_20       16
430 #else
431         def             16
432 #endif
433         nadtlb_20       17
434         def             18
435         def             19
436         dbit_20         20
437         def             21
438         def             22
439         def             23
440         def             24
441         def             25
442         def             26
443         def             27
444         def             28
445         def             29
446         def             30
447         def             31
448
449 #ifndef __LP64__
450
451         .export fault_vector_11
452         
453         .align 2048
454
455 fault_vector_11:
456         /* First vector is invalid (0) */
457         .ascii  "cows can fly"
458         .byte 0
459         .align 32
460
461         hpmc             1
462         def              2
463         def              3
464         extint           4
465         def              5
466         itlb_11          6
467         def              7
468         def              8
469         def              9
470         def             10
471         def             11
472         def             12
473         def             13
474         def             14
475         dtlb_11         15
476 #if 0
477         naitlb_11       16
478 #else
479         def             16
480 #endif
481         nadtlb_11       17
482         def             18
483         def             19
484         dbit_11         20
485         def             21
486         def             22
487         def             23
488         def             24
489         def             25
490         def             26
491         def             27
492         def             28
493         def             29
494         def             30
495         def             31
496
497 #endif
498
499         .import         handle_interruption,code
500         .import         do_cpu_irq_mask,code
501
502         /*
503          * r26 = function to be called
504          * r25 = argument to pass in
505          * r24 = flags for do_fork()
506          *
507          * Kernel threads don't ever return, so they don't need
508          * a true register context. We just save away the arguments
509          * for copy_thread/ret_ to properly set up the child.
510          */
511
512 #define CLONE_VM 0x100  /* Must agree with <linux/sched.h> */
513 #define CLONE_UNTRACED 0x00800000
514
515         .export __kernel_thread, code
516         .import do_fork
517 __kernel_thread:
518         STREG   %r2, -RP_OFFSET(%r30)
519
520         copy    %r30, %r1
521         ldo     PT_SZ_ALGN(%r30),%r30
522 #ifdef __LP64__
523         /* Yo, function pointers in wide mode are little structs... -PB */
524         ldd     24(%r26), %r2
525         STREG   %r2, PT_GR27(%r1)       /* Store childs %dp */
526         ldd     16(%r26), %r26
527
528         STREG   %r22, PT_GR22(%r1)      /* save r22 (arg5) */
529         copy    %r0, %r22               /* user_tid */
530 #endif
531         STREG   %r26, PT_GR26(%r1)  /* Store function & argument for child */
532         STREG   %r25, PT_GR25(%r1)
533         ldil    L%CLONE_UNTRACED, %r26
534         ldo     CLONE_VM(%r26), %r26   /* Force CLONE_VM since only init_mm */
535         or      %r26, %r24, %r26      /* will have kernel mappings.      */
536         ldi     1, %r25                 /* stack_start, signals kernel thread */
537         stw     %r0, -52(%r30)          /* user_tid */
538 #ifdef __LP64__
539         ldo     -16(%r30),%r29          /* Reference param save area */
540 #endif
541         bl      do_fork, %r2
542         copy    %r1, %r24               /* pt_regs */
543
544         /* Parent Returns here */
545
546         LDREG   -PT_SZ_ALGN-RP_OFFSET(%r30), %r2
547         ldo     -PT_SZ_ALGN(%r30), %r30
548         bv      %r0(%r2)
549         nop
550
551         /*
552          * Child Returns here
553          *
554          * copy_thread moved args from temp save area set up above
555          * into task save area.
556          */
557
558         .export ret_from_kernel_thread
559 ret_from_kernel_thread:
560
561         /* Call schedule_tail first though */
562         bl      schedule_tail, %r2
563         nop
564
565         LDREG   TI_TASK-THREAD_SZ_ALGN(%r30), %r1
566         LDREG   TASK_PT_GR25(%r1), %r26
567 #ifdef __LP64__
568         LDREG   TASK_PT_GR27(%r1), %r27
569         LDREG   TASK_PT_GR22(%r1), %r22
570 #endif
571         LDREG   TASK_PT_GR26(%r1), %r1
572         ble     0(%sr7, %r1)
573         copy    %r31, %r2
574
575 #ifdef __LP64__
576         ldo     -16(%r30),%r29          /* Reference param save area */
577         loadgp                          /* Thread could have been in a module */
578 #endif
579         b       sys_exit
580         ldi     0, %r26
581
582         .import sys_execve, code
583         .export __execve, code
584 __execve:
585         copy    %r2, %r15
586         copy    %r30, %r16
587         ldo     PT_SZ_ALGN(%r30), %r30
588         STREG   %r26, PT_GR26(%r16)
589         STREG   %r25, PT_GR25(%r16)
590         STREG   %r24, PT_GR24(%r16)
591 #ifdef __LP64__
592         ldo     -16(%r30),%r29          /* Reference param save area */
593 #endif
594         bl      sys_execve, %r2
595         copy    %r16, %r26
596
597         cmpib,=,n 0,%r28,intr_return    /* forward */
598
599         /* yes, this will trap and die. */
600         copy    %r15, %r2
601         copy    %r16, %r30
602         bv      %r0(%r2)
603         nop
604
605         .align 4
606
607         /*
608          * struct task_struct *_switch_to(struct task_struct *prev,
609          *      struct task_struct *next)
610          *
611          * switch kernel stacks and return prev */
612         .export _switch_to, code
613 _switch_to:
614         STREG    %r2, -RP_OFFSET(%r30)
615
616         callee_save
617
618         ldil    L%_switch_to_ret, %r2
619         ldo     R%_switch_to_ret(%r2), %r2
620
621         STREG   %r2, TASK_PT_KPC(%r26)
622         LDREG   TASK_PT_KPC(%r25), %r2
623
624         STREG   %r30, TASK_PT_KSP(%r26)
625         LDREG   TASK_PT_KSP(%r25), %r30
626         LDREG   TASK_THREAD_INFO(%r25), %r25
627         bv      %r0(%r2)
628         mtctl   %r25,%cr30
629
630 _switch_to_ret:
631         mtctl   %r0, %cr0               /* Needed for single stepping */
632         callee_rest
633
634         LDREG   -RP_OFFSET(%r30), %r2
635         bv      %r0(%r2)
636         copy    %r26, %r28
637
638         /*
639          * Common rfi return path for interruptions, kernel execve, and
640          * sys_rt_sigreturn (sometimes).  The sys_rt_sigreturn syscall will
641          * return via this path if the signal was received when the process
642          * was running; if the process was blocked on a syscall then the
643          * normal syscall_exit path is used.  All syscalls for traced
644          * proceses exit via intr_restore.
645          *
646          * XXX If any syscalls that change a processes space id ever exit
647          * this way, then we will need to copy %sr3 in to PT_SR[3..7], and
648          * adjust IASQ[0..1].
649          *
650          * Note that the following code uses a "relied upon translation".
651          * See the parisc ACD for details. The ssm is necessary due to a
652          * PCXT bug.
653          */
654
655         .align 4096
656
657         .export syscall_exit_rfi
658 syscall_exit_rfi:
659         mfctl   %cr30,%r16
660         LDREG   TI_TASK(%r16), %r16     /* thread_info -> task_struct */
661         ldo     TASK_REGS(%r16),%r16
662         /* Force iaoq to userspace, as the user has had access to our current
663          * context via sigcontext. Also Filter the PSW for the same reason.
664          */
665         LDREG   PT_IAOQ0(%r16),%r19
666         depi    3,31,2,%r19
667         STREG   %r19,PT_IAOQ0(%r16)
668         LDREG   PT_IAOQ1(%r16),%r19
669         depi    3,31,2,%r19
670         STREG   %r19,PT_IAOQ1(%r16)
671         LDREG   PT_PSW(%r16),%r19
672         ldil    L%USER_PSW_MASK,%r1
673         ldo     R%USER_PSW_MASK(%r1),%r1
674 #ifdef __LP64__
675         ldil    L%USER_PSW_HI_MASK,%r20
676         ldo     R%USER_PSW_HI_MASK(%r20),%r20
677         depd    %r20,31,32,%r1
678 #endif
679         and     %r19,%r1,%r19 /* Mask out bits that user shouldn't play with */
680         ldil    L%USER_PSW,%r1
681         ldo     R%USER_PSW(%r1),%r1
682         or      %r19,%r1,%r19 /* Make sure default USER_PSW bits are set */
683         STREG   %r19,PT_PSW(%r16)
684
685         /*
686          * If we aren't being traced, we never saved space registers
687          * (we don't store them in the sigcontext), so set them
688          * to "proper" values now (otherwise we'll wind up restoring
689          * whatever was last stored in the task structure, which might
690          * be inconsistent if an interrupt occured while on the gateway
691          * page) Note that we may be "trashing" values the user put in
692          * them, but we don't support the the user changing them.
693          */
694
695         STREG   %r0,PT_SR2(%r16)
696         mfsp    %sr3,%r19
697         STREG   %r19,PT_SR0(%r16)
698         STREG   %r19,PT_SR1(%r16)
699         STREG   %r19,PT_SR3(%r16)
700         STREG   %r19,PT_SR4(%r16)
701         STREG   %r19,PT_SR5(%r16)
702         STREG   %r19,PT_SR6(%r16)
703         STREG   %r19,PT_SR7(%r16)
704
705 intr_return:
706         ssm     PSW_SM_I, %r0
707
708         /* Check for software interrupts */
709
710         .import irq_stat,data
711
712         ldil    L%irq_stat,%r19
713         ldo     R%irq_stat(%r19),%r19
714 #ifdef CONFIG_SMP
715         mfctl   %cr30,%r1
716         ldw     TI_CPU(%r1),%r1 /* get cpu # - int */
717         /* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) amount
718         ** irq_stat[] is defined using ____cacheline_aligned.
719         */
720 #ifdef __LP64__
721         shld    %r1, 6, %r20
722 #else
723         shlw    %r1, 5, %r20
724 #endif
725         add     %r19,%r20,%r19  /* now have &irq_stat[smp_processor_id()] */
726 #endif /* CONFIG_SMP */
727
728         LDREG   IRQSTAT_SIRQ_PEND(%r19),%r20    /* hardirq.h: unsigned long */
729         cmpib,<>,n 0,%r20,intr_do_softirq /* forward */
730
731 intr_check_resched:
732
733         /* check for reschedule */
734         mfctl   %cr30,%r1
735         LDREG   TI_FLAGS(%r1),%r19      /* sched.h: TIF_NEED_RESCHED */
736         bb,<,n  %r19,31-TIF_NEED_RESCHED,intr_do_resched /* forward */
737
738 intr_check_sig:
739         /* As above */
740         mfctl   %cr30,%r1
741         LDREG   TI_FLAGS(%r1),%r19      /* sched.h: TIF_SIGPENDING */
742         bb,<,n %r19, 31-TIF_SIGPENDING, intr_do_signal /* forward */
743
744 intr_restore:
745         copy            %r16,%r29
746         ldo             PT_FR31(%r29),%r1
747         rest_fp         %r1
748         rest_general    %r29
749         ssm             0,%r0
750         nop
751         nop
752         nop
753         nop
754         nop
755         nop
756         nop
757         tophys_r1       %r29
758         rsm             (PSW_SM_Q|PSW_SM_P|PSW_SM_D|PSW_SM_I),%r0
759         rest_specials   %r29
760         rest_stack
761         rfi
762         nop
763         nop
764         nop
765         nop
766         nop
767         nop
768         nop
769         nop
770
771         .import do_softirq,code
772 intr_do_softirq:
773         bl      do_softirq,%r2
774 #ifdef __LP64__
775         ldo     -16(%r30),%r29          /* Reference param save area */
776 #else
777         nop
778 #endif
779         b       intr_check_resched
780         nop
781
782         .import schedule,code
783 intr_do_resched:
784         /* Only do reschedule if we are returning to user space */
785         LDREG   PT_IASQ0(%r16), %r20
786         CMPIB= 0,%r20,intr_restore /* backward */
787         nop
788         LDREG   PT_IASQ1(%r16), %r20
789         CMPIB= 0,%r20,intr_restore /* backward */
790         nop
791
792 #ifdef __LP64__
793         ldo     -16(%r30),%r29          /* Reference param save area */
794 #endif
795
796         ldil    L%intr_check_sig, %r2
797         b       schedule
798         ldo     R%intr_check_sig(%r2), %r2
799
800
801         .import do_signal,code
802 intr_do_signal:
803         /* Only do signals if we are returning to user space */
804         LDREG   PT_IASQ0(%r16), %r20
805         CMPIB= 0,%r20,intr_restore /* backward */
806         nop
807         LDREG   PT_IASQ1(%r16), %r20
808         CMPIB= 0,%r20,intr_restore /* backward */
809         nop
810
811         copy    %r0, %r24                       /* unsigned long in_syscall */
812         copy    %r16, %r25                      /* struct pt_regs *regs */
813 #ifdef __LP64__
814         ldo     -16(%r30),%r29                  /* Reference param save area */
815 #endif
816
817         bl      do_signal,%r2
818         copy    %r0, %r26                       /* sigset_t *oldset = NULL */
819
820         b       intr_restore
821         nop
822
823         /*
824          * External interrupts.
825          */
826
827 intr_extint:
828         CMPIB=,n 0,%r16,1f
829         get_stack_use_cr30
830         b,n 3f
831
832 1:
833 #if 0  /* Interrupt Stack support not working yet! */
834         mfctl   %cr31,%r1
835         copy    %r30,%r17
836         /* FIXME! depi below has hardcoded idea of interrupt stack size (32k)*/
837 #ifdef __LP64__
838         depdi   0,63,15,%r17
839 #else
840         depi    0,31,15,%r17
841 #endif
842         CMPB=,n %r1,%r17,2f
843         get_stack_use_cr31
844         b,n 3f
845 #endif
846 2:
847         get_stack_use_r30
848
849 3:
850         save_specials   %r29
851         virt_map
852         save_general    %r29
853
854         ldo     PT_FR0(%r29), %r24
855         save_fp %r24
856         
857         loadgp
858
859         copy    %r29, %r26      /* arg0 is pt_regs */
860         copy    %r29, %r16      /* save pt_regs */
861
862         ldil    L%intr_return, %r2
863
864 #ifdef __LP64__
865         ldo     -16(%r30),%r29  /* Reference param save area */
866 #endif
867
868         b       do_cpu_irq_mask
869         ldo     R%intr_return(%r2), %r2 /* return to intr_return, not here */
870
871
872         /* Generic interruptions (illegal insn, unaligned, page fault, etc) */
873
874         .export         intr_save, code /* for os_hpmc */
875
876 intr_save:
877         mfsp    %sr7,%r16
878         CMPIB=,n 0,%r16,1f
879         get_stack_use_cr30
880         b       2f
881         copy    %r8,%r26
882
883 1:
884         get_stack_use_r30
885         copy    %r8,%r26
886
887 2:
888         save_specials   %r29
889
890         /* If this trap is a itlb miss, skip saving/adjusting isr/ior */
891
892         /*
893          * FIXME: 1) Use a #define for the hardwired "6" below (and in
894          *           traps.c.
895          *        2) Once we start executing code above 4 Gb, we need
896          *           to adjust iasq/iaoq here in the same way we
897          *           adjust isr/ior below.
898          */
899
900         CMPIB=,n        6,%r26,skip_save_ior
901
902         /* save_specials left ipsw value in r8 for us to test */
903
904         mfctl           %cr20, %r16 /* isr */
905         mfctl           %cr21, %r17 /* ior */
906
907 #ifdef __LP64__
908         /*
909          * If the interrupted code was running with W bit off (32 bit),
910          * clear the b bits (bits 0 & 1) in the ior.
911          */
912         extrd,u,*<>     %r8,PSW_W_BIT,1,%r0
913         depdi           0,1,2,%r17
914
915         /*
916          * FIXME: This code has hardwired assumptions about the split
917          *        between space bits and offset bits. This will change
918          *        when we allow alternate page sizes.
919          */
920
921         /* adjust isr/ior. */
922
923         extrd,u         %r16,63,7,%r1    /* get high bits from isr for ior */
924         depd            %r1,31,7,%r17    /* deposit them into ior */
925         depdi           0,63,7,%r16      /* clear them from isr */
926 #endif
927         STREG           %r16, PT_ISR(%r29)
928         STREG           %r17, PT_IOR(%r29)
929
930
931 skip_save_ior:
932         virt_map
933         save_general    %r29
934
935         ldo             PT_FR0(%r29), %r25
936         save_fp         %r25
937         
938         loadgp
939
940         copy            %r29, %r25      /* arg1 is pt_regs */
941 #ifdef __LP64__
942         ldo             -16(%r30),%r29  /* Reference param save area */
943 #endif
944
945         ldil            L%intr_check_sig, %r2
946         copy            %r25, %r16      /* save pt_regs */
947
948         b               handle_interruption
949         ldo             R%intr_check_sig(%r2), %r2
950
951
952         /*
953          * Note for all tlb miss handlers:
954          *
955          * cr24 contains a pointer to the kernel address space
956          * page directory.
957          *
958          * cr25 contains a pointer to the current user address
959          * space page directory.
960          *
961          * sr3 will contain the space id of the user address space
962          * of the current running thread while that thread is
963          * running in the kernel.
964          */
965
966         /*
967          * register number allocations.  Note that these are all
968          * in the shadowed registers
969          */
970
971         t0 = r1         /* temporary register 0 */
972         va = r8         /* virtual address for which the trap occured */
973         t1 = r9         /* temporary register 1 */
974         pte  = r16      /* pte/phys page # */
975         prot = r17      /* prot bits */
976         spc  = r24      /* space for which the trap occured */
977         ptp = r25       /* page directory/page table pointer */
978
979 #ifdef __LP64__
980
981 dtlb_miss_20w:
982         extrd,u         spc,63,7,t1     /* adjust va */
983         depd            t1,31,7,va      /* adjust va */
984         depdi           0,63,7,spc      /* adjust space */
985         mfctl           %cr25,ptp       /* Assume user space miss */
986         or,*<>          %r0,spc,%r0     /* If it is user space, nullify */
987         mfctl           %cr24,ptp       /* Load kernel pgd instead */
988         extrd,u         va,33,9,t1      /* Get pgd index */
989
990         mfsp            %sr7,t0         /* Get current space */
991         or,*=           %r0,t0,%r0      /* If kernel, nullify following test */
992         cmpb,*<>,n       t0,spc,dtlb_fault /* forward */
993
994         /* First level page table lookup */
995
996         ldd,s           t1(ptp),ptp
997         extrd,u         va,42,9,t0     /* get second-level index */
998         bb,>=,n         ptp,_PAGE_PRESENT_BIT,dtlb_check_alias_20w
999         depdi           0,63,12,ptp     /* clear prot bits */
1000
1001         /* Second level page table lookup */
1002
1003         ldd,s           t0(ptp),ptp
1004         extrd,u         va,51,9,t0     /* get third-level index */
1005         bb,>=,n         ptp,_PAGE_PRESENT_BIT,dtlb_check_alias_20w
1006         depdi           0,63,12,ptp     /* clear prot bits */
1007
1008         /* Third level page table lookup */
1009
1010         shladd           t0,3,ptp,ptp
1011         ldi             _PAGE_ACCESSED,t1
1012         ldd              0(ptp),pte
1013         bb,>=,n          pte,_PAGE_PRESENT_BIT,dtlb_check_alias_20w
1014
1015         /* Check whether the "accessed" bit was set, otherwise do so */
1016
1017         or              t1,pte,t0       /* t0 has R bit set */
1018         and,*<>         t1,pte,%r0      /* test and nullify if already set */
1019         std             t0,0(ptp)       /* write back pte */
1020
1021         space_to_prot   spc prot        /* create prot id from space */
1022         depd            pte,8,7,prot    /* add in prot bits from pte */
1023
1024         extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
1025         depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
1026         extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
1027         depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1028
1029         /* Get rid of prot bits and convert to page addr for idtlbt */
1030
1031         depdi           0,63,12,pte
1032         extrd,u         pte,56,52,pte
1033         idtlbt          pte,prot
1034
1035         rfir
1036         nop
1037
1038 dtlb_check_alias_20w:
1039
1040         /* Check to see if fault is in the temporary alias region */
1041
1042         cmpib,*<>,n     0,spc,dtlb_fault /* forward */
1043         ldil            L%(TMPALIAS_MAP_START),t0
1044         copy            va,t1
1045         depdi           0,63,23,t1
1046         cmpb,*<>,n      t0,t1,dtlb_fault /* forward */
1047         ldi             (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot
1048         depd,z          prot,8,7,prot
1049
1050         /*
1051          * OK, it is in the temp alias region, check whether "from" or "to".
1052          * Check "subtle" note in pacache.S re: r23/r26.
1053          */
1054
1055         extrd,u,*=      va,41,1,r0
1056         or,*tr          %r23,%r0,pte    /* If "from" use "from" page */
1057         or,*            %r26,%r0,pte    /* else "to", use "to" page  */
1058
1059         idtlbt          pte,prot
1060
1061         rfir
1062         nop
1063
1064 nadtlb_miss_20w:
1065         extrd,u         spc,63,7,t1     /* adjust va */
1066         depd            t1,31,7,va      /* adjust va */
1067         depdi           0,63,7,spc      /* adjust space */
1068         mfctl           %cr25,ptp       /* Assume user space miss */
1069         or,*<>          %r0,spc,%r0     /* If it is user space, nullify */
1070         mfctl           %cr24,ptp       /* Load kernel pgd instead */
1071         extrd,u         va,33,9,t1      /* Get pgd index */
1072
1073         mfsp            %sr7,t0         /* Get current space */
1074         or,*=           %r0,t0,%r0      /* If kernel, nullify following test */
1075         cmpb,*<>,n       t0,spc,nadtlb_fault /* forward */
1076
1077         /* First level page table lookup */
1078
1079         ldd,s           t1(ptp),ptp
1080         extrd,u         va,42,9,t0     /* get second-level index */
1081         bb,>=,n         ptp,_PAGE_PRESENT_BIT,nadtlb_emulate
1082         depdi           0,63,12,ptp     /* clear prot bits */
1083
1084         /* Second level page table lookup */
1085
1086         ldd,s           t0(ptp),ptp
1087         extrd,u         va,51,9,t0     /* get third-level index */
1088         bb,>=,n         ptp,_PAGE_PRESENT_BIT,nadtlb_emulate
1089         depdi           0,63,12,ptp     /* clear prot bits */
1090
1091         /* Third level page table lookup */
1092
1093         shladd           t0,3,ptp,ptp
1094         ldi             _PAGE_ACCESSED,t1
1095         ldd              0(ptp),pte
1096         bb,>=,n          pte,_PAGE_PRESENT_BIT,nadtlb_check_flush_20w
1097
1098         space_to_prot   spc prot        /* create prot id from space */
1099         depd            pte,8,7,prot    /* add in prot bits from pte */
1100
1101         extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
1102         depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
1103         extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
1104         depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1105
1106         /* Get rid of prot bits and convert to page addr for idtlbt */
1107
1108         depdi           0,63,12,pte
1109         extrd,u         pte,56,52,pte
1110         idtlbt          pte,prot
1111
1112         rfir
1113         nop
1114
1115 nadtlb_check_flush_20w:
1116         bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
1117
1118         /* Insert a "flush only" translation */
1119
1120         depdi,z         7,7,3,prot
1121         depdi           1,10,1,prot
1122
1123         /* Get rid of prot bits and convert to page addr for idtlbt */
1124
1125         depdi           0,63,12,pte
1126         extrd,u         pte,56,52,pte
1127         idtlbt          pte,prot
1128
1129         rfir
1130         nop
1131
1132 #else
1133
1134 dtlb_miss_11:
1135         mfctl           %cr25,ptp       /* Assume user space miss */
1136         or,<>           %r0,spc,%r0     /* If it is user space, nullify */
1137         mfctl           %cr24,ptp       /* Load kernel pgd instead */
1138         extru           va,9,10,t1      /* Get pgd index */
1139
1140         mfsp            %sr7,t0         /* Get current space */
1141         or,=            %r0,t0,%r0      /* If kernel, nullify following test */
1142         cmpb,<>,n       t0,spc,dtlb_fault /* forward */
1143
1144         /* First level page table lookup */
1145
1146         ldwx,s          t1(ptp),ptp
1147         extru           va,19,10,t0     /* get second-level index */
1148         bb,>=,n         ptp,_PAGE_PRESENT_BIT,dtlb_check_alias_11
1149         depi            0,31,12,ptp     /* clear prot bits */
1150
1151         /* Second level page table lookup */
1152
1153         sh2addl          t0,ptp,ptp
1154         ldi             _PAGE_ACCESSED,t1
1155         ldw              0(ptp),pte
1156         bb,>=,n          pte,_PAGE_PRESENT_BIT,dtlb_check_alias_11
1157
1158         /* Check whether the "accessed" bit was set, otherwise do so */
1159
1160         or              t1,pte,t0       /* t0 has R bit set */
1161         and,<>          t1,pte,%r0      /* test and nullify if already set */
1162         stw             t0,0(ptp)       /* write back pte */
1163
1164         zdep            spc,30,15,prot  /* create prot id from space */
1165         dep             pte,8,7,prot    /* add in prot bits from pte */
1166
1167         extru,=         pte,_PAGE_NO_CACHE_BIT,1,r0
1168         depi            1,12,1,prot
1169         extru,=         pte,_PAGE_USER_BIT,1,r0
1170         depi            7,11,3,prot   /* Set for user space (1 rsvd for read) */
1171         extru,=         pte,_PAGE_GATEWAY_BIT,1,r0
1172         depi            0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1173
1174         /* Get rid of prot bits and convert to page addr for idtlba */
1175
1176         depi            0,31,12,pte
1177         extru           pte,24,25,pte
1178
1179         mfsp            %sr1,t0  /* Save sr1 so we can use it in tlb inserts */
1180         mtsp            spc,%sr1
1181
1182         idtlba          pte,(%sr1,va)
1183         idtlbp          prot,(%sr1,va)
1184
1185         mtsp            t0, %sr1        /* Restore sr1 */
1186
1187         rfir
1188         nop
1189
1190 dtlb_check_alias_11:
1191
1192         /* Check to see if fault is in the temporary alias region */
1193
1194         cmpib,<>,n      0,spc,dtlb_fault /* forward */
1195         ldil            L%(TMPALIAS_MAP_START),t0
1196         copy            va,t1
1197         depwi           0,31,23,t1
1198         cmpb,<>,n       t0,t1,dtlb_fault /* forward */
1199         ldi             (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot
1200         depw,z          prot,8,7,prot
1201
1202         /*
1203          * OK, it is in the temp alias region, check whether "from" or "to".
1204          * Check "subtle" note in pacache.S re: r23/r26.
1205          */
1206
1207         extrw,u,=       va,9,1,r0
1208         or,tr           %r23,%r0,pte    /* If "from" use "from" page */
1209         or              %r26,%r0,pte    /* else "to", use "to" page  */
1210
1211         idtlba          pte,(va)
1212         idtlbp          prot,(va)
1213
1214         rfir
1215         nop
1216
1217 nadtlb_miss_11:
1218         mfctl           %cr25,ptp       /* Assume user space miss */
1219         or,<>           %r0,spc,%r0     /* If it is user space, nullify */
1220         mfctl           %cr24,ptp       /* Load kernel pgd instead */
1221         extru           va,9,10,t1      /* Get pgd index */
1222
1223         mfsp            %sr7,t0         /* Get current space */
1224         or,=            %r0,t0,%r0      /* If kernel, nullify following test */
1225         cmpb,<>,n       t0,spc,nadtlb_fault /* forward */
1226
1227         /* First level page table lookup */
1228
1229         ldwx,s          t1(ptp),ptp
1230         extru           va,19,10,t0     /* get second-level index */
1231         bb,>=,n         ptp,_PAGE_PRESENT_BIT,nadtlb_emulate
1232         depi            0,31,12,ptp     /* clear prot bits */
1233
1234         /* Second level page table lookup */
1235
1236         sh2addl          t0,ptp,ptp
1237         ldi             _PAGE_ACCESSED,t1
1238         ldw              0(ptp),pte
1239         bb,>=,n          pte,_PAGE_PRESENT_BIT,nadtlb_check_flush_11
1240
1241         zdep            spc,30,15,prot  /* create prot id from space */
1242         dep             pte,8,7,prot    /* add in prot bits from pte */
1243
1244         extru,=         pte,_PAGE_NO_CACHE_BIT,1,r0
1245         depi            1,12,1,prot
1246         extru,=         pte,_PAGE_USER_BIT,1,r0
1247         depi            7,11,3,prot   /* Set for user space (1 rsvd for read) */
1248         extru,=         pte,_PAGE_GATEWAY_BIT,1,r0
1249         depi            0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1250
1251         /* Get rid of prot bits and convert to page addr for idtlba */
1252
1253         depi            0,31,12,pte
1254         extru           pte,24,25,pte
1255
1256         mfsp            %sr1,t0  /* Save sr1 so we can use it in tlb inserts */
1257         mtsp            spc,%sr1
1258
1259         idtlba          pte,(%sr1,va)
1260         idtlbp          prot,(%sr1,va)
1261
1262         mtsp            t0, %sr1        /* Restore sr1 */
1263
1264         rfir
1265         nop
1266
1267 nadtlb_check_flush_11:
1268         bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
1269
1270         /* Insert a "flush only" translation */
1271
1272         zdepi           7,7,3,prot
1273         depi            1,10,1,prot
1274
1275         /* Get rid of prot bits and convert to page addr for idtlba */
1276
1277         depi            0,31,12,pte
1278         extru           pte,24,25,pte
1279
1280         mfsp            %sr1,t0  /* Save sr1 so we can use it in tlb inserts */
1281         mtsp            spc,%sr1
1282
1283         idtlba          pte,(%sr1,va)
1284         idtlbp          prot,(%sr1,va)
1285
1286         mtsp            t0, %sr1        /* Restore sr1 */
1287
1288         rfir
1289         nop
1290
1291 dtlb_miss_20:
1292         mfctl           %cr25,ptp       /* Assume user space miss */
1293         or,<>           %r0,spc,%r0     /* If it is user space, nullify */
1294         mfctl           %cr24,ptp       /* Load kernel pgd instead */
1295         extru           va,9,10,t1      /* Get pgd index */
1296
1297         mfsp            %sr7,t0         /* Get current space */
1298         or,=            %r0,t0,%r0      /* If kernel, nullify following test */
1299         cmpb,<>,n       t0,spc,dtlb_fault /* forward */
1300
1301         /* First level page table lookup */
1302
1303         ldwx,s          t1(ptp),ptp
1304         extru           va,19,10,t0     /* get second-level index */
1305         bb,>=,n         ptp,_PAGE_PRESENT_BIT,dtlb_check_alias_20
1306         depi            0,31,12,ptp     /* clear prot bits */
1307
1308         /* Second level page table lookup */
1309
1310         sh2addl          t0,ptp,ptp
1311         ldi             _PAGE_ACCESSED,t1
1312         ldw              0(ptp),pte
1313         bb,>=,n          pte,_PAGE_PRESENT_BIT,dtlb_check_alias_20
1314
1315         /* Check whether the "accessed" bit was set, otherwise do so */
1316
1317         or              t1,pte,t0       /* t0 has R bit set */
1318         and,<>          t1,pte,%r0      /* test and nullify if already set */
1319         stw             t0,0(ptp)       /* write back pte */
1320
1321         space_to_prot   spc prot        /* create prot id from space */
1322         depd            pte,8,7,prot    /* add in prot bits from pte */
1323
1324         extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
1325         depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
1326         extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
1327         depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1328
1329         /* Get rid of prot bits and convert to page addr for idtlbt */
1330
1331         extrd,s         pte,35,4,t0
1332         depdi           0,63,12,pte     /* clear lower 12 bits */
1333         addi,=          1,t0,0 
1334         extrd,u,*tr     pte,56,25,pte 
1335         extrd,s         pte,56,25,pte   /* bit 31:8 >> 8  */ 
1336         idtlbt          pte,prot
1337
1338         rfir
1339         nop
1340
1341 dtlb_check_alias_20:
1342
1343         /* Check to see if fault is in the temporary alias region */
1344
1345         cmpib,<>,n      0,spc,dtlb_fault /* forward */
1346         ldil            L%(TMPALIAS_MAP_START),t0
1347         copy            va,t1
1348         depwi           0,31,23,t1
1349         cmpb,<>,n       t0,t1,dtlb_fault /* forward */
1350         ldi             (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot
1351         depd,z          prot,8,7,prot
1352
1353         /*
1354          * OK, it is in the temp alias region, check whether "from" or "to".
1355          * Check "subtle" note in pacache.S re: r23/r26.
1356          */
1357
1358         extrw,u,=       va,9,1,r0
1359         or,tr           %r23,%r0,pte    /* If "from" use "from" page */
1360         or              %r26,%r0,pte    /* else "to", use "to" page  */
1361
1362         idtlbt          pte,prot
1363
1364         rfir
1365         nop
1366
1367 nadtlb_miss_20:
1368         mfctl           %cr25,ptp       /* Assume user space miss */
1369         or,<>           %r0,spc,%r0     /* If it is user space, nullify */
1370         mfctl           %cr24,ptp       /* Load kernel pgd instead */
1371         extru           va,9,10,t1      /* Get pgd index */
1372
1373         mfsp            %sr7,t0         /* Get current space */
1374         or,=            %r0,t0,%r0      /* If kernel, nullify following test */
1375         cmpb,<>,n       t0,spc,nadtlb_fault /* forward */
1376
1377         /* First level page table lookup */
1378
1379         ldwx,s          t1(ptp),ptp
1380         extru           va,19,10,t0     /* get second-level index */
1381         bb,>=,n         ptp,_PAGE_PRESENT_BIT,nadtlb_emulate
1382         depi            0,31,12,ptp     /* clear prot bits */
1383
1384         /* Second level page table lookup */
1385
1386         sh2addl          t0,ptp,ptp
1387         ldi             _PAGE_ACCESSED,t1
1388         ldw              0(ptp),pte
1389         bb,>=,n          pte,_PAGE_PRESENT_BIT,nadtlb_check_flush_20
1390
1391         space_to_prot   spc prot        /* create prot id from space */
1392         depd            pte,8,7,prot    /* add in prot bits from pte */
1393
1394         extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
1395         depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
1396         extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
1397         depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1398
1399         /* Get rid of prot bits and convert to page addr for idtlbt */
1400
1401         extrd,s         pte,35,4,t0
1402         depdi           0,63,12,pte     /* clear lower 12 bits */
1403         addi,=          1,t0,0
1404         extrd,u,*tr     pte,56,25,pte
1405         extrd,s         pte,56,25,pte   /* bit 31:8 >> 8  */
1406         idtlbt          pte,prot
1407
1408         rfir
1409         nop
1410
1411 nadtlb_check_flush_20:
1412         bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
1413
1414         /* Insert a "flush only" translation */
1415
1416         depdi,z         7,7,3,prot
1417         depdi           1,10,1,prot
1418
1419         /* Get rid of prot bits and convert to page addr for idtlbt */
1420
1421         depdi           0,63,12,pte
1422         extrd,u         pte,56,32,pte
1423         idtlbt          pte,prot
1424
1425         rfir
1426         nop
1427 #endif
1428
1429 nadtlb_emulate:
1430
1431         /*
1432          * Non access misses can be caused by fdc,fic,pdc,lpa,probe and
1433          * probei instructions. We don't want to fault for these
1434          * instructions (not only does it not make sense, it can cause
1435          * deadlocks, since some flushes are done with the mmap
1436          * semaphore held). If the translation doesn't exist, we can't
1437          * insert a translation, so have to emulate the side effects
1438          * of the instruction. Since we don't insert a translation
1439          * we can get a lot of faults during a flush loop, so it makes
1440          * sense to try to do it here with minimum overhead. We only
1441          * emulate fdc,fic & pdc instructions whose base and index
1442          * registers are not shadowed. We defer everything else to the
1443          * "slow" path.
1444          */
1445
1446         mfctl           %cr19,%r9 /* Get iir */
1447         ldi             0x280,%r16
1448         and             %r9,%r16,%r17
1449         cmpb,<>,n       %r16,%r17,nadtlb_fault /* Not fdc,fic,pdc */
1450         bb,>=,n         %r9,26,nadtlb_nullify  /* m bit not set, just nullify */
1451         b,l             get_register,%r25
1452         extrw,u         %r9,15,5,%r8           /* Get index register # */
1453         CMPIB=,n        -1,%r1,nadtlb_fault    /* have to use slow path */
1454         copy            %r1,%r24
1455         b,l             get_register,%r25
1456         extrw,u         %r9,10,5,%r8           /* Get base register # */
1457         CMPIB=,n        -1,%r1,nadtlb_fault    /* have to use slow path */
1458         b,l             set_register,%r25
1459         add,l           %r1,%r24,%r1           /* doesn't affect c/b bits */
1460
1461 nadtlb_nullify:
1462         mfctl           %cr22,%r8              /* Get ipsw */
1463         ldil            L%PSW_N,%r9
1464         or              %r8,%r9,%r8            /* Set PSW_N */
1465         mtctl           %r8,%cr22
1466
1467         rfir
1468         nop
1469
1470 #ifdef __LP64__
1471 itlb_miss_20w:
1472
1473         /*
1474          * I miss is a little different, since we allow users to fault
1475          * on the gateway page which is in the kernel address space.
1476          */
1477
1478         extrd,u         spc,63,7,t1     /* adjust va */
1479         depd            t1,31,7,va      /* adjust va */
1480         depdi           0,63,7,spc      /* adjust space */
1481         cmpib,*=        0,spc,itlb_miss_kernel_20w
1482         extrd,u         va,33,9,t1      /* Get pgd index */
1483
1484         mfctl           %cr25,ptp       /* load user pgd */
1485
1486         mfsp            %sr7,t0         /* Get current space */
1487         or,*=           %r0,t0,%r0      /* If kernel, nullify following test */
1488         cmpb,*<>,n      t0,spc,itlb_fault /* forward */
1489
1490         /* First level page table lookup */
1491
1492 itlb_miss_common_20w:
1493         ldd,s           t1(ptp),ptp
1494         extrd,u         va,42,9,t0     /* get second-level index */
1495         bb,>=,n         ptp,_PAGE_PRESENT_BIT,itlb_fault
1496         depdi           0,63,12,ptp     /* clear prot bits */
1497
1498         /* Second level page table lookup */
1499
1500         ldd,s           t0(ptp),ptp
1501         extrd,u         va,51,9,t0     /* get third-level index */
1502         bb,>=,n         ptp,_PAGE_PRESENT_BIT,itlb_fault
1503         depdi           0,63,12,ptp     /* clear prot bits */
1504
1505         /* Third level page table lookup */
1506
1507         shladd           t0,3,ptp,ptp
1508         ldi             _PAGE_ACCESSED,t1
1509         ldd              0(ptp),pte
1510         bb,>=,n          pte,_PAGE_PRESENT_BIT,itlb_fault
1511
1512         /* Check whether the "accessed" bit was set, otherwise do so */
1513
1514         or              t1,pte,t0       /* t0 has R bit set */
1515         and,*<>         t1,pte,%r0      /* test and nullify if already set */
1516         std             t0,0(ptp)       /* write back pte */
1517
1518         space_to_prot   spc prot        /* create prot id from space */
1519         depd            pte,8,7,prot    /* add in prot bits from pte */
1520
1521         extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
1522         depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
1523         extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
1524         depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1525
1526         /* Get rid of prot bits and convert to page addr for iitlbt */
1527
1528         depdi           0,63,12,pte
1529         extrd,u         pte,56,32,pte
1530         iitlbt          pte,prot
1531
1532         rfir
1533         nop
1534
1535 itlb_miss_kernel_20w:
1536         b               itlb_miss_common_20w
1537         mfctl           %cr24,ptp       /* Load kernel pgd */
1538 #else
1539
1540 itlb_miss_11:
1541
1542         /*
1543          * I miss is a little different, since we allow users to fault
1544          * on the gateway page which is in the kernel address space.
1545          */
1546
1547         cmpib,=         0,spc,itlb_miss_kernel_11
1548         extru           va,9,10,t1      /* Get pgd index */
1549
1550         mfctl           %cr25,ptp       /* load user pgd */
1551
1552         mfsp            %sr7,t0         /* Get current space */
1553         or,=            %r0,t0,%r0      /* If kernel, nullify following test */
1554         cmpb,<>,n       t0,spc,itlb_fault /* forward */
1555
1556         /* First level page table lookup */
1557
1558 itlb_miss_common_11:
1559         ldwx,s          t1(ptp),ptp
1560         extru           va,19,10,t0     /* get second-level index */
1561         bb,>=,n         ptp,_PAGE_PRESENT_BIT,itlb_fault
1562         depi            0,31,12,ptp     /* clear prot bits */
1563
1564         /* Second level page table lookup */
1565
1566         sh2addl          t0,ptp,ptp
1567         ldi             _PAGE_ACCESSED,t1
1568         ldw              0(ptp),pte
1569         bb,>=,n          pte,_PAGE_PRESENT_BIT,itlb_fault
1570
1571         /* Check whether the "accessed" bit was set, otherwise do so */
1572
1573         or              t1,pte,t0       /* t0 has R bit set */
1574         and,<>          t1,pte,%r0      /* test and nullify if already set */
1575         stw             t0,0(ptp)       /* write back pte */
1576
1577         zdep            spc,30,15,prot  /* create prot id from space */
1578         dep             pte,8,7,prot    /* add in prot bits from pte */
1579
1580         extru,=         pte,_PAGE_NO_CACHE_BIT,1,r0
1581         depi            1,12,1,prot
1582         extru,=         pte,_PAGE_USER_BIT,1,r0
1583         depi            7,11,3,prot   /* Set for user space (1 rsvd for read) */
1584         extru,=         pte,_PAGE_GATEWAY_BIT,1,r0
1585         depi            0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1586
1587         /* Get rid of prot bits and convert to page addr for iitlba */
1588
1589         depi            0,31,12,pte
1590         extru           pte,24,25,pte
1591
1592         mfsp            %sr1,t0  /* Save sr1 so we can use it in tlb inserts */
1593         mtsp            spc,%sr1
1594
1595         iitlba          pte,(%sr1,va)
1596         iitlbp          prot,(%sr1,va)
1597
1598         mtsp            t0, %sr1        /* Restore sr1 */
1599
1600         rfir
1601         nop
1602
1603 itlb_miss_kernel_11:
1604         b               itlb_miss_common_11
1605         mfctl           %cr24,ptp       /* Load kernel pgd */
1606
1607 itlb_miss_20:
1608
1609         /*
1610          * I miss is a little different, since we allow users to fault
1611          * on the gateway page which is in the kernel address space.
1612          */
1613
1614         cmpib,=         0,spc,itlb_miss_kernel_20
1615         extru           va,9,10,t1      /* Get pgd index */
1616
1617         mfctl           %cr25,ptp       /* load user pgd */
1618
1619         mfsp            %sr7,t0         /* Get current space */
1620         or,=            %r0,t0,%r0      /* If kernel, nullify following test */
1621         cmpb,<>,n       t0,spc,itlb_fault /* forward */
1622
1623         /* First level page table lookup */
1624
1625 itlb_miss_common_20:
1626         ldwx,s          t1(ptp),ptp
1627         extru           va,19,10,t0     /* get second-level index */
1628         bb,>=,n         ptp,_PAGE_PRESENT_BIT,itlb_fault
1629         depi            0,31,12,ptp     /* clear prot bits */
1630
1631         /* Second level page table lookup */
1632
1633         sh2addl          t0,ptp,ptp
1634         ldi             _PAGE_ACCESSED,t1
1635         ldw              0(ptp),pte
1636         bb,>=,n          pte,_PAGE_PRESENT_BIT,itlb_fault
1637
1638         /* Check whether the "accessed" bit was set, otherwise do so */
1639
1640         or              t1,pte,t0       /* t0 has R bit set */
1641         and,<>          t1,pte,%r0      /* test and nullify if already set */
1642         stw             t0,0(ptp)       /* write back pte */
1643
1644         space_to_prot   spc prot        /* create prot id from space */
1645         depd            pte,8,7,prot    /* add in prot bits from pte */
1646
1647         extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
1648         depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
1649         extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
1650         depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1651
1652         /* Get rid of prot bits and convert to page addr for iitlbt */
1653
1654         extrd,s         pte,35,4,t0 
1655         depdi           0,63,12,pte     /* clear lower 12 bits */
1656         addi,=          1,t0,0
1657         extrd,u,*tr     pte,56,25,pte 
1658         extrd,s         pte,56,25,pte   /* bit 31:8 >> 8  */
1659         iitlbt          pte,prot
1660
1661         rfir
1662         nop
1663
1664
1665 itlb_miss_kernel_20:
1666         b               itlb_miss_common_20
1667         mfctl           %cr24,ptp       /* Load kernel pgd */
1668 #endif
1669
1670 #ifdef __LP64__
1671
1672 dbit_trap_20w:
1673         extrd,u         spc,63,7,t1     /* adjust va */
1674         depd            t1,31,7,va      /* adjust va */
1675         depdi           0,1,2,va        /* adjust va */
1676         depdi           0,63,7,spc      /* adjust space */
1677         mfctl           %cr25,ptp       /* Assume user space miss */
1678         or,*<>          %r0,spc,%r0     /* If it is user space, nullify */
1679         mfctl           %cr24,ptp       /* Load kernel pgd instead */
1680         extrd,u         va,33,9,t1      /* Get pgd index */
1681
1682         mfsp            %sr7,t0         /* Get current space */
1683         or,*=           %r0,t0,%r0      /* If kernel, nullify following test */
1684         cmpb,*<>,n       t0,spc,dbit_fault /* forward */
1685
1686         /* First level page table lookup */
1687
1688         ldd,s           t1(ptp),ptp
1689         extrd,u         va,42,9,t0     /* get second-level index */
1690         bb,>=,n         ptp,_PAGE_PRESENT_BIT,dbit_fault
1691         depdi           0,63,12,ptp     /* clear prot bits */
1692
1693         /* Second level page table lookup */
1694
1695         ldd,s           t0(ptp),ptp
1696         extrd,u         va,51,9,t0     /* get third-level index */
1697         bb,>=,n         ptp,_PAGE_PRESENT_BIT,dbit_fault
1698         depdi           0,63,12,ptp     /* clear prot bits */
1699
1700         /* Third level page table lookup */
1701
1702         shladd           t0,3,ptp,ptp
1703 #ifdef CONFIG_SMP
1704         CMPIB=,n        0,spc,dbit_nolock_20w
1705         ldil            L%PA(pa_dbit_lock),t0
1706         ldo             R%PA(pa_dbit_lock)(t0),t0
1707
1708 dbit_spin_20w:
1709         ldcw            0(t0),t1
1710         cmpib,=         0,t1,dbit_spin_20w
1711         nop
1712
1713 dbit_nolock_20w:
1714 #endif
1715         ldi             (_PAGE_ACCESSED|_PAGE_DIRTY),t1
1716         ldd              0(ptp),pte
1717         bb,>=,n          pte,_PAGE_PRESENT_BIT,dbit_fault
1718
1719         /* Set Accessed and Dirty bits in the pte */
1720
1721         or              t1,pte,pte
1722         std             pte,0(ptp)      /* write back pte */
1723
1724         space_to_prot   spc prot        /* create prot id from space */
1725         depd            pte,8,7,prot    /* add in prot bits from pte */
1726
1727         extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
1728         depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
1729         extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
1730         depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1731
1732         /* Get rid of prot bits and convert to page addr for idtlbt */
1733
1734         depdi           0,63,12,pte
1735         extrd,u         pte,56,52,pte
1736         idtlbt          pte,prot
1737 #ifdef CONFIG_SMP
1738         CMPIB=,n        0,spc,dbit_nounlock_20w
1739         ldi             1,t1
1740         stw             t1,0(t0)
1741
1742 dbit_nounlock_20w:
1743 #endif
1744
1745         rfir
1746         nop
1747 #else
1748
1749 dbit_trap_11:
1750         mfctl           %cr25,ptp       /* Assume user space trap */
1751         or,<>           %r0,spc,%r0     /* If it is user space, nullify */
1752         mfctl           %cr24,ptp       /* Load kernel pgd instead */
1753         extru           va,9,10,t1      /* Get pgd index */
1754
1755         mfsp            %sr7,t0         /* Get current space */
1756         or,=            %r0,t0,%r0      /* If kernel, nullify following test */
1757         cmpb,<>,n       t0,spc,dbit_fault /* forward */
1758
1759         /* First level page table lookup */
1760
1761         ldwx,s          t1(ptp),ptp
1762         extru           va,19,10,t0     /* get second-level index */
1763         bb,>=,n         ptp,_PAGE_PRESENT_BIT,dbit_fault
1764         depi            0,31,12,ptp     /* clear prot bits */
1765
1766         /* Second level page table lookup */
1767
1768         sh2addl          t0,ptp,ptp
1769 #ifdef CONFIG_SMP
1770         CMPIB=,n        0,spc,dbit_nolock_11
1771         ldil            L%PA(pa_dbit_lock),t0
1772         ldo             R%PA(pa_dbit_lock)(t0),t0
1773
1774 dbit_spin_11:
1775         ldcw            0(t0),t1
1776         cmpib,=         0,t1,dbit_spin_11
1777         nop
1778
1779 dbit_nolock_11:
1780 #endif
1781         ldi             (_PAGE_ACCESSED|_PAGE_DIRTY),t1
1782         ldw              0(ptp),pte
1783         bb,>=,n          pte,_PAGE_PRESENT_BIT,dbit_fault
1784
1785         /* Set Accessed and Dirty bits in the pte */
1786
1787         or              t1,pte,pte
1788         stw             pte,0(ptp)      /* write back pte */
1789
1790         zdep            spc,30,15,prot  /* create prot id from space */
1791         dep             pte,8,7,prot    /* add in prot bits from pte */
1792
1793         extru,=         pte,_PAGE_NO_CACHE_BIT,1,r0
1794         depi            1,12,1,prot
1795         extru,=         pte,_PAGE_USER_BIT,1,r0
1796         depi            7,11,3,prot /* Set for user space (1 rsvd for read) */
1797         extru,=         pte,_PAGE_GATEWAY_BIT,1,r0
1798         depi            0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1799
1800         /* Get rid of prot bits and convert to page addr for idtlba */
1801
1802         depi            0,31,12,pte
1803         extru           pte,24,25,pte
1804
1805         mfsp            %sr1,t1  /* Save sr1 so we can use it in tlb inserts */
1806         mtsp            spc,%sr1
1807
1808         idtlba          pte,(%sr1,va)
1809         idtlbp          prot,(%sr1,va)
1810
1811         mtsp            t1, %sr1     /* Restore sr1 */
1812 #ifdef CONFIG_SMP
1813         CMPIB=,n        0,spc,dbit_nounlock_11
1814         ldi             1,t1
1815         stw             t1,0(t0)
1816
1817 dbit_nounlock_11:
1818 #endif
1819
1820         rfir
1821         nop
1822
1823 dbit_trap_20:
1824         mfctl           %cr25,ptp       /* Assume user space trap */
1825         or,<>           %r0,spc,%r0     /* If it is user space, nullify */
1826         mfctl           %cr24,ptp       /* Load kernel pgd instead */
1827         extru           va,9,10,t1      /* Get pgd index */
1828
1829         mfsp            %sr7,t0         /* Get current space */
1830         or,=            %r0,t0,%r0      /* If kernel, nullify following test */
1831         cmpb,<>,n       t0,spc,dbit_fault /* forward */
1832
1833         /* First level page table lookup */
1834
1835         ldwx,s          t1(ptp),ptp
1836         extru           va,19,10,t0     /* get second-level index */
1837         bb,>=,n         ptp,_PAGE_PRESENT_BIT,dbit_fault
1838         depi            0,31,12,ptp     /* clear prot bits */
1839
1840         /* Second level page table lookup */
1841
1842         sh2addl          t0,ptp,ptp
1843 #ifdef CONFIG_SMP
1844         CMPIB=,n        0,spc,dbit_nolock_20
1845         ldil            L%PA(pa_dbit_lock),t0
1846         ldo             R%PA(pa_dbit_lock)(t0),t0
1847
1848 dbit_spin_20:
1849         ldcw            0(t0),t1
1850         cmpib,=         0,t1,dbit_spin_20
1851         nop
1852
1853 dbit_nolock_20:
1854 #endif
1855         ldi             (_PAGE_ACCESSED|_PAGE_DIRTY),t1
1856         ldw              0(ptp),pte
1857         bb,>=,n          pte,_PAGE_PRESENT_BIT,dbit_fault
1858
1859         /* Set Accessed and Dirty bits in the pte */
1860
1861         or              t1,pte,pte
1862         stw             pte,0(ptp)      /* write back pte */
1863
1864         space_to_prot   spc prot        /* create prot id from space */
1865         depd            pte,8,7,prot    /* add in prot bits from pte */
1866
1867         extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
1868         depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
1869         extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
1870         depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1871
1872         extrd,s         pte,35,4,t0 
1873         depdi           0,63,12,pte     /* clear lower 12 bits */
1874         addi,=          1,t0,0
1875         extrd,u,*tr     pte,56,25,pte 
1876         extrd,s         pte,56,25,pte   /* bit 31:8 >> 8  */
1877         idtlbt          pte,prot
1878
1879 #ifdef CONFIG_SMP
1880         CMPIB=,n        0,spc,dbit_nounlock_20
1881         ldi             1,t1
1882         stw             t1,0(t0)
1883
1884 dbit_nounlock_20:
1885 #endif
1886
1887         rfir
1888         nop
1889 #endif
1890
1891         .import handle_interruption,code
1892
1893 kernel_bad_space:
1894         b               intr_save
1895         ldi             31,%r8  /* Use an unused code */
1896
1897 dbit_fault:
1898         b               intr_save
1899         ldi             20,%r8
1900
1901 itlb_fault:
1902         b               intr_save
1903         ldi             6,%r8
1904
1905 nadtlb_fault:
1906         b               intr_save
1907         ldi             17,%r8
1908
1909 dtlb_fault:
1910         b               intr_save
1911         ldi             15,%r8
1912
1913         /* Register saving semantics for system calls:
1914
1915            %r1             clobbered by system call macro in userspace
1916            %r2             saved in PT_REGS by gateway page
1917            %r3  - %r18     preserved by C code (saved by signal code)
1918            %r19 - %r20     saved in PT_REGS by gateway page
1919            %r21 - %r22     non-standard syscall args
1920                            stored in kernel stack by gateway page
1921            %r23 - %r26     arg3-arg0, saved in PT_REGS by gateway page
1922            %r27 - %r30     saved in PT_REGS by gateway page
1923            %r31            syscall return pointer
1924          */
1925
1926         /* Floating point registers (FIXME: what do we do with these?)
1927
1928            %fr0  - %fr3    status/exception, not preserved
1929            %fr4  - %fr7    arguments
1930            %fr8  - %fr11   not preserved by C code
1931            %fr12 - %fr21   preserved by C code
1932            %fr22 - %fr31   not preserved by C code
1933          */
1934
1935         .macro  reg_save regs
1936         STREG   %r3, PT_GR3(\regs)
1937         STREG   %r4, PT_GR4(\regs)
1938         STREG   %r5, PT_GR5(\regs)
1939         STREG   %r6, PT_GR6(\regs)
1940         STREG   %r7, PT_GR7(\regs)
1941         STREG   %r8, PT_GR8(\regs)
1942         STREG   %r9, PT_GR9(\regs)
1943         STREG   %r10,PT_GR10(\regs)
1944         STREG   %r11,PT_GR11(\regs)
1945         STREG   %r12,PT_GR12(\regs)
1946         STREG   %r13,PT_GR13(\regs)
1947         STREG   %r14,PT_GR14(\regs)
1948         STREG   %r15,PT_GR15(\regs)
1949         STREG   %r16,PT_GR16(\regs)
1950         STREG   %r17,PT_GR17(\regs)
1951         STREG   %r18,PT_GR18(\regs)
1952         .endm
1953
1954         .macro  reg_restore regs
1955         LDREG   PT_GR3(\regs), %r3
1956         LDREG   PT_GR4(\regs), %r4
1957         LDREG   PT_GR5(\regs), %r5
1958         LDREG   PT_GR6(\regs), %r6
1959         LDREG   PT_GR7(\regs), %r7
1960         LDREG   PT_GR8(\regs), %r8
1961         LDREG   PT_GR9(\regs), %r9
1962         LDREG   PT_GR10(\regs),%r10
1963         LDREG   PT_GR11(\regs),%r11
1964         LDREG   PT_GR12(\regs),%r12
1965         LDREG   PT_GR13(\regs),%r13
1966         LDREG   PT_GR14(\regs),%r14
1967         LDREG   PT_GR15(\regs),%r15
1968         LDREG   PT_GR16(\regs),%r16
1969         LDREG   PT_GR17(\regs),%r17
1970         LDREG   PT_GR18(\regs),%r18
1971         .endm
1972
1973         .export sys_fork_wrapper
1974         .export child_return
1975 sys_fork_wrapper:
1976         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
1977         ldo     TASK_REGS(%r1),%r1
1978         reg_save %r1
1979         mfctl   %cr27, %r3
1980         STREG   %r3, PT_CR27(%r1)
1981
1982         STREG   %r2,-RP_OFFSET(%r30)
1983         ldo     FRAME_SIZE(%r30),%r30
1984 #ifdef __LP64__
1985         ldo     -16(%r30),%r29          /* Reference param save area */
1986 #endif
1987
1988         /* These are call-clobbered registers and therefore
1989            also syscall-clobbered (we hope). */
1990         STREG   %r2,PT_GR19(%r1)        /* save for child */
1991         STREG   %r30,PT_GR21(%r1)
1992
1993         LDREG   PT_GR30(%r1),%r25
1994         copy    %r1,%r24
1995         bl      sys_clone,%r2
1996         ldi     SIGCHLD,%r26
1997
1998         LDREG   -RP_OFFSET-FRAME_SIZE(%r30),%r2
1999 wrapper_exit:
2000         ldo     -FRAME_SIZE(%r30),%r30          /* get the stackframe */
2001         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2002         ldo     TASK_REGS(%r1),%r1       /* get pt regs */
2003
2004         LDREG   PT_CR27(%r1), %r3
2005         mtctl   %r3, %cr27
2006         reg_restore %r1
2007
2008         /* strace expects syscall # to be preserved in r20 */
2009         ldi     __NR_fork,%r20
2010         bv %r0(%r2)
2011         STREG   %r20,PT_GR20(%r1)
2012
2013         /* Set the return value for the child */
2014 child_return:
2015         bl      schedule_tail, %r2
2016         nop
2017
2018         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30), %r1
2019         LDREG   TASK_PT_GR19(%r1),%r2
2020         b       wrapper_exit
2021         copy    %r0,%r28
2022
2023         
2024         .export sys_clone_wrapper
2025 sys_clone_wrapper:
2026         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2027         ldo     TASK_REGS(%r1),%r1      /* get pt regs */
2028         reg_save %r1
2029         mfctl   %cr27, %r3
2030         STREG   %r3, PT_CR27(%r1)
2031
2032         STREG   %r2,-RP_OFFSET(%r30)
2033         ldo     FRAME_SIZE(%r30),%r30
2034 #ifdef __LP64__
2035         ldo     -16(%r30),%r29          /* Reference param save area */
2036 #endif
2037
2038         STREG   %r2,PT_GR19(%r1)        /* save for child */
2039         STREG   %r30,PT_GR21(%r1)
2040         bl      sys_clone,%r2
2041         copy    %r1,%r24
2042
2043         b       wrapper_exit
2044         LDREG   -RP_OFFSET-FRAME_SIZE(%r30),%r2
2045
2046         .export sys_vfork_wrapper
2047 sys_vfork_wrapper:
2048         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2049         ldo     TASK_REGS(%r1),%r1      /* get pt regs */
2050         reg_save %r1
2051         mfctl   %cr27, %r3
2052         STREG   %r3, PT_CR27(%r1)
2053
2054         STREG   %r2,-RP_OFFSET(%r30)
2055         ldo     FRAME_SIZE(%r30),%r30
2056 #ifdef __LP64__
2057         ldo     -16(%r30),%r29          /* Reference param save area */
2058 #endif
2059
2060         STREG   %r2,PT_GR19(%r1)        /* save for child */
2061         STREG   %r30,PT_GR21(%r1)
2062
2063         bl      sys_vfork,%r2
2064         copy    %r1,%r26
2065
2066         b       wrapper_exit
2067         LDREG   -RP_OFFSET-FRAME_SIZE(%r30),%r2
2068
2069         
2070         .macro  execve_wrapper execve
2071         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2072         ldo     TASK_REGS(%r1),%r1      /* get pt regs */
2073
2074         /*
2075          * Do we need to save/restore r3-r18 here?
2076          * I don't think so. why would new thread need old
2077          * threads registers?
2078          */
2079
2080         /* %arg0 - %arg3 are already saved for us. */
2081
2082         STREG %r2,-RP_OFFSET(%r30)
2083         ldo FRAME_SIZE(%r30),%r30
2084 #ifdef __LP64__
2085         ldo     -16(%r30),%r29          /* Reference param save area */
2086 #endif
2087         bl \execve,%r2
2088         copy %r1,%arg0
2089
2090         ldo -FRAME_SIZE(%r30),%r30
2091         LDREG -RP_OFFSET(%r30),%r2
2092
2093         /* If exec succeeded we need to load the args */
2094
2095         ldo -1024(%r0),%r1
2096         cmpb,>>= %r28,%r1,error_\execve
2097         copy %r2,%r19
2098
2099 error_\execve:
2100         bv %r0(%r19)
2101         nop
2102         .endm
2103
2104         .export sys_execve_wrapper
2105         .import sys_execve
2106
2107 sys_execve_wrapper:
2108         execve_wrapper sys_execve
2109
2110 #ifdef __LP64__
2111         .export sys32_execve_wrapper
2112         .import sys32_execve
2113
2114 sys32_execve_wrapper:
2115         execve_wrapper sys32_execve
2116 #endif
2117
2118         .export sys_rt_sigreturn_wrapper
2119 sys_rt_sigreturn_wrapper:
2120         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26
2121         ldo     TASK_REGS(%r26),%r26    /* get pt regs */
2122         /* Don't save regs, we are going to restore them from sigcontext. */
2123         STREG   %r2, -RP_OFFSET(%r30)
2124 #ifdef __LP64__
2125         ldo     FRAME_SIZE(%r30), %r30
2126         bl      sys_rt_sigreturn,%r2
2127         ldo     -16(%r30),%r29          /* Reference param save area */
2128 #else
2129         bl      sys_rt_sigreturn,%r2
2130         ldo     FRAME_SIZE(%r30), %r30
2131 #endif
2132
2133         ldo     -FRAME_SIZE(%r30), %r30
2134         LDREG   -RP_OFFSET(%r30), %r2
2135
2136         /* FIXME: I think we need to restore a few more things here. */
2137         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2138         ldo     TASK_REGS(%r1),%r1      /* get pt regs */
2139         reg_restore %r1
2140
2141         /* If the signal was received while the process was blocked on a
2142          * syscall, then r2 will take us to syscall_exit; otherwise r2 will
2143          * take us to syscall_exit_rfi and on to intr_return.
2144          */
2145         bv      %r0(%r2)
2146         LDREG   PT_GR28(%r1),%r28  /* reload original r28 for syscall_exit */
2147
2148         .export sys_sigaltstack_wrapper
2149 sys_sigaltstack_wrapper:
2150         /* Get the user stack pointer */
2151         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2152         ldo     TASK_REGS(%r1),%r24     /* get pt regs */
2153         LDREG   TASK_PT_GR30(%r24),%r24
2154         STREG   %r2, -RP_OFFSET(%r30)
2155 #ifdef __LP64__
2156         ldo     FRAME_SIZE(%r30), %r30
2157         bl      do_sigaltstack,%r2
2158         ldo     -16(%r30),%r29          /* Reference param save area */
2159 #else
2160         bl      do_sigaltstack,%r2
2161         ldo     FRAME_SIZE(%r30), %r30
2162 #endif
2163
2164         ldo     -FRAME_SIZE(%r30), %r30
2165         LDREG   -RP_OFFSET(%r30), %r2
2166         bv      %r0(%r2)
2167         nop
2168
2169 #ifdef __LP64__
2170         .export sys32_sigaltstack_wrapper
2171 sys32_sigaltstack_wrapper:
2172         /* Get the user stack pointer */
2173         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r24
2174         LDREG   TASK_PT_GR30(%r24),%r24
2175         STREG   %r2, -RP_OFFSET(%r30)
2176         ldo     FRAME_SIZE(%r30), %r30
2177         bl      do_sigaltstack32,%r2
2178         ldo     -16(%r30),%r29          /* Reference param save area */
2179
2180         ldo     -FRAME_SIZE(%r30), %r30
2181         LDREG   -RP_OFFSET(%r30), %r2
2182         bv      %r0(%r2)
2183         nop
2184 #endif
2185
2186         .export sys_rt_sigsuspend_wrapper
2187 sys_rt_sigsuspend_wrapper:
2188         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
2189         ldo     TASK_REGS(%r1),%r24
2190         reg_save %r24
2191
2192         STREG   %r2, -RP_OFFSET(%r30)
2193 #ifdef __LP64__
2194         ldo     FRAME_SIZE(%r30), %r30
2195         bl      sys_rt_sigsuspend,%r2
2196         ldo     -16(%r30),%r29          /* Reference param save area */
2197 #else
2198         bl      sys_rt_sigsuspend,%r2
2199         ldo     FRAME_SIZE(%r30), %r30
2200 #endif
2201
2202         ldo     -FRAME_SIZE(%r30), %r30
2203         LDREG   -RP_OFFSET(%r30), %r2
2204
2205         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
2206         ldo     TASK_REGS(%r1),%r1
2207         reg_restore %r1
2208
2209         bv      %r0(%r2)
2210         nop
2211
2212         .export syscall_exit
2213 syscall_exit:
2214         /* NOTE: HP-UX syscalls also come through here
2215            after hpux_syscall_exit fixes up return
2216            values. */
2217         /* NOTE: Not all syscalls exit this way.  rt_sigreturn will exit
2218          * via syscall_exit_rfi if the signal was received while the process
2219          * was running.
2220          */
2221
2222         /* save return value now */
2223
2224         mfctl     %cr30, %r1
2225         LDREG     TI_TASK(%r1),%r1
2226         STREG     %r28,TASK_PT_GR28(%r1)
2227
2228 #ifdef CONFIG_HPUX
2229
2230 /* <linux/personality.h> cannot be easily included */
2231 #define PER_HPUX 0x10
2232         LDREG     TASK_PERSONALITY(%r1),%r19
2233
2234         /* We can't use "CMPIB<> PER_HPUX" since "im5" field is sign extended */
2235         ldo       -PER_HPUX(%r19), %r19
2236         CMPIB<>,n 0,%r19,1f
2237
2238         /* Save other hpux returns if personality is PER_HPUX */
2239         STREG     %r22,TASK_PT_GR22(%r1)
2240         STREG     %r29,TASK_PT_GR29(%r1)
2241 1:
2242
2243 #endif /* CONFIG_HPUX */
2244
2245         /* Seems to me that dp could be wrong here, if the syscall involved
2246          * calling a module, and nothing got round to restoring dp on return.
2247          */
2248         loadgp
2249
2250 syscall_check_bh:
2251
2252         /* Check for software interrupts */
2253
2254         .import irq_stat,data
2255
2256         ldil    L%irq_stat,%r19
2257         ldo     R%irq_stat(%r19),%r19
2258
2259 #ifdef CONFIG_SMP
2260         /* sched.h: int processor */
2261         /* %r26 is used as scratch register to index into irq_stat[] */
2262         ldw     TI_CPU-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26 /* cpu # */
2263
2264         /* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) bits */
2265 #ifdef __LP64__
2266         shld    %r26, 6, %r20
2267 #else
2268         shlw    %r26, 5, %r20
2269 #endif
2270         add     %r19,%r20,%r19  /* now have &irq_stat[smp_processor_id()] */
2271 #endif /* CONFIG_SMP */
2272
2273         LDREG   IRQSTAT_SIRQ_PEND(%r19),%r20    /* hardirq.h: unsigned long */
2274         cmpib,<>,n 0,%r20,syscall_do_softirq /* forward */
2275
2276 syscall_check_resched:
2277
2278         /* check for reschedule */
2279
2280         LDREG   TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19   /* long */
2281         bb,<,n  %r19, 31-TIF_NEED_RESCHED, syscall_do_resched /* forward */
2282
2283 syscall_check_sig:
2284         LDREG   TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19    /* get ti flags */
2285         bb,<,n  %r19, 31-TIF_SIGPENDING, syscall_do_signal /* forward */
2286
2287 syscall_restore:
2288         LDREG   TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19    /* get ti flags */
2289         bb,<    %r19, 31-TIF_SYSCALL_TRACE,syscall_restore_rfi
2290         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1     /* delay slot! */
2291         ldo     TASK_PT_FR31(%r1),%r19             /* reload fpregs */
2292         rest_fp %r19
2293
2294         LDREG   TASK_PT_SAR(%r1),%r19              /* restore SAR */
2295         mtsar   %r19
2296
2297         LDREG   TASK_PT_GR2(%r1),%r2               /* restore user rp */
2298         LDREG   TASK_PT_GR19(%r1),%r19
2299         LDREG   TASK_PT_GR20(%r1),%r20
2300         LDREG   TASK_PT_GR21(%r1),%r21
2301         LDREG   TASK_PT_GR22(%r1),%r22
2302         LDREG   TASK_PT_GR23(%r1),%r23
2303         LDREG   TASK_PT_GR24(%r1),%r24
2304         LDREG   TASK_PT_GR25(%r1),%r25
2305         LDREG   TASK_PT_GR26(%r1),%r26
2306         LDREG   TASK_PT_GR27(%r1),%r27     /* restore user dp */
2307         LDREG   TASK_PT_GR28(%r1),%r28     /* syscall return value */
2308         LDREG   TASK_PT_GR29(%r1),%r29
2309         LDREG   TASK_PT_GR31(%r1),%r31     /* restore syscall rp */
2310
2311         rsm     PSW_SM_I, %r0
2312         LDREG   TASK_PT_GR30(%r1),%r30             /* restore user sp */
2313         mfsp    %sr3,%r1                           /* Get users space id */
2314         mtsp    %r1,%sr7                           /* Restore sr7 */
2315         ssm     PSW_SM_I, %r0
2316         mtsp    %r1,%sr4                           /* Restore sr4 */
2317         mtsp    %r1,%sr5                           /* Restore sr5 */
2318         mtsp    %r1,%sr6                           /* Restore sr6 */
2319
2320         depi    3,31,2,%r31                        /* ensure return to user mode. */
2321
2322 #ifdef __LP64__
2323         /* decide whether to reset the wide mode bit
2324          *
2325          * For a syscall, the W bit is stored in the lowest bit
2326          * of sp.  Extract it and reset W if it is zero */
2327         extrd,u,*<>     %r30,63,1,%r1
2328         rsm     PSW_SM_W, %r0
2329         /* now reset the lowest bit of sp if it was set */
2330         xor     %r30,%r1,%r30
2331 #endif
2332         be,n    0(%sr3,%r31)                       /* return to user space */
2333
2334         /* We have to return via an RFI, so that PSW T and R bits can be set
2335          * appropriately.
2336          * This sets up pt_regs so we can return via intr_restore, which is not
2337          * the most efficient way of doing things, but it works.
2338          */
2339 syscall_restore_rfi:
2340         LDREG   TASK_PTRACE(%r1), %r19
2341         ldo     -1(%r0),%r2                        /* Set recovery cntr to -1 */
2342         mtctl   %r2,%cr0                           /*   for immediate trap */
2343         LDREG   TASK_PT_PSW(%r1),%r2               /* Get old PSW */
2344         ldi     0x0b,%r20                          /* Create new PSW */
2345         depi    -1,13,1,%r20                       /* C, Q, D, and I bits */
2346
2347         /* The values of PA_SINGLESTEP_BIT and PA_BLOCKSTEP_BIT are
2348          * set in include/linux/ptrace.h and converted to PA bitmap
2349          * numbers in asm-offsets.c */
2350
2351         /* if ((%r19.PA_SINGLESTEP_BIT)) { %r20.27=1} */
2352         extru,= %r19,PA_SINGLESTEP_BIT,1,%r0
2353         depi    -1,27,1,%r20                       /* R bit */
2354
2355         /* if ((%r19.PA_BLOCKSTEP_BIT)) { %r20.7=1} */
2356         extru,= %r19,PA_BLOCKSTEP_BIT,1,%r0
2357         depi    -1,7,1,%r20                        /* T bit */
2358
2359         STREG   %r20,TASK_PT_PSW(%r1)
2360
2361         /* Always store space registers, since sr3 can be changed (e.g. fork) */
2362
2363         mfsp    %sr3,%r25
2364         STREG   %r25,TASK_PT_SR3(%r1)
2365         STREG   %r25,TASK_PT_SR4(%r1)
2366         STREG   %r25,TASK_PT_SR5(%r1)
2367         STREG   %r25,TASK_PT_SR6(%r1)
2368         STREG   %r25,TASK_PT_SR7(%r1)
2369         STREG   %r25,TASK_PT_IASQ0(%r1)
2370         STREG   %r25,TASK_PT_IASQ1(%r1)
2371
2372         /* XXX W bit??? */
2373         /* Now if old D bit is clear, it means we didn't save all registers
2374          * on syscall entry, so do that now.  This only happens on TRACEME
2375          * calls, or if someone attached to us while we were on a syscall.
2376          * We could make this more efficient by not saving r3-r18, but
2377          * then we wouldn't be able to use the common intr_restore path.
2378          * It is only for traced processes anyway, so performance is not
2379          * an issue.
2380          */
2381         bb,<    %r2,30,pt_regs_ok                  /* Branch if D set */
2382         ldo     TASK_REGS(%r1),%r25
2383         reg_save %r25                              /* Save r3 to r18 */
2384         mfsp    %sr0,%r2
2385         STREG   %r2,TASK_PT_SR0(%r1)
2386         mfsp    %sr1,%r2
2387         STREG   %r2,TASK_PT_SR1(%r1)
2388         mfsp    %sr2,%r2
2389         STREG   %r2,TASK_PT_SR2(%r1)
2390 pt_regs_ok:
2391         LDREG   TASK_PT_GR31(%r1),%r2
2392         depi    3,31,2,%r2                         /* ensure return to user mode. */
2393         STREG   %r2,TASK_PT_IAOQ0(%r1)
2394         ldo     4(%r2),%r2
2395         STREG   %r2,TASK_PT_IAOQ1(%r1)
2396         copy    %r25,%r16
2397         b       intr_restore
2398         nop
2399
2400         .import do_softirq,code
2401 syscall_do_softirq:
2402         bl      do_softirq,%r2
2403         nop
2404         b       syscall_check_resched
2405         ssm     PSW_SM_I, %r0  /* do_softirq returns with I bit off */
2406
2407         .import schedule,code
2408 syscall_do_resched:
2409         bl      schedule,%r2
2410 #ifdef __LP64__
2411         ldo     -16(%r30),%r29          /* Reference param save area */
2412 #else
2413         nop
2414 #endif
2415         b       syscall_check_bh  /* if resched, we start over again */
2416         nop
2417
2418         .import do_signal,code
2419 syscall_do_signal:
2420         /* Save callee-save registers (for sigcontext).
2421            FIXME: After this point the process structure should be
2422            consistent with all the relevant state of the process
2423            before the syscall.  We need to verify this. */
2424         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 
2425         ldo     TASK_REGS(%r1), %r25            /* struct pt_regs *regs */
2426         reg_save %r25
2427
2428         ldi     1, %r24                         /* unsigned long in_syscall */
2429
2430 #ifdef __LP64__
2431         ldo     -16(%r30),%r29                  /* Reference param save area */
2432 #endif
2433         bl      do_signal,%r2
2434         copy    %r0, %r26                       /* sigset_t *oldset = NULL */
2435
2436         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2437         ldo     TASK_REGS(%r1), %r20            /* reload pt_regs */
2438         reg_restore %r20
2439
2440         b,n     syscall_restore
2441
2442         /*
2443          * get_register is used by the non access tlb miss handlers to
2444          * copy the value of the general register specified in r8 into
2445          * r1. This routine can't be used for shadowed registers, since
2446          * the rfir will restore the original value. So, for the shadowed
2447          * registers we put a -1 into r1 to indicate that the register
2448          * should not be used (the register being copied could also have
2449          * a -1 in it, but that is OK, it just means that we will have
2450          * to use the slow path instead).
2451          */
2452
2453 get_register:
2454         blr     %r8,%r0
2455         nop
2456         bv      %r0(%r25)    /* r0 */
2457         copy    %r0,%r1
2458         bv      %r0(%r25)    /* r1 - shadowed */
2459         ldi     -1,%r1
2460         bv      %r0(%r25)    /* r2 */
2461         copy    %r2,%r1
2462         bv      %r0(%r25)    /* r3 */
2463         copy    %r3,%r1
2464         bv      %r0(%r25)    /* r4 */
2465         copy    %r4,%r1
2466         bv      %r0(%r25)    /* r5 */
2467         copy    %r5,%r1
2468         bv      %r0(%r25)    /* r6 */
2469         copy    %r6,%r1
2470         bv      %r0(%r25)    /* r7 */
2471         copy    %r7,%r1
2472         bv      %r0(%r25)    /* r8 - shadowed */
2473         ldi     -1,%r1
2474         bv      %r0(%r25)    /* r9 - shadowed */
2475         ldi     -1,%r1
2476         bv      %r0(%r25)    /* r10 */
2477         copy    %r10,%r1
2478         bv      %r0(%r25)    /* r11 */
2479         copy    %r11,%r1
2480         bv      %r0(%r25)    /* r12 */
2481         copy    %r12,%r1
2482         bv      %r0(%r25)    /* r13 */
2483         copy    %r13,%r1
2484         bv      %r0(%r25)    /* r14 */
2485         copy    %r14,%r1
2486         bv      %r0(%r25)    /* r15 */
2487         copy    %r15,%r1
2488         bv      %r0(%r25)    /* r16 - shadowed */
2489         ldi     -1,%r1
2490         bv      %r0(%r25)    /* r17 - shadowed */
2491         ldi     -1,%r1
2492         bv      %r0(%r25)    /* r18 */
2493         copy    %r18,%r1
2494         bv      %r0(%r25)    /* r19 */
2495         copy    %r19,%r1
2496         bv      %r0(%r25)    /* r20 */
2497         copy    %r20,%r1
2498         bv      %r0(%r25)    /* r21 */
2499         copy    %r21,%r1
2500         bv      %r0(%r25)    /* r22 */
2501         copy    %r22,%r1
2502         bv      %r0(%r25)    /* r23 */
2503         copy    %r23,%r1
2504         bv      %r0(%r25)    /* r24 - shadowed */
2505         ldi     -1,%r1
2506         bv      %r0(%r25)    /* r25 - shadowed */
2507         ldi     -1,%r1
2508         bv      %r0(%r25)    /* r26 */
2509         copy    %r26,%r1
2510         bv      %r0(%r25)    /* r27 */
2511         copy    %r27,%r1
2512         bv      %r0(%r25)    /* r28 */
2513         copy    %r28,%r1
2514         bv      %r0(%r25)    /* r29 */
2515         copy    %r29,%r1
2516         bv      %r0(%r25)    /* r30 */
2517         copy    %r30,%r1
2518         bv      %r0(%r25)    /* r31 */
2519         copy    %r31,%r1
2520
2521         /*
2522          * set_register is used by the non access tlb miss handlers to
2523          * copy the value of r1 into the general register specified in
2524          * r8.
2525          */
2526
2527 set_register:
2528         blr     %r8,%r0
2529         nop
2530         bv      %r0(%r25)    /* r0 (silly, but it is a place holder) */
2531         copy    %r1,%r0
2532         bv      %r0(%r25)    /* r1 */
2533         copy    %r1,%r1
2534         bv      %r0(%r25)    /* r2 */
2535         copy    %r1,%r2
2536         bv      %r0(%r25)    /* r3 */
2537         copy    %r1,%r3
2538         bv      %r0(%r25)    /* r4 */
2539         copy    %r1,%r4
2540         bv      %r0(%r25)    /* r5 */
2541         copy    %r1,%r5
2542         bv      %r0(%r25)    /* r6 */
2543         copy    %r1,%r6
2544         bv      %r0(%r25)    /* r7 */
2545         copy    %r1,%r7
2546         bv      %r0(%r25)    /* r8 */
2547         copy    %r1,%r8
2548         bv      %r0(%r25)    /* r9 */
2549         copy    %r1,%r9
2550         bv      %r0(%r25)    /* r10 */
2551         copy    %r1,%r10
2552         bv      %r0(%r25)    /* r11 */
2553         copy    %r1,%r11
2554         bv      %r0(%r25)    /* r12 */
2555         copy    %r1,%r12
2556         bv      %r0(%r25)    /* r13 */
2557         copy    %r1,%r13
2558         bv      %r0(%r25)    /* r14 */
2559         copy    %r1,%r14
2560         bv      %r0(%r25)    /* r15 */
2561         copy    %r1,%r15
2562         bv      %r0(%r25)    /* r16 */
2563         copy    %r1,%r16
2564         bv      %r0(%r25)    /* r17 */
2565         copy    %r1,%r17
2566         bv      %r0(%r25)    /* r18 */
2567         copy    %r1,%r18
2568         bv      %r0(%r25)    /* r19 */
2569         copy    %r1,%r19
2570         bv      %r0(%r25)    /* r20 */
2571         copy    %r1,%r20
2572         bv      %r0(%r25)    /* r21 */
2573         copy    %r1,%r21
2574         bv      %r0(%r25)    /* r22 */
2575         copy    %r1,%r22
2576         bv      %r0(%r25)    /* r23 */
2577         copy    %r1,%r23
2578         bv      %r0(%r25)    /* r24 */
2579         copy    %r1,%r24
2580         bv      %r0(%r25)    /* r25 */
2581         copy    %r1,%r25
2582         bv      %r0(%r25)    /* r26 */
2583         copy    %r1,%r26
2584         bv      %r0(%r25)    /* r27 */
2585         copy    %r1,%r27
2586         bv      %r0(%r25)    /* r28 */
2587         copy    %r1,%r28
2588         bv      %r0(%r25)    /* r29 */
2589         copy    %r1,%r29
2590         bv      %r0(%r25)    /* r30 */
2591         copy    %r1,%r30
2592         bv      %r0(%r25)    /* r31 */
2593         copy    %r1,%r31