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>
22 #if (!defined (__ARM_ARCH_2__) && !defined (__ARM_ARCH_3__) \
23 && !defined (__ARM_ARCH_3M__) && !defined (__ARM_ARCH_4__))
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. */
38 #define LOADREGS(cond, base, reglist...)\
39 ldm##cond base,reglist
41 #define RETINSTR(cond, reg) \
43 #define DO_RET(_reg) \
46 #define RETINSTR(cond, reg) \
48 #define DO_RET(_reg) \
52 #define LOADREGS(cond, base, reglist...)\
53 ldm##cond base,reglist^
54 #define RETINSTR(cond, reg) \
56 #define DO_RET(_reg) \
60 /* Define an entry point visible from C. */
62 .globl C_SYMBOL_NAME(name); \
63 .type C_SYMBOL_NAME(name),%function; \
70 #define CFI_SECTIONS \
71 .cfi_sections .debug_frame
76 ASM_SIZE_DIRECTIVE(name)
78 /* If compiled for profiling, call `mcount' at the start of each function. */
80 /* Call __gnu_mcount_nc if GCC >= 4.4. */
81 #if __GNUC_PREREQ(4,4)
84 cfi_adjust_cfa_offset (4); \
85 cfi_rel_offset (lr, 0); \
87 cfi_adjust_cfa_offset (-4); \
89 #else /* else call _mcount */
92 cfi_adjust_cfa_offset (4); \
93 cfi_rel_offset (lr, 0); \
96 cfi_adjust_cfa_offset (-4); \
100 #define CALL_MCOUNT /* Do nothing. */
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
110 #define mcount _mcount
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
118 .eabi_attribute
24, 1
120 /* The thumb2 encoding is reasonably complete. Unless suppressed, use it. */
122 # if defined(__thumb2__) && !defined(NO_THUMB)
130 /* Load or store to/from a pc-relative EXPR into/from R, using T. */
132 # define LDST_PCREL(OP, R, T, EXPR) \
135 98: .word EXPR - 99f - PC_OFS; \
140 # define LDST_PCREL(OP, R, T, EXPR) \
143 98: .word EXPR - 99f - PC_OFS; \
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. */
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))]
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]
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 }; \
182 #endif /* __ASSEMBLER__ */
184 /* This number is the offset from the pc at the current location. */