1*0c81fcd6SJens Wiklander/* 2*0c81fcd6SJens Wiklander * Copyright (c) 1994-2009 Red Hat, Inc. 3*0c81fcd6SJens Wiklander * All rights reserved. 4*0c81fcd6SJens Wiklander * 5*0c81fcd6SJens Wiklander * Redistribution and use in source and binary forms, with or without 6*0c81fcd6SJens Wiklander * modification, are permitted provided that the following conditions are met: 7*0c81fcd6SJens Wiklander * 8*0c81fcd6SJens Wiklander * 1. Redistributions of source code must retain the above copyright notice, 9*0c81fcd6SJens Wiklander * this list of conditions and the following disclaimer. 10*0c81fcd6SJens Wiklander * 11*0c81fcd6SJens Wiklander * 2. Redistributions in binary form must reproduce the above copyright notice, 12*0c81fcd6SJens Wiklander * this list of conditions and the following disclaimer in the documentation 13*0c81fcd6SJens Wiklander * and/or other materials provided with the distribution. 14*0c81fcd6SJens Wiklander * 15*0c81fcd6SJens Wiklander * 3. Neither the name of the copyright holder nor the names of its 16*0c81fcd6SJens Wiklander * contributors may be used to endorse or promote products derived from this 17*0c81fcd6SJens Wiklander * software without specific prior written permission. 18*0c81fcd6SJens Wiklander * 19*0c81fcd6SJens Wiklander * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20*0c81fcd6SJens Wiklander * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21*0c81fcd6SJens Wiklander * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22*0c81fcd6SJens Wiklander * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23*0c81fcd6SJens Wiklander * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24*0c81fcd6SJens Wiklander * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25*0c81fcd6SJens Wiklander * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26*0c81fcd6SJens Wiklander * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27*0c81fcd6SJens Wiklander * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28*0c81fcd6SJens Wiklander * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29*0c81fcd6SJens Wiklander * POSSIBILITY OF SUCH DAMAGE. 30*0c81fcd6SJens Wiklander */ 31*0c81fcd6SJens Wiklander/* This is a simple version of setjmp and longjmp. 32*0c81fcd6SJens Wiklander 33*0c81fcd6SJens Wiklander Nick Clifton, Cygnus Solutions, 13 June 1997. */ 34*0c81fcd6SJens Wiklander 35*0c81fcd6SJens Wiklander/* ANSI concatenation macros. */ 36*0c81fcd6SJens Wiklander#define CONCAT(a, b) CONCAT2(a, b) 37*0c81fcd6SJens Wiklander#define CONCAT2(a, b) a##b 38*0c81fcd6SJens Wiklander 39*0c81fcd6SJens Wiklander#ifndef __USER_LABEL_PREFIX__ 40*0c81fcd6SJens Wiklander#error __USER_LABEL_PREFIX__ not defined 41*0c81fcd6SJens Wiklander#endif 42*0c81fcd6SJens Wiklander 43*0c81fcd6SJens Wiklander#define SYM(x) CONCAT (__USER_LABEL_PREFIX__, x) 44*0c81fcd6SJens Wiklander 45*0c81fcd6SJens Wiklander#ifdef __ELF__ 46*0c81fcd6SJens Wiklander#define TYPE(x) .type SYM(x),function 47*0c81fcd6SJens Wiklander#define SIZE(x) .size SYM(x), . - SYM(x) 48*0c81fcd6SJens Wiklander#else 49*0c81fcd6SJens Wiklander#define TYPE(x) 50*0c81fcd6SJens Wiklander#define SIZE(x) 51*0c81fcd6SJens Wiklander#endif 52*0c81fcd6SJens Wiklander 53*0c81fcd6SJens Wiklander/* Arm/Thumb interworking support: 54*0c81fcd6SJens Wiklander 55*0c81fcd6SJens Wiklander The interworking scheme expects functions to use a BX instruction 56*0c81fcd6SJens Wiklander to return control to their parent. Since we need this code to work 57*0c81fcd6SJens Wiklander in both interworked and non-interworked environments as well as with 58*0c81fcd6SJens Wiklander older processors which do not have the BX instruction we do the 59*0c81fcd6SJens Wiklander following: 60*0c81fcd6SJens Wiklander Test the return address. 61*0c81fcd6SJens Wiklander If the bottom bit is clear perform an "old style" function exit. 62*0c81fcd6SJens Wiklander (We know that we are in ARM mode and returning to an ARM mode caller). 63*0c81fcd6SJens Wiklander Otherwise use the BX instruction to perform the function exit. 64*0c81fcd6SJens Wiklander 65*0c81fcd6SJens Wiklander We know that we will never attempt to perform the BX instruction on 66*0c81fcd6SJens Wiklander an older processor, because that kind of processor will never be 67*0c81fcd6SJens Wiklander interworked, and a return address with the bottom bit set will never 68*0c81fcd6SJens Wiklander be generated. 69*0c81fcd6SJens Wiklander 70*0c81fcd6SJens Wiklander In addition, we do not actually assemble the BX instruction as this would 71*0c81fcd6SJens Wiklander require us to tell the assembler that the processor is an ARM7TDMI and 72*0c81fcd6SJens Wiklander it would store this information in the binary. We want this binary to be 73*0c81fcd6SJens Wiklander able to be linked with binaries compiled for older processors however, so 74*0c81fcd6SJens Wiklander we do not want such information stored there. 75*0c81fcd6SJens Wiklander 76*0c81fcd6SJens Wiklander If we are running using the APCS-26 convention however, then we never 77*0c81fcd6SJens Wiklander test the bottom bit, because this is part of the processor status. 78*0c81fcd6SJens Wiklander Instead we just do a normal return, since we know that we cannot be 79*0c81fcd6SJens Wiklander returning to a Thumb caller - the Thumb does not support APCS-26. 80*0c81fcd6SJens Wiklander 81*0c81fcd6SJens Wiklander Function entry is much simpler. If we are compiling for the Thumb we 82*0c81fcd6SJens Wiklander just switch into ARM mode and then drop through into the rest of the 83*0c81fcd6SJens Wiklander function. The function exit code will take care of the restore to 84*0c81fcd6SJens Wiklander Thumb mode. 85*0c81fcd6SJens Wiklander 86*0c81fcd6SJens Wiklander For Thumb-2 do everything in Thumb mode. */ 87*0c81fcd6SJens Wiklander 88*0c81fcd6SJens Wiklander#if defined(__ARM_ARCH_6M__) 89*0c81fcd6SJens Wiklander/* ARMv6-M has to be implemented in Thumb mode. */ 90*0c81fcd6SJens Wiklander 91*0c81fcd6SJens Wiklander.thumb 92*0c81fcd6SJens Wiklander.thumb_func 93*0c81fcd6SJens Wiklander .globl SYM (setjmp) 94*0c81fcd6SJens Wiklander TYPE (setjmp) 95*0c81fcd6SJens WiklanderSYM (setjmp): 96*0c81fcd6SJens Wiklander /* Save registers in jump buffer. */ 97*0c81fcd6SJens Wiklander stmia r0!, {r4, r5, r6, r7} 98*0c81fcd6SJens Wiklander mov r1, r8 99*0c81fcd6SJens Wiklander mov r2, r9 100*0c81fcd6SJens Wiklander mov r3, r10 101*0c81fcd6SJens Wiklander mov r4, fp 102*0c81fcd6SJens Wiklander mov r5, sp 103*0c81fcd6SJens Wiklander mov r6, lr 104*0c81fcd6SJens Wiklander stmia r0!, {r1, r2, r3, r4, r5, r6} 105*0c81fcd6SJens Wiklander sub r0, r0, #40 106*0c81fcd6SJens Wiklander /* Restore callee-saved low regs. */ 107*0c81fcd6SJens Wiklander ldmia r0!, {r4, r5, r6, r7} 108*0c81fcd6SJens Wiklander /* Return zero. */ 109*0c81fcd6SJens Wiklander mov r0, #0 110*0c81fcd6SJens Wiklander bx lr 111*0c81fcd6SJens Wiklander 112*0c81fcd6SJens Wiklander.thumb_func 113*0c81fcd6SJens Wiklander .globl SYM (longjmp) 114*0c81fcd6SJens Wiklander TYPE (longjmp) 115*0c81fcd6SJens WiklanderSYM (longjmp): 116*0c81fcd6SJens Wiklander /* Restore High regs. */ 117*0c81fcd6SJens Wiklander add r0, r0, #16 118*0c81fcd6SJens Wiklander ldmia r0!, {r2, r3, r4, r5, r6} 119*0c81fcd6SJens Wiklander mov r8, r2 120*0c81fcd6SJens Wiklander mov r9, r3 121*0c81fcd6SJens Wiklander mov r10, r4 122*0c81fcd6SJens Wiklander mov fp, r5 123*0c81fcd6SJens Wiklander mov sp, r6 124*0c81fcd6SJens Wiklander ldmia r0!, {r3} /* lr */ 125*0c81fcd6SJens Wiklander /* Restore low regs. */ 126*0c81fcd6SJens Wiklander sub r0, r0, #40 127*0c81fcd6SJens Wiklander ldmia r0!, {r4, r5, r6, r7} 128*0c81fcd6SJens Wiklander /* Return the result argument, or 1 if it is zero. */ 129*0c81fcd6SJens Wiklander mov r0, r1 130*0c81fcd6SJens Wiklander bne 1f 131*0c81fcd6SJens Wiklander mov r0, #1 132*0c81fcd6SJens Wiklander1: 133*0c81fcd6SJens Wiklander bx r3 134*0c81fcd6SJens Wiklander 135*0c81fcd6SJens Wiklander#else 136*0c81fcd6SJens Wiklander 137*0c81fcd6SJens Wiklander#ifdef __APCS_26__ 138*0c81fcd6SJens Wiklander#define RET movs pc, lr 139*0c81fcd6SJens Wiklander#elif defined(__thumb2__) 140*0c81fcd6SJens Wiklander#define RET bx lr 141*0c81fcd6SJens Wiklander#else 142*0c81fcd6SJens Wiklander#define RET tst lr, #1; \ 143*0c81fcd6SJens Wiklander moveq pc, lr ; \ 144*0c81fcd6SJens Wiklander.word 0xe12fff1e /* bx lr */ 145*0c81fcd6SJens Wiklander#endif 146*0c81fcd6SJens Wiklander 147*0c81fcd6SJens Wiklander#ifdef __thumb2__ 148*0c81fcd6SJens Wiklander.macro COND where when 149*0c81fcd6SJens Wiklander i\where \when 150*0c81fcd6SJens Wiklander.endm 151*0c81fcd6SJens Wiklander#else 152*0c81fcd6SJens Wiklander.macro COND where when 153*0c81fcd6SJens Wiklander.endm 154*0c81fcd6SJens Wiklander#endif 155*0c81fcd6SJens Wiklander 156*0c81fcd6SJens Wiklander#if defined(__thumb2__) 157*0c81fcd6SJens Wiklander.syntax unified 158*0c81fcd6SJens Wiklander.macro MODE 159*0c81fcd6SJens Wiklander .thumb 160*0c81fcd6SJens Wiklander .thumb_func 161*0c81fcd6SJens Wiklander.endm 162*0c81fcd6SJens Wiklander.macro PROLOGUE name 163*0c81fcd6SJens Wiklander.endm 164*0c81fcd6SJens Wiklander 165*0c81fcd6SJens Wiklander#elif defined(__thumb__) 166*0c81fcd6SJens Wiklander#define MODE .thumb_func 167*0c81fcd6SJens Wiklander.macro PROLOGUE name 168*0c81fcd6SJens Wiklander .code 16 169*0c81fcd6SJens Wiklander bx pc 170*0c81fcd6SJens Wiklander nop 171*0c81fcd6SJens Wiklander .code 32 172*0c81fcd6SJens WiklanderSYM (.arm_start_of.\name): 173*0c81fcd6SJens Wiklander.endm 174*0c81fcd6SJens Wiklander#else /* Arm */ 175*0c81fcd6SJens Wiklander#define MODE .code 32 176*0c81fcd6SJens Wiklander.macro PROLOGUE name 177*0c81fcd6SJens Wiklander.endm 178*0c81fcd6SJens Wiklander#endif 179*0c81fcd6SJens Wiklander 180*0c81fcd6SJens Wiklander.macro FUNC_START name 181*0c81fcd6SJens Wiklander .text 182*0c81fcd6SJens Wiklander .align 2 183*0c81fcd6SJens Wiklander MODE 184*0c81fcd6SJens Wiklander .globl SYM (\name) 185*0c81fcd6SJens Wiklander TYPE (\name) 186*0c81fcd6SJens WiklanderSYM (\name): 187*0c81fcd6SJens Wiklander PROLOGUE \name 188*0c81fcd6SJens Wiklander.endm 189*0c81fcd6SJens Wiklander 190*0c81fcd6SJens Wiklander.macro FUNC_END name 191*0c81fcd6SJens Wiklander RET 192*0c81fcd6SJens Wiklander SIZE (\name) 193*0c81fcd6SJens Wiklander.endm 194*0c81fcd6SJens Wiklander 195*0c81fcd6SJens Wiklander/* -------------------------------------------------------------------- 196*0c81fcd6SJens Wiklander int setjmp (jmp_buf); 197*0c81fcd6SJens Wiklander -------------------------------------------------------------------- */ 198*0c81fcd6SJens Wiklander 199*0c81fcd6SJens Wiklander FUNC_START setjmp 200*0c81fcd6SJens Wiklander 201*0c81fcd6SJens Wiklander /* Save all the callee-preserved registers into the jump buffer. */ 202*0c81fcd6SJens Wiklander#ifdef __thumb2__ 203*0c81fcd6SJens Wiklander mov ip, sp 204*0c81fcd6SJens Wiklander stmea a1!, { v1-v7, fp, ip, lr } 205*0c81fcd6SJens Wiklander#else 206*0c81fcd6SJens Wiklander stmea a1!, { v1-v7, fp, ip, sp, lr } 207*0c81fcd6SJens Wiklander#endif 208*0c81fcd6SJens Wiklander 209*0c81fcd6SJens Wiklander#if 0 /* Simulator does not cope with FP instructions yet. */ 210*0c81fcd6SJens Wiklander#ifndef __SOFTFP__ 211*0c81fcd6SJens Wiklander /* Save the floating point registers. */ 212*0c81fcd6SJens Wiklander sfmea f4, 4, [a1] 213*0c81fcd6SJens Wiklander#endif 214*0c81fcd6SJens Wiklander#endif 215*0c81fcd6SJens Wiklander /* When setting up the jump buffer return 0. */ 216*0c81fcd6SJens Wiklander mov a1, #0 217*0c81fcd6SJens Wiklander 218*0c81fcd6SJens Wiklander FUNC_END setjmp 219*0c81fcd6SJens Wiklander 220*0c81fcd6SJens Wiklander/* -------------------------------------------------------------------- 221*0c81fcd6SJens Wiklander volatile void longjmp (jmp_buf, int); 222*0c81fcd6SJens Wiklander -------------------------------------------------------------------- */ 223*0c81fcd6SJens Wiklander 224*0c81fcd6SJens Wiklander FUNC_START longjmp 225*0c81fcd6SJens Wiklander 226*0c81fcd6SJens Wiklander /* If we have stack extension code it ought to be handled here. */ 227*0c81fcd6SJens Wiklander 228*0c81fcd6SJens Wiklander /* Restore the registers, retrieving the state when setjmp() was called. */ 229*0c81fcd6SJens Wiklander#ifdef __thumb2__ 230*0c81fcd6SJens Wiklander ldmfd a1!, { v1-v7, fp, ip, lr } 231*0c81fcd6SJens Wiklander mov sp, ip 232*0c81fcd6SJens Wiklander#else 233*0c81fcd6SJens Wiklander ldmfd a1!, { v1-v7, fp, ip, sp, lr } 234*0c81fcd6SJens Wiklander#endif 235*0c81fcd6SJens Wiklander 236*0c81fcd6SJens Wiklander#if 0 /* Simulator does not cope with FP instructions yet. */ 237*0c81fcd6SJens Wiklander#ifndef __SOFTFP__ 238*0c81fcd6SJens Wiklander /* Restore floating point registers as well. */ 239*0c81fcd6SJens Wiklander lfmfd f4, 4, [a1] 240*0c81fcd6SJens Wiklander#endif 241*0c81fcd6SJens Wiklander#endif 242*0c81fcd6SJens Wiklander /* Put the return value into the integer result register. 243*0c81fcd6SJens Wiklander But if it is zero then return 1 instead. */ 244*0c81fcd6SJens Wiklander movs a1, a2 245*0c81fcd6SJens Wiklander#ifdef __thumb2__ 246*0c81fcd6SJens Wiklander it eq 247*0c81fcd6SJens Wiklander#endif 248*0c81fcd6SJens Wiklander moveq a1, #1 249*0c81fcd6SJens Wiklander 250*0c81fcd6SJens Wiklander FUNC_END longjmp 251*0c81fcd6SJens Wiklander#endif 252