summaryrefslogtreecommitdiff
path: root/lib/libsetjmp/arm/setjmp.S
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libsetjmp/arm/setjmp.S')
-rw-r--r--lib/libsetjmp/arm/setjmp.S174
1 files changed, 174 insertions, 0 deletions
diff --git a/lib/libsetjmp/arm/setjmp.S b/lib/libsetjmp/arm/setjmp.S
new file mode 100644
index 0000000000..ee5ebd9169
--- /dev/null
+++ b/lib/libsetjmp/arm/setjmp.S
@@ -0,0 +1,174 @@
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#ifdef __APCS_26__
59#define RET movs pc, lr
60#elif defined(__thumb2__)
61#define RET bx lr
62#elif !defined(ROCKBOX_SUPPORTS_AN_ARMV4_NON_T_CPU)
63#define RET bx lr /* BX exists on v4T, v5 and more recent architectures */
64#else
65#define RET tst lr, #1; \
66 moveq pc, lr ; \
67.word 0xe12fff1e /* bx lr */
68#endif
69
70#ifdef __thumb2__
71.macro COND where when
72 i\where \when
73.endm
74#else
75.macro COND where when
76.endm
77#endif
78
79#if defined(__thumb2__)
80.syntax unified
81.macro MODE
82 .thumb
83 .thumb_func
84.endm
85.macro PROLOGUE name
86.endm
87
88#elif defined(__thumb__)
89#define MODE .thumb_func
90.macro PROLOGUE name
91 .code 16
92 bx pc
93 nop
94 .code 32
95SYM (.arm_start_of.\name):
96.endm
97#else /* Arm */
98#define MODE .code 32
99.macro PROLOGUE name
100.endm
101#endif
102
103.macro FUNC_START name
104 .text
105 .align 2
106 MODE
107 .globl SYM (\name)
108 TYPE (\name)
109SYM (\name):
110 PROLOGUE \name
111.endm
112
113.macro FUNC_END name
114 RET
115 SIZE (\name)
116.endm
117
118/* --------------------------------------------------------------------
119 int setjmp (jmp_buf);
120 -------------------------------------------------------------------- */
121
122 FUNC_START setjmp
123
124 /* Save all the callee-preserved registers into the jump buffer. */
125#ifdef __thumb2__
126 stmea a1!, { v1-v7, fp, ip, lr }
127 str sp, [a1],#+4
128#else
129 stmea a1!, { v1-v7, fp, ip, sp, lr }
130#endif
131
132#if 0 /* Simulator does not cope with FP instructions yet. */
133#ifndef __SOFTFP__
134 /* Save the floating point registers. */
135 sfmea f4, 4, [a1]
136#endif
137#endif
138 /* When setting up the jump buffer return 0. */
139 mov a1, #0
140
141 FUNC_END setjmp
142
143/* --------------------------------------------------------------------
144 volatile void longjmp (jmp_buf, int);
145 -------------------------------------------------------------------- */
146
147 FUNC_START longjmp
148
149 /* If we have stack extension code it ought to be handled here. */
150
151 /* Restore the registers, retrieving the state when setjmp() was called. */
152#ifdef __thumb2__
153 ldmfd a1!, { v1-v7, fp, ip, lr }
154 ldr sp, [a1],#+4
155#else
156 ldmfd a1!, { v1-v7, fp, ip, sp, lr }
157#endif
158
159#if 0 /* Simulator does not cope with FP instructions yet. */
160#ifndef __SOFTFP__
161 /* Restore floating point registers as well. */
162 lfmfd f4, 4, [a1]
163#endif
164#endif
165 /* Put the return value into the integer result register.
166 But if it is zero then return 1 instead. */
167 movs a1, a2
168#ifdef __thumb2__
169 it eq
170#endif
171 moveq a1, #1
172
173 FUNC_END longjmp
174