[PATCH] parisc updates for 2.5.56
[linux-flexiantxendom0-3.2.10.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
81         mtctl   %r0, %cr17
82         ldil    L%4f, %r1
83         ldo     R%4f(%r1), %r1
84         mtctl   %r1, %cr18
85         ldo     4(%r1), %r1
86         mtctl   %r1, %cr18
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         copy    %r0, %r25               /* stack_start */
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         ldw     TASK_PID(%r28), %r28
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 #if CONFIG_PREEMPT || CONFIG_SMP
562         /* Call schedule_tail first though */
563         bl      schedule_tail, %r2
564         nop
565 #endif
566
567         LDREG   TI_TASK-THREAD_SZ_ALGN(%r30), %r1
568         LDREG   TASK_PT_GR25(%r1), %r26
569 #ifdef __LP64__
570         LDREG   TASK_PT_GR27(%r1), %r27
571         LDREG   TASK_PT_GR22(%r1), %r22
572 #endif
573         LDREG   TASK_PT_GR26(%r1), %r1
574         ble     0(%sr7, %r1)
575         copy    %r31, %r2
576
577 #ifdef __LP64__
578         ldo     -16(%r30),%r29          /* Reference param save area */
579         loadgp                          /* Thread could have been in a module */
580 #endif
581         b       sys_exit
582         ldi     0, %r26
583
584         .import sys_execve, code
585         .export __execve, code
586 __execve:
587         copy    %r2, %r15
588         copy    %r30, %r16
589         ldo     PT_SZ_ALGN(%r30), %r30
590         STREG   %r26, PT_GR26(%r16)
591         STREG   %r25, PT_GR25(%r16)
592         STREG   %r24, PT_GR24(%r16)
593 #ifdef __LP64__
594         ldo     -16(%r30),%r29          /* Reference param save area */
595 #endif
596         bl      sys_execve, %r2
597         copy    %r16, %r26
598
599         cmpib,=,n 0,%r28,intr_return    /* forward */
600
601         /* yes, this will trap and die. */
602         copy    %r15, %r2
603         copy    %r16, %r30
604         bv      %r0(%r2)
605         nop
606
607         .align 4
608
609         /*
610          * struct task_struct *_switch_to(struct task_struct *prev,
611          *      struct task_struct *next)
612          *
613          * switch kernel stacks and return prev */
614         .export _switch_to, code
615 _switch_to:
616         STREG    %r2, -RP_OFFSET(%r30)
617
618         callee_save
619
620         ldil    L%_switch_to_ret, %r2
621         ldo     R%_switch_to_ret(%r2), %r2
622
623         STREG   %r2, TASK_PT_KPC(%r26)
624         LDREG   TASK_PT_KPC(%r25), %r2
625
626         STREG   %r30, TASK_PT_KSP(%r26)
627         LDREG   TASK_PT_KSP(%r25), %r30
628         LDREG   TASK_THREAD_INFO(%r25), %r25
629         bv      %r0(%r2)
630         mtctl   %r25,%cr30
631
632 _switch_to_ret:
633         mtctl   %r0, %cr0               /* Needed for single stepping */
634         callee_rest
635
636         LDREG   -RP_OFFSET(%r30), %r2
637         bv      %r0(%r2)
638         copy    %r26, %r28
639
640         /*
641          * Common rfi return path for interruptions, kernel execve, and
642          * sys_rt_sigreturn (sometimes).  The sys_rt_sigreturn syscall will
643          * return via this path if the signal was received when the process
644          * was running; if the process was blocked on a syscall then the
645          * normal syscall_exit path is used.  All syscalls for traced
646          * proceses exit via intr_restore.
647          *
648          * XXX If any syscalls that change a processes space id ever exit
649          * this way, then we will need to copy %sr3 in to PT_SR[3..7], and
650          * adjust IASQ[0..1].
651          *
652          * Note that the following code uses a "relied upon translation".
653          * See the parisc ACD for details. The ssm is necessary due to a
654          * PCXT bug.
655          */
656
657         .align 4096
658
659         .export syscall_exit_rfi
660 syscall_exit_rfi:
661         mfctl   %cr30,%r16
662         LDREG   TI_TASK(%r16), %r16     /* thread_info -> task_struct */
663         ldo     TASK_REGS(%r16),%r16
664         /* Force iaoq to userspace, as the user has had access to our current
665          * context via sigcontext. Also Filter the PSW for the same reason.
666          */
667         LDREG   PT_IAOQ0(%r16),%r19
668         depi    3,31,2,%r19
669         STREG   %r19,PT_IAOQ0(%r16)
670         LDREG   PT_IAOQ1(%r16),%r19
671         depi    3,31,2,%r19
672         STREG   %r19,PT_IAOQ1(%r16)
673         LDREG   PT_PSW(%r16),%r19
674         ldil    L%USER_PSW_MASK,%r1
675         ldo     R%USER_PSW_MASK(%r1),%r1
676 #ifdef __LP64__
677         ldil    L%USER_PSW_HI_MASK,%r20
678         ldo     R%USER_PSW_HI_MASK(%r20),%r20
679         depd    %r20,31,32,%r1
680 #endif
681         and     %r19,%r1,%r19 /* Mask out bits that user shouldn't play with */
682         ldil    L%USER_PSW,%r1
683         ldo     R%USER_PSW(%r1),%r1
684         or      %r19,%r1,%r19 /* Make sure default USER_PSW bits are set */
685         STREG   %r19,PT_PSW(%r16)
686
687         /*
688          * If we aren't being traced, we never saved space registers
689          * (we don't store them in the sigcontext), so set them
690          * to "proper" values now (otherwise we'll wind up restoring
691          * whatever was last stored in the task structure, which might
692          * be inconsistant if an interrupt occured while on the gateway
693          * page) Note that we may be "trashing" values the user put in
694          * them, but we don't support the the user changing them.
695          */
696
697         STREG   %r0,PT_SR2(%r16)
698         mfsp    %sr3,%r19
699         STREG   %r19,PT_SR0(%r16)
700         STREG   %r19,PT_SR1(%r16)
701         STREG   %r19,PT_SR3(%r16)
702         STREG   %r19,PT_SR4(%r16)
703         STREG   %r19,PT_SR5(%r16)
704         STREG   %r19,PT_SR6(%r16)
705         STREG   %r19,PT_SR7(%r16)
706
707 intr_return:
708         ssm     PSW_SM_I, %r0
709
710         /* Check for software interrupts */
711
712         .import irq_stat,data
713
714         ldil    L%irq_stat,%r19
715         ldo     R%irq_stat(%r19),%r19
716 #ifdef CONFIG_SMP
717         mfctl   %cr30,%r1
718         ldw     TI_CPU(%r1),%r1 /* get cpu # - int */
719         /* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) amount
720         ** irq_stat[] is defined using ____cacheline_aligned.
721         */
722 #ifdef __LP64__
723         shld    %r1, 6, %r20
724 #else
725         shlw    %r1, 5, %r20
726 #endif
727         add     %r19,%r20,%r19  /* now have &irq_stat[smp_processor_id()] */
728 #endif /* CONFIG_SMP */
729
730         LDREG   IRQSTAT_SIRQ_PEND(%r19),%r20    /* hardirq.h: unsigned long */
731         cmpib,<>,n 0,%r20,intr_do_softirq /* forward */
732
733 intr_check_resched:
734
735         /* check for reschedule */
736         mfctl   %cr30,%r1
737         LDREG   TI_FLAGS(%r1),%r19      /* sched.h: TIF_NEED_RESCHED */
738         bb,<,n  %r19,31-TIF_NEED_RESCHED,intr_do_resched /* forward */
739
740 intr_check_sig:
741         /* As above */
742         mfctl   %cr30,%r1
743         LDREG   TI_FLAGS(%r1),%r19      /* sched.h: TIF_SIGPENDING */
744         bb,<,n %r19, 31-TIF_SIGPENDING, intr_do_signal /* forward */
745
746 intr_restore:
747         copy            %r16,%r29
748         ldo             PT_FR31(%r29),%r1
749         rest_fp         %r1
750         rest_general    %r29
751         ssm             0,%r0
752         nop
753         nop
754         nop
755         nop
756         nop
757         nop
758         nop
759         tophys_r1       %r29
760         rsm             (PSW_SM_Q|PSW_SM_P|PSW_SM_D|PSW_SM_I),%r0
761         rest_specials   %r29
762         rest_stack
763         rfi
764         nop
765         nop
766         nop
767         nop
768         nop
769         nop
770         nop
771         nop
772
773         .import do_softirq,code
774 intr_do_softirq:
775         bl      do_softirq,%r2
776 #ifdef __LP64__
777         ldo     -16(%r30),%r29          /* Reference param save area */
778 #else
779         nop
780 #endif
781         b       intr_check_resched
782         nop
783
784         .import schedule,code
785 intr_do_resched:
786         /* Only do reschedule if we are returning to user space */
787         LDREG   PT_IASQ0(%r16), %r20
788         CMPIB= 0,%r20,intr_restore /* backward */
789         nop
790         LDREG   PT_IASQ1(%r16), %r20
791         CMPIB= 0,%r20,intr_restore /* backward */
792         nop
793
794 #ifdef __LP64__
795         ldo     -16(%r30),%r29          /* Reference param save area */
796 #endif
797
798         ldil    L%intr_check_sig, %r2
799         b       schedule
800         ldo     R%intr_check_sig(%r2), %r2
801
802
803         .import do_signal,code
804 intr_do_signal:
805         /* Only do signals if we are returning to user space */
806         LDREG   PT_IASQ0(%r16), %r20
807         CMPIB= 0,%r20,intr_restore /* backward */
808         nop
809         LDREG   PT_IASQ1(%r16), %r20
810         CMPIB= 0,%r20,intr_restore /* backward */
811         nop
812
813         copy    %r0, %r24                       /* unsigned long in_syscall */
814         copy    %r16, %r25                      /* struct pt_regs *regs */
815 #ifdef __LP64__
816         ldo     -16(%r30),%r29                  /* Reference param save area */
817 #endif
818
819         bl      do_signal,%r2
820         copy    %r0, %r26                       /* sigset_t *oldset = NULL */
821
822         b       intr_restore
823         nop
824
825         /*
826          * External interrupts.
827          */
828
829 intr_extint:
830         CMPIB=,n 0,%r16,1f
831         get_stack_use_cr30
832         b,n 3f
833
834 1:
835 #if 0  /* Interrupt Stack support not working yet! */
836         mfctl   %cr31,%r1
837         copy    %r30,%r17
838         /* FIXME! depi below has hardcoded idea of interrupt stack size (32k)*/
839 #ifdef __LP64__
840         depdi   0,63,15,%r17
841 #else
842         depi    0,31,15,%r17
843 #endif
844         CMPB=,n %r1,%r17,2f
845         get_stack_use_cr31
846         b,n 3f
847 #endif
848 2:
849         get_stack_use_r30
850
851 3:
852         save_specials   %r29
853         virt_map
854         save_general    %r29
855
856         ldo     PT_FR0(%r29), %r24
857         save_fp %r24
858         
859         loadgp
860
861         copy    %r29, %r26      /* arg0 is pt_regs */
862         copy    %r29, %r16      /* save pt_regs */
863
864         ldil    L%intr_return, %r2
865
866 #ifdef __LP64__
867         ldo     -16(%r30),%r29  /* Reference param save area */
868 #endif
869
870         b       do_cpu_irq_mask
871         ldo     R%intr_return(%r2), %r2 /* return to intr_return, not here */
872
873
874         /* Generic interruptions (illegal insn, unaligned, page fault, etc) */
875
876         .export         intr_save, code /* for os_hpmc */
877
878 intr_save:
879         mfsp    %sr7,%r16
880         CMPIB=,n 0,%r16,1f
881         get_stack_use_cr30
882         b       2f
883         copy    %r8,%r26
884
885 1:
886         get_stack_use_r30
887         copy    %r8,%r26
888
889 2:
890         save_specials   %r29
891
892         /* If this trap is a itlb miss, skip saving/adjusting isr/ior */
893
894         /*
895          * FIXME: 1) Use a #define for the hardwired "6" below (and in
896          *           traps.c.
897          *        2) Once we start executing code above 4 Gb, we need
898          *           to adjust iasq/iaoq here in the same way we
899          *           adjust isr/ior below.
900          */
901
902         CMPIB=,n        6,%r26,skip_save_ior
903
904         /* save_specials left ipsw value in r8 for us to test */
905
906         mfctl           %cr20, %r16 /* isr */
907         mfctl           %cr21, %r17 /* ior */
908
909 #ifdef __LP64__
910         /*
911          * If the interrupted code was running with W bit off (32 bit),
912          * clear the b bits (bits 0 & 1) in the ior.
913          */
914         extrd,u,*<>     %r8,PSW_W_BIT,1,%r0
915         depdi           0,1,2,%r17
916
917         /*
918          * FIXME: This code has hardwired assumptions about the split
919          *        between space bits and offset bits. This will change
920          *        when we allow alternate page sizes.
921          */
922
923         /* adjust isr/ior. */
924
925         extrd,u         %r16,63,7,%r1    /* get high bits from isr for ior */
926         depd            %r1,31,7,%r17    /* deposit them into ior */
927         depdi           0,63,7,%r16      /* clear them from isr */
928 #endif
929         STREG           %r16, PT_ISR(%r29)
930         STREG           %r17, PT_IOR(%r29)
931
932
933 skip_save_ior:
934         virt_map
935         save_general    %r29
936
937         ldo             PT_FR0(%r29), %r25
938         save_fp         %r25
939         
940         loadgp
941
942         copy            %r29, %r25      /* arg1 is pt_regs */
943 #ifdef __LP64__
944         ldo             -16(%r30),%r29  /* Reference param save area */
945 #endif
946
947         ldil            L%intr_check_sig, %r2
948         copy            %r25, %r16      /* save pt_regs */
949
950         b               handle_interruption
951         ldo             R%intr_check_sig(%r2), %r2
952
953
954         /*
955          * Note for all tlb miss handlers:
956          *
957          * cr24 contains a pointer to the kernel address space
958          * page directory.
959          *
960          * cr25 contains a pointer to the current user address
961          * space page directory.
962          *
963          * sr3 will contain the space id of the user address space
964          * of the current running thread while that thread is
965          * running in the kernel.
966          */
967
968         /*
969          * register number allocations.  Note that these are all
970          * in the shadowed registers
971          */
972
973         t0 = r1         /* temporary register 0 */
974         va = r8         /* virtual address for which the trap occured */
975         t1 = r9         /* temporary register 1 */
976         pte  = r16      /* pte/phys page # */
977         prot = r17      /* prot bits */
978         spc  = r24      /* space for which the trap occured */
979         ptp = r25       /* page directory/page table pointer */
980
981 #ifdef __LP64__
982
983 dtlb_miss_20w:
984         extrd,u         spc,63,7,t1     /* adjust va */
985         depd            t1,31,7,va      /* adjust va */
986         depdi           0,63,7,spc      /* adjust space */
987         mfctl           %cr25,ptp       /* Assume user space miss */
988         or,*<>          %r0,spc,%r0     /* If it is user space, nullify */
989         mfctl           %cr24,ptp       /* Load kernel pgd instead */
990         extrd,u         va,33,9,t1      /* Get pgd index */
991
992         mfsp            %sr7,t0         /* Get current space */
993         or,*=           %r0,t0,%r0      /* If kernel, nullify following test */
994         cmpb,*<>,n       t0,spc,dtlb_fault /* forward */
995
996         /* First level page table lookup */
997
998         ldd,s           t1(ptp),ptp
999         extrd,u         va,42,9,t0     /* get second-level index */
1000         bb,>=,n         ptp,_PAGE_PRESENT_BIT,dtlb_check_alias_20w
1001         depdi           0,63,12,ptp     /* clear prot bits */
1002
1003         /* Second level page table lookup */
1004
1005         ldd,s           t0(ptp),ptp
1006         extrd,u         va,51,9,t0     /* get third-level index */
1007         bb,>=,n         ptp,_PAGE_PRESENT_BIT,dtlb_check_alias_20w
1008         depdi           0,63,12,ptp     /* clear prot bits */
1009
1010         /* Third level page table lookup */
1011
1012         shladd           t0,3,ptp,ptp
1013         ldi             _PAGE_ACCESSED,t1
1014         ldd              0(ptp),pte
1015         bb,>=,n          pte,_PAGE_PRESENT_BIT,dtlb_check_alias_20w
1016
1017         /* Check whether the "accessed" bit was set, otherwise do so */
1018
1019         or              t1,pte,t0       /* t0 has R bit set */
1020         and,*<>         t1,pte,%r0      /* test and nullify if already set */
1021         std             t0,0(ptp)       /* write back pte */
1022
1023         space_to_prot   spc prot        /* create prot id from space */
1024         depd            pte,8,7,prot    /* add in prot bits from pte */
1025
1026         extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
1027         depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
1028         extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
1029         depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1030
1031         /* Get rid of prot bits and convert to page addr for idtlbt */
1032
1033         depdi           0,63,12,pte
1034         extrd,u         pte,56,52,pte
1035         idtlbt          pte,prot
1036
1037         rfir
1038         nop
1039
1040 dtlb_check_alias_20w:
1041
1042         /* Check to see if fault is in the temporary alias region */
1043
1044         cmpib,*<>,n     0,spc,dtlb_fault /* forward */
1045         ldil            L%(TMPALIAS_MAP_START),t0
1046         copy            va,t1
1047         depdi           0,63,23,t1
1048         cmpb,*<>,n      t0,t1,dtlb_fault /* forward */
1049         ldi             (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot
1050         depd,z          prot,8,7,prot
1051
1052         /*
1053          * OK, it is in the temp alias region, check whether "from" or "to".
1054          * Check "subtle" note in pacache.S re: r23/r26.
1055          */
1056
1057         extrd,u,*=      va,41,1,r0
1058         or,*tr          %r23,%r0,pte    /* If "from" use "from" page */
1059         or,*            %r26,%r0,pte    /* else "to", use "to" page  */
1060
1061         idtlbt          pte,prot
1062
1063         rfir
1064         nop
1065
1066 nadtlb_miss_20w:
1067         extrd,u         spc,63,7,t1     /* adjust va */
1068         depd            t1,31,7,va      /* adjust va */
1069         depdi           0,63,7,spc      /* adjust space */
1070         mfctl           %cr25,ptp       /* Assume user space miss */
1071         or,*<>          %r0,spc,%r0     /* If it is user space, nullify */
1072         mfctl           %cr24,ptp       /* Load kernel pgd instead */
1073         extrd,u         va,33,9,t1      /* Get pgd index */
1074
1075         mfsp            %sr7,t0         /* Get current space */
1076         or,*=           %r0,t0,%r0      /* If kernel, nullify following test */
1077         cmpb,*<>,n       t0,spc,nadtlb_fault /* forward */
1078
1079         /* First level page table lookup */
1080
1081         ldd,s           t1(ptp),ptp
1082         extrd,u         va,42,9,t0     /* get second-level index */
1083         bb,>=,n         ptp,_PAGE_PRESENT_BIT,nadtlb_emulate
1084         depdi           0,63,12,ptp     /* clear prot bits */
1085
1086         /* Second level page table lookup */
1087
1088         ldd,s           t0(ptp),ptp
1089         extrd,u         va,51,9,t0     /* get third-level index */
1090         bb,>=,n         ptp,_PAGE_PRESENT_BIT,nadtlb_emulate
1091         depdi           0,63,12,ptp     /* clear prot bits */
1092
1093         /* Third level page table lookup */
1094
1095         shladd           t0,3,ptp,ptp
1096         ldi             _PAGE_ACCESSED,t1
1097         ldd              0(ptp),pte
1098         bb,>=,n          pte,_PAGE_PRESENT_BIT,nadtlb_check_flush_20w
1099
1100         space_to_prot   spc prot        /* create prot id from space */
1101         depd            pte,8,7,prot    /* add in prot bits from pte */
1102
1103         extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
1104         depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
1105         extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
1106         depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1107
1108         /* Get rid of prot bits and convert to page addr for idtlbt */
1109
1110         depdi           0,63,12,pte
1111         extrd,u         pte,56,52,pte
1112         idtlbt          pte,prot
1113
1114         rfir
1115         nop
1116
1117 nadtlb_check_flush_20w:
1118         bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
1119
1120         /* Insert a "flush only" translation */
1121
1122         depdi,z         7,7,3,prot
1123         depdi           1,10,1,prot
1124
1125         /* Get rid of prot bits and convert to page addr for idtlbt */
1126
1127         depdi           0,63,12,pte
1128         extrd,u         pte,56,52,pte
1129         idtlbt          pte,prot
1130
1131         rfir
1132         nop
1133
1134 #else
1135
1136 dtlb_miss_11:
1137         mfctl           %cr25,ptp       /* Assume user space miss */
1138         or,<>           %r0,spc,%r0     /* If it is user space, nullify */
1139         mfctl           %cr24,ptp       /* Load kernel pgd instead */
1140         extru           va,9,10,t1      /* Get pgd index */
1141
1142         mfsp            %sr7,t0         /* Get current space */
1143         or,=            %r0,t0,%r0      /* If kernel, nullify following test */
1144         cmpb,<>,n       t0,spc,dtlb_fault /* forward */
1145
1146         /* First level page table lookup */
1147
1148         ldwx,s          t1(ptp),ptp
1149         extru           va,19,10,t0     /* get second-level index */
1150         bb,>=,n         ptp,_PAGE_PRESENT_BIT,dtlb_check_alias_11
1151         depi            0,31,12,ptp     /* clear prot bits */
1152
1153         /* Second level page table lookup */
1154
1155         sh2addl          t0,ptp,ptp
1156         ldi             _PAGE_ACCESSED,t1
1157         ldw              0(ptp),pte
1158         bb,>=,n          pte,_PAGE_PRESENT_BIT,dtlb_check_alias_11
1159
1160         /* Check whether the "accessed" bit was set, otherwise do so */
1161
1162         or              t1,pte,t0       /* t0 has R bit set */
1163         and,<>          t1,pte,%r0      /* test and nullify if already set */
1164         stw             t0,0(ptp)       /* write back pte */
1165
1166         zdep            spc,30,15,prot  /* create prot id from space */
1167         dep             pte,8,7,prot    /* add in prot bits from pte */
1168
1169         extru,=         pte,_PAGE_NO_CACHE_BIT,1,r0
1170         depi            1,12,1,prot
1171         extru,=         pte,_PAGE_USER_BIT,1,r0
1172         depi            7,11,3,prot   /* Set for user space (1 rsvd for read) */
1173         extru,=         pte,_PAGE_GATEWAY_BIT,1,r0
1174         depi            0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1175
1176         /* Get rid of prot bits and convert to page addr for idtlba */
1177
1178         depi            0,31,12,pte
1179         extru           pte,24,25,pte
1180
1181         mfsp            %sr1,t0  /* Save sr1 so we can use it in tlb inserts */
1182         mtsp            spc,%sr1
1183
1184         idtlba          pte,(%sr1,va)
1185         idtlbp          prot,(%sr1,va)
1186
1187         mtsp            t0, %sr1        /* Restore sr1 */
1188
1189         rfir
1190         nop
1191
1192 dtlb_check_alias_11:
1193
1194         /* Check to see if fault is in the temporary alias region */
1195
1196         cmpib,<>,n      0,spc,dtlb_fault /* forward */
1197         ldil            L%(TMPALIAS_MAP_START),t0
1198         copy            va,t1
1199         depwi           0,31,23,t1
1200         cmpb,<>,n       t0,t1,dtlb_fault /* forward */
1201         ldi             (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot
1202         depw,z          prot,8,7,prot
1203
1204         /*
1205          * OK, it is in the temp alias region, check whether "from" or "to".
1206          * Check "subtle" note in pacache.S re: r23/r26.
1207          */
1208
1209         extrw,u,=       va,9,1,r0
1210         or,tr           %r23,%r0,pte    /* If "from" use "from" page */
1211         or              %r26,%r0,pte    /* else "to", use "to" page  */
1212
1213         idtlba          pte,(va)
1214         idtlbp          prot,(va)
1215
1216         rfir
1217         nop
1218
1219 nadtlb_miss_11:
1220         mfctl           %cr25,ptp       /* Assume user space miss */
1221         or,<>           %r0,spc,%r0     /* If it is user space, nullify */
1222         mfctl           %cr24,ptp       /* Load kernel pgd instead */
1223         extru           va,9,10,t1      /* Get pgd index */
1224
1225         mfsp            %sr7,t0         /* Get current space */
1226         or,=            %r0,t0,%r0      /* If kernel, nullify following test */
1227         cmpb,<>,n       t0,spc,nadtlb_fault /* forward */
1228
1229         /* First level page table lookup */
1230
1231         ldwx,s          t1(ptp),ptp
1232         extru           va,19,10,t0     /* get second-level index */
1233         bb,>=,n         ptp,_PAGE_PRESENT_BIT,nadtlb_emulate
1234         depi            0,31,12,ptp     /* clear prot bits */
1235
1236         /* Second level page table lookup */
1237
1238         sh2addl          t0,ptp,ptp
1239         ldi             _PAGE_ACCESSED,t1
1240         ldw              0(ptp),pte
1241         bb,>=,n          pte,_PAGE_PRESENT_BIT,nadtlb_check_flush_11
1242
1243         zdep            spc,30,15,prot  /* create prot id from space */
1244         dep             pte,8,7,prot    /* add in prot bits from pte */
1245
1246         extru,=         pte,_PAGE_NO_CACHE_BIT,1,r0
1247         depi            1,12,1,prot
1248         extru,=         pte,_PAGE_USER_BIT,1,r0
1249         depi            7,11,3,prot   /* Set for user space (1 rsvd for read) */
1250         extru,=         pte,_PAGE_GATEWAY_BIT,1,r0
1251         depi            0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1252
1253         /* Get rid of prot bits and convert to page addr for idtlba */
1254
1255         depi            0,31,12,pte
1256         extru           pte,24,25,pte
1257
1258         mfsp            %sr1,t0  /* Save sr1 so we can use it in tlb inserts */
1259         mtsp            spc,%sr1
1260
1261         idtlba          pte,(%sr1,va)
1262         idtlbp          prot,(%sr1,va)
1263
1264         mtsp            t0, %sr1        /* Restore sr1 */
1265
1266         rfir
1267         nop
1268
1269 nadtlb_check_flush_11:
1270         bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
1271
1272         /* Insert a "flush only" translation */
1273
1274         zdepi           7,7,3,prot
1275         depi            1,10,1,prot
1276
1277         /* Get rid of prot bits and convert to page addr for idtlba */
1278
1279         depi            0,31,12,pte
1280         extru           pte,24,25,pte
1281
1282         mfsp            %sr1,t0  /* Save sr1 so we can use it in tlb inserts */
1283         mtsp            spc,%sr1
1284
1285         idtlba          pte,(%sr1,va)
1286         idtlbp          prot,(%sr1,va)
1287
1288         mtsp            t0, %sr1        /* Restore sr1 */
1289
1290         rfir
1291         nop
1292
1293 dtlb_miss_20:
1294         mfctl           %cr25,ptp       /* Assume user space miss */
1295         or,<>           %r0,spc,%r0     /* If it is user space, nullify */
1296         mfctl           %cr24,ptp       /* Load kernel pgd instead */
1297         extru           va,9,10,t1      /* Get pgd index */
1298
1299         mfsp            %sr7,t0         /* Get current space */
1300         or,=            %r0,t0,%r0      /* If kernel, nullify following test */
1301         cmpb,<>,n       t0,spc,dtlb_fault /* forward */
1302
1303         /* First level page table lookup */
1304
1305         ldwx,s          t1(ptp),ptp
1306         extru           va,19,10,t0     /* get second-level index */
1307         bb,>=,n         ptp,_PAGE_PRESENT_BIT,dtlb_check_alias_20
1308         depi            0,31,12,ptp     /* clear prot bits */
1309
1310         /* Second level page table lookup */
1311
1312         sh2addl          t0,ptp,ptp
1313         ldi             _PAGE_ACCESSED,t1
1314         ldw              0(ptp),pte
1315         bb,>=,n          pte,_PAGE_PRESENT_BIT,dtlb_check_alias_20
1316
1317         /* Check whether the "accessed" bit was set, otherwise do so */
1318
1319         or              t1,pte,t0       /* t0 has R bit set */
1320         and,<>          t1,pte,%r0      /* test and nullify if already set */
1321         stw             t0,0(ptp)       /* write back pte */
1322
1323         space_to_prot   spc prot        /* create prot id from space */
1324         depd            pte,8,7,prot    /* add in prot bits from pte */
1325
1326         extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
1327         depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
1328         extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
1329         depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1330
1331         /* Get rid of prot bits and convert to page addr for idtlbt */
1332
1333         extrd,s         pte,35,4,t0
1334         depdi           0,63,12,pte     /* clear lower 12 bits */
1335         addi,=          1,t0,0 
1336         extrd,u,*tr     pte,56,25,pte 
1337         extrd,s         pte,56,25,pte   /* bit 31:8 >> 8  */ 
1338         idtlbt          pte,prot
1339
1340         rfir
1341         nop
1342
1343 dtlb_check_alias_20:
1344
1345         /* Check to see if fault is in the temporary alias region */
1346
1347         cmpib,<>,n      0,spc,dtlb_fault /* forward */
1348         ldil            L%(TMPALIAS_MAP_START),t0
1349         copy            va,t1
1350         depwi           0,31,23,t1
1351         cmpb,<>,n       t0,t1,dtlb_fault /* forward */
1352         ldi             (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot
1353         depd,z          prot,8,7,prot
1354
1355         /*
1356          * OK, it is in the temp alias region, check whether "from" or "to".
1357          * Check "subtle" note in pacache.S re: r23/r26.
1358          */
1359
1360         extrw,u,=       va,9,1,r0
1361         or,tr           %r23,%r0,pte    /* If "from" use "from" page */
1362         or              %r26,%r0,pte    /* else "to", use "to" page  */
1363
1364         idtlbt          pte,prot
1365
1366         rfir
1367         nop
1368
1369 nadtlb_miss_20:
1370         mfctl           %cr25,ptp       /* Assume user space miss */
1371         or,<>           %r0,spc,%r0     /* If it is user space, nullify */
1372         mfctl           %cr24,ptp       /* Load kernel pgd instead */
1373         extru           va,9,10,t1      /* Get pgd index */
1374
1375         mfsp            %sr7,t0         /* Get current space */
1376         or,=            %r0,t0,%r0      /* If kernel, nullify following test */
1377         cmpb,<>,n       t0,spc,nadtlb_fault /* forward */
1378
1379         /* First level page table lookup */
1380
1381         ldwx,s          t1(ptp),ptp
1382         extru           va,19,10,t0     /* get second-level index */
1383         bb,>=,n         ptp,_PAGE_PRESENT_BIT,nadtlb_emulate
1384         depi            0,31,12,ptp     /* clear prot bits */
1385
1386         /* Second level page table lookup */
1387
1388         sh2addl          t0,ptp,ptp
1389         ldi             _PAGE_ACCESSED,t1
1390         ldw              0(ptp),pte
1391         bb,>=,n          pte,_PAGE_PRESENT_BIT,nadtlb_check_flush_20
1392
1393         space_to_prot   spc prot        /* create prot id from space */
1394         depd            pte,8,7,prot    /* add in prot bits from pte */
1395
1396         extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
1397         depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
1398         extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
1399         depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1400
1401         /* Get rid of prot bits and convert to page addr for idtlbt */
1402
1403         extrd,s         pte,35,4,t0
1404         depdi           0,63,12,pte     /* clear lower 12 bits */
1405         addi,=          1,t0,0
1406         extrd,u,*tr     pte,56,25,pte
1407         extrd,s         pte,56,25,pte   /* bit 31:8 >> 8  */
1408         idtlbt          pte,prot
1409
1410         rfir
1411         nop
1412
1413 nadtlb_check_flush_20:
1414         bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
1415
1416         /* Insert a "flush only" translation */
1417
1418         depdi,z         7,7,3,prot
1419         depdi           1,10,1,prot
1420
1421         /* Get rid of prot bits and convert to page addr for idtlbt */
1422
1423         depdi           0,63,12,pte
1424         extrd,u         pte,56,32,pte
1425         idtlbt          pte,prot
1426
1427         rfir
1428         nop
1429 #endif
1430
1431 nadtlb_emulate:
1432
1433         /*
1434          * Non access misses can be caused by fdc,fic,pdc,lpa,probe and
1435          * probei instructions. We don't want to fault for these
1436          * instructions (not only does it not make sense, it can cause
1437          * deadlocks, since some flushes are done with the mmap
1438          * semaphore held). If the translation doesn't exist, we can't
1439          * insert a translation, so have to emulate the side effects
1440          * of the instruction. Since we don't insert a translation
1441          * we can get a lot of faults during a flush loop, so it makes
1442          * sense to try to do it here with minimum overhead. We only
1443          * emulate fdc,fic & pdc instructions whose base and index
1444          * registers are not shadowed. We defer everything else to the
1445          * "slow" path.
1446          */
1447
1448         mfctl           %cr19,%r9 /* Get iir */
1449         ldi             0x280,%r16
1450         and             %r9,%r16,%r17
1451         cmpb,<>,n       %r16,%r17,nadtlb_fault /* Not fdc,fic,pdc */
1452         bb,>=,n         %r9,26,nadtlb_nullify  /* m bit not set, just nullify */
1453         b,l             get_register,%r25
1454         extrw,u         %r9,15,5,%r8           /* Get index register # */
1455         CMPIB=,n        -1,%r1,nadtlb_fault    /* have to use slow path */
1456         copy            %r1,%r24
1457         b,l             get_register,%r25
1458         extrw,u         %r9,10,5,%r8           /* Get base register # */
1459         CMPIB=,n        -1,%r1,nadtlb_fault    /* have to use slow path */
1460         b,l             set_register,%r25
1461         add,l           %r1,%r24,%r1           /* doesn't affect c/b bits */
1462
1463 nadtlb_nullify:
1464         mfctl           %cr22,%r8              /* Get ipsw */
1465         ldil            L%PSW_N,%r9
1466         or              %r8,%r9,%r8            /* Set PSW_N */
1467         mtctl           %r8,%cr22
1468
1469         rfir
1470         nop
1471
1472 #ifdef __LP64__
1473 itlb_miss_20w:
1474
1475         /*
1476          * I miss is a little different, since we allow users to fault
1477          * on the gateway page which is in the kernel address space.
1478          */
1479
1480         extrd,u         spc,63,7,t1     /* adjust va */
1481         depd            t1,31,7,va      /* adjust va */
1482         depdi           0,63,7,spc      /* adjust space */
1483         cmpib,*=        0,spc,itlb_miss_kernel_20w
1484         extrd,u         va,33,9,t1      /* Get pgd index */
1485
1486         mfctl           %cr25,ptp       /* load user pgd */
1487
1488         mfsp            %sr7,t0         /* Get current space */
1489         or,*=           %r0,t0,%r0      /* If kernel, nullify following test */
1490         cmpb,*<>,n      t0,spc,itlb_fault /* forward */
1491
1492         /* First level page table lookup */
1493
1494 itlb_miss_common_20w:
1495         ldd,s           t1(ptp),ptp
1496         extrd,u         va,42,9,t0     /* get second-level index */
1497         bb,>=,n         ptp,_PAGE_PRESENT_BIT,itlb_fault
1498         depdi           0,63,12,ptp     /* clear prot bits */
1499
1500         /* Second level page table lookup */
1501
1502         ldd,s           t0(ptp),ptp
1503         extrd,u         va,51,9,t0     /* get third-level index */
1504         bb,>=,n         ptp,_PAGE_PRESENT_BIT,itlb_fault
1505         depdi           0,63,12,ptp     /* clear prot bits */
1506
1507         /* Third level page table lookup */
1508
1509         shladd           t0,3,ptp,ptp
1510         ldi             _PAGE_ACCESSED,t1
1511         ldd              0(ptp),pte
1512         bb,>=,n          pte,_PAGE_PRESENT_BIT,itlb_fault
1513
1514         /* Check whether the "accessed" bit was set, otherwise do so */
1515
1516         or              t1,pte,t0       /* t0 has R bit set */
1517         and,*<>         t1,pte,%r0      /* test and nullify if already set */
1518         std             t0,0(ptp)       /* write back pte */
1519
1520         space_to_prot   spc prot        /* create prot id from space */
1521         depd            pte,8,7,prot    /* add in prot bits from pte */
1522
1523         extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
1524         depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
1525         extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
1526         depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1527
1528         /* Get rid of prot bits and convert to page addr for iitlbt */
1529
1530         depdi           0,63,12,pte
1531         extrd,u         pte,56,32,pte
1532         iitlbt          pte,prot
1533
1534         rfir
1535         nop
1536
1537 itlb_miss_kernel_20w:
1538         b               itlb_miss_common_20w
1539         mfctl           %cr24,ptp       /* Load kernel pgd */
1540 #else
1541
1542 itlb_miss_11:
1543
1544         /*
1545          * I miss is a little different, since we allow users to fault
1546          * on the gateway page which is in the kernel address space.
1547          */
1548
1549         cmpib,=         0,spc,itlb_miss_kernel_11
1550         extru           va,9,10,t1      /* Get pgd index */
1551
1552         mfctl           %cr25,ptp       /* load user pgd */
1553
1554         mfsp            %sr7,t0         /* Get current space */
1555         or,=            %r0,t0,%r0      /* If kernel, nullify following test */
1556         cmpb,<>,n       t0,spc,itlb_fault /* forward */
1557
1558         /* First level page table lookup */
1559
1560 itlb_miss_common_11:
1561         ldwx,s          t1(ptp),ptp
1562         extru           va,19,10,t0     /* get second-level index */
1563         bb,>=,n         ptp,_PAGE_PRESENT_BIT,itlb_fault
1564         depi            0,31,12,ptp     /* clear prot bits */
1565
1566         /* Second level page table lookup */
1567
1568         sh2addl          t0,ptp,ptp
1569         ldi             _PAGE_ACCESSED,t1
1570         ldw              0(ptp),pte
1571         bb,>=,n          pte,_PAGE_PRESENT_BIT,itlb_fault
1572
1573         /* Check whether the "accessed" bit was set, otherwise do so */
1574
1575         or              t1,pte,t0       /* t0 has R bit set */
1576         and,<>          t1,pte,%r0      /* test and nullify if already set */
1577         stw             t0,0(ptp)       /* write back pte */
1578
1579         zdep            spc,30,15,prot  /* create prot id from space */
1580         dep             pte,8,7,prot    /* add in prot bits from pte */
1581
1582         extru,=         pte,_PAGE_NO_CACHE_BIT,1,r0
1583         depi            1,12,1,prot
1584         extru,=         pte,_PAGE_USER_BIT,1,r0
1585         depi            7,11,3,prot   /* Set for user space (1 rsvd for read) */
1586         extru,=         pte,_PAGE_GATEWAY_BIT,1,r0
1587         depi            0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1588
1589         /* Get rid of prot bits and convert to page addr for iitlba */
1590
1591         depi            0,31,12,pte
1592         extru           pte,24,25,pte
1593
1594         mfsp            %sr1,t0  /* Save sr1 so we can use it in tlb inserts */
1595         mtsp            spc,%sr1
1596
1597         iitlba          pte,(%sr1,va)
1598         iitlbp          prot,(%sr1,va)
1599
1600         mtsp            t0, %sr1        /* Restore sr1 */
1601
1602         rfir
1603         nop
1604
1605 itlb_miss_kernel_11:
1606         b               itlb_miss_common_11
1607         mfctl           %cr24,ptp       /* Load kernel pgd */
1608
1609 itlb_miss_20:
1610
1611         /*
1612          * I miss is a little different, since we allow users to fault
1613          * on the gateway page which is in the kernel address space.
1614          */
1615
1616         cmpib,=         0,spc,itlb_miss_kernel_20
1617         extru           va,9,10,t1      /* Get pgd index */
1618
1619         mfctl           %cr25,ptp       /* load user pgd */
1620
1621         mfsp            %sr7,t0         /* Get current space */
1622         or,=            %r0,t0,%r0      /* If kernel, nullify following test */
1623         cmpb,<>,n       t0,spc,itlb_fault /* forward */
1624
1625         /* First level page table lookup */
1626
1627 itlb_miss_common_20:
1628         ldwx,s          t1(ptp),ptp
1629         extru           va,19,10,t0     /* get second-level index */
1630         bb,>=,n         ptp,_PAGE_PRESENT_BIT,itlb_fault
1631         depi            0,31,12,ptp     /* clear prot bits */
1632
1633         /* Second level page table lookup */
1634
1635         sh2addl          t0,ptp,ptp
1636         ldi             _PAGE_ACCESSED,t1
1637         ldw              0(ptp),pte
1638         bb,>=,n          pte,_PAGE_PRESENT_BIT,itlb_fault
1639
1640         /* Check whether the "accessed" bit was set, otherwise do so */
1641
1642         or              t1,pte,t0       /* t0 has R bit set */
1643         and,<>          t1,pte,%r0      /* test and nullify if already set */
1644         stw             t0,0(ptp)       /* write back pte */
1645
1646         space_to_prot   spc prot        /* create prot id from space */
1647         depd            pte,8,7,prot    /* add in prot bits from pte */
1648
1649         extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
1650         depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
1651         extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
1652         depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1653
1654         /* Get rid of prot bits and convert to page addr for iitlbt */
1655
1656         extrd,s         pte,35,4,t0 
1657         depdi           0,63,12,pte     /* clear lower 12 bits */
1658         addi,=          1,t0,0
1659         extrd,u,*tr     pte,56,25,pte 
1660         extrd,s         pte,56,25,pte   /* bit 31:8 >> 8  */
1661         iitlbt          pte,prot
1662
1663         rfir
1664         nop
1665
1666
1667 itlb_miss_kernel_20:
1668         b               itlb_miss_common_20
1669         mfctl           %cr24,ptp       /* Load kernel pgd */
1670 #endif
1671
1672 #ifdef __LP64__
1673
1674 dbit_trap_20w:
1675         extrd,u         spc,63,7,t1     /* adjust va */
1676         depd            t1,31,7,va      /* adjust va */
1677         depdi           0,1,2,va        /* adjust va */
1678         depdi           0,63,7,spc      /* adjust space */
1679         mfctl           %cr25,ptp       /* Assume user space miss */
1680         or,*<>          %r0,spc,%r0     /* If it is user space, nullify */
1681         mfctl           %cr24,ptp       /* Load kernel pgd instead */
1682         extrd,u         va,33,9,t1      /* Get pgd index */
1683
1684         mfsp            %sr7,t0         /* Get current space */
1685         or,*=           %r0,t0,%r0      /* If kernel, nullify following test */
1686         cmpb,*<>,n       t0,spc,dbit_fault /* forward */
1687
1688         /* First level page table lookup */
1689
1690         ldd,s           t1(ptp),ptp
1691         extrd,u         va,42,9,t0     /* get second-level index */
1692         bb,>=,n         ptp,_PAGE_PRESENT_BIT,dbit_fault
1693         depdi           0,63,12,ptp     /* clear prot bits */
1694
1695         /* Second level page table lookup */
1696
1697         ldd,s           t0(ptp),ptp
1698         extrd,u         va,51,9,t0     /* get third-level index */
1699         bb,>=,n         ptp,_PAGE_PRESENT_BIT,dbit_fault
1700         depdi           0,63,12,ptp     /* clear prot bits */
1701
1702         /* Third level page table lookup */
1703
1704         shladd           t0,3,ptp,ptp
1705 #ifdef CONFIG_SMP
1706         CMPIB=,n        0,spc,dbit_nolock_20w
1707         ldil            L%PA(pa_dbit_lock),t0
1708         ldo             R%PA(pa_dbit_lock)(t0),t0
1709
1710 dbit_spin_20w:
1711         ldcw            0(t0),t1
1712         cmpib,=         0,t1,dbit_spin_20w
1713         nop
1714
1715 dbit_nolock_20w:
1716 #endif
1717         ldi             (_PAGE_ACCESSED|_PAGE_DIRTY),t1
1718         ldd              0(ptp),pte
1719         bb,>=,n          pte,_PAGE_PRESENT_BIT,dbit_fault
1720
1721         /* Set Accessed and Dirty bits in the pte */
1722
1723         or              t1,pte,pte
1724         std             pte,0(ptp)      /* write back pte */
1725
1726         space_to_prot   spc prot        /* create prot id from space */
1727         depd            pte,8,7,prot    /* add in prot bits from pte */
1728
1729         extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
1730         depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
1731         extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
1732         depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1733
1734         /* Get rid of prot bits and convert to page addr for idtlbt */
1735
1736         depdi           0,63,12,pte
1737         extrd,u         pte,56,52,pte
1738         idtlbt          pte,prot
1739 #ifdef CONFIG_SMP
1740         CMPIB=,n        0,spc,dbit_nounlock_20w
1741         ldi             1,t1
1742         stw             t1,0(t0)
1743
1744 dbit_nounlock_20w:
1745 #endif
1746
1747         rfir
1748         nop
1749 #else
1750
1751 dbit_trap_11:
1752         mfctl           %cr25,ptp       /* Assume user space trap */
1753         or,<>           %r0,spc,%r0     /* If it is user space, nullify */
1754         mfctl           %cr24,ptp       /* Load kernel pgd instead */
1755         extru           va,9,10,t1      /* Get pgd index */
1756
1757         mfsp            %sr7,t0         /* Get current space */
1758         or,=            %r0,t0,%r0      /* If kernel, nullify following test */
1759         cmpb,<>,n       t0,spc,dbit_fault /* forward */
1760
1761         /* First level page table lookup */
1762
1763         ldwx,s          t1(ptp),ptp
1764         extru           va,19,10,t0     /* get second-level index */
1765         bb,>=,n         ptp,_PAGE_PRESENT_BIT,dbit_fault
1766         depi            0,31,12,ptp     /* clear prot bits */
1767
1768         /* Second level page table lookup */
1769
1770         sh2addl          t0,ptp,ptp
1771 #ifdef CONFIG_SMP
1772         CMPIB=,n        0,spc,dbit_nolock_11
1773         ldil            L%PA(pa_dbit_lock),t0
1774         ldo             R%PA(pa_dbit_lock)(t0),t0
1775
1776 dbit_spin_11:
1777         ldcw            0(t0),t1
1778         cmpib,=         0,t1,dbit_spin_11
1779         nop
1780
1781 dbit_nolock_11:
1782 #endif
1783         ldi             (_PAGE_ACCESSED|_PAGE_DIRTY),t1
1784         ldw              0(ptp),pte
1785         bb,>=,n          pte,_PAGE_PRESENT_BIT,dbit_fault
1786
1787         /* Set Accessed and Dirty bits in the pte */
1788
1789         or              t1,pte,pte
1790         stw             pte,0(ptp)      /* write back pte */
1791
1792         zdep            spc,30,15,prot  /* create prot id from space */
1793         dep             pte,8,7,prot    /* add in prot bits from pte */
1794
1795         extru,=         pte,_PAGE_NO_CACHE_BIT,1,r0
1796         depi            1,12,1,prot
1797         extru,=         pte,_PAGE_USER_BIT,1,r0
1798         depi            7,11,3,prot /* Set for user space (1 rsvd for read) */
1799         extru,=         pte,_PAGE_GATEWAY_BIT,1,r0
1800         depi            0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1801
1802         /* Get rid of prot bits and convert to page addr for idtlba */
1803
1804         depi            0,31,12,pte
1805         extru           pte,24,25,pte
1806
1807         mfsp            %sr1,t1  /* Save sr1 so we can use it in tlb inserts */
1808         mtsp            spc,%sr1
1809
1810         idtlba          pte,(%sr1,va)
1811         idtlbp          prot,(%sr1,va)
1812
1813         mtsp            t1, %sr1     /* Restore sr1 */
1814 #ifdef CONFIG_SMP
1815         CMPIB=,n        0,spc,dbit_nounlock_11
1816         ldi             1,t1
1817         stw             t1,0(t0)
1818
1819 dbit_nounlock_11:
1820 #endif
1821
1822         rfir
1823         nop
1824
1825 dbit_trap_20:
1826         mfctl           %cr25,ptp       /* Assume user space trap */
1827         or,<>           %r0,spc,%r0     /* If it is user space, nullify */
1828         mfctl           %cr24,ptp       /* Load kernel pgd instead */
1829         extru           va,9,10,t1      /* Get pgd index */
1830
1831         mfsp            %sr7,t0         /* Get current space */
1832         or,=            %r0,t0,%r0      /* If kernel, nullify following test */
1833         cmpb,<>,n       t0,spc,dbit_fault /* forward */
1834
1835         /* First level page table lookup */
1836
1837         ldwx,s          t1(ptp),ptp
1838         extru           va,19,10,t0     /* get second-level index */
1839         bb,>=,n         ptp,_PAGE_PRESENT_BIT,dbit_fault
1840         depi            0,31,12,ptp     /* clear prot bits */
1841
1842         /* Second level page table lookup */
1843
1844         sh2addl          t0,ptp,ptp
1845 #ifdef CONFIG_SMP
1846         CMPIB=,n        0,spc,dbit_nolock_20
1847         ldil            L%PA(pa_dbit_lock),t0
1848         ldo             R%PA(pa_dbit_lock)(t0),t0
1849
1850 dbit_spin_20:
1851         ldcw            0(t0),t1
1852         cmpib,=         0,t1,dbit_spin_20
1853         nop
1854
1855 dbit_nolock_20:
1856 #endif
1857         ldi             (_PAGE_ACCESSED|_PAGE_DIRTY),t1
1858         ldw              0(ptp),pte
1859         bb,>=,n          pte,_PAGE_PRESENT_BIT,dbit_fault
1860
1861         /* Set Accessed and Dirty bits in the pte */
1862
1863         or              t1,pte,pte
1864         stw             pte,0(ptp)      /* write back pte */
1865
1866         space_to_prot   spc prot        /* create prot id from space */
1867         depd            pte,8,7,prot    /* add in prot bits from pte */
1868
1869         extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
1870         depdi           7,11,3,prot   /* Set for user space (1 rsvd for read) */
1871         extrd,u,*=      pte,_PAGE_GATEWAY_BIT+32,1,r0
1872         depdi           0,11,2,prot     /* If Gateway, Set PL2 to 0 */
1873
1874         extrd,s         pte,35,4,t0 
1875         depdi           0,63,12,pte     /* clear lower 12 bits */
1876         addi,=          1,t0,0
1877         extrd,u,*tr     pte,56,25,pte 
1878         extrd,s         pte,56,25,pte   /* bit 31:8 >> 8  */
1879         idtlbt          pte,prot
1880
1881 #ifdef CONFIG_SMP
1882         CMPIB=,n        0,spc,dbit_nounlock_20
1883         ldi             1,t1
1884         stw             t1,0(t0)
1885
1886 dbit_nounlock_20:
1887 #endif
1888
1889         rfir
1890         nop
1891 #endif
1892
1893         .import handle_interruption,code
1894
1895 kernel_bad_space:
1896         b               intr_save
1897         ldi             31,%r8  /* Use an unused code */
1898
1899 dbit_fault:
1900         b               intr_save
1901         ldi             20,%r8
1902
1903 itlb_fault:
1904         b               intr_save
1905         ldi             6,%r8
1906
1907 nadtlb_fault:
1908         b               intr_save
1909         ldi             17,%r8
1910
1911 dtlb_fault:
1912         b               intr_save
1913         ldi             15,%r8
1914
1915         /* Register saving semantics for system calls:
1916
1917            %r1             clobbered by system call macro in userspace
1918            %r2             saved in PT_REGS by gateway page
1919            %r3  - %r18     preserved by C code (saved by signal code)
1920            %r19 - %r20     saved in PT_REGS by gateway page
1921            %r21 - %r22     non-standard syscall args
1922                            stored in kernel stack by gateway page
1923            %r23 - %r26     arg3-arg0, saved in PT_REGS by gateway page
1924            %r27 - %r30     saved in PT_REGS by gateway page
1925            %r31            syscall return pointer
1926          */
1927
1928         /* Floating point registers (FIXME: what do we do with these?)
1929
1930            %fr0  - %fr3    status/exception, not preserved
1931            %fr4  - %fr7    arguments
1932            %fr8  - %fr11   not preserved by C code
1933            %fr12 - %fr21   preserved by C code
1934            %fr22 - %fr31   not preserved by C code
1935          */
1936
1937         .macro  reg_save regs
1938         STREG   %r3, PT_GR3(\regs)
1939         STREG   %r4, PT_GR4(\regs)
1940         STREG   %r5, PT_GR5(\regs)
1941         STREG   %r6, PT_GR6(\regs)
1942         STREG   %r7, PT_GR7(\regs)
1943         STREG   %r8, PT_GR8(\regs)
1944         STREG   %r9, PT_GR9(\regs)
1945         STREG   %r10,PT_GR10(\regs)
1946         STREG   %r11,PT_GR11(\regs)
1947         STREG   %r12,PT_GR12(\regs)
1948         STREG   %r13,PT_GR13(\regs)
1949         STREG   %r14,PT_GR14(\regs)
1950         STREG   %r15,PT_GR15(\regs)
1951         STREG   %r16,PT_GR16(\regs)
1952         STREG   %r17,PT_GR17(\regs)
1953         STREG   %r18,PT_GR18(\regs)
1954         .endm
1955
1956         .macro  reg_restore regs
1957         LDREG   PT_GR3(\regs), %r3
1958         LDREG   PT_GR4(\regs), %r4
1959         LDREG   PT_GR5(\regs), %r5
1960         LDREG   PT_GR6(\regs), %r6
1961         LDREG   PT_GR7(\regs), %r7
1962         LDREG   PT_GR8(\regs), %r8
1963         LDREG   PT_GR9(\regs), %r9
1964         LDREG   PT_GR10(\regs),%r10
1965         LDREG   PT_GR11(\regs),%r11
1966         LDREG   PT_GR12(\regs),%r12
1967         LDREG   PT_GR13(\regs),%r13
1968         LDREG   PT_GR14(\regs),%r14
1969         LDREG   PT_GR15(\regs),%r15
1970         LDREG   PT_GR16(\regs),%r16
1971         LDREG   PT_GR17(\regs),%r17
1972         LDREG   PT_GR18(\regs),%r18
1973         .endm
1974
1975         .export sys_fork_wrapper
1976         .export child_return
1977 sys_fork_wrapper:
1978         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
1979         ldo     TASK_REGS(%r1),%r1
1980         reg_save %r1
1981         mfctl   %cr27, %r3
1982         STREG   %r3, PT_CR27(%r1)
1983
1984         STREG   %r2,-RP_OFFSET(%r30)
1985         ldo     FRAME_SIZE(%r30),%r30
1986 #ifdef __LP64__
1987         ldo     -16(%r30),%r29          /* Reference param save area */
1988 #endif
1989
1990         /* These are call-clobbered registers and therefore
1991            also syscall-clobbered (we hope). */
1992         STREG   %r2,PT_GR19(%r1)        /* save for child */
1993         STREG   %r30,PT_GR21(%r1)
1994
1995         LDREG   PT_GR30(%r1),%r25
1996         copy    %r1,%r24
1997         bl      sys_clone,%r2
1998         ldi     SIGCHLD,%r26
1999
2000         LDREG   -RP_OFFSET-FRAME_SIZE(%r30),%r2
2001 wrapper_exit:
2002         ldo     -FRAME_SIZE(%r30),%r30          /* get the stackframe */
2003         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2004         ldo     TASK_REGS(%r1),%r1       /* get pt regs */
2005
2006         LDREG   PT_CR27(%r1), %r3
2007         mtctl   %r3, %cr27
2008         reg_restore %r1
2009
2010         /* strace expects syscall # to be preserved in r20 */
2011         ldi     __NR_fork,%r20
2012         bv %r0(%r2)
2013         STREG   %r20,PT_GR20(%r1)
2014
2015         /* Set the return value for the child */
2016 child_return:
2017 #if CONFIG_SMP || CONFIG_PREEMPT
2018         bl      schedule_tail, %r2
2019         nop
2020 #endif
2021
2022         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30), %r1
2023         LDREG   TASK_PT_GR19(%r1),%r2
2024         b       wrapper_exit
2025         copy    %r0,%r28
2026
2027         
2028         .export sys_clone_wrapper
2029 sys_clone_wrapper:
2030         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2031         ldo     TASK_REGS(%r1),%r1      /* get pt regs */
2032         reg_save %r1
2033         mfctl   %cr27, %r3
2034         STREG   %r3, PT_CR27(%r1)
2035
2036         STREG   %r2,-RP_OFFSET(%r30)
2037         ldo     FRAME_SIZE(%r30),%r30
2038 #ifdef __LP64__
2039         ldo     -16(%r30),%r29          /* Reference param save area */
2040 #endif
2041
2042         STREG   %r2,PT_GR19(%r1)        /* save for child */
2043         STREG   %r30,PT_GR21(%r1)
2044         bl      sys_clone,%r2
2045         copy    %r1,%r24
2046
2047         b       wrapper_exit
2048         LDREG   -RP_OFFSET-FRAME_SIZE(%r30),%r2
2049
2050         .export sys_vfork_wrapper
2051 sys_vfork_wrapper:
2052         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2053         ldo     TASK_REGS(%r1),%r1      /* get pt regs */
2054         reg_save %r1
2055         mfctl   %cr27, %r3
2056         STREG   %r3, PT_CR27(%r1)
2057
2058         STREG   %r2,-RP_OFFSET(%r30)
2059         ldo     FRAME_SIZE(%r30),%r30
2060 #ifdef __LP64__
2061         ldo     -16(%r30),%r29          /* Reference param save area */
2062 #endif
2063
2064         STREG   %r2,PT_GR19(%r1)        /* save for child */
2065         STREG   %r30,PT_GR21(%r1)
2066
2067         bl      sys_vfork,%r2
2068         copy    %r1,%r26
2069
2070         b       wrapper_exit
2071         LDREG   -RP_OFFSET-FRAME_SIZE(%r30),%r2
2072
2073         
2074         .macro  execve_wrapper execve
2075         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2076         ldo     TASK_REGS(%r1),%r1      /* get pt regs */
2077
2078         /*
2079          * Do we need to save/restore r3-r18 here?
2080          * I don't think so. why would new thread need old
2081          * threads registers?
2082          */
2083
2084         /* %arg0 - %arg3 are already saved for us. */
2085
2086         STREG %r2,-RP_OFFSET(%r30)
2087         ldo FRAME_SIZE(%r30),%r30
2088 #ifdef __LP64__
2089         ldo     -16(%r30),%r29          /* Reference param save area */
2090 #endif
2091         bl \execve,%r2
2092         copy %r1,%arg0
2093
2094         ldo -FRAME_SIZE(%r30),%r30
2095         LDREG -RP_OFFSET(%r30),%r2
2096
2097         /* If exec succeeded we need to load the args */
2098
2099         ldo -1024(%r0),%r1
2100         cmpb,>>= %r28,%r1,error_\execve
2101         copy %r2,%r19
2102
2103 error_\execve:
2104         bv %r0(%r19)
2105         nop
2106         .endm
2107
2108         .export sys_execve_wrapper
2109         .import sys_execve
2110
2111 sys_execve_wrapper:
2112         execve_wrapper sys_execve
2113
2114 #ifdef __LP64__
2115         .export sys32_execve_wrapper
2116         .import sys32_execve
2117
2118 sys32_execve_wrapper:
2119         execve_wrapper sys32_execve
2120 #endif
2121
2122         .export sys_rt_sigreturn_wrapper
2123 sys_rt_sigreturn_wrapper:
2124         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26
2125         ldo     TASK_REGS(%r26),%r26    /* get pt regs */
2126         /* Don't save regs, we are going to restore them from sigcontext. */
2127         STREG   %r2, -RP_OFFSET(%r30)
2128 #ifdef __LP64__
2129         ldo     FRAME_SIZE(%r30), %r30
2130         bl      sys_rt_sigreturn,%r2
2131         ldo     -16(%r30),%r29          /* Reference param save area */
2132 #else
2133         bl      sys_rt_sigreturn,%r2
2134         ldo     FRAME_SIZE(%r30), %r30
2135 #endif
2136
2137         ldo     -FRAME_SIZE(%r30), %r30
2138         LDREG   -RP_OFFSET(%r30), %r2
2139
2140         /* FIXME: I think we need to restore a few more things here. */
2141         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2142         ldo     TASK_REGS(%r1),%r1      /* get pt regs */
2143         reg_restore %r1
2144
2145         /* If the signal was received while the process was blocked on a
2146          * syscall, then r2 will take us to syscall_exit; otherwise r2 will
2147          * take us to syscall_exit_rfi and on to intr_return.
2148          */
2149         bv      %r0(%r2)
2150         LDREG   PT_GR28(%r1),%r28  /* reload original r28 for syscall_exit */
2151
2152         .export sys_sigaltstack_wrapper
2153 sys_sigaltstack_wrapper:
2154         /* Get the user stack pointer */
2155         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2156         ldo     TASK_REGS(%r1),%r24     /* get pt regs */
2157         LDREG   TASK_PT_GR30(%r24),%r24
2158         STREG   %r2, -RP_OFFSET(%r30)
2159 #ifdef __LP64__
2160         ldo     FRAME_SIZE(%r30), %r30
2161         bl      do_sigaltstack,%r2
2162         ldo     -16(%r30),%r29          /* Reference param save area */
2163 #else
2164         bl      do_sigaltstack,%r2
2165         ldo     FRAME_SIZE(%r30), %r30
2166 #endif
2167
2168         ldo     -FRAME_SIZE(%r30), %r30
2169         LDREG   -RP_OFFSET(%r30), %r2
2170         bv      %r0(%r2)
2171         nop
2172
2173 #ifdef __LP64__
2174         .export sys32_sigaltstack_wrapper
2175 sys32_sigaltstack_wrapper:
2176         /* Get the user stack pointer */
2177         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r24
2178         LDREG   TASK_PT_GR30(%r24),%r24
2179         STREG   %r2, -RP_OFFSET(%r30)
2180         ldo     FRAME_SIZE(%r30), %r30
2181         bl      do_sigaltstack32,%r2
2182         ldo     -16(%r30),%r29          /* Reference param save area */
2183
2184         ldo     -FRAME_SIZE(%r30), %r30
2185         LDREG   -RP_OFFSET(%r30), %r2
2186         bv      %r0(%r2)
2187         nop
2188 #endif
2189
2190         .export sys_rt_sigsuspend_wrapper
2191 sys_rt_sigsuspend_wrapper:
2192         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
2193         ldo     TASK_REGS(%r1),%r24
2194         reg_save %r24
2195
2196         STREG   %r2, -RP_OFFSET(%r30)
2197 #ifdef __LP64__
2198         ldo     FRAME_SIZE(%r30), %r30
2199         bl      sys_rt_sigsuspend,%r2
2200         ldo     -16(%r30),%r29          /* Reference param save area */
2201 #else
2202         bl      sys_rt_sigsuspend,%r2
2203         ldo     FRAME_SIZE(%r30), %r30
2204 #endif
2205
2206         ldo     -FRAME_SIZE(%r30), %r30
2207         LDREG   -RP_OFFSET(%r30), %r2
2208
2209         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
2210         ldo     TASK_REGS(%r1),%r1
2211         reg_restore %r1
2212
2213         bv      %r0(%r2)
2214         nop
2215
2216         .export syscall_exit
2217 syscall_exit:
2218         /* NOTE: HP-UX syscalls also come through here
2219            after hpux_syscall_exit fixes up return
2220            values. */
2221         /* NOTE: Not all syscalls exit this way.  rt_sigreturn will exit
2222          * via syscall_exit_rfi if the signal was received while the process
2223          * was running.
2224          */
2225
2226         /* save return value now */
2227
2228         mfctl     %cr30, %r1
2229         LDREG     TI_TASK(%r1),%r1
2230         STREG     %r28,TASK_PT_GR28(%r1)
2231
2232         /* Save other hpux returns if personality is PER_HPUX */
2233
2234 /* <linux/personality.h> cannot be easily included */
2235 #define PER_HPUX 0x10
2236         LDREG     TASK_PERSONALITY(%r1),%r19
2237 #warning the ldo+CMPIB could probably be done better but 0x10 i soutside of range of CMPIB
2238         ldo       -PER_HPUX(%r19), %r19
2239         CMPIB<>,n 0,%r19,1f
2240         STREG     %r22,TASK_PT_GR22(%r1)
2241         STREG     %r29,TASK_PT_GR29(%r1)
2242 1:
2243
2244         /* Seems to me that dp could be wrong here, if the syscall involved
2245          * calling a module, and nothing got round to restoring dp on return.
2246          */
2247         loadgp
2248
2249 syscall_check_bh:
2250
2251         /* Check for software interrupts */
2252
2253         .import irq_stat,data
2254
2255         ldil    L%irq_stat,%r19
2256         ldo     R%irq_stat(%r19),%r19
2257
2258 #ifdef CONFIG_SMP
2259         /* sched.h: int processor */
2260         /* %r26 is used as scratch register to index into irq_stat[] */
2261         ldw     TI_CPU-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26 /* cpu # */
2262
2263         /* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) bits */
2264 #ifdef __LP64__
2265         shld    %r26, 6, %r20
2266 #else
2267         shlw    %r26, 5, %r20
2268 #endif
2269         add     %r19,%r20,%r19  /* now have &irq_stat[smp_processor_id()] */
2270 #endif /* CONFIG_SMP */
2271
2272         LDREG   IRQSTAT_SIRQ_PEND(%r19),%r20    /* hardirq.h: unsigned long */
2273         cmpib,<>,n 0,%r20,syscall_do_softirq /* forward */
2274
2275 syscall_check_resched:
2276
2277         /* check for reschedule */
2278
2279         LDREG   TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19   /* long */
2280         bb,<,n  %r19, 31-TIF_NEED_RESCHED, syscall_do_resched /* forward */
2281
2282 syscall_check_sig:
2283         LDREG   TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19    /* get ti flags */
2284         bb,<,n  %r19, 31-TIF_SIGPENDING, syscall_do_signal /* forward */
2285
2286 syscall_restore:
2287         LDREG   TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19    /* get ti flags */
2288         bb,<    %r19, 31-TIF_SYSCALL_TRACE,syscall_restore_rfi
2289         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1     /* delay slot! */
2290         ldo     TASK_PT_FR31(%r1),%r19             /* reload fpregs */
2291         rest_fp %r19
2292
2293         LDREG   TASK_PT_SAR(%r1),%r19              /* restore SAR */
2294         mtsar   %r19
2295
2296         LDREG   TASK_PT_GR2(%r1),%r2               /* restore user rp */
2297         LDREG   TASK_PT_GR19(%r1),%r19
2298         LDREG   TASK_PT_GR20(%r1),%r20
2299         LDREG   TASK_PT_GR21(%r1),%r21
2300         LDREG   TASK_PT_GR22(%r1),%r22
2301         LDREG   TASK_PT_GR23(%r1),%r23
2302         LDREG   TASK_PT_GR24(%r1),%r24
2303         LDREG   TASK_PT_GR25(%r1),%r25
2304         LDREG   TASK_PT_GR26(%r1),%r26
2305         LDREG   TASK_PT_GR27(%r1),%r27     /* restore user dp */
2306         LDREG   TASK_PT_GR28(%r1),%r28     /* syscall return value */
2307         LDREG   TASK_PT_GR29(%r1),%r29
2308         LDREG   TASK_PT_GR31(%r1),%r31     /* restore syscall rp */
2309
2310         rsm     PSW_SM_I, %r0
2311         LDREG   TASK_PT_GR30(%r1),%r30             /* restore user sp */
2312         mfsp    %sr3,%r1                           /* Get users space id */
2313         mtsp    %r1,%sr7                           /* Restore sr7 */
2314         ssm     PSW_SM_I, %r0
2315         mtsp    %r1,%sr4                           /* Restore sr4 */
2316         mtsp    %r1,%sr5                           /* Restore sr5 */
2317         mtsp    %r1,%sr6                           /* Restore sr6 */
2318
2319         depi    3,31,2,%r31                        /* ensure return to user mode. */
2320
2321 #ifdef __LP64__
2322         /* Since we are returning to a 32 bit user process, we always
2323          * clear the W bit. This means that the be (and mtsp) gets
2324          * executed in narrow mode, but that is OK, since we are
2325          * returning to a 32 bit process. When we support 64 bit processes
2326          * we won't clear the W bit, so the be will run in wide mode.
2327          */
2328
2329         be      0(%sr3,%r31)                       /* return to user space */
2330         rsm     PSW_SM_W, %r0
2331 #else
2332         be,n    0(%sr3,%r31)                       /* return to user space */
2333 #endif
2334
2335         /* We have to return via an RFI, so that PSW T and R bits can be set
2336          * appropriately.
2337          * This sets up pt_regs so we can return via intr_restore, which is not
2338          * the most efficient way of doing things, but it works.
2339          */
2340 syscall_restore_rfi:
2341         LDREG   TASK_PTRACE(%r1), %r19
2342         ldo     -1(%r0),%r2                        /* Set recovery cntr to -1 */
2343         mtctl   %r2,%cr0                           /*   for immediate trap */
2344         LDREG   TASK_PT_PSW(%r1),%r2               /* Get old PSW */
2345         ldi     0x0b,%r20                          /* Create new PSW */
2346         depi    -1,13,1,%r20                       /* C, Q, D, and I bits */
2347         bb,>=,n %r19,15,try_tbit                   /* PT_SINGLESTEP */
2348         depi    -1,27,1,%r20                       /* R bit */
2349 try_tbit:
2350         bb,>=,n %r19,14,psw_setup                  /* PT_BLOCKSTEP, see ptrace.c */
2351         depi    -1,7,1,%r20                        /* T bit */
2352 psw_setup:
2353         STREG   %r20,TASK_PT_PSW(%r1)
2354
2355         /* Always store space registers, since sr3 can be changed (e.g. fork) */
2356
2357         mfsp    %sr3,%r25
2358         STREG   %r25,TASK_PT_SR3(%r1)
2359         STREG   %r25,TASK_PT_SR4(%r1)
2360         STREG   %r25,TASK_PT_SR5(%r1)
2361         STREG   %r25,TASK_PT_SR6(%r1)
2362         STREG   %r25,TASK_PT_SR7(%r1)
2363         STREG   %r25,TASK_PT_IASQ0(%r1)
2364         STREG   %r25,TASK_PT_IASQ1(%r1)
2365
2366         /* XXX W bit??? */
2367         /* Now if old D bit is clear, it means we didn't save all registers
2368          * on syscall entry, so do that now.  This only happens on TRACEME
2369          * calls, or if someone attached to us while we were on a syscall.
2370          * We could make this more efficient by not saving r3-r18, but
2371          * then we wouldn't be able to use the common intr_restore path.
2372          * It is only for traced processes anyway, so performance is not
2373          * an issue.
2374          */
2375         bb,<    %r2,30,pt_regs_ok                  /* Branch if D set */
2376         ldo     TASK_REGS(%r1),%r25
2377         reg_save %r25                              /* Save r3 to r18 */
2378         mfsp    %sr0,%r2
2379         STREG   %r2,TASK_PT_SR0(%r1)
2380         mfsp    %sr1,%r2
2381         STREG   %r2,TASK_PT_SR1(%r1)
2382         mfsp    %sr2,%r2
2383         STREG   %r2,TASK_PT_SR2(%r1)
2384 pt_regs_ok:
2385         LDREG   TASK_PT_GR31(%r1),%r2
2386         depi    3,31,2,%r2                         /* ensure return to user mode. */
2387         STREG   %r2,TASK_PT_IAOQ0(%r1)
2388         ldo     4(%r2),%r2
2389         STREG   %r2,TASK_PT_IAOQ1(%r1)
2390         copy    %r25,%r16
2391         b       intr_restore
2392         nop
2393
2394         .import do_softirq,code
2395 syscall_do_softirq:
2396         bl      do_softirq,%r2
2397         nop
2398         b       syscall_check_resched
2399         ssm     PSW_SM_I, %r0  /* do_softirq returns with I bit off */
2400
2401         .import schedule,code
2402 syscall_do_resched:
2403         bl      schedule,%r2
2404 #ifdef __LP64__
2405         ldo     -16(%r30),%r29          /* Reference param save area */
2406 #else
2407         nop
2408 #endif
2409         b       syscall_check_bh  /* if resched, we start over again */
2410         nop
2411
2412         .import do_signal,code
2413 syscall_do_signal:
2414         /* Save callee-save registers (for sigcontext).
2415            FIXME: After this point the process structure should be
2416            consistent with all the relevant state of the process
2417            before the syscall.  We need to verify this. */
2418         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 
2419         ldo     TASK_REGS(%r1), %r25            /* struct pt_regs *regs */
2420         reg_save %r25
2421
2422         ldi     1, %r24                         /* unsigned long in_syscall */
2423
2424 #ifdef __LP64__
2425         ldo     -16(%r30),%r29                  /* Reference param save area */
2426 #endif
2427         bl      do_signal,%r2
2428         copy    %r0, %r26                       /* sigset_t *oldset = NULL */
2429
2430         LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
2431         ldo     TASK_REGS(%r1), %r20            /* reload pt_regs */
2432         reg_restore %r20
2433
2434         b,n     syscall_restore
2435
2436         /*
2437          * get_register is used by the non access tlb miss handlers to
2438          * copy the value of the general register specified in r8 into
2439          * r1. This routine can't be used for shadowed registers, since
2440          * the rfir will restore the original value. So, for the shadowed
2441          * registers we put a -1 into r1 to indicate that the register
2442          * should not be used (the register being copied could also have
2443          * a -1 in it, but that is OK, it just means that we will have
2444          * to use the slow path instead).
2445          */
2446
2447 get_register:
2448         blr     %r8,%r0
2449         nop
2450         bv      %r0(%r25)    /* r0 */
2451         copy    %r0,%r1
2452         bv      %r0(%r25)    /* r1 - shadowed */
2453         ldi     -1,%r1
2454         bv      %r0(%r25)    /* r2 */
2455         copy    %r2,%r1
2456         bv      %r0(%r25)    /* r3 */
2457         copy    %r3,%r1
2458         bv      %r0(%r25)    /* r4 */
2459         copy    %r4,%r1
2460         bv      %r0(%r25)    /* r5 */
2461         copy    %r5,%r1
2462         bv      %r0(%r25)    /* r6 */
2463         copy    %r6,%r1
2464         bv      %r0(%r25)    /* r7 */
2465         copy    %r7,%r1
2466         bv      %r0(%r25)    /* r8 - shadowed */
2467         ldi     -1,%r1
2468         bv      %r0(%r25)    /* r9 - shadowed */
2469         ldi     -1,%r1
2470         bv      %r0(%r25)    /* r10 */
2471         copy    %r10,%r1
2472         bv      %r0(%r25)    /* r11 */
2473         copy    %r11,%r1
2474         bv      %r0(%r25)    /* r12 */
2475         copy    %r12,%r1
2476         bv      %r0(%r25)    /* r13 */
2477         copy    %r13,%r1
2478         bv      %r0(%r25)    /* r14 */
2479         copy    %r14,%r1
2480         bv      %r0(%r25)    /* r15 */
2481         copy    %r15,%r1
2482         bv      %r0(%r25)    /* r16 - shadowed */
2483         ldi     -1,%r1
2484         bv      %r0(%r25)    /* r17 - shadowed */
2485         ldi     -1,%r1
2486         bv      %r0(%r25)    /* r18 */
2487         copy    %r18,%r1
2488         bv      %r0(%r25)    /* r19 */
2489         copy    %r19,%r1
2490         bv      %r0(%r25)    /* r20 */
2491         copy    %r20,%r1
2492         bv      %r0(%r25)    /* r21 */
2493         copy    %r21,%r1
2494         bv      %r0(%r25)    /* r22 */
2495         copy    %r22,%r1
2496         bv      %r0(%r25)    /* r23 */
2497         copy    %r23,%r1
2498         bv      %r0(%r25)    /* r24 - shadowed */
2499         ldi     -1,%r1
2500         bv      %r0(%r25)    /* r25 - shadowed */
2501         ldi     -1,%r1
2502         bv      %r0(%r25)    /* r26 */
2503         copy    %r26,%r1
2504         bv      %r0(%r25)    /* r27 */
2505         copy    %r27,%r1
2506         bv      %r0(%r25)    /* r28 */
2507         copy    %r28,%r1
2508         bv      %r0(%r25)    /* r29 */
2509         copy    %r29,%r1
2510         bv      %r0(%r25)    /* r30 */
2511         copy    %r30,%r1
2512         bv      %r0(%r25)    /* r31 */
2513         copy    %r31,%r1
2514
2515         /*
2516          * set_register is used by the non access tlb miss handlers to
2517          * copy the value of r1 into the general register specified in
2518          * r8.
2519          */
2520
2521 set_register:
2522         blr     %r8,%r0
2523         nop
2524         bv      %r0(%r25)    /* r0 (silly, but it is a place holder) */
2525         copy    %r1,%r0
2526         bv      %r0(%r25)    /* r1 */
2527         copy    %r1,%r1
2528         bv      %r0(%r25)    /* r2 */
2529         copy    %r1,%r2
2530         bv      %r0(%r25)    /* r3 */
2531         copy    %r1,%r3
2532         bv      %r0(%r25)    /* r4 */
2533         copy    %r1,%r4
2534         bv      %r0(%r25)    /* r5 */
2535         copy    %r1,%r5
2536         bv      %r0(%r25)    /* r6 */
2537         copy    %r1,%r6
2538         bv      %r0(%r25)    /* r7 */
2539         copy    %r1,%r7
2540         bv      %r0(%r25)    /* r8 */
2541         copy    %r1,%r8
2542         bv      %r0(%r25)    /* r9 */
2543         copy    %r1,%r9
2544         bv      %r0(%r25)    /* r10 */
2545         copy    %r1,%r10
2546         bv      %r0(%r25)    /* r11 */
2547         copy    %r1,%r11
2548         bv      %r0(%r25)    /* r12 */
2549         copy    %r1,%r12
2550         bv      %r0(%r25)    /* r13 */
2551         copy    %r1,%r13
2552         bv      %r0(%r25)    /* r14 */
2553         copy    %r1,%r14
2554         bv      %r0(%r25)    /* r15 */
2555         copy    %r1,%r15
2556         bv      %r0(%r25)    /* r16 */
2557         copy    %r1,%r16
2558         bv      %r0(%r25)    /* r17 */
2559         copy    %r1,%r17
2560         bv      %r0(%r25)    /* r18 */
2561         copy    %r1,%r18
2562         bv      %r0(%r25)    /* r19 */
2563         copy    %r1,%r19
2564         bv      %r0(%r25)    /* r20 */
2565         copy    %r1,%r20
2566         bv      %r0(%r25)    /* r21 */
2567         copy    %r1,%r21
2568         bv      %r0(%r25)    /* r22 */
2569         copy    %r1,%r22
2570         bv      %r0(%r25)    /* r23 */
2571         copy    %r1,%r23
2572         bv      %r0(%r25)    /* r24 */
2573         copy    %r1,%r24
2574         bv      %r0(%r25)    /* r25 */
2575         copy    %r1,%r25
2576         bv      %r0(%r25)    /* r26 */
2577         copy    %r1,%r26
2578         bv      %r0(%r25)    /* r27 */
2579         copy    %r1,%r27
2580         bv      %r0(%r25)    /* r28 */
2581         copy    %r1,%r28
2582         bv      %r0(%r25)    /* r29 */
2583         copy    %r1,%r29
2584         bv      %r0(%r25)    /* r30 */
2585         copy    %r1,%r30
2586         bv      %r0(%r25)    /* r31 */
2587         copy    %r1,%r31