arm: add RESET_PID in the clone impl
[uclibc-ng.git] / libc / sysdeps / linux / arm / sysdep.h
blob2d0a9cc417b474e80293bb6fc0d77b0ba82a328f
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>
25 #include <sys/syscall.h>
26 /* For Linux we can use the system call table in the header file
27 /usr/include/asm/unistd.h
28 of the kernel. But these symbols do not follow the SYS_* syntax
29 so we have to redefine the `SYS_ify' macro here. */
30 #undef SYS_ify
31 #define SWI_BASE (0x900000)
32 #define SYS_ify(syscall_name) (__NR_##syscall_name)
34 #ifdef __ASSEMBLER__
36 /* Syntactic details of assembler. */
38 #define ALIGNARG(log2) log2
39 /* For ELF we need the `.type' directive to make shared libs work right. */
40 #define ASM_TYPE_DIRECTIVE(name,typearg) .type name,%##typearg;
41 #define ASM_SIZE_DIRECTIVE(name) .size name,.-name
43 /* In ELF C symbols are asm symbols. */
44 #undef NO_UNDERSCORES
45 #define NO_UNDERSCORES
47 #define PLTJMP(_x) _x##(PLT)
49 /* APCS-32 doesn't preserve the condition codes across function call. */
50 #ifdef __APCS_32__
51 #define LOADREGS(cond, base, reglist...)\
52 ldm##cond base,reglist
53 #ifdef __USE_BX__
54 #define RETINSTR(cond, reg) \
55 bx##cond reg
56 #define DO_RET(_reg) \
57 bx _reg
58 #else
59 #define RETINSTR(cond, reg) \
60 mov##cond pc, reg
61 #define DO_RET(_reg) \
62 mov pc, _reg
63 #endif
64 #else /* APCS-26 */
65 #define LOADREGS(cond, base, reglist...) \
66 ldm##cond base,reglist^
67 #define RETINSTR(cond, reg) \
68 mov##cond##s pc, reg
69 #define DO_RET(_reg) \
70 movs pc, _reg
71 #endif
73 /* Define an entry point visible from C. */
74 #define ENTRY(name) \
75 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \
76 ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),function) \
77 .align ALIGNARG(4); \
78 name##: \
79 CALL_MCOUNT
81 #undef END
82 #define END(name) \
83 ASM_SIZE_DIRECTIVE(name)
85 /* If compiled for profiling, call `mcount' at the start of each function. */
86 #ifdef PROF
87 #define CALL_MCOUNT \
88 str lr,[sp, #-4]! ; \
89 bl PLTJMP(mcount) ; \
90 ldr lr, [sp], #4 ;
91 #else
92 #define CALL_MCOUNT /* Do nothing. */
93 #endif
95 #ifdef NO_UNDERSCORES
96 /* Since C identifiers are not normally prefixed with an underscore
97 on this system, the asm identifier `syscall_error' intrudes on the
98 C name space. Make sure we use an innocuous name. */
99 #define syscall_error __syscall_error
100 #define mcount _mcount
101 #endif
102 /* Linux uses a negative return value to indicate syscall errors,
103 unlike most Unices, which use the condition codes' carry flag.
105 Since version 2.1 the return value of a system call might be
106 negative even if the call succeeded. E.g., the `lseek' system call
107 might return a large offset. Therefore we must not anymore test
108 for < 0, but test for a real error by making sure the value in R0
109 is a real error number. Linus said he will make sure the no syscall
110 returns a value in -1 .. -4095 as a valid result so we can safely
111 test with -4095. */
113 #undef PSEUDO
114 #define PSEUDO(name, syscall_name, args) \
115 .text; \
116 ENTRY (name); \
117 DO_CALL (syscall_name, args); \
118 cmn r0, $4096;
120 #define PSEUDO_RET \
121 RETINSTR(cc, lr); \
122 b PLTJMP(SYSCALL_ERROR)
123 #undef ret
124 #define ret PSEUDO_RET
126 #undef PSEUDO_END
127 #define PSEUDO_END(name) \
128 SYSCALL_ERROR_HANDLER \
129 END (name)
131 #undef PSEUDO_NOERRNO
132 #define PSEUDO_NOERRNO(name, syscall_name, args) \
133 .text; \
134 ENTRY (name); \
135 DO_CALL (syscall_name, args);
137 #define PSEUDO_RET_NOERRNO \
138 DO_RET (lr);
140 #undef ret_NOERRNO
141 #define ret_NOERRNO PSEUDO_RET_NOERRNO
143 #undef PSEUDO_END_NOERRNO
144 #define PSEUDO_END_NOERRNO(name) \
145 END (name)
147 /* The function has to return the error code. */
148 #undef PSEUDO_ERRVAL
149 #define PSEUDO_ERRVAL(name, syscall_name, args) \
150 .text; \
151 ENTRY (name) \
152 DO_CALL (syscall_name, args); \
153 rsb r0, r0, #0
155 #undef PSEUDO_END_ERRVAL
156 #define PSEUDO_END_ERRVAL(name) \
157 END (name)
159 #undef ret_ERRVAL
160 #define ret_ERRVAL PSEUDO_RET_NOERRNO
162 #if defined NOT_IN_libc
163 # define SYSCALL_ERROR __local_syscall_error
164 # ifdef RTLD_PRIVATE_ERRNO
165 # define SYSCALL_ERROR_HANDLER \
166 __local_syscall_error: \
167 ldr r1, 1f; \
168 rsb r0, r0, #0; \
169 0: str r0, [pc, r1]; \
170 mvn r0, #0; \
171 DO_RET(lr); \
172 1: .word C_SYMBOL_NAME(rtld_errno) - 0b - 8;
173 # else
174 # define SYSCALL_ERROR_HANDLER \
175 __local_syscall_error: \
176 str lr, [sp, #-4]!; \
177 str r0, [sp, #-4]!; \
178 bl PLTJMP(C_SYMBOL_NAME(__errno_location)); \
179 ldr r1, [sp], #4; \
180 rsb r1, r1, #0; \
181 str r1, [r0]; \
182 mvn r0, #0; \
183 ldr pc, [sp], #4;
184 # endif
185 #else
186 # define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */
187 # define SYSCALL_ERROR __syscall_error
188 #endif
190 /* Linux takes system call args in registers:
191 syscall number in the SWI instruction
192 arg 1 r0
193 arg 2 r1
194 arg 3 r2
195 arg 4 r3
196 arg 5 r4 (this is different from the APCS convention)
197 arg 6 r5
198 arg 7 r6
200 The compiler is going to form a call by coming here, through PSEUDO, with
201 arguments
202 syscall number in the DO_CALL macro
203 arg 1 r0
204 arg 2 r1
205 arg 3 r2
206 arg 4 r3
207 arg 5 [sp]
208 arg 6 [sp+4]
209 arg 7 [sp+8]
211 We need to shuffle values between R4..R6 and the stack so that the
212 caller's v1..v3 and stack frame are not corrupted, and the kernel
213 sees the right arguments.
216 #if __ARM_ARCH > 6 || defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6ZK__)
217 # define ARCH_HAS_HARD_TP
218 #endif
220 # ifdef __thumb2__
221 # define NEGOFF_ADJ_BASE(R, OFF) add R, R, $OFF
222 # define NEGOFF_ADJ_BASE2(D, S, OFF) add D, S, $OFF
223 # define NEGOFF_OFF1(R, OFF) [R]
224 # define NEGOFF_OFF2(R, OFFA, OFFB) [R, $((OFFA) - (OFFB))]
225 # else
226 # define NEGOFF_ADJ_BASE(R, OFF)
227 # define NEGOFF_ADJ_BASE2(D, S, OFF) mov D, S
228 # define NEGOFF_OFF1(R, OFF) [R, $OFF]
229 # define NEGOFF_OFF2(R, OFFA, OFFB) [R, $OFFA]
230 # endif
232 # ifdef ARCH_HAS_HARD_TP
233 /* If the cpu has cp15 available, use it. */
234 # define GET_TLS(TMP) mrc p15, 0, r0, c13, c0, 3
235 # else
236 /* At this generic level we have no tricks to pull. Call the ABI routine. */
237 # define GET_TLS(TMP) \
238 push { r1, r2, r3, lr }; \
239 cfi_remember_state; \
240 cfi_adjust_cfa_offset (16); \
241 cfi_rel_offset (r1, 0); \
242 cfi_rel_offset (r2, 4); \
243 cfi_rel_offset (r3, 8); \
244 cfi_rel_offset (lr, 12); \
245 bl __aeabi_read_tp; \
246 pop { r1, r2, r3, lr }; \
247 cfi_restore_state
248 # endif /* ARCH_HAS_HARD_TP */
253 #undef DO_CALL
254 #if defined(__ARM_EABI__)
255 #define DO_CALL(syscall_name, args) \
256 DOARGS_##args \
257 mov ip, r7; \
258 ldr r7, =SYS_ify (syscall_name); \
259 swi 0x0; \
260 mov r7, ip; \
261 UNDOARGS_##args
262 #else
263 #define DO_CALL(syscall_name, args) \
264 DOARGS_##args \
265 swi SYS_ify (syscall_name); \
266 UNDOARGS_##args
267 #endif
269 #define DOARGS_0 /* nothing */
270 #define DOARGS_1 /* nothing */
271 #define DOARGS_2 /* nothing */
272 #define DOARGS_3 /* nothing */
273 #define DOARGS_4 /* nothing */
274 #define DOARGS_5 str r4, [sp, $-4]!; ldr r4, [sp, $4];
275 #define DOARGS_6 mov ip, sp; stmfd sp!, {r4, r5}; ldmia ip, {r4, r5};
276 #define DOARGS_7 mov ip, sp; stmfd sp!, {r4, r5, r6}; ldmia ip, {r4, r5, r6};
278 #define UNDOARGS_0 /* nothing */
279 #define UNDOARGS_1 /* nothing */
280 #define UNDOARGS_2 /* nothing */
281 #define UNDOARGS_3 /* nothing */
282 #define UNDOARGS_4 /* nothing */
283 #define UNDOARGS_5 ldr r4, [sp], $4;
284 #define UNDOARGS_6 ldmfd sp!, {r4, r5};
285 #define UNDOARGS_7 ldmfd sp!, {r4, r5, r6};
287 #else /* not __ASSEMBLER__ */
288 /* Define a macro which expands into the inline wrapper code for a system
289 call. */
290 #undef INLINE_SYSCALL
291 #define INLINE_SYSCALL(name, nr, args...) \
292 ({ unsigned int _inline_sys_result = INTERNAL_SYSCALL (name, , nr, args); \
293 if (unlikely (INTERNAL_SYSCALL_ERROR_P (_inline_sys_result, ))) \
295 __set_errno (INTERNAL_SYSCALL_ERRNO (_inline_sys_result, )); \
296 _inline_sys_result = (unsigned int) -1; \
298 (int) _inline_sys_result; })
300 #undef INTERNAL_SYSCALL_DECL
301 #define INTERNAL_SYSCALL_DECL(err) do { } while (0)
303 #undef INTERNAL_SYSCALL_RAW
304 #if defined(__thumb__)
305 /* Hide the use of r7 from the compiler, this would be a lot
306 * easier but for the fact that the syscalls can exceed 255.
307 * For the moment the LOAD_ARG_7 is sacrificed.
308 * We can't use push/pop inside the asm because that breaks
309 * unwinding (ie. thread cancellation).
311 #define INTERNAL_SYSCALL_RAW(name, err, nr, args...) \
312 ({ unsigned int _internal_sys_result; \
314 int _sys_buf[2]; \
315 register int __a1 __asm__ ("a1"); \
316 register int *_v3 __asm__ ("v3") = _sys_buf; \
317 LOAD_ARGS_##nr (args) \
318 *_v3 = (int) (name); \
319 __asm__ __volatile__ ("str r7, [v3, #4]\n" \
320 "\tldr r7, [v3]\n" \
321 "\tswi 0 @ syscall " #name "\n" \
322 "\tldr r7, [v3, #4]" \
323 : "=r" (__a1) \
324 : "r" (_v3) ASM_ARGS_##nr \
325 : "memory"); \
326 _internal_sys_result = __a1; \
328 (int) _internal_sys_result; })
329 #elif defined(__ARM_EABI__)
330 #define INTERNAL_SYSCALL_RAW(name, err, nr, args...) \
331 ({unsigned int _internal_sys_result; \
333 register int __a1 __asm__ ("r0"), _nr __asm__ ("r7"); \
334 LOAD_ARGS_##nr (args) \
335 _nr = name; \
336 __asm__ __volatile__ ("swi 0x0 @ syscall " #name \
337 : "=r" (__a1) \
338 : "r" (_nr) ASM_ARGS_##nr \
339 : "memory"); \
340 _internal_sys_result = __a1; \
342 (int) _internal_sys_result; })
343 #else /* !defined(__ARM_EABI__) */
344 #define INTERNAL_SYSCALL_RAW(name, err, nr, args...) \
345 ({ unsigned int _internal_sys_result; \
347 register int __a1 __asm__ ("a1"); \
348 LOAD_ARGS_##nr (args) \
349 __asm__ __volatile__ ("swi %1 @ syscall " #name \
350 : "=r" (__a1) \
351 : "i" (name) ASM_ARGS_##nr \
352 : "memory"); \
353 _internal_sys_result = __a1; \
355 (int) _internal_sys_result; })
356 #endif
358 #undef INTERNAL_SYSCALL
359 #define INTERNAL_SYSCALL(name, err, nr, args...) \
360 INTERNAL_SYSCALL_RAW(SYS_ify(name), err, nr, args)
362 #undef INTERNAL_SYSCALL_ARM
363 #define INTERNAL_SYSCALL_ARM(name, err, nr, args...) \
364 INTERNAL_SYSCALL_RAW(__ARM_NR_##name, err, nr, args)
366 #undef INTERNAL_SYSCALL_ERROR_P
367 #define INTERNAL_SYSCALL_ERROR_P(val, err) \
368 ((unsigned int) (val) >= 0xfffff001u)
370 #undef INTERNAL_SYSCALL_ERRNO
371 #define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))
373 #if defined(__ARM_EABI__)
374 #undef INTERNAL_SYSCALL_NCS
375 #define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
376 INTERNAL_SYSCALL_RAW(number, err, nr, args)
377 #else
378 /* We can't implement non-constant syscalls directly since the syscall
379 number is normally encoded in the instruction. So use SYS_syscall. */
380 #undef INTERNAL_SYSCALL_NCS
381 #define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
382 INTERNAL_SYSCALL_NCS_##nr (number, err, args)
384 #define INTERNAL_SYSCALL_NCS_0(number, err, args...) \
385 INTERNAL_SYSCALL (syscall, err, 1, number, args)
386 #define INTERNAL_SYSCALL_NCS_1(number, err, args...) \
387 INTERNAL_SYSCALL (syscall, err, 2, number, args)
388 #define INTERNAL_SYSCALL_NCS_2(number, err, args...) \
389 INTERNAL_SYSCALL (syscall, err, 3, number, args)
390 #define INTERNAL_SYSCALL_NCS_3(number, err, args...) \
391 INTERNAL_SYSCALL (syscall, err, 4, number, args)
392 #define INTERNAL_SYSCALL_NCS_4(number, err, args...) \
393 INTERNAL_SYSCALL (syscall, err, 5, number, args)
394 #define INTERNAL_SYSCALL_NCS_5(number, err, args...) \
395 INTERNAL_SYSCALL (syscall, err, 6, number, args)
396 #endif
398 #endif /* __ASSEMBLER__ */
400 /* Pointer mangling is not yet supported for ARM. */
401 #define PTR_MANGLE(var) (void) (var)
402 #define PTR_DEMANGLE(var) (void) (var)
404 #endif /* linux/arm/sysdep.h */