| 1 | /*- |
| 2 | * Copyright (c) 1991 The Regents of the University of California. |
| 3 | * All rights reserved. |
| 4 | * |
| 5 | * This code is derived from software contributed to Berkeley by |
| 6 | * Ralph Campbell. |
| 7 | * |
| 8 | * %sccs.include.redist.c% |
| 9 | */ |
| 10 | |
| 11 | #include <sys/syscall.h> |
| 12 | #include <machine/reg.h> |
| 13 | #include <machine/machAsmDefs.h> |
| 14 | |
| 15 | #if defined(LIBC_SCCS) && !defined(lint) |
| 16 | ASMSTR("@(#)setjmp.s 5.6 (Berkeley) %G%") |
| 17 | #endif /* LIBC_SCCS and not lint */ |
| 18 | |
| 19 | /* |
| 20 | * C library -- setjmp, longjmp |
| 21 | * |
| 22 | * longjmp(a,v) |
| 23 | * will generate a "return(v)" from |
| 24 | * the last call to |
| 25 | * setjmp(a) |
| 26 | * by restoring registers from the stack, |
| 27 | * and a struct sigcontext, see <signal.h> |
| 28 | */ |
| 29 | |
| 30 | #define SETJMP_FRAME_SIZE (STAND_FRAME_SIZE + 12) |
| 31 | |
| 32 | NON_LEAF(setjmp, SETJMP_FRAME_SIZE, ra) |
| 33 | subu sp, sp, SETJMP_FRAME_SIZE # allocate stack frame |
| 34 | .mask 0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE) |
| 35 | sw ra, STAND_RA_OFFSET(sp) # save state |
| 36 | sw a0, SETJMP_FRAME_SIZE(sp) |
| 37 | move a0, zero # get current signal mask |
| 38 | jal sigblock |
| 39 | lw v1, SETJMP_FRAME_SIZE(sp) # v1 = jmpbuf |
| 40 | sw v0, (1 * 4)(v1) # save sc_mask = sigblock(0) |
| 41 | move a0, zero |
| 42 | addu a1, sp, STAND_FRAME_SIZE # pointer to struct sigaltstack |
| 43 | jal sigaltstack |
| 44 | lw a0, SETJMP_FRAME_SIZE(sp) # restore jmpbuf |
| 45 | lw v1, STAND_FRAME_SIZE+8(sp) # get old ss_onstack |
| 46 | and v1, v1, 1 # extract onstack flag |
| 47 | sw v1, 0(a0) # save it in sc_onstack |
| 48 | lw ra, STAND_RA_OFFSET(sp) |
| 49 | addu sp, sp, SETJMP_FRAME_SIZE |
| 50 | blt v0, zero, botch # check for sigstack() error |
| 51 | sw ra, (2 * 4)(a0) # sc_pc = return address |
| 52 | li v0, 0xACEDBADE # sigcontext magic number |
| 53 | sw v0, ((ZERO + 3) * 4)(a0) # saved in sc_regs[0] |
| 54 | sw s0, ((S0 + 3) * 4)(a0) |
| 55 | sw s1, ((S1 + 3) * 4)(a0) |
| 56 | sw s2, ((S2 + 3) * 4)(a0) |
| 57 | sw s3, ((S3 + 3) * 4)(a0) |
| 58 | sw s4, ((S4 + 3) * 4)(a0) |
| 59 | sw s5, ((S5 + 3) * 4)(a0) |
| 60 | sw s6, ((S6 + 3) * 4)(a0) |
| 61 | sw s7, ((S7 + 3) * 4)(a0) |
| 62 | sw gp, ((GP + 3) * 4)(a0) |
| 63 | sw sp, ((SP + 3) * 4)(a0) |
| 64 | sw s8, ((S8 + 3) * 4)(a0) |
| 65 | li v0, 1 # be nice if we could tell |
| 66 | sw v0, (37 * 4)(a0) # sc_fpused = 1 |
| 67 | cfc1 v0, $31 |
| 68 | swc1 $f20, ((20 + 38) * 4)(a0) |
| 69 | swc1 $f21, ((21 + 38) * 4)(a0) |
| 70 | swc1 $f22, ((22 + 38) * 4)(a0) |
| 71 | swc1 $f23, ((23 + 38) * 4)(a0) |
| 72 | swc1 $f24, ((24 + 38) * 4)(a0) |
| 73 | swc1 $f25, ((25 + 38) * 4)(a0) |
| 74 | swc1 $f26, ((26 + 38) * 4)(a0) |
| 75 | swc1 $f27, ((27 + 38) * 4)(a0) |
| 76 | swc1 $f28, ((28 + 38) * 4)(a0) |
| 77 | swc1 $f29, ((29 + 38) * 4)(a0) |
| 78 | swc1 $f30, ((30 + 38) * 4)(a0) |
| 79 | swc1 $f31, ((31 + 38) * 4)(a0) |
| 80 | sw v0, ((32 + 38) * 4)(a0) |
| 81 | move v0, zero |
| 82 | j ra |
| 83 | END(setjmp) |
| 84 | |
| 85 | LEAF(longjmp) |
| 86 | sw a1, ((V0 + 3) * 4)(a0) # save return value in sc_regs[V0] |
| 87 | li v0, SYS_sigreturn |
| 88 | syscall |
| 89 | botch: |
| 90 | jal longjmperror |
| 91 | jal abort |
| 92 | END(longjmp) |