]>
Commit | Line | Data |
---|---|---|
d80b3f3c | 1 | /* Assembler macros for ARM. |
d4697bc9 | 2 | Copyright (C) 1997-2014 Free Software Foundation, Inc. |
d80b3f3c UD |
3 | This file is part of the GNU C Library. |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
3214b89b AJ |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
d80b3f3c UD |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
3214b89b | 13 | Lesser General Public License for more details. |
d80b3f3c | 14 | |
3214b89b | 15 | You should have received a copy of the GNU Lesser General Public |
ab84e3ff PE |
16 | License along with the GNU C Library. If not, see |
17 | <http://www.gnu.org/licenses/>. */ | |
d80b3f3c UD |
18 | |
19 | #include <sysdeps/generic/sysdep.h> | |
94fd527b | 20 | #include <features.h> |
d80b3f3c | 21 | |
3377126b RH |
22 | /* The __ARM_ARCH define is provided by gcc 4.8. Construct it otherwise. */ |
23 | #ifndef __ARM_ARCH | |
24 | # ifdef __ARM_ARCH_2__ | |
25 | # define __ARM_ARCH 2 | |
26 | # elif defined (__ARM_ARCH_3__) || defined (__ARM_ARCH_3M__) | |
27 | # define __ARM_ARCH 3 | |
28 | # elif defined (__ARM_ARCH_4__) || defined (__ARM_ARCH_4T__) | |
29 | # define __ARM_ARCH 4 | |
30 | # elif defined (__ARM_ARCH_5__) || defined (__ARM_ARCH_5E__) \ | |
31 | || defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) \ | |
32 | || defined(__ARM_ARCH_5TEJ__) | |
33 | # define __ARM_ARCH 5 | |
34 | # elif defined (__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ | |
35 | || defined (__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \ | |
36 | || defined (__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) | |
37 | # define __ARM_ARCH 6 | |
38 | # elif defined (__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ | |
39 | || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ | |
40 | || defined(__ARM_ARCH_7EM__) | |
41 | # define __ARM_ARCH 7 | |
42 | # else | |
43 | # error unknown arm architecture | |
44 | # endif | |
45 | #endif | |
46 | ||
47 | #if __ARM_ARCH > 4 || defined (__ARM_ARCH_4T__) | |
48 | # define ARCH_HAS_BX | |
49 | #endif | |
50 | #if __ARM_ARCH > 4 | |
51 | # define ARCH_HAS_BLX | |
52 | #endif | |
79fd8731 RH |
53 | #if __ARM_ARCH > 6 || defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6ZK__) |
54 | # define ARCH_HAS_HARD_TP | |
55 | #endif | |
3377126b RH |
56 | #if __ARM_ARCH > 6 || defined (__ARM_ARCH_6T2__) |
57 | # define ARCH_HAS_T2 | |
47f0752a RM |
58 | #endif |
59 | ||
e0ebc3b2 | 60 | #ifdef __ASSEMBLER__ |
d80b3f3c UD |
61 | |
62 | /* Syntactic details of assembler. */ | |
63 | ||
0c56aa63 | 64 | #define ALIGNARG(log2) log2 |
d80b3f3c UD |
65 | #define ASM_SIZE_DIRECTIVE(name) .size name,.-name |
66 | ||
fe0955cd UD |
67 | #define PLTJMP(_x) _x##(PLT) |
68 | ||
3377126b | 69 | #ifdef ARCH_HAS_BX |
46dede0c RH |
70 | # define BX(R) bx R |
71 | # define BXC(C, R) bx##C R | |
3377126b | 72 | # ifdef ARCH_HAS_BLX |
46dede0c | 73 | # define BLX(R) blx R |
3377126b RH |
74 | # else |
75 | # define BLX(R) mov lr, pc; bx R | |
46dede0c | 76 | # endif |
644d8224 | 77 | #else |
46dede0c RH |
78 | # define BX(R) mov pc, R |
79 | # define BXC(C, R) mov##C pc, R | |
80 | # define BLX(R) mov lr, pc; mov pc, R | |
d80b3f3c UD |
81 | #endif |
82 | ||
46dede0c RH |
83 | #define DO_RET(R) BX(R) |
84 | #define RETINSTR(C, R) BXC(C, R) | |
85 | ||
d80b3f3c | 86 | /* Define an entry point visible from C. */ |
63cc0e75 RH |
87 | #define ENTRY(name) \ |
88 | .globl C_SYMBOL_NAME(name); \ | |
89 | .type C_SYMBOL_NAME(name),%function; \ | |
90 | .align ALIGNARG(4); \ | |
91 | C_LABEL(name) \ | |
92 | CFI_SECTIONS; \ | |
93 | cfi_startproc; \ | |
94 | CALL_MCOUNT | |
95 | ||
96 | #define CFI_SECTIONS \ | |
97 | .cfi_sections .debug_frame | |
f4564ff0 | 98 | |
d80b3f3c | 99 | #undef END |
63cc0e75 RH |
100 | #define END(name) \ |
101 | cfi_endproc; \ | |
102 | ASM_SIZE_DIRECTIVE(name) | |
d80b3f3c UD |
103 | |
104 | /* If compiled for profiling, call `mcount' at the start of each function. */ | |
105 | #ifdef PROF | |
84664590 JM |
106 | /* Call __gnu_mcount_nc if GCC >= 4.4. */ |
107 | #if __GNUC_PREREQ(4,4) | |
63cc0e75 | 108 | #define CALL_MCOUNT \ |
55668624 | 109 | push {lr}; \ |
63cc0e75 RH |
110 | cfi_adjust_cfa_offset (4); \ |
111 | cfi_rel_offset (lr, 0); \ | |
112 | bl PLTJMP(mcount); \ | |
113 | cfi_adjust_cfa_offset (-4); \ | |
114 | cfi_restore (lr) | |
94fd527b | 115 | #else /* else call _mcount */ |
63cc0e75 | 116 | #define CALL_MCOUNT \ |
55668624 | 117 | push {lr}; \ |
63cc0e75 RH |
118 | cfi_adjust_cfa_offset (4); \ |
119 | cfi_rel_offset (lr, 0); \ | |
120 | bl PLTJMP(mcount); \ | |
55668624 | 121 | pops {lr}; \ |
63cc0e75 RH |
122 | cfi_adjust_cfa_offset (-4); \ |
123 | cfi_restore (lr) | |
94fd527b | 124 | #endif |
d80b3f3c UD |
125 | #else |
126 | #define CALL_MCOUNT /* Do nothing. */ | |
127 | #endif | |
128 | ||
d80b3f3c UD |
129 | /* Since C identifiers are not normally prefixed with an underscore |
130 | on this system, the asm identifier `syscall_error' intrudes on the | |
131 | C name space. Make sure we use an innocuous name. */ | |
132 | #define syscall_error __syscall_error | |
84664590 | 133 | #if __GNUC_PREREQ(4,4) |
94fd527b MM |
134 | #define mcount __gnu_mcount_nc |
135 | #else | |
d80b3f3c UD |
136 | #define mcount _mcount |
137 | #endif | |
138 | ||
27489557 DG |
139 | /* Tag_ABI_align8_preserved: This code preserves 8-byte |
140 | alignment in any callee. */ | |
141 | .eabi_attribute 25, 1 | |
142 | /* Tag_ABI_align8_needed: This code may require 8-byte alignment from | |
143 | the caller. */ | |
144 | .eabi_attribute 24, 1 | |
27489557 | 145 | |
5ff5dfe7 RH |
146 | /* The thumb2 encoding is reasonably complete. Unless suppressed, use it. */ |
147 | .syntax unified | |
148 | # if defined(__thumb2__) && !defined(NO_THUMB) | |
149 | .thumb | |
150 | #else | |
151 | # undef __thumb__ | |
152 | # undef __thumb2__ | |
153 | .arm | |
154 | # endif | |
155 | ||
cd24e113 RH |
156 | /* Load or store to/from a pc-relative EXPR into/from R, using T. */ |
157 | # ifdef __thumb2__ | |
158 | # define LDST_PCREL(OP, R, T, EXPR) \ | |
159 | ldr T, 98f; \ | |
160 | .subsection 2; \ | |
161 | 98: .word EXPR - 99f - PC_OFS; \ | |
162 | .previous; \ | |
163 | 99: add T, T, pc; \ | |
164 | OP R, [T] | |
165 | # else | |
166 | # define LDST_PCREL(OP, R, T, EXPR) \ | |
167 | ldr T, 98f; \ | |
168 | .subsection 2; \ | |
169 | 98: .word EXPR - 99f - PC_OFS; \ | |
170 | .previous; \ | |
171 | 99: OP R, [pc, T] | |
172 | # endif | |
3ae44082 | 173 | |
b7f2d27d WN |
174 | /* Load or store to/from a global EXPR into/from R, using T. */ |
175 | # define LDST_GLOBAL(OP, R, T, EXPR) \ | |
176 | ldr T, 99f; \ | |
177 | ldr R, 100f; \ | |
178 | 98: add T, T, pc; \ | |
179 | ldr T, [T, R]; \ | |
180 | .subsection 2; \ | |
181 | 99: .word _GLOBAL_OFFSET_TABLE_ - 98b - PC_OFS; \ | |
182 | 100: .word EXPR##(GOT); \ | |
183 | .previous; \ | |
184 | OP R, [T] | |
185 | ||
3ae44082 RH |
186 | /* Cope with negative memory offsets, which thumb can't encode. |
187 | Use NEGOFF_ADJ_BASE to (conditionally) alter the base register, | |
188 | and then NEGOFF_OFF1 to use 0 for thumb and the offset for arm, | |
189 | or NEGOFF_OFF2 to use A-B for thumb and A for arm. */ | |
190 | # ifdef __thumb2__ | |
191 | # define NEGOFF_ADJ_BASE(R, OFF) add R, R, $OFF | |
192 | # define NEGOFF_ADJ_BASE2(D, S, OFF) add D, S, $OFF | |
193 | # define NEGOFF_OFF1(R, OFF) [R] | |
194 | # define NEGOFF_OFF2(R, OFFA, OFFB) [R, $((OFFA) - (OFFB))] | |
195 | # else | |
196 | # define NEGOFF_ADJ_BASE(R, OFF) | |
197 | # define NEGOFF_ADJ_BASE2(D, S, OFF) mov D, S | |
198 | # define NEGOFF_OFF1(R, OFF) [R, $OFF] | |
199 | # define NEGOFF_OFF2(R, OFFA, OFFB) [R, $OFFA] | |
200 | # endif | |
5232b909 RH |
201 | |
202 | /* Helper to get the TLS base pointer. The interface is that TMP is a | |
203 | register that may be used to hold the LR, if necessary. TMP may be | |
204 | LR itself to indicate that LR need not be saved. The base pointer | |
79fd8731 | 205 | is returned in R0. Only R0 and TMP are modified. */ |
5232b909 | 206 | |
79fd8731 RH |
207 | # ifdef ARCH_HAS_HARD_TP |
208 | /* If the cpu has cp15 available, use it. */ | |
209 | # define GET_TLS(TMP) mrc p15, 0, r0, c13, c0, 3 | |
210 | # else | |
211 | /* At this generic level we have no tricks to pull. Call the ABI routine. */ | |
212 | # define GET_TLS(TMP) \ | |
5232b909 RH |
213 | push { r1, r2, r3, lr }; \ |
214 | cfi_remember_state; \ | |
215 | cfi_adjust_cfa_offset (16); \ | |
216 | cfi_rel_offset (r1, 0); \ | |
217 | cfi_rel_offset (r2, 4); \ | |
218 | cfi_rel_offset (r3, 8); \ | |
219 | cfi_rel_offset (lr, 12); \ | |
220 | bl __aeabi_read_tp; \ | |
221 | pop { r1, r2, r3, lr }; \ | |
222 | cfi_restore_state | |
79fd8731 | 223 | # endif /* ARCH_HAS_HARD_TP */ |
5232b909 | 224 | |
a7ac7522 RM |
225 | # ifndef ARM_SFI_MACROS |
226 | # define ARM_SFI_MACROS 1 | |
227 | /* This assembly macro is prepended to any load/store instruction, | |
228 | pulling the base register out of the addressing mode syntax and | |
229 | making it the first operand of the macro. For example: | |
230 | ldr r0, [r1] | |
231 | becomes: | |
232 | sfi_breg r1, ldr r0, [\B] | |
233 | The \B stands in for the base register that is the first operand | |
234 | to the macro, so we can avoid error-prone repetition of the base | |
235 | register in two places on the line. | |
236 | ||
237 | This is used for all memory access through a base register other | |
238 | than PC or SP. It's intended to support SFI schemes such as | |
239 | Native Client, where the OS will enforce that all load/store | |
240 | instructions use a special form. In any such configuration, | |
241 | another sysdep.h file will have defined ARM_SFI_MACROS and | |
242 | provided its own assembly macros with the same interface. */ | |
243 | ||
244 | .macro sfi_breg basereg, insn, operands:vararg | |
245 | .macro _sfi_breg_doit B | |
246 | \insn \operands | |
247 | .endm | |
248 | _sfi_breg_doit \basereg | |
249 | .purgem _sfi_breg_doit | |
250 | .endm | |
251 | ||
252 | /* This assembly macro replaces the "pld" instruction. | |
253 | The syntax: | |
254 | sfi_pld REGISTER, #OFFSET | |
255 | is exactly equivalent to: | |
256 | sfi_breg REGISTER, pld [\B, #OFFSET] | |
257 | (and ", #OFFSET" is optional). We have a separate macro | |
258 | only to work around a bug in GAS versions prior to 2.23.2, | |
259 | that misparses the sfi_breg macro expansion in this case. */ | |
260 | ||
261 | .macro sfi_pld basereg, offset=#0 | |
262 | pld [\basereg, \offset] | |
263 | .endm | |
264 | ||
1362a2aa RM |
265 | /* This macro precedes any instruction that directly changes the SP. |
266 | It's not needed for push/pop or for any kind of load or store that | |
267 | implicitly changes the SP via the ! syntax. */ | |
268 | # define sfi_sp /* Nothing to do. */ | |
269 | ||
a7ac7522 RM |
270 | # endif |
271 | ||
7214d558 RM |
272 | /* These are the directives used for EABI unwind info. |
273 | Wrap them in macros so another configuration's sysdep.h | |
274 | file can define them away if it doesn't use EABI unwind info. */ | |
275 | # define eabi_fnstart .fnstart | |
276 | # define eabi_fnend .fnend | |
277 | # define eabi_save(...) .save __VA_ARGS__ | |
278 | # define eabi_cantunwind .cantunwind | |
279 | # define eabi_pad(n) .pad n | |
280 | ||
e0ebc3b2 | 281 | #endif /* __ASSEMBLER__ */ |
783a65c2 RH |
282 | |
283 | /* This number is the offset from the pc at the current location. */ | |
5ff5dfe7 | 284 | #ifdef __thumb__ |
783a65c2 RH |
285 | # define PC_OFS 4 |
286 | #else | |
287 | # define PC_OFS 8 | |
288 | #endif |