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