1 /* Derived from: $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 <asm-generic/portability.h> 33 #include <machine/asm.h> 34 #include <machine/regnum.h> 35 36 #include "jboffsets.h" 37 38 /* 39 * setjmp, longjmp implementation for libc. 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 60 61 NON_LEAF(WRAP(setjmp), FRAMESZ, ra) 62 .mask 0x80000000, RAOFF 63 PTR_SUBU sp, FRAMESZ # allocate stack frame 64 SETUP_GP64(GPOFF, WRAP(setjmp)) 65 SAVE_GP(GPOFF) 66 .set reorder 67 REG_S ra, RAOFF(sp) # save state 68 REG_S a0, A0OFF(sp) 69 70 move a0, zero # get current signal mask 71 jal sigblock 72 73 REG_L v1, A0OFF(sp) # v1 = jmpbuf 74 REG_S v0, JB_MASK(v1) # save sc_mask = sigblock(0) 75 76 REG_L a0, A0OFF(sp) # restore jmpbuf 77 REG_L ra, RAOFF(sp) 78 REG_S ra, JB_PC(a0) # sc_pc = return address 79 #if defined(__mips64) 80 dli v0, MAGIC_SETJMP 81 #else 82 li v0, MAGIC_SETJMP 83 #endif 84 REG_S v0, JB_MAGIC(a0) 85 REG_S s0, JB_S0(a0) 86 REG_S s1, JB_S1(a0) 87 REG_S s2, JB_S2(a0) 88 REG_S s3, JB_S3(a0) 89 REG_S s4, JB_S4(a0) 90 REG_S s5, JB_S5(a0) 91 REG_S s6, JB_S6(a0) 92 REG_S s7, JB_S7(a0) 93 REG_S s8, JB_S8(a0) 94 REG_L v0, GPOFF(sp) 95 REG_S v0, JB_GP(a0) 96 PTR_ADDU v0, sp, FRAMESZ 97 REG_S v0, JB_SP(a0) 98 99 #if !defined(SOFTFLOAT) 100 /* 101 * Would be nice if we could tell if the FP registers are currently being used. 102 * Assume they are, and use pointer to jmp_buf in a0 to save FP registers and the 103 * jmp_buf.fpused flag. 104 */ 105 li v0, 1 # v0 = 1 106 REG_S v0, JB_FPUSED(a0) # a0->jb_fpused = v0:1 107 cfc1 v0, $31 108 #if _MIPS_FPSET == 32 109 FPREG64_S($f20, JB_F20, a0) 110 FPREG64_S($f21, JB_F21, a0) 111 FPREG64_S($f22, JB_F22, a0) 112 FPREG64_S($f23, JB_F23, a0) 113 FPREG64_S($f24, JB_F24, a0) 114 FPREG64_S($f25, JB_F25, a0) 115 FPREG64_S($f26, JB_F26, a0) 116 FPREG64_S($f27, JB_F27, a0) 117 FPREG64_S($f28, JB_F28, a0) 118 FPREG64_S($f29, JB_F29, a0) 119 FPREG64_S($f30, JB_F30, a0) 120 FPREG64_S($f31, JB_F31, a0) 121 #else 122 swc1 $f20, JB_F20(a0) 123 swc1 $f21, JB_F21(a0) 124 swc1 $f22, JB_F22(a0) 125 swc1 $f23, JB_F23(a0) 126 swc1 $f24, JB_F24(a0) 127 swc1 $f25, JB_F25(a0) 128 swc1 $f26, JB_F26(a0) 129 swc1 $f27, JB_F27(a0) 130 swc1 $f28, JB_F28(a0) 131 swc1 $f29, JB_F29(a0) 132 swc1 $f30, JB_F30(a0) 133 swc1 $f31, JB_F31(a0) 134 #endif 135 REG_S v0, JB_FSR(a0) 136 #endif /* !SOFTFLOAT */ 137 move v0, zero 138 RESTORE_GP64 139 PTR_ADDU sp, FRAMESZ 140 j ra 141 142 botch: 143 jal longjmperror 144 jal abort 145 RESTORE_GP64 146 PTR_ADDU sp, FRAMESZ 147 END(WRAP(setjmp)) 148 149 150 LEAF(WRAP(longjmp), FRAMESZ) 151 PTR_SUBU sp, FRAMESZ 152 SETUP_GP64(GPOFF, WRAP(longjmp)) 153 SAVE_GP(GPOFF) 154 .set reorder 155 sw a1, A1OFF(sp) 156 sw a0, A0OFF(sp) 157 158 lw a0, JB_MASK(a0) 159 jal sigsetmask 160 161 lw a0, A0OFF(sp) 162 lw a1, A1OFF(sp) 163 164 .set noreorder 165 REG_L v0, JB_MAGIC(a0) 166 bne v0, MAGIC_SETJMP, botch # jump if error 167 REG_L ra, JB_PC(a0) 168 REG_L s0, JB_S0(a0) 169 REG_L s1, JB_S1(a0) 170 REG_L s2, JB_S2(a0) 171 REG_L s3, JB_S3(a0) 172 REG_L s4, JB_S4(a0) 173 REG_L s5, JB_S5(a0) 174 REG_L s6, JB_S6(a0) 175 REG_L s7, JB_S7(a0) 176 REG_L s8, JB_S8(a0) 177 REG_L gp, JB_GP(a0) 178 REG_L sp, JB_SP(a0) 179 180 #if !defined(SOFTFLOAT) 181 REG_L v0, JB_FSR(a0) 182 ctc1 v0, $31 183 #if _MIPS_FPSET == 32 184 FPREG64_L($f20, JB_F20, a0) 185 FPREG64_L($f21, JB_F21, a0) 186 FPREG64_L($f22, JB_F22, a0) 187 FPREG64_L($f23, JB_F23, a0) 188 FPREG64_L($f24, JB_F24, a0) 189 FPREG64_L($f25, JB_F25, a0) 190 FPREG64_L($f26, JB_F26, a0) 191 FPREG64_L($f27, JB_F27, a0) 192 FPREG64_L($f28, JB_F28, a0) 193 FPREG64_L($f29, JB_F29, a0) 194 FPREG64_L($f30, JB_F30, a0) 195 FPREG64_L($f31, JB_F31, a0) 196 #else 197 lwc1 $f20, JB_F20(a0) 198 lwc1 $f21, JB_F21(a0) 199 lwc1 $f22, JB_F22(a0) 200 lwc1 $f23, JB_F23(a0) 201 lwc1 $f24, JB_F24(a0) 202 lwc1 $f25, JB_F25(a0) 203 lwc1 $f26, JB_F26(a0) 204 lwc1 $f27, JB_F27(a0) 205 lwc1 $f28, JB_F28(a0) 206 lwc1 $f29, JB_F29(a0) 207 lwc1 $f30, JB_F30(a0) 208 lwc1 $f31, JB_F31(a0) 209 #endif 210 #endif /* !SOFTFLOAT */ 211 bne a1, zero, 1f 212 nop 213 li a1, 1 # never return 0! 214 1: 215 j ra 216 move v0, a1 217 218 END(WRAP(longjmp)) 219