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