remove unused code, RTLD_PRIVATE_ERRNO is never defined
[uclibc-ng.git] / libc / sysdeps / linux / arm / sysdep.h
blob80bf9eca9ef51abb7a85072d792e728fb8ddb9e1
1 /* Assembler macros for ARM.
2 Copyright (C) 1997, 1998, 2003 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 #ifndef _LINUX_ARM_SYSDEP_H
20 #define _LINUX_ARM_SYSDEP_H 1
22 #include <common/sysdep.h>
23 #include <bits/arm_bx.h>
24 #include <sys/syscall.h>
25 /* For Linux we can use the system call table in the header file
26 /usr/include/asm/unistd.h
27 of the kernel. But these symbols do not follow the SYS_* syntax
28 so we have to redefine the `SYS_ify' macro here. */
29 #undef SYS_ify
30 #define SWI_BASE (0x900000)
31 #define SYS_ify(syscall_name) (__NR_##syscall_name)
33 #ifdef __ASSEMBLER__
35 /* Syntactic details of assembler. */
37 #define ALIGNARG(log2) log2
38 /* For ELF we need the `.type' directive to make shared libs work right. */
39 #define ASM_TYPE_DIRECTIVE(name,typearg) .type name,%##typearg;
40 #define ASM_SIZE_DIRECTIVE(name) .size name,.-name
42 /* In ELF C symbols are asm symbols. */
43 #undef NO_UNDERSCORES
44 #define NO_UNDERSCORES
46 #define PLTJMP(_x) _x##(PLT)
48 /* APCS-32 doesn't preserve the condition codes across function call. */
49 #ifdef __APCS_32__
50 #define LOADREGS(cond, base, reglist...)\
51 ldm##cond base,reglist
52 #define RETINSTR(cond, reg) \
53 BXC(cond, reg)
54 #define DO_RET(_reg) \
55 BX(_reg)
56 #else /* APCS-26 */
57 #define LOADREGS(cond, base, reglist...) \
58 ldm##cond base,reglist^
59 #define RETINSTR(cond, reg) \
60 mov##cond##s pc, reg
61 #define DO_RET(_reg) \
62 movs pc, _reg
63 #endif
65 /* Define an entry point visible from C. */
66 #define ENTRY(name) \
67 .globl C_SYMBOL_NAME(name); \
68 ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),function) \
69 .align ALIGNARG(4); \
70 name##:
72 #undef END
73 #define END(name) \
74 ASM_SIZE_DIRECTIVE(name)
76 #ifdef NO_UNDERSCORES
77 /* Since C identifiers are not normally prefixed with an underscore
78 on this system, the asm identifier `syscall_error' intrudes on the
79 C name space. Make sure we use an innocuous name. */
80 #define syscall_error __syscall_error
81 #define mcount _mcount
82 #endif
83 /* Linux uses a negative return value to indicate syscall errors,
84 unlike most Unices, which use the condition codes' carry flag.
86 Since version 2.1 the return value of a system call might be
87 negative even if the call succeeded. E.g., the `lseek' system call
88 might return a large offset. Therefore we must not anymore test
89 for < 0, but test for a real error by making sure the value in R0
90 is a real error number. Linus said he will make sure the no syscall
91 returns a value in -1 .. -4095 as a valid result so we can safely
92 test with -4095. */
94 #undef PSEUDO
95 #define PSEUDO(name, syscall_name, args) \
96 .text; \
97 ENTRY (name); \
98 DO_CALL (syscall_name, args); \
99 cmn r0, $4096;
101 #define PSEUDO_RET \
102 RETINSTR(cc, lr); \
103 b PLTJMP(SYSCALL_ERROR)
104 #undef ret
105 #define ret PSEUDO_RET
107 #undef PSEUDO_END
108 #define PSEUDO_END(name) \
109 SYSCALL_ERROR_HANDLER \
110 END (name)
112 #undef PSEUDO_NOERRNO
113 #define PSEUDO_NOERRNO(name, syscall_name, args) \
114 .text; \
115 ENTRY (name); \
116 DO_CALL (syscall_name, args);
118 #define PSEUDO_RET_NOERRNO \
119 DO_RET (lr);
121 #undef ret_NOERRNO
122 #define ret_NOERRNO PSEUDO_RET_NOERRNO
124 #undef PSEUDO_END_NOERRNO
125 #define PSEUDO_END_NOERRNO(name) \
126 END (name)
128 /* The function has to return the error code. */
129 #undef PSEUDO_ERRVAL
130 #define PSEUDO_ERRVAL(name, syscall_name, args) \
131 .text; \
132 ENTRY (name) \
133 DO_CALL (syscall_name, args); \
134 rsb r0, r0, #0
136 #undef PSEUDO_END_ERRVAL
137 #define PSEUDO_END_ERRVAL(name) \
138 END (name)
140 #undef ret_ERRVAL
141 #define ret_ERRVAL PSEUDO_RET_NOERRNO
143 #if defined NOT_IN_libc
144 # define SYSCALL_ERROR __local_syscall_error
145 # define SYSCALL_ERROR_HANDLER \
146 __local_syscall_error: \
147 str lr, [sp, #-4]!; \
148 str r0, [sp, #-4]!; \
149 bl PLTJMP(C_SYMBOL_NAME(__errno_location)); \
150 ldr r1, [sp], #4; \
151 rsb r1, r1, #0; \
152 str r1, [r0]; \
153 mvn r0, #0; \
154 ldr pc, [sp], #4;
155 #else
156 # define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */
157 # define SYSCALL_ERROR __syscall_error
158 #endif
160 /* Linux takes system call args in registers:
161 syscall number in the SWI instruction
162 arg 1 r0
163 arg 2 r1
164 arg 3 r2
165 arg 4 r3
166 arg 5 r4 (this is different from the APCS convention)
167 arg 6 r5
168 arg 7 r6
170 The compiler is going to form a call by coming here, through PSEUDO, with
171 arguments
172 syscall number in the DO_CALL macro
173 arg 1 r0
174 arg 2 r1
175 arg 3 r2
176 arg 4 r3
177 arg 5 [sp]
178 arg 6 [sp+4]
179 arg 7 [sp+8]
181 We need to shuffle values between R4..R6 and the stack so that the
182 caller's v1..v3 and stack frame are not corrupted, and the kernel
183 sees the right arguments.
186 #if __ARM_ARCH > 6 || defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6ZK__)
187 # define ARCH_HAS_HARD_TP
188 #endif
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
202 # ifdef ARCH_HAS_HARD_TP
203 /* If the cpu has cp15 available, use it. */
204 # define GET_TLS(TMP) mrc p15, 0, r0, c13, c0, 3
205 # else
206 /* At this generic level we have no tricks to pull. Call the ABI routine. */
207 # define GET_TLS(TMP) \
208 push { r1, r2, r3, lr }; \
209 cfi_remember_state; \
210 cfi_adjust_cfa_offset (16); \
211 cfi_rel_offset (r1, 0); \
212 cfi_rel_offset (r2, 4); \
213 cfi_rel_offset (r3, 8); \
214 cfi_rel_offset (lr, 12); \
215 bl __aeabi_read_tp; \
216 pop { r1, r2, r3, lr }; \
217 cfi_restore_state
218 # endif /* ARCH_HAS_HARD_TP */
223 #undef DO_CALL
224 #if defined(__ARM_EABI__)
225 #define DO_CALL(syscall_name, args) \
226 DOARGS_##args \
227 mov ip, r7; \
228 ldr r7, =SYS_ify (syscall_name); \
229 swi 0x0; \
230 mov r7, ip; \
231 UNDOARGS_##args
232 #else
233 #define DO_CALL(syscall_name, args) \
234 DOARGS_##args \
235 swi SYS_ify (syscall_name); \
236 UNDOARGS_##args
237 #endif
239 #define DOARGS_0 /* nothing */
240 #define DOARGS_1 /* nothing */
241 #define DOARGS_2 /* nothing */
242 #define DOARGS_3 /* nothing */
243 #define DOARGS_4 /* nothing */
244 #define DOARGS_5 str r4, [sp, $-4]!; ldr r4, [sp, $4];
245 #define DOARGS_6 mov ip, sp; stmfd sp!, {r4, r5}; ldmia ip, {r4, r5};
246 #define DOARGS_7 mov ip, sp; stmfd sp!, {r4, r5, r6}; ldmia ip, {r4, r5, r6};
248 #define UNDOARGS_0 /* nothing */
249 #define UNDOARGS_1 /* nothing */
250 #define UNDOARGS_2 /* nothing */
251 #define UNDOARGS_3 /* nothing */
252 #define UNDOARGS_4 /* nothing */
253 #define UNDOARGS_5 ldr r4, [sp], $4;
254 #define UNDOARGS_6 ldmfd sp!, {r4, r5};
255 #define UNDOARGS_7 ldmfd sp!, {r4, r5, r6};
257 #endif /* __ASSEMBLER__ */
258 #endif /* linux/arm/sysdep.h */