arm: Tidy architecture selection
[glibc.git] / ports / sysdeps / arm / sysdep.h
blob156bc017345e513bc6d581f75d856b7c280902f2
1 /* Assembler macros for ARM.
2 Copyright (C) 1997-2013 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
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.
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
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library. If not, see
17 <http://www.gnu.org/licenses/>. */
19 #include <sysdeps/generic/sysdep.h>
20 #include <features.h>
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
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
53 #if __ARM_ARCH > 6 || defined (__ARM_ARCH_6T2__)
54 # define ARCH_HAS_T2
55 #endif
57 #ifdef __ASSEMBLER__
59 /* Syntactic details of assembler. */
61 #define ALIGNARG(log2) log2
62 #define ASM_SIZE_DIRECTIVE(name) .size name,.-name
64 #define PLTJMP(_x) _x##(PLT)
66 #ifdef ARCH_HAS_BX
67 # define BX(R) bx R
68 # define BXC(C, R) bx##C R
69 # ifdef ARCH_HAS_BLX
70 # define BLX(R) blx R
71 # else
72 # define BLX(R) mov lr, pc; bx R
73 # endif
74 #else
75 # define BX(R) mov pc, R
76 # define BXC(C, R) mov##C pc, R
77 # define BLX(R) mov lr, pc; mov pc, R
78 #endif
80 #define DO_RET(R) BX(R)
81 #define RETINSTR(C, R) BXC(C, R)
83 /* Define an entry point visible from C. */
84 #define ENTRY(name) \
85 .globl C_SYMBOL_NAME(name); \
86 .type C_SYMBOL_NAME(name),%function; \
87 .align ALIGNARG(4); \
88 C_LABEL(name) \
89 CFI_SECTIONS; \
90 cfi_startproc; \
91 CALL_MCOUNT
93 #define CFI_SECTIONS \
94 .cfi_sections .debug_frame
96 #undef END
97 #define END(name) \
98 cfi_endproc; \
99 ASM_SIZE_DIRECTIVE(name)
101 /* If compiled for profiling, call `mcount' at the start of each function. */
102 #ifdef PROF
103 /* Call __gnu_mcount_nc if GCC >= 4.4. */
104 #if __GNUC_PREREQ(4,4)
105 #define CALL_MCOUNT \
106 push {lr}; \
107 cfi_adjust_cfa_offset (4); \
108 cfi_rel_offset (lr, 0); \
109 bl PLTJMP(mcount); \
110 cfi_adjust_cfa_offset (-4); \
111 cfi_restore (lr)
112 #else /* else call _mcount */
113 #define CALL_MCOUNT \
114 push {lr}; \
115 cfi_adjust_cfa_offset (4); \
116 cfi_rel_offset (lr, 0); \
117 bl PLTJMP(mcount); \
118 pops {lr}; \
119 cfi_adjust_cfa_offset (-4); \
120 cfi_restore (lr)
121 #endif
122 #else
123 #define CALL_MCOUNT /* Do nothing. */
124 #endif
126 /* Since C identifiers are not normally prefixed with an underscore
127 on this system, the asm identifier `syscall_error' intrudes on the
128 C name space. Make sure we use an innocuous name. */
129 #define syscall_error __syscall_error
130 #if __GNUC_PREREQ(4,4)
131 #define mcount __gnu_mcount_nc
132 #else
133 #define mcount _mcount
134 #endif
136 /* Tag_ABI_align8_preserved: This code preserves 8-byte
137 alignment in any callee. */
138 .eabi_attribute 25, 1
139 /* Tag_ABI_align8_needed: This code may require 8-byte alignment from
140 the caller. */
141 .eabi_attribute 24, 1
143 /* The thumb2 encoding is reasonably complete. Unless suppressed, use it. */
144 .syntax unified
145 # if defined(__thumb2__) && !defined(NO_THUMB)
146 .thumb
147 #else
148 # undef __thumb__
149 # undef __thumb2__
150 .arm
151 # endif
153 /* Load or store to/from a pc-relative EXPR into/from R, using T. */
154 # ifdef __thumb2__
155 # define LDST_PCREL(OP, R, T, EXPR) \
156 ldr T, 98f; \
157 .subsection 2; \
158 98: .word EXPR - 99f - PC_OFS; \
159 .previous; \
160 99: add T, T, pc; \
161 OP R, [T]
162 # else
163 # define LDST_PCREL(OP, R, T, EXPR) \
164 ldr T, 98f; \
165 .subsection 2; \
166 98: .word EXPR - 99f - PC_OFS; \
167 .previous; \
168 99: OP R, [pc, T]
169 # endif
171 /* Cope with negative memory offsets, which thumb can't encode.
172 Use NEGOFF_ADJ_BASE to (conditionally) alter the base register,
173 and then NEGOFF_OFF1 to use 0 for thumb and the offset for arm,
174 or NEGOFF_OFF2 to use A-B for thumb and A for arm. */
175 # ifdef __thumb2__
176 # define NEGOFF_ADJ_BASE(R, OFF) add R, R, $OFF
177 # define NEGOFF_ADJ_BASE2(D, S, OFF) add D, S, $OFF
178 # define NEGOFF_OFF1(R, OFF) [R]
179 # define NEGOFF_OFF2(R, OFFA, OFFB) [R, $((OFFA) - (OFFB))]
180 # else
181 # define NEGOFF_ADJ_BASE(R, OFF)
182 # define NEGOFF_ADJ_BASE2(D, S, OFF) mov D, S
183 # define NEGOFF_OFF1(R, OFF) [R, $OFF]
184 # define NEGOFF_OFF2(R, OFFA, OFFB) [R, $OFFA]
185 # endif
187 /* Helper to get the TLS base pointer. The interface is that TMP is a
188 register that may be used to hold the LR, if necessary. TMP may be
189 LR itself to indicate that LR need not be saved. The base pointer
190 is returned in R0. Only R0 and TMP are modified.
192 At this generic level we have no tricks to pull. Call the ABI routine. */
193 # define GET_TLS(TMP) \
194 push { r1, r2, r3, lr }; \
195 cfi_remember_state; \
196 cfi_adjust_cfa_offset (16); \
197 cfi_rel_offset (r1, 0); \
198 cfi_rel_offset (r2, 4); \
199 cfi_rel_offset (r3, 8); \
200 cfi_rel_offset (lr, 12); \
201 bl __aeabi_read_tp; \
202 pop { r1, r2, r3, lr }; \
203 cfi_restore_state
205 #endif /* __ASSEMBLER__ */
207 /* This number is the offset from the pc at the current location. */
208 #ifdef __thumb__
209 # define PC_OFS 4
210 #else
211 # define PC_OFS 8
212 #endif