GNU Linux-libre 4.9.337-gnu1
[releases.git] / arch / alpha / kernel / entry.S
1 /*
2  * arch/alpha/kernel/entry.S
3  *
4  * Kernel entry-points.
5  */
6
7 #include <asm/asm-offsets.h>
8 #include <asm/thread_info.h>
9 #include <asm/pal.h>
10 #include <asm/errno.h>
11 #include <asm/unistd.h>
12
13         .text
14         .set noat
15         .cfi_sections   .debug_frame
16
17 /* Stack offsets.  */
18 #define SP_OFF                  184
19 #define SWITCH_STACK_SIZE       320
20
21 .macro  CFI_START_OSF_FRAME     func
22         .align  4
23         .globl  \func
24         .type   \func,@function
25 \func:
26         .cfi_startproc simple
27         .cfi_return_column 64
28         .cfi_def_cfa    $sp, 48
29         .cfi_rel_offset 64, 8
30         .cfi_rel_offset $gp, 16
31         .cfi_rel_offset $16, 24
32         .cfi_rel_offset $17, 32
33         .cfi_rel_offset $18, 40
34 .endm
35
36 .macro  CFI_END_OSF_FRAME       func
37         .cfi_endproc
38         .size   \func, . - \func
39 .endm
40
41 /*
42  * This defines the normal kernel pt-regs layout.
43  *
44  * regs 9-15 preserved by C code
45  * regs 16-18 saved by PAL-code
46  * regs 29-30 saved and set up by PAL-code
47  * JRP - Save regs 16-18 in a special area of the stack, so that
48  * the palcode-provided values are available to the signal handler.
49  */
50
51 .macro  SAVE_ALL
52         subq    $sp, SP_OFF, $sp
53         .cfi_adjust_cfa_offset  SP_OFF
54         stq     $0, 0($sp)
55         stq     $1, 8($sp)
56         stq     $2, 16($sp)
57         stq     $3, 24($sp)
58         stq     $4, 32($sp)
59         stq     $28, 144($sp)
60         .cfi_rel_offset $0, 0
61         .cfi_rel_offset $1, 8
62         .cfi_rel_offset $2, 16
63         .cfi_rel_offset $3, 24
64         .cfi_rel_offset $4, 32
65         .cfi_rel_offset $28, 144
66         lda     $2, alpha_mv
67         stq     $5, 40($sp)
68         stq     $6, 48($sp)
69         stq     $7, 56($sp)
70         stq     $8, 64($sp)
71         stq     $19, 72($sp)
72         stq     $20, 80($sp)
73         stq     $21, 88($sp)
74         ldq     $2, HAE_CACHE($2)
75         stq     $22, 96($sp)
76         stq     $23, 104($sp)
77         stq     $24, 112($sp)
78         stq     $25, 120($sp)
79         stq     $26, 128($sp)
80         stq     $27, 136($sp)
81         stq     $2, 152($sp)
82         stq     $16, 160($sp)
83         stq     $17, 168($sp)
84         stq     $18, 176($sp)
85         .cfi_rel_offset $5, 40
86         .cfi_rel_offset $6, 48
87         .cfi_rel_offset $7, 56
88         .cfi_rel_offset $8, 64
89         .cfi_rel_offset $19, 72
90         .cfi_rel_offset $20, 80
91         .cfi_rel_offset $21, 88
92         .cfi_rel_offset $22, 96
93         .cfi_rel_offset $23, 104
94         .cfi_rel_offset $24, 112
95         .cfi_rel_offset $25, 120
96         .cfi_rel_offset $26, 128
97         .cfi_rel_offset $27, 136
98 .endm
99
100 .macro  RESTORE_ALL
101         lda     $19, alpha_mv
102         ldq     $0, 0($sp)
103         ldq     $1, 8($sp)
104         ldq     $2, 16($sp)
105         ldq     $3, 24($sp)
106         ldq     $21, 152($sp)
107         ldq     $20, HAE_CACHE($19)
108         ldq     $4, 32($sp)
109         ldq     $5, 40($sp)
110         ldq     $6, 48($sp)
111         ldq     $7, 56($sp)
112         subq    $20, $21, $20
113         ldq     $8, 64($sp)
114         beq     $20, 99f
115         ldq     $20, HAE_REG($19)
116         stq     $21, HAE_CACHE($19)
117         stq     $21, 0($20)
118 99:     ldq     $19, 72($sp)
119         ldq     $20, 80($sp)
120         ldq     $21, 88($sp)
121         ldq     $22, 96($sp)
122         ldq     $23, 104($sp)
123         ldq     $24, 112($sp)
124         ldq     $25, 120($sp)
125         ldq     $26, 128($sp)
126         ldq     $27, 136($sp)
127         ldq     $28, 144($sp)
128         addq    $sp, SP_OFF, $sp
129         .cfi_restore    $0
130         .cfi_restore    $1
131         .cfi_restore    $2
132         .cfi_restore    $3
133         .cfi_restore    $4
134         .cfi_restore    $5
135         .cfi_restore    $6
136         .cfi_restore    $7
137         .cfi_restore    $8
138         .cfi_restore    $19
139         .cfi_restore    $20
140         .cfi_restore    $21
141         .cfi_restore    $22
142         .cfi_restore    $23
143         .cfi_restore    $24
144         .cfi_restore    $25
145         .cfi_restore    $26
146         .cfi_restore    $27
147         .cfi_restore    $28
148         .cfi_adjust_cfa_offset  -SP_OFF
149 .endm
150
151 .macro  DO_SWITCH_STACK
152         bsr     $1, do_switch_stack
153         .cfi_adjust_cfa_offset  SWITCH_STACK_SIZE
154         .cfi_rel_offset $9, 0
155         .cfi_rel_offset $10, 8
156         .cfi_rel_offset $11, 16
157         .cfi_rel_offset $12, 24
158         .cfi_rel_offset $13, 32
159         .cfi_rel_offset $14, 40
160         .cfi_rel_offset $15, 48
161         /* We don't really care about the FP registers for debugging.  */
162 .endm
163
164 .macro  UNDO_SWITCH_STACK
165         bsr     $1, undo_switch_stack
166         .cfi_restore    $9
167         .cfi_restore    $10
168         .cfi_restore    $11
169         .cfi_restore    $12
170         .cfi_restore    $13
171         .cfi_restore    $14
172         .cfi_restore    $15
173         .cfi_adjust_cfa_offset  -SWITCH_STACK_SIZE
174 .endm
175
176 /*
177  * Non-syscall kernel entry points.
178  */
179
180 CFI_START_OSF_FRAME entInt
181         SAVE_ALL
182         lda     $8, 0x3fff
183         lda     $26, ret_from_sys_call
184         bic     $sp, $8, $8
185         mov     $sp, $19
186         jsr     $31, do_entInt
187 CFI_END_OSF_FRAME entInt
188
189 CFI_START_OSF_FRAME entArith
190         SAVE_ALL
191         lda     $8, 0x3fff
192         lda     $26, ret_from_sys_call
193         bic     $sp, $8, $8
194         mov     $sp, $18
195         jsr     $31, do_entArith
196 CFI_END_OSF_FRAME entArith
197
198 CFI_START_OSF_FRAME entMM
199         SAVE_ALL
200 /* save $9 - $15 so the inline exception code can manipulate them.  */
201         subq    $sp, 56, $sp
202         .cfi_adjust_cfa_offset  56
203         stq     $9, 0($sp)
204         stq     $10, 8($sp)
205         stq     $11, 16($sp)
206         stq     $12, 24($sp)
207         stq     $13, 32($sp)
208         stq     $14, 40($sp)
209         stq     $15, 48($sp)
210         .cfi_rel_offset $9, 0
211         .cfi_rel_offset $10, 8
212         .cfi_rel_offset $11, 16
213         .cfi_rel_offset $12, 24
214         .cfi_rel_offset $13, 32
215         .cfi_rel_offset $14, 40
216         .cfi_rel_offset $15, 48
217         addq    $sp, 56, $19
218 /* handle the fault */
219         lda     $8, 0x3fff
220         bic     $sp, $8, $8
221         jsr     $26, do_page_fault
222 /* reload the registers after the exception code played.  */
223         ldq     $9, 0($sp)
224         ldq     $10, 8($sp)
225         ldq     $11, 16($sp)
226         ldq     $12, 24($sp)
227         ldq     $13, 32($sp)
228         ldq     $14, 40($sp)
229         ldq     $15, 48($sp)
230         addq    $sp, 56, $sp
231         .cfi_restore    $9
232         .cfi_restore    $10
233         .cfi_restore    $11
234         .cfi_restore    $12
235         .cfi_restore    $13
236         .cfi_restore    $14
237         .cfi_restore    $15
238         .cfi_adjust_cfa_offset  -56
239 /* finish up the syscall as normal.  */
240         br      ret_from_sys_call
241 CFI_END_OSF_FRAME entMM
242
243 CFI_START_OSF_FRAME entIF
244         SAVE_ALL
245         lda     $8, 0x3fff
246         lda     $26, ret_from_sys_call
247         bic     $sp, $8, $8
248         mov     $sp, $17
249         jsr     $31, do_entIF
250 CFI_END_OSF_FRAME entIF
251
252 CFI_START_OSF_FRAME entUna
253         lda     $sp, -256($sp)
254         .cfi_adjust_cfa_offset  256
255         stq     $0, 0($sp)
256         .cfi_rel_offset $0, 0
257         .cfi_remember_state
258         ldq     $0, 256($sp)    /* get PS */
259         stq     $1, 8($sp)
260         stq     $2, 16($sp)
261         stq     $3, 24($sp)
262         and     $0, 8, $0               /* user mode? */
263         stq     $4, 32($sp)
264         bne     $0, entUnaUser  /* yup -> do user-level unaligned fault */
265         stq     $5, 40($sp)
266         stq     $6, 48($sp)
267         stq     $7, 56($sp)
268         stq     $8, 64($sp)
269         stq     $9, 72($sp)
270         stq     $10, 80($sp)
271         stq     $11, 88($sp)
272         stq     $12, 96($sp)
273         stq     $13, 104($sp)
274         stq     $14, 112($sp)
275         stq     $15, 120($sp)
276         /* 16-18 PAL-saved */
277         stq     $19, 152($sp)
278         stq     $20, 160($sp)
279         stq     $21, 168($sp)
280         stq     $22, 176($sp)
281         stq     $23, 184($sp)
282         stq     $24, 192($sp)
283         stq     $25, 200($sp)
284         stq     $26, 208($sp)
285         stq     $27, 216($sp)
286         stq     $28, 224($sp)
287         mov     $sp, $19
288         stq     $gp, 232($sp)
289         .cfi_rel_offset $1, 1*8
290         .cfi_rel_offset $2, 2*8
291         .cfi_rel_offset $3, 3*8
292         .cfi_rel_offset $4, 4*8
293         .cfi_rel_offset $5, 5*8
294         .cfi_rel_offset $6, 6*8
295         .cfi_rel_offset $7, 7*8
296         .cfi_rel_offset $8, 8*8
297         .cfi_rel_offset $9, 9*8
298         .cfi_rel_offset $10, 10*8
299         .cfi_rel_offset $11, 11*8
300         .cfi_rel_offset $12, 12*8
301         .cfi_rel_offset $13, 13*8
302         .cfi_rel_offset $14, 14*8
303         .cfi_rel_offset $15, 15*8
304         .cfi_rel_offset $19, 19*8
305         .cfi_rel_offset $20, 20*8
306         .cfi_rel_offset $21, 21*8
307         .cfi_rel_offset $22, 22*8
308         .cfi_rel_offset $23, 23*8
309         .cfi_rel_offset $24, 24*8
310         .cfi_rel_offset $25, 25*8
311         .cfi_rel_offset $26, 26*8
312         .cfi_rel_offset $27, 27*8
313         .cfi_rel_offset $28, 28*8
314         .cfi_rel_offset $29, 29*8
315         lda     $8, 0x3fff
316         stq     $31, 248($sp)
317         bic     $sp, $8, $8
318         jsr     $26, do_entUna
319         ldq     $0, 0($sp)
320         ldq     $1, 8($sp)
321         ldq     $2, 16($sp)
322         ldq     $3, 24($sp)
323         ldq     $4, 32($sp)
324         ldq     $5, 40($sp)
325         ldq     $6, 48($sp)
326         ldq     $7, 56($sp)
327         ldq     $8, 64($sp)
328         ldq     $9, 72($sp)
329         ldq     $10, 80($sp)
330         ldq     $11, 88($sp)
331         ldq     $12, 96($sp)
332         ldq     $13, 104($sp)
333         ldq     $14, 112($sp)
334         ldq     $15, 120($sp)
335         /* 16-18 PAL-saved */
336         ldq     $19, 152($sp)
337         ldq     $20, 160($sp)
338         ldq     $21, 168($sp)
339         ldq     $22, 176($sp)
340         ldq     $23, 184($sp)
341         ldq     $24, 192($sp)
342         ldq     $25, 200($sp)
343         ldq     $26, 208($sp)
344         ldq     $27, 216($sp)
345         ldq     $28, 224($sp)
346         ldq     $gp, 232($sp)
347         lda     $sp, 256($sp)
348         .cfi_restore    $1
349         .cfi_restore    $2
350         .cfi_restore    $3
351         .cfi_restore    $4
352         .cfi_restore    $5
353         .cfi_restore    $6
354         .cfi_restore    $7
355         .cfi_restore    $8
356         .cfi_restore    $9
357         .cfi_restore    $10
358         .cfi_restore    $11
359         .cfi_restore    $12
360         .cfi_restore    $13
361         .cfi_restore    $14
362         .cfi_restore    $15
363         .cfi_restore    $19
364         .cfi_restore    $20
365         .cfi_restore    $21
366         .cfi_restore    $22
367         .cfi_restore    $23
368         .cfi_restore    $24
369         .cfi_restore    $25
370         .cfi_restore    $26
371         .cfi_restore    $27
372         .cfi_restore    $28
373         .cfi_restore    $29
374         .cfi_adjust_cfa_offset  -256
375         call_pal PAL_rti
376
377         .align  4
378 entUnaUser:
379         .cfi_restore_state
380         ldq     $0, 0($sp)      /* restore original $0 */
381         lda     $sp, 256($sp)   /* pop entUna's stack frame */
382         .cfi_restore    $0
383         .cfi_adjust_cfa_offset  -256
384         SAVE_ALL                /* setup normal kernel stack */
385         lda     $sp, -56($sp)
386         .cfi_adjust_cfa_offset  56
387         stq     $9, 0($sp)
388         stq     $10, 8($sp)
389         stq     $11, 16($sp)
390         stq     $12, 24($sp)
391         stq     $13, 32($sp)
392         stq     $14, 40($sp)
393         stq     $15, 48($sp)
394         .cfi_rel_offset $9, 0
395         .cfi_rel_offset $10, 8
396         .cfi_rel_offset $11, 16
397         .cfi_rel_offset $12, 24
398         .cfi_rel_offset $13, 32
399         .cfi_rel_offset $14, 40
400         .cfi_rel_offset $15, 48
401         lda     $8, 0x3fff
402         addq    $sp, 56, $19
403         bic     $sp, $8, $8
404         jsr     $26, do_entUnaUser
405         ldq     $9, 0($sp)
406         ldq     $10, 8($sp)
407         ldq     $11, 16($sp)
408         ldq     $12, 24($sp)
409         ldq     $13, 32($sp)
410         ldq     $14, 40($sp)
411         ldq     $15, 48($sp)
412         lda     $sp, 56($sp)
413         .cfi_restore    $9
414         .cfi_restore    $10
415         .cfi_restore    $11
416         .cfi_restore    $12
417         .cfi_restore    $13
418         .cfi_restore    $14
419         .cfi_restore    $15
420         .cfi_adjust_cfa_offset  -56
421         br      ret_from_sys_call
422 CFI_END_OSF_FRAME entUna
423
424 CFI_START_OSF_FRAME entDbg
425         SAVE_ALL
426         lda     $8, 0x3fff
427         lda     $26, ret_from_sys_call
428         bic     $sp, $8, $8
429         mov     $sp, $16
430         jsr     $31, do_entDbg
431 CFI_END_OSF_FRAME entDbg
432 \f
433 /*
434  * The system call entry point is special.  Most importantly, it looks
435  * like a function call to userspace as far as clobbered registers.  We
436  * do preserve the argument registers (for syscall restarts) and $26
437  * (for leaf syscall functions).
438  *
439  * So much for theory.  We don't take advantage of this yet.
440  *
441  * Note that a0-a2 are not saved by PALcode as with the other entry points.
442  */
443
444         .align  4
445         .globl  entSys
446         .type   entSys, @function
447         .cfi_startproc simple
448         .cfi_return_column 64
449         .cfi_def_cfa    $sp, 48
450         .cfi_rel_offset 64, 8
451         .cfi_rel_offset $gp, 16
452 entSys:
453         SAVE_ALL
454         lda     $8, 0x3fff
455         bic     $sp, $8, $8
456         lda     $4, NR_SYSCALLS($31)
457         stq     $16, SP_OFF+24($sp)
458         lda     $5, sys_call_table
459         lda     $27, sys_ni_syscall
460         cmpult  $0, $4, $4
461         ldl     $3, TI_FLAGS($8)
462         stq     $17, SP_OFF+32($sp)
463         s8addq  $0, $5, $5
464         stq     $18, SP_OFF+40($sp)
465         .cfi_rel_offset $16, SP_OFF+24
466         .cfi_rel_offset $17, SP_OFF+32
467         .cfi_rel_offset $18, SP_OFF+40
468 #ifdef CONFIG_AUDITSYSCALL
469         lda     $6, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT
470         and     $3, $6, $3
471         bne     $3, strace
472 #else
473         blbs    $3, strace              /* check for SYSCALL_TRACE in disguise */
474 #endif
475         beq     $4, 1f
476         ldq     $27, 0($5)
477 1:      jsr     $26, ($27), alpha_ni_syscall
478         ldgp    $gp, 0($26)
479         blt     $0, $syscall_error      /* the call failed */
480         stq     $0, 0($sp)
481         stq     $31, 72($sp)            /* a3=0 => no error */
482
483         .align  4
484         .globl  ret_from_sys_call
485 ret_from_sys_call:
486         cmovne  $26, 0, $18             /* $18 = 0 => non-restartable */
487         ldq     $0, SP_OFF($sp)
488         and     $0, 8, $0
489         beq     $0, ret_to_kernel
490 ret_to_user:
491         /* Make sure need_resched and sigpending don't change between
492                 sampling and the rti.  */
493         lda     $16, 7
494         call_pal PAL_swpipl
495         ldl     $17, TI_FLAGS($8)
496         and     $17, _TIF_WORK_MASK, $2
497         bne     $2, work_pending
498 restore_all:
499         .cfi_remember_state
500         RESTORE_ALL
501         call_pal PAL_rti
502
503 ret_to_kernel:
504         .cfi_restore_state
505         lda     $16, 7
506         call_pal PAL_swpipl
507         br restore_all
508
509         .align 3
510 $syscall_error:
511         /*
512          * Some system calls (e.g., ptrace) can return arbitrary
513          * values which might normally be mistaken as error numbers.
514          * Those functions must zero $0 (v0) directly in the stack
515          * frame to indicate that a negative return value wasn't an
516          * error number..
517          */
518         ldq     $18, 0($sp)     /* old syscall nr (zero if success) */
519         beq     $18, $ret_success
520
521         ldq     $19, 72($sp)    /* .. and this a3 */
522         subq    $31, $0, $0     /* with error in v0 */
523         addq    $31, 1, $1      /* set a3 for errno return */
524         stq     $0, 0($sp)
525         mov     $31, $26        /* tell "ret_from_sys_call" we can restart */
526         stq     $1, 72($sp)     /* a3 for return */
527         br      ret_from_sys_call
528
529 $ret_success:
530         stq     $0, 0($sp)
531         stq     $31, 72($sp)    /* a3=0 => no error */
532         br      ret_from_sys_call
533
534 /*
535  * Do all cleanup when returning from all interrupts and system calls.
536  *
537  * Arguments:
538  *       $8: current.
539  *      $17: TI_FLAGS.
540  *      $18: The old syscall number, or zero if this is not a return
541  *           from a syscall that errored and is possibly restartable.
542  *      $19: The old a3 value
543  */
544
545         .align  4
546         .type   work_pending, @function
547 work_pending:
548         and     $17, _TIF_NOTIFY_RESUME | _TIF_SIGPENDING, $2
549         bne     $2, $work_notifysig
550
551 $work_resched:
552         /*
553          * We can get here only if we returned from syscall without SIGPENDING
554          * or got through work_notifysig already.  Either case means no syscall
555          * restarts for us, so let $18 and $19 burn.
556          */
557         jsr     $26, schedule
558         mov     0, $18
559         br      ret_to_user
560
561 $work_notifysig:
562         mov     $sp, $16
563         DO_SWITCH_STACK
564         jsr     $26, do_work_pending
565         UNDO_SWITCH_STACK
566         br      restore_all
567
568 /*
569  * PTRACE syscall handler
570  */
571
572         .align  4
573         .type   strace, @function
574 strace:
575         /* set up signal stack, call syscall_trace */
576         DO_SWITCH_STACK
577         jsr     $26, syscall_trace_enter /* returns the syscall number */
578         UNDO_SWITCH_STACK
579
580         /* get the arguments back.. */
581         ldq     $16, SP_OFF+24($sp)
582         ldq     $17, SP_OFF+32($sp)
583         ldq     $18, SP_OFF+40($sp)
584         ldq     $19, 72($sp)
585         ldq     $20, 80($sp)
586         ldq     $21, 88($sp)
587
588         /* get the system call pointer.. */
589         lda     $1, NR_SYSCALLS($31)
590         lda     $2, sys_call_table
591         lda     $27, alpha_ni_syscall
592         cmpult  $0, $1, $1
593         s8addq  $0, $2, $2
594         beq     $1, 1f
595         ldq     $27, 0($2)
596 1:      jsr     $26, ($27), sys_gettimeofday
597 ret_from_straced:
598         ldgp    $gp, 0($26)
599
600         /* check return.. */
601         blt     $0, $strace_error       /* the call failed */
602         stq     $31, 72($sp)            /* a3=0 => no error */
603 $strace_success:
604         stq     $0, 0($sp)              /* save return value */
605
606         DO_SWITCH_STACK
607         jsr     $26, syscall_trace_leave
608         UNDO_SWITCH_STACK
609         br      $31, ret_from_sys_call
610
611         .align  3
612 $strace_error:
613         ldq     $18, 0($sp)     /* old syscall nr (zero if success) */
614         beq     $18, $strace_success
615         ldq     $19, 72($sp)    /* .. and this a3 */
616
617         subq    $31, $0, $0     /* with error in v0 */
618         addq    $31, 1, $1      /* set a3 for errno return */
619         stq     $0, 0($sp)
620         stq     $1, 72($sp)     /* a3 for return */
621
622         DO_SWITCH_STACK
623         mov     $18, $9         /* save old syscall number */
624         mov     $19, $10        /* save old a3 */
625         jsr     $26, syscall_trace_leave
626         mov     $9, $18
627         mov     $10, $19
628         UNDO_SWITCH_STACK
629
630         mov     $31, $26        /* tell "ret_from_sys_call" we can restart */
631         br      ret_from_sys_call
632 CFI_END_OSF_FRAME entSys
633 \f
634 /*
635  * Save and restore the switch stack -- aka the balance of the user context.
636  */
637
638         .align  4
639         .type   do_switch_stack, @function
640         .cfi_startproc simple
641         .cfi_return_column 64
642         .cfi_def_cfa $sp, 0
643         .cfi_register 64, $1
644 do_switch_stack:
645         lda     $sp, -SWITCH_STACK_SIZE($sp)
646         .cfi_adjust_cfa_offset  SWITCH_STACK_SIZE
647         stq     $9, 0($sp)
648         stq     $10, 8($sp)
649         stq     $11, 16($sp)
650         stq     $12, 24($sp)
651         stq     $13, 32($sp)
652         stq     $14, 40($sp)
653         stq     $15, 48($sp)
654         stq     $26, 56($sp)
655         stt     $f0, 64($sp)
656         stt     $f1, 72($sp)
657         stt     $f2, 80($sp)
658         stt     $f3, 88($sp)
659         stt     $f4, 96($sp)
660         stt     $f5, 104($sp)
661         stt     $f6, 112($sp)
662         stt     $f7, 120($sp)
663         stt     $f8, 128($sp)
664         stt     $f9, 136($sp)
665         stt     $f10, 144($sp)
666         stt     $f11, 152($sp)
667         stt     $f12, 160($sp)
668         stt     $f13, 168($sp)
669         stt     $f14, 176($sp)
670         stt     $f15, 184($sp)
671         stt     $f16, 192($sp)
672         stt     $f17, 200($sp)
673         stt     $f18, 208($sp)
674         stt     $f19, 216($sp)
675         stt     $f20, 224($sp)
676         stt     $f21, 232($sp)
677         stt     $f22, 240($sp)
678         stt     $f23, 248($sp)
679         stt     $f24, 256($sp)
680         stt     $f25, 264($sp)
681         stt     $f26, 272($sp)
682         stt     $f27, 280($sp)
683         mf_fpcr $f0             # get fpcr
684         stt     $f28, 288($sp)
685         stt     $f29, 296($sp)
686         stt     $f30, 304($sp)
687         stt     $f0, 312($sp)   # save fpcr in slot of $f31
688         ldt     $f0, 64($sp)    # dont let "do_switch_stack" change fp state.
689         ret     $31, ($1), 1
690         .cfi_endproc
691         .size   do_switch_stack, .-do_switch_stack
692
693         .align  4
694         .type   undo_switch_stack, @function
695         .cfi_startproc simple
696         .cfi_def_cfa $sp, 0
697         .cfi_register 64, $1
698 undo_switch_stack:
699         ldq     $9, 0($sp)
700         ldq     $10, 8($sp)
701         ldq     $11, 16($sp)
702         ldq     $12, 24($sp)
703         ldq     $13, 32($sp)
704         ldq     $14, 40($sp)
705         ldq     $15, 48($sp)
706         ldq     $26, 56($sp)
707         ldt     $f30, 312($sp)  # get saved fpcr
708         ldt     $f0, 64($sp)
709         ldt     $f1, 72($sp)
710         ldt     $f2, 80($sp)
711         ldt     $f3, 88($sp)
712         mt_fpcr $f30            # install saved fpcr
713         ldt     $f4, 96($sp)
714         ldt     $f5, 104($sp)
715         ldt     $f6, 112($sp)
716         ldt     $f7, 120($sp)
717         ldt     $f8, 128($sp)
718         ldt     $f9, 136($sp)
719         ldt     $f10, 144($sp)
720         ldt     $f11, 152($sp)
721         ldt     $f12, 160($sp)
722         ldt     $f13, 168($sp)
723         ldt     $f14, 176($sp)
724         ldt     $f15, 184($sp)
725         ldt     $f16, 192($sp)
726         ldt     $f17, 200($sp)
727         ldt     $f18, 208($sp)
728         ldt     $f19, 216($sp)
729         ldt     $f20, 224($sp)
730         ldt     $f21, 232($sp)
731         ldt     $f22, 240($sp)
732         ldt     $f23, 248($sp)
733         ldt     $f24, 256($sp)
734         ldt     $f25, 264($sp)
735         ldt     $f26, 272($sp)
736         ldt     $f27, 280($sp)
737         ldt     $f28, 288($sp)
738         ldt     $f29, 296($sp)
739         ldt     $f30, 304($sp)
740         lda     $sp, SWITCH_STACK_SIZE($sp)
741         ret     $31, ($1), 1
742         .cfi_endproc
743         .size   undo_switch_stack, .-undo_switch_stack
744 \f
745 /*
746  * The meat of the context switch code.
747  */
748
749         .align  4
750         .globl  alpha_switch_to
751         .type   alpha_switch_to, @function
752         .cfi_startproc
753 alpha_switch_to:
754         DO_SWITCH_STACK
755         call_pal PAL_swpctx
756         lda     $8, 0x3fff
757         UNDO_SWITCH_STACK
758         bic     $sp, $8, $8
759         mov     $17, $0
760         ret
761         .cfi_endproc
762         .size   alpha_switch_to, .-alpha_switch_to
763
764 /*
765  * New processes begin life here.
766  */
767
768         .globl  ret_from_fork
769         .align  4
770         .ent    ret_from_fork
771 ret_from_fork:
772         lda     $26, ret_from_sys_call
773         mov     $17, $16
774         jmp     $31, schedule_tail
775 .end ret_from_fork
776
777 /*
778  * ... and new kernel threads - here
779  */
780         .align 4
781         .globl  ret_from_kernel_thread
782         .ent    ret_from_kernel_thread
783 ret_from_kernel_thread:
784         mov     $17, $16
785         jsr     $26, schedule_tail
786         mov     $9, $27
787         mov     $10, $16
788         jsr     $26, ($9)
789         mov     $31, $19                /* to disable syscall restarts */
790         br      $31, ret_to_user
791 .end ret_from_kernel_thread
792
793 \f
794 /*
795  * Special system calls.  Most of these are special in that they either
796  * have to play switch_stack games or in some way use the pt_regs struct.
797  */
798
799 .macro  fork_like name
800         .align  4
801         .globl  alpha_\name
802         .ent    alpha_\name
803 alpha_\name:
804         .prologue 0
805         bsr     $1, do_switch_stack
806         jsr     $26, sys_\name
807         ldq     $26, 56($sp)
808         lda     $sp, SWITCH_STACK_SIZE($sp)
809         ret
810 .end    alpha_\name
811 .endm
812
813 fork_like fork
814 fork_like vfork
815 fork_like clone
816
817         .align  4
818         .globl  sys_sigreturn
819         .ent    sys_sigreturn
820 sys_sigreturn:
821         .prologue 0
822         lda     $9, ret_from_straced
823         cmpult  $26, $9, $9
824         lda     $sp, -SWITCH_STACK_SIZE($sp)
825         jsr     $26, do_sigreturn
826         bne     $9, 1f
827         jsr     $26, syscall_trace_leave
828 1:      br      $1, undo_switch_stack
829         br      ret_from_sys_call
830 .end sys_sigreturn
831
832         .align  4
833         .globl  sys_rt_sigreturn
834         .ent    sys_rt_sigreturn
835 sys_rt_sigreturn:
836         .prologue 0
837         lda     $9, ret_from_straced
838         cmpult  $26, $9, $9
839         lda     $sp, -SWITCH_STACK_SIZE($sp)
840         jsr     $26, do_rt_sigreturn
841         bne     $9, 1f
842         jsr     $26, syscall_trace_leave
843 1:      br      $1, undo_switch_stack
844         br      ret_from_sys_call
845 .end sys_rt_sigreturn
846
847         .align  4
848         .globl  alpha_ni_syscall
849         .ent    alpha_ni_syscall
850 alpha_ni_syscall:
851         .prologue 0
852         /* Special because it also implements overflow handling via
853            syscall number 0.  And if you recall, zero is a special
854            trigger for "not an error".  Store large non-zero there.  */
855         lda     $0, -ENOSYS
856         unop
857         stq     $0, 0($sp)
858         ret
859 .end alpha_ni_syscall