Home | History | Annotate | Download | only in bionic
      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