arm: Enable thumb2 mode in assembly files
[glibc.git] / ports / sysdeps / arm / sysdep.h
blobd855ceb3c39a76953afe88f6f719be8ae8d52956
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 #if (!defined (__ARM_ARCH_2__) && !defined (__ARM_ARCH_3__) \
23 && !defined (__ARM_ARCH_3M__) && !defined (__ARM_ARCH_4__))
24 # define __USE_BX__
25 #endif
27 #ifdef __ASSEMBLER__
29 /* Syntactic details of assembler. */
31 #define ALIGNARG(log2) log2
32 #define ASM_SIZE_DIRECTIVE(name) .size name,.-name
34 #define PLTJMP(_x) _x##(PLT)
36 /* APCS-32 doesn't preserve the condition codes across function call. */
37 #ifdef __APCS_32__
38 #define LOADREGS(cond, base, reglist...)\
39 ldm##cond base,reglist
40 #ifdef __USE_BX__
41 #define RETINSTR(cond, reg) \
42 bx##cond reg
43 #define DO_RET(_reg) \
44 bx _reg
45 #else
46 #define RETINSTR(cond, reg) \
47 mov##cond pc, reg
48 #define DO_RET(_reg) \
49 mov pc, _reg
50 #endif
51 #else /* APCS-26 */
52 #define LOADREGS(cond, base, reglist...)\
53 ldm##cond base,reglist^
54 #define RETINSTR(cond, reg) \
55 mov##cond##s pc, reg
56 #define DO_RET(_reg) \
57 movs pc, _reg
58 #endif
60 /* Define an entry point visible from C. */
61 #define ENTRY(name) \
62 .globl C_SYMBOL_NAME(name); \
63 .type C_SYMBOL_NAME(name),%function; \
64 .align ALIGNARG(4); \
65 C_LABEL(name) \
66 CFI_SECTIONS; \
67 cfi_startproc; \
68 CALL_MCOUNT
70 #define CFI_SECTIONS \
71 .cfi_sections .debug_frame
73 #undef END
74 #define END(name) \
75 cfi_endproc; \
76 ASM_SIZE_DIRECTIVE(name)
78 /* If compiled for profiling, call `mcount' at the start of each function. */
79 #ifdef PROF
80 /* Call __gnu_mcount_nc if GCC >= 4.4. */
81 #if __GNUC_PREREQ(4,4)
82 #define CALL_MCOUNT \
83 str lr,[sp, #-4]!; \
84 cfi_adjust_cfa_offset (4); \
85 cfi_rel_offset (lr, 0); \
86 bl PLTJMP(mcount); \
87 cfi_adjust_cfa_offset (-4); \
88 cfi_restore (lr)
89 #else /* else call _mcount */
90 #define CALL_MCOUNT \
91 str lr,[sp, #-4]!; \
92 cfi_adjust_cfa_offset (4); \
93 cfi_rel_offset (lr, 0); \
94 bl PLTJMP(mcount); \
95 ldr lr, [sp], #4; \
96 cfi_adjust_cfa_offset (-4); \
97 cfi_restore (lr)
98 #endif
99 #else
100 #define CALL_MCOUNT /* Do nothing. */
101 #endif
103 /* Since C identifiers are not normally prefixed with an underscore
104 on this system, the asm identifier `syscall_error' intrudes on the
105 C name space. Make sure we use an innocuous name. */
106 #define syscall_error __syscall_error
107 #if __GNUC_PREREQ(4,4)
108 #define mcount __gnu_mcount_nc
109 #else
110 #define mcount _mcount
111 #endif
113 /* Tag_ABI_align8_preserved: This code preserves 8-byte
114 alignment in any callee. */
115 .eabi_attribute 25, 1
116 /* Tag_ABI_align8_needed: This code may require 8-byte alignment from
117 the caller. */
118 .eabi_attribute 24, 1
120 /* The thumb2 encoding is reasonably complete. Unless suppressed, use it. */
121 .syntax unified
122 # if defined(__thumb2__) && !defined(NO_THUMB)
123 .thumb
124 #else
125 # undef __thumb__
126 # undef __thumb2__
127 .arm
128 # endif
130 /* Load or store to/from a pc-relative EXPR into/from R, using T. */
131 # ifdef __thumb2__
132 # define LDST_PCREL(OP, R, T, EXPR) \
133 ldr T, 98f; \
134 .subsection 2; \
135 98: .word EXPR - 99f - PC_OFS; \
136 .previous; \
137 99: add T, T, pc; \
138 OP R, [T]
139 # else
140 # define LDST_PCREL(OP, R, T, EXPR) \
141 ldr T, 98f; \
142 .subsection 2; \
143 98: .word EXPR - 99f - PC_OFS; \
144 .previous; \
145 99: OP R, [pc, T]
146 # endif
148 /* Cope with negative memory offsets, which thumb can't encode.
149 Use NEGOFF_ADJ_BASE to (conditionally) alter the base register,
150 and then NEGOFF_OFF1 to use 0 for thumb and the offset for arm,
151 or NEGOFF_OFF2 to use A-B for thumb and A for arm. */
152 # ifdef __thumb2__
153 # define NEGOFF_ADJ_BASE(R, OFF) add R, R, $OFF
154 # define NEGOFF_ADJ_BASE2(D, S, OFF) add D, S, $OFF
155 # define NEGOFF_OFF1(R, OFF) [R]
156 # define NEGOFF_OFF2(R, OFFA, OFFB) [R, $((OFFA) - (OFFB))]
157 # else
158 # define NEGOFF_ADJ_BASE(R, OFF)
159 # define NEGOFF_ADJ_BASE2(D, S, OFF) mov D, S
160 # define NEGOFF_OFF1(R, OFF) [R, $OFF]
161 # define NEGOFF_OFF2(R, OFFA, OFFB) [R, $OFFA]
162 # endif
164 /* Helper to get the TLS base pointer. The interface is that TMP is a
165 register that may be used to hold the LR, if necessary. TMP may be
166 LR itself to indicate that LR need not be saved. The base pointer
167 is returned in R0. Only R0 and TMP are modified.
169 At this generic level we have no tricks to pull. Call the ABI routine. */
170 # define GET_TLS(TMP) \
171 push { r1, r2, r3, lr }; \
172 cfi_remember_state; \
173 cfi_adjust_cfa_offset (16); \
174 cfi_rel_offset (r1, 0); \
175 cfi_rel_offset (r2, 4); \
176 cfi_rel_offset (r3, 8); \
177 cfi_rel_offset (lr, 12); \
178 bl __aeabi_read_tp; \
179 pop { r1, r2, r3, lr }; \
180 cfi_restore_state
182 #endif /* __ASSEMBLER__ */
184 /* This number is the offset from the pc at the current location. */
185 #ifdef __thumb__
186 # define PC_OFS 4
187 #else
188 # define PC_OFS 8
189 #endif