arm: Implement hard-tp for GET_TLS
[glibc.git] / ports / sysdeps / arm / sysdep.h
blob4a7a13f6fb3b2f4ca7b5aa1ed50d4ed097bb18db
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_6K__) || defined (__ARM_ARCH_6ZK__)
54 # define ARCH_HAS_HARD_TP
55 #endif
56 #if __ARM_ARCH > 6 || defined (__ARM_ARCH_6T2__)
57 # define ARCH_HAS_T2
58 #endif
60 #ifdef __ASSEMBLER__
62 /* Syntactic details of assembler. */
64 #define ALIGNARG(log2) log2
65 #define ASM_SIZE_DIRECTIVE(name) .size name,.-name
67 #define PLTJMP(_x) _x##(PLT)
69 #ifdef ARCH_HAS_BX
70 # define BX(R) bx R
71 # define BXC(C, R) bx##C R
72 # ifdef ARCH_HAS_BLX
73 # define BLX(R) blx R
74 # else
75 # define BLX(R) mov lr, pc; bx R
76 # endif
77 #else
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
81 #endif
83 #define DO_RET(R) BX(R)
84 #define RETINSTR(C, R) BXC(C, R)
86 /* Define an entry point visible from C. */
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
96 #define CFI_SECTIONS \
97 .cfi_sections .debug_frame
99 #undef END
100 #define END(name) \
101 cfi_endproc; \
102 ASM_SIZE_DIRECTIVE(name)
104 /* If compiled for profiling, call `mcount' at the start of each function. */
105 #ifdef PROF
106 /* Call __gnu_mcount_nc if GCC >= 4.4. */
107 #if __GNUC_PREREQ(4,4)
108 #define CALL_MCOUNT \
109 push {lr}; \
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)
115 #else /* else call _mcount */
116 #define CALL_MCOUNT \
117 push {lr}; \
118 cfi_adjust_cfa_offset (4); \
119 cfi_rel_offset (lr, 0); \
120 bl PLTJMP(mcount); \
121 pops {lr}; \
122 cfi_adjust_cfa_offset (-4); \
123 cfi_restore (lr)
124 #endif
125 #else
126 #define CALL_MCOUNT /* Do nothing. */
127 #endif
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
133 #if __GNUC_PREREQ(4,4)
134 #define mcount __gnu_mcount_nc
135 #else
136 #define mcount _mcount
137 #endif
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
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
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
174 /* Cope with negative memory offsets, which thumb can't encode.
175 Use NEGOFF_ADJ_BASE to (conditionally) alter the base register,
176 and then NEGOFF_OFF1 to use 0 for thumb and the offset for arm,
177 or NEGOFF_OFF2 to use A-B for thumb and A for arm. */
178 # ifdef __thumb2__
179 # define NEGOFF_ADJ_BASE(R, OFF) add R, R, $OFF
180 # define NEGOFF_ADJ_BASE2(D, S, OFF) add D, S, $OFF
181 # define NEGOFF_OFF1(R, OFF) [R]
182 # define NEGOFF_OFF2(R, OFFA, OFFB) [R, $((OFFA) - (OFFB))]
183 # else
184 # define NEGOFF_ADJ_BASE(R, OFF)
185 # define NEGOFF_ADJ_BASE2(D, S, OFF) mov D, S
186 # define NEGOFF_OFF1(R, OFF) [R, $OFF]
187 # define NEGOFF_OFF2(R, OFFA, OFFB) [R, $OFFA]
188 # endif
190 /* Helper to get the TLS base pointer. The interface is that TMP is a
191 register that may be used to hold the LR, if necessary. TMP may be
192 LR itself to indicate that LR need not be saved. The base pointer
193 is returned in R0. Only R0 and TMP are modified. */
195 # ifdef ARCH_HAS_HARD_TP
196 /* If the cpu has cp15 available, use it. */
197 # define GET_TLS(TMP) mrc p15, 0, r0, c13, c0, 3
198 # else
199 /* At this generic level we have no tricks to pull. Call the ABI routine. */
200 # define GET_TLS(TMP) \
201 push { r1, r2, r3, lr }; \
202 cfi_remember_state; \
203 cfi_adjust_cfa_offset (16); \
204 cfi_rel_offset (r1, 0); \
205 cfi_rel_offset (r2, 4); \
206 cfi_rel_offset (r3, 8); \
207 cfi_rel_offset (lr, 12); \
208 bl __aeabi_read_tp; \
209 pop { r1, r2, r3, lr }; \
210 cfi_restore_state
211 # endif /* ARCH_HAS_HARD_TP */
213 #endif /* __ASSEMBLER__ */
215 /* This number is the offset from the pc at the current location. */
216 #ifdef __thumb__
217 # define PC_OFS 4
218 #else
219 # define PC_OFS 8
220 #endif