1 /* $OpenBSD: setjmp.S,v 1.5 2005/08/07 16:40:15 espie Exp $ */ 2 3 /* 4 * Copyright (c) 2001-2002 Opsycon AB (www.opsycon.se / www.opsycon.com) 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of Opsycon AB nor the names of its contributors 15 * may be used to endorse or promote products derived from this software 16 * without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 19 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 */ 31 32 #include <machine/asm.h> 33 #include <machine/regnum.h> 34 #include <machine/signal.h> 35 36 /* 37 * setjmp, longjmp implementation for libc. this code depends 38 * on the layout of the struct sigcontext in machine/signal.h. 39 * 40 */ 41 42 FRAMESZ= MKFSIZ(2,6) 43 A1OFF= FRAMESZ-4*REGSZ 44 A0OFF= FRAMESZ-3*REGSZ 45 GPOFF= FRAMESZ-2*REGSZ 46 RAOFF= FRAMESZ-1*REGSZ 47 48 #define FPREG64_S(FPR, OFF, BASE) \ 49 swc1 FPR, OFF(BASE) ; \ 50 mfhc1 t0, FPR ; \ 51 sw t0, OFF+4(BASE) ; 52 53 #define FPREG64_L(FPR, OFF, BASE) \ 54 lw t0, OFF+4(BASE) ; \ 55 lw t1, OFF(BASE) ; \ 56 mtc1 t1, FPR ; \ 57 mthc1 t0, FPR ; \ 58 59 NON_LEAF(setjmp, FRAMESZ, ra) 60 .mask 0x80000000, RAOFF 61 PTR_SUBU sp, FRAMESZ # allocate stack frame 62 SETUP_GP64(GPOFF, setjmp) 63 SAVE_GP(GPOFF) 64 .set reorder 65 REG_S ra, RAOFF(sp) # save state 66 REG_S a0, A0OFF(sp) 67 68 move a0, zero # get current signal mask 69 jal sigblock 70 71 REG_L v1, A0OFF(sp) # v1 = jmpbuf 72 REG_S v0, SC_MASK(v1) # save sc_mask = sigblock(0) 73 74 REG_L a0, A0OFF(sp) # restore jmpbuf 75 REG_L ra, RAOFF(sp) 76 REG_S ra, SC_PC(a0) # sc_pc = return address 77 #if defined(__mips64) 78 dli v0, 0xACEDBADE # sigcontext magic number 79 #else 80 li v0, 0xACEDBADE # sigcontext magic number 81 #endif 82 REG_S v0, SC_REGS+ZERO*REGSZ(a0) 83 REG_S s0, SC_REGS+S0*REGSZ(a0) 84 REG_S s1, SC_REGS+S1*REGSZ(a0) 85 REG_S s2, SC_REGS+S2*REGSZ(a0) 86 REG_S s3, SC_REGS+S3*REGSZ(a0) 87 REG_S s4, SC_REGS+S4*REGSZ(a0) 88 REG_S s5, SC_REGS+S5*REGSZ(a0) 89 REG_S s6, SC_REGS+S6*REGSZ(a0) 90 REG_S s7, SC_REGS+S7*REGSZ(a0) 91 REG_S s8, SC_REGS+S8*REGSZ(a0) 92 REG_L v0, GPOFF(sp) 93 REG_S v0, SC_REGS+GP*REGSZ(a0) 94 PTR_ADDU v0, sp, FRAMESZ 95 REG_S v0, SC_REGS+SP*REGSZ(a0) 96 97 #if !defined(SOFTFLOAT) 98 li v0, 1 # be nice if we could tell 99 REG_S v0, SC_FPUSED(a0) # sc_fpused = 1 100 cfc1 v0, $31 101 #if _MIPS_FPSET == 32 102 FPREG64_S($f20, SC_FPREGS+((F20-F0)*REGSZ_FP), a0) 103 FPREG64_S($f21, SC_FPREGS+((F21-F0)*REGSZ_FP), a0) 104 FPREG64_S($f22, SC_FPREGS+((F22-F0)*REGSZ_FP), a0) 105 FPREG64_S($f23, SC_FPREGS+((F23-F0)*REGSZ_FP), a0) 106 FPREG64_S($f24, SC_FPREGS+((F24-F0)*REGSZ_FP), a0) 107 FPREG64_S($f25, SC_FPREGS+((F25-F0)*REGSZ_FP), a0) 108 FPREG64_S($f26, SC_FPREGS+((F26-F0)*REGSZ_FP), a0) 109 FPREG64_S($f27, SC_FPREGS+((F27-F0)*REGSZ_FP), a0) 110 FPREG64_S($f28, SC_FPREGS+((F28-F0)*REGSZ_FP), a0) 111 FPREG64_S($f29, SC_FPREGS+((F29-F0)*REGSZ_FP), a0) 112 FPREG64_S($f30, SC_FPREGS+((F30-F0)*REGSZ_FP), a0) 113 FPREG64_S($f31, SC_FPREGS+((F31-F0)*REGSZ_FP), a0) 114 #else 115 swc1 $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0) 116 swc1 $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0) 117 swc1 $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0) 118 swc1 $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0) 119 swc1 $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0) 120 swc1 $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0) 121 swc1 $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0) 122 swc1 $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0) 123 swc1 $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0) 124 swc1 $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0) 125 swc1 $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0) 126 swc1 $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0) 127 #endif 128 REG_S v0, SC_FPREGS+((FSR-F0)*REGSZ)(a0) 129 #endif /* !SOFTFLOAT */ 130 move v0, zero 131 RESTORE_GP64 132 PTR_ADDU sp, FRAMESZ 133 j ra 134 135 botch: 136 jal longjmperror 137 jal abort 138 RESTORE_GP64 139 PTR_ADDU sp, FRAMESZ 140 END(setjmp) 141 142 143 LEAF(longjmp, FRAMESZ) 144 PTR_SUBU sp, FRAMESZ 145 SETUP_GP64(GPOFF, longjmp) 146 SAVE_GP(GPOFF) 147 .set reorder 148 sw a1, A1OFF(sp) 149 sw a0, A0OFF(sp) 150 151 lw a0, SC_MASK(a0) 152 jal sigsetmask 153 154 lw a0, A0OFF(sp) 155 lw a1, A1OFF(sp) 156 157 .set noreorder 158 REG_L v0, SC_REGS+ZERO*REGSZ(a0) 159 bne v0, 0xACEDBADE, botch # jump if error 160 REG_L ra, SC_PC(a0) 161 REG_L s0, SC_REGS+S0*REGSZ(a0) 162 REG_L s1, SC_REGS+S1*REGSZ(a0) 163 REG_L s2, SC_REGS+S2*REGSZ(a0) 164 REG_L s3, SC_REGS+S3*REGSZ(a0) 165 REG_L s4, SC_REGS+S4*REGSZ(a0) 166 REG_L s5, SC_REGS+S5*REGSZ(a0) 167 REG_L s6, SC_REGS+S6*REGSZ(a0) 168 REG_L s7, SC_REGS+S7*REGSZ(a0) 169 REG_L s8, SC_REGS+S8*REGSZ(a0) 170 REG_L gp, SC_REGS+GP*REGSZ(a0) 171 REG_L sp, SC_REGS+SP*REGSZ(a0) 172 173 #if !defined(SOFTFLOAT) 174 REG_L v0, SC_FPREGS+((FSR-F0)*REGSZ)(a0) 175 ctc1 v0, $31 176 #if _MIPS_FPSET == 32 177 FPREG64_L($f20, SC_FPREGS+((F20-F0)*REGSZ_FP), a0) 178 FPREG64_L($f21, SC_FPREGS+((F21-F0)*REGSZ_FP), a0) 179 FPREG64_L($f22, SC_FPREGS+((F22-F0)*REGSZ_FP), a0) 180 FPREG64_L($f23, SC_FPREGS+((F23-F0)*REGSZ_FP), a0) 181 FPREG64_L($f24, SC_FPREGS+((F24-F0)*REGSZ_FP), a0) 182 FPREG64_L($f25, SC_FPREGS+((F25-F0)*REGSZ_FP), a0) 183 FPREG64_L($f26, SC_FPREGS+((F26-F0)*REGSZ_FP), a0) 184 FPREG64_L($f27, SC_FPREGS+((F27-F0)*REGSZ_FP), a0) 185 FPREG64_L($f28, SC_FPREGS+((F28-F0)*REGSZ_FP), a0) 186 FPREG64_L($f29, SC_FPREGS+((F29-F0)*REGSZ_FP), a0) 187 FPREG64_L($f30, SC_FPREGS+((F30-F0)*REGSZ_FP), a0) 188 FPREG64_L($f31, SC_FPREGS+((F31-F0)*REGSZ_FP), a0) 189 #else 190 lwc1 $f20, SC_FPREGS+((F20-F0)*REGSZ_FP)(a0) 191 lwc1 $f21, SC_FPREGS+((F21-F0)*REGSZ_FP)(a0) 192 lwc1 $f22, SC_FPREGS+((F22-F0)*REGSZ_FP)(a0) 193 lwc1 $f23, SC_FPREGS+((F23-F0)*REGSZ_FP)(a0) 194 lwc1 $f24, SC_FPREGS+((F24-F0)*REGSZ_FP)(a0) 195 lwc1 $f25, SC_FPREGS+((F25-F0)*REGSZ_FP)(a0) 196 lwc1 $f26, SC_FPREGS+((F26-F0)*REGSZ_FP)(a0) 197 lwc1 $f27, SC_FPREGS+((F27-F0)*REGSZ_FP)(a0) 198 lwc1 $f28, SC_FPREGS+((F28-F0)*REGSZ_FP)(a0) 199 lwc1 $f29, SC_FPREGS+((F29-F0)*REGSZ_FP)(a0) 200 lwc1 $f30, SC_FPREGS+((F30-F0)*REGSZ_FP)(a0) 201 lwc1 $f31, SC_FPREGS+((F31-F0)*REGSZ_FP)(a0) 202 #endif 203 #endif /* !SOFTFLOAT */ 204 bne a1, zero, 1f 205 nop 206 li a1, 1 # never return 0! 207 1: 208 j ra 209 move v0, a1 210 211 END(longjmp) 212