root/lib/lua/setjmp.S

/* [<][>][^][v][top][bottom][index][help] */
   1 /* This is a simple version of setjmp and longjmp.
   2 
   3    Nick Clifton, Cygnus Solutions, 13 June 1997.  */
   4 
   5 /* ANSI concatenation macros.  */
   6 #define CONCAT(a, b)  CONCAT2(a, b)
   7 #define CONCAT2(a, b) a##b
   8 
   9 #ifndef __USER_LABEL_PREFIX__
  10 #error  __USER_LABEL_PREFIX__ not defined
  11 #endif
  12 
  13 #define SYM(x) CONCAT (__USER_LABEL_PREFIX__, x)
  14 
  15 #ifdef __ELF__
  16 #define TYPE(x) .type SYM(x),function
  17 #define SIZE(x) .size SYM(x), . - SYM(x)
  18 #else
  19 #define TYPE(x)
  20 #define SIZE(x)
  21 #endif
  22 
  23 /* Arm/Thumb interworking support:
  24 
  25    The interworking scheme expects functions to use a BX instruction
  26    to return control to their parent.  Since we need this code to work
  27    in both interworked and non-interworked environments as well as with
  28    older processors which do not have the BX instruction we do the 
  29    following:
  30         Test the return address.
  31         If the bottom bit is clear perform an "old style" function exit.
  32         (We know that we are in ARM mode and returning to an ARM mode caller).
  33         Otherwise use the BX instruction to perform the function exit.
  34 
  35    We know that we will never attempt to perform the BX instruction on 
  36    an older processor, because that kind of processor will never be 
  37    interworked, and a return address with the bottom bit set will never 
  38    be generated.
  39 
  40    In addition, we do not actually assemble the BX instruction as this would
  41    require us to tell the assembler that the processor is an ARM7TDMI and
  42    it would store this information in the binary.  We want this binary to be
  43    able to be linked with binaries compiled for older processors however, so
  44    we do not want such information stored there.  
  45 
  46    If we are running using the APCS-26 convention however, then we never
  47    test the bottom bit, because this is part of the processor status.  
  48    Instead we just do a normal return, since we know that we cannot be 
  49    returning to a Thumb caller - the Thumb does not support APCS-26.
  50         
  51    Function entry is much simpler.  If we are compiling for the Thumb we 
  52    just switch into ARM mode and then drop through into the rest of the
  53    function.  The function exit code will take care of the restore to
  54    Thumb mode.
  55    
  56    For Thumb-2 do everything in Thumb mode.  */
  57 
  58 #if defined(__ARM_ARCH_6M__)
  59 /* ARMv6-M has to be implemented in Thumb mode.  */
  60 
  61 .thumb
  62 .thumb_func
  63         .globl SYM (setjmp)
  64         TYPE (setjmp)
  65 SYM (setjmp):
  66         /* Save registers in jump buffer.  */
  67         stmia   r0!, {r4, r5, r6, r7}
  68         mov     r1, r8
  69         mov     r2, r9
  70         mov     r3, r10
  71         mov     r4, fp
  72         mov     r5, sp
  73         mov     r6, lr
  74         stmia   r0!, {r1, r2, r3, r4, r5, r6}
  75         sub     r0, r0, #40
  76         /* Restore callee-saved low regs.  */
  77         ldmia   r0!, {r4, r5, r6, r7}
  78         /* Return zero.  */
  79         mov     r0, #0
  80         bx lr
  81 
  82 .thumb_func
  83         .globl SYM (longjmp)
  84         TYPE (longjmp)
  85 SYM (longjmp):
  86         /* Restore High regs.  */
  87         add     r0, r0, #16
  88         ldmia   r0!, {r2, r3, r4, r5, r6}
  89         mov     r8, r2
  90         mov     r9, r3
  91         mov     r10, r4
  92         mov     fp, r5
  93         mov     sp, r6
  94         ldmia   r0!, {r3} /* lr */
  95         /* Restore low regs.  */
  96         sub     r0, r0, #40
  97         ldmia   r0!, {r4, r5, r6, r7}
  98         /* Return the result argument, or 1 if it is zero.  */
  99         mov     r0, r1
 100         bne     1f
 101         mov     r0, #1
 102 1:
 103         bx      r3
 104 
 105 #else
 106 
 107 #ifdef __APCS_26__
 108 #define RET     movs            pc, lr
 109 #elif defined(__thumb2__)
 110 #define RET     bx lr
 111 #else
 112 #define RET     tst             lr, #1; \
 113                 moveq           pc, lr ; \
 114 .word           0xe12fff1e      /* bx lr */
 115 #endif
 116 
 117 #ifdef __thumb2__
 118 .macro COND where when 
 119         i\where \when
 120 .endm
 121 #else
 122 .macro COND where when 
 123 .endm
 124 #endif
 125 
 126 #if defined(__thumb2__)
 127 .syntax unified
 128 .macro MODE
 129         .thumb
 130         .thumb_func
 131 .endm
 132 .macro PROLOGUE name
 133 .endm
 134 
 135 #elif defined(__thumb__)
 136 #define MODE            .thumb_func
 137 .macro PROLOGUE name
 138         .code 16
 139         bx      pc
 140         nop     
 141         .code 32
 142 SYM (.arm_start_of.\name):
 143 .endm
 144 #else /* Arm */
 145 #define MODE            .code 32
 146 .macro PROLOGUE name
 147 .endm
 148 #endif
 149         
 150 .macro FUNC_START name
 151         .text
 152         .align 2
 153         MODE
 154         .globl SYM (\name)
 155         TYPE (\name)
 156 SYM (\name):
 157         PROLOGUE \name
 158 .endm
 159 
 160 .macro FUNC_END name
 161         RET
 162         SIZE (\name)
 163 .endm
 164         
 165 /* --------------------------------------------------------------------
 166                  int setjmp (jmp_buf); 
 167    -------------------------------------------------------------------- */
 168         
 169         FUNC_START setjmp
 170 
 171         /* Save all the callee-preserved registers into the jump buffer.  */
 172 #ifdef __thumb2__
 173         mov             ip, sp
 174         stmea           a1!, { v1-v7, fp, ip, lr }
 175 #else
 176         stmea           a1!, { v1-v7, fp, ip, sp, lr }
 177 #endif
 178         
 179 #if 0   /* Simulator does not cope with FP instructions yet.  */
 180 #ifndef __SOFTFP__
 181         /* Save the floating point registers.  */
 182         sfmea           f4, 4, [a1]
 183 #endif
 184 #endif          
 185         /* When setting up the jump buffer return 0.  */
 186         mov             a1, #0
 187 
 188         FUNC_END setjmp
 189         
 190 /* --------------------------------------------------------------------
 191                 volatile void longjmp (jmp_buf, int);
 192    -------------------------------------------------------------------- */
 193         
 194         FUNC_START longjmp
 195 
 196         /* If we have stack extension code it ought to be handled here.  */
 197         
 198         /* Restore the registers, retrieving the state when setjmp() was called.  */
 199 #ifdef __thumb2__
 200         ldmfd           a1!, { v1-v7, fp, ip, lr }
 201         mov             sp, ip
 202 #else
 203         ldmfd           a1!, { v1-v7, fp, ip, sp, lr }
 204 #endif
 205         
 206 #if 0   /* Simulator does not cope with FP instructions yet.  */
 207 #ifndef __SOFTFP__
 208         /* Restore floating point registers as well.  */
 209         lfmfd           f4, 4, [a1]
 210 #endif
 211 #endif  
 212         /* Put the return value into the integer result register.
 213            But if it is zero then return 1 instead.  */ 
 214         movs            a1, a2
 215 #ifdef __thumb2__
 216         it              eq
 217 #endif
 218         moveq           a1, #1
 219 
 220         FUNC_END longjmp
 221 #endif

/* [<][>][^][v][top][bottom][index][help] */