OSDN Git Service

e498695be8ac6f7064f5c7d19294fbef1a0a02df
[uclinux-h8/uClibc.git] / libc / sysdeps / linux / arm / sysdep.h
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.
4
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.
9
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.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #ifndef _LINUX_ARM_SYSDEP_H
21 #define _LINUX_ARM_SYSDEP_H 1
22
23 #include <common/sysdep.h>
24 #include <bits/arm_asm.h>
25
26 #include <sys/syscall.h>
27 /* For Linux we can use the system call table in the header file
28         /usr/include/asm/unistd.h
29    of the kernel.  But these symbols do not follow the SYS_* syntax
30    so we have to redefine the `SYS_ify' macro here.  */
31 #undef SYS_ify
32 #define SWI_BASE  (0x900000)
33 #define SYS_ify(syscall_name)   (__NR_##syscall_name)
34
35 #ifdef  __ASSEMBLER__
36
37 /* Syntactic details of assembler.  */
38
39 #define ALIGNARG(log2) log2
40 /* For ELF we need the `.type' directive to make shared libs work right.  */
41 #define ASM_TYPE_DIRECTIVE(name,typearg) .type name,%##typearg;
42 #define ASM_SIZE_DIRECTIVE(name) .size name,.-name
43
44 /* In ELF C symbols are asm symbols.  */
45 #undef  NO_UNDERSCORES
46 #define NO_UNDERSCORES
47
48 #define PLTJMP(_x)      _x##(PLT)
49
50 /* APCS-32 doesn't preserve the condition codes across function call. */
51 #ifdef __APCS_32__
52 #define LOADREGS(cond, base, reglist...)\
53         ldm##cond       base,reglist
54 #ifdef __USE_BX__
55 #define RETINSTR(cond, reg)     \
56         bx##cond        reg
57 #define DO_RET(_reg)            \
58         bx _reg
59 #else
60 #define RETINSTR(cond, reg)     \
61         mov##cond       pc, reg
62 #define DO_RET(_reg)            \
63         mov pc, _reg
64 #endif
65 #else  /* APCS-26 */
66 #define LOADREGS(cond, base, reglist...)        \
67         ldm##cond       base,reglist^
68 #define RETINSTR(cond, reg)     \
69         mov##cond##s    pc, reg
70 #define DO_RET(_reg)            \
71         movs pc, _reg
72 #endif
73
74 /* Define an entry point visible from C.  */
75 #define ENTRY(name)                                             \
76   ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name);                     \
77   ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),function)             \
78   .align ALIGNARG(4);                                           \
79   name##:                                                       \
80   CALL_MCOUNT
81
82 #undef  END
83 #define END(name)                                               \
84   ASM_SIZE_DIRECTIVE(name)
85
86 /* If compiled for profiling, call `mcount' at the start of each function.  */
87 #ifdef  PROF
88 #define CALL_MCOUNT                     \
89         str     lr,[sp, #-4]!   ;       \
90         bl      PLTJMP(mcount)  ;       \
91         ldr     lr, [sp], #4    ;
92 #else
93 #define CALL_MCOUNT             /* Do nothing.  */
94 #endif
95
96 #ifdef  NO_UNDERSCORES
97 /* Since C identifiers are not normally prefixed with an underscore
98    on this system, the asm identifier `syscall_error' intrudes on the
99    C name space.  Make sure we use an innocuous name.  */
100 #define syscall_error   __syscall_error
101 #define mcount          _mcount
102 #endif
103 /* Linux uses a negative return value to indicate syscall errors,
104    unlike most Unices, which use the condition codes' carry flag.
105
106    Since version 2.1 the return value of a system call might be
107    negative even if the call succeeded.  E.g., the `lseek' system call
108    might return a large offset.  Therefore we must not anymore test
109    for < 0, but test for a real error by making sure the value in R0
110    is a real error number.  Linus said he will make sure the no syscall
111    returns a value in -1 .. -4095 as a valid result so we can safely
112    test with -4095.  */
113
114 #undef  PSEUDO
115 #define PSEUDO(name, syscall_name, args)                                \
116   .text;                                                                \
117   ENTRY (name);                                                         \
118     DO_CALL (syscall_name, args);                                       \
119     cmn r0, $4096;
120
121 #define PSEUDO_RET                                                      \
122     RETINSTR(cc, lr);                                                   \
123     b PLTJMP(SYSCALL_ERROR)
124 #undef ret
125 #define ret PSEUDO_RET
126
127 #undef  PSEUDO_END
128 #define PSEUDO_END(name)                                                \
129   SYSCALL_ERROR_HANDLER                                                 \
130   END (name)
131
132 #undef  PSEUDO_NOERRNO
133 #define PSEUDO_NOERRNO(name, syscall_name, args)                        \
134   .text;                                                                \
135   ENTRY (name);                                                         \
136     DO_CALL (syscall_name, args);
137
138 #define PSEUDO_RET_NOERRNO                                              \
139     DO_RET (lr);
140
141 #undef ret_NOERRNO
142 #define ret_NOERRNO PSEUDO_RET_NOERRNO
143
144 #undef  PSEUDO_END_NOERRNO
145 #define PSEUDO_END_NOERRNO(name)                                        \
146   END (name)
147
148 /* The function has to return the error code.  */
149 #undef  PSEUDO_ERRVAL
150 #define PSEUDO_ERRVAL(name, syscall_name, args) \
151   .text;                                                                \
152   ENTRY (name)                                                          \
153     DO_CALL (syscall_name, args);                                       \
154     rsb r0, r0, #0
155
156 #undef  PSEUDO_END_ERRVAL
157 #define PSEUDO_END_ERRVAL(name) \
158   END (name)
159
160 #define ret_ERRVAL PSEUDO_RET_NOERRNO
161
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
189
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
199
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]
210
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.
214
215 */
216
217 #undef  DO_CALL
218 #if defined(__ARM_EABI__)
219 #define DO_CALL(syscall_name, args)             \
220     DOARGS_##args                               \
221     mov ip, r7;                                 \
222     ldr r7, =SYS_ify (syscall_name);            \
223     swi 0x0;                                    \
224     mov r7, ip;                                 \
225     UNDOARGS_##args
226 #else
227 #define DO_CALL(syscall_name, args)             \
228     DOARGS_##args                               \
229     swi SYS_ify (syscall_name);                 \
230     UNDOARGS_##args
231 #endif
232
233 #define DOARGS_0 /* nothing */
234 #define DOARGS_1 /* nothing */
235 #define DOARGS_2 /* nothing */
236 #define DOARGS_3 /* nothing */
237 #define DOARGS_4 /* nothing */
238 #define DOARGS_5 str r4, [sp, $-4]!; ldr r4, [sp, $4];
239 #define DOARGS_6 mov ip, sp; stmfd sp!, {r4, r5}; ldmia ip, {r4, r5};
240 #define DOARGS_7 mov ip, sp; stmfd sp!, {r4, r5, r6}; ldmia ip, {r4, r5, r6};
241
242 #define UNDOARGS_0 /* nothing */
243 #define UNDOARGS_1 /* nothing */
244 #define UNDOARGS_2 /* nothing */
245 #define UNDOARGS_3 /* nothing */
246 #define UNDOARGS_4 /* nothing */
247 #define UNDOARGS_5 ldr r4, [sp], $4;
248 #define UNDOARGS_6 ldmfd sp!, {r4, r5};
249 #define UNDOARGS_7 ldmfd sp!, {r4, r5, r6};
250
251 #else /* not __ASSEMBLER__ */
252 /* Define a macro which expands into the inline wrapper code for a system
253    call.  */
254 #undef INLINE_SYSCALL
255 #define INLINE_SYSCALL(name, nr, args...)                                       \
256   ({ unsigned int _inline_sys_result = INTERNAL_SYSCALL (name, , nr, args);     \
257      if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_inline_sys_result, ), 0)) \
258        {                                                                        \
259          __set_errno (INTERNAL_SYSCALL_ERRNO (_inline_sys_result, ));           \
260          _inline_sys_result = (unsigned int) -1;                                \
261        }                                                                        \
262      (int) _inline_sys_result; })
263
264 #undef INTERNAL_SYSCALL_DECL
265 #define INTERNAL_SYSCALL_DECL(err) do { } while (0)
266
267 #undef INTERNAL_SYSCALL_RAW
268 #if defined(__thumb__)
269 /* Hide the use of r7 from the compiler, this would be a lot
270  * easier but for the fact that the syscalls can exceed 255.
271  * For the moment the LOAD_ARG_7 is sacrificed.
272  * We can't use push/pop inside the asm because that breaks
273  * unwinding (ie. thread cancellation).
274  */
275 #define INTERNAL_SYSCALL_RAW(name, err, nr, args...)            \
276   ({ unsigned int _internal_sys_result;                         \
277     {                                                           \
278       int _sys_buf[2];                                          \
279       register int __a1 __asm__ ("a1");                         \
280       register int *_v3 __asm__ ("v3") = _sys_buf;              \
281       LOAD_ARGS_##nr (args)                                     \
282       *_v3 = (int) (name);                                      \
283       __asm__ __volatile__ ("str        r7, [v3, #4]\n"         \
284                     "\tldr      r7, [v3]\n"                     \
285                     "\tswi      0       @ syscall " #name "\n"  \
286                     "\tldr      r7, [v3, #4]"                   \
287                    : "=r" (__a1)                                \
288                     : "r" (_v3) ASM_ARGS_##nr                   \
289                     : "memory");                                \
290       _internal_sys_result = __a1;                              \
291     }                                                           \
292     (int) _internal_sys_result; })
293 #elif defined(__ARM_EABI__)
294 #define INTERNAL_SYSCALL_RAW(name, err, nr, args...)            \
295   ({unsigned int _internal_sys_result;                          \
296      {                                                          \
297        register int __a1 __asm__ ("r0"), _nr __asm__ ("r7");    \
298        LOAD_ARGS_##nr (args)                                    \
299        _nr = name;                                              \
300        __asm__ __volatile__ ("swi       0x0 @ syscall " #name   \
301                      : "=r" (__a1)                              \
302                      : "r" (_nr) ASM_ARGS_##nr                  \
303                      : "memory");                               \
304        _internal_sys_result = __a1;                             \
305      }                                                          \
306      (int) _internal_sys_result; })
307 #else /* !defined(__ARM_EABI__) */
308 #define INTERNAL_SYSCALL_RAW(name, err, nr, args...)            \
309   ({ unsigned int _internal_sys_result;                         \
310      {                                                          \
311        register int __a1 __asm__ ("a1");                        \
312        LOAD_ARGS_##nr (args)                                    \
313        __asm__ __volatile__ ("swi       %1 @ syscall " #name    \
314                      : "=r" (__a1)                              \
315                      : "i" (name) ASM_ARGS_##nr                 \
316                      : "memory");                               \
317        _internal_sys_result = __a1;                             \
318      }                                                          \
319      (int) _internal_sys_result; })
320 #endif
321
322 #undef INTERNAL_SYSCALL
323 #define INTERNAL_SYSCALL(name, err, nr, args...)                \
324         INTERNAL_SYSCALL_RAW(SYS_ify(name), err, nr, args)
325
326 #undef INTERNAL_SYSCALL_ARM
327 #define INTERNAL_SYSCALL_ARM(name, err, nr, args...)            \
328         INTERNAL_SYSCALL_RAW(__ARM_NR_##name, err, nr, args)
329
330 #undef INTERNAL_SYSCALL_ERROR_P
331 #define INTERNAL_SYSCALL_ERROR_P(val, err) \
332   ((unsigned int) (val) >= 0xfffff001u)
333
334 #undef INTERNAL_SYSCALL_ERRNO
335 #define INTERNAL_SYSCALL_ERRNO(val, err)        (-(val))
336
337 #if defined(__ARM_EABI__)
338 #undef INTERNAL_SYSCALL_NCS
339 #define INTERNAL_SYSCALL_NCS(number, err, nr, args...)          \
340         INTERNAL_SYSCALL_RAW(number, err, nr, args)
341 #else
342 /* We can't implement non-constant syscalls directly since the syscall
343    number is normally encoded in the instruction.  So use SYS_syscall.  */
344 #undef INTERNAL_SYSCALL_NCS
345 #define INTERNAL_SYSCALL_NCS(number, err, nr, args...)          \
346         INTERNAL_SYSCALL_NCS_##nr (number, err, args)
347
348 #define INTERNAL_SYSCALL_NCS_0(number, err, args...)            \
349         INTERNAL_SYSCALL (syscall, err, 1, number, args)
350 #define INTERNAL_SYSCALL_NCS_1(number, err, args...)            \
351         INTERNAL_SYSCALL (syscall, err, 2, number, args)
352 #define INTERNAL_SYSCALL_NCS_2(number, err, args...)            \
353         INTERNAL_SYSCALL (syscall, err, 3, number, args)
354 #define INTERNAL_SYSCALL_NCS_3(number, err, args...)            \
355         INTERNAL_SYSCALL (syscall, err, 4, number, args)
356 #define INTERNAL_SYSCALL_NCS_4(number, err, args...)            \
357         INTERNAL_SYSCALL (syscall, err, 5, number, args)
358 #define INTERNAL_SYSCALL_NCS_5(number, err, args...)            \
359         INTERNAL_SYSCALL (syscall, err, 6, number, args)
360 #endif
361
362 #endif  /* __ASSEMBLER__ */
363
364 /* Pointer mangling is not yet supported for ARM.  */
365 #define PTR_MANGLE(var) (void) (var)
366 #define PTR_DEMANGLE(var) (void) (var)
367
368 #endif /* linux/arm/sysdep.h */