Update copyright notices with scripts/update-copyrights
[glibc.git] / ports / sysdeps / unix / sysv / linux / am33 / sysdep.h
blob63fe716594592791cd920a062d5ff06e835418f2
1 /* Copyright 2001-2014 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Alexandre Oliva <aoliva@redhat.com>.
4 Based on ../i386/sysdep.h.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library. If not, see
18 <http://www.gnu.org/licenses/>. */
20 #ifndef _LINUX_AM33_SYSDEP_H
21 #define _LINUX_AM33_SYSDEP_H 1
23 /* There is some commonality. */
24 #include "../../../am33/sysdep.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 SYS_ify(syscall_name) __NR_##syscall_name
33 /* ELF-like local names start with `.L'. */
34 #undef L
35 #define L(name) .L##name
37 #ifdef __ASSEMBLER__
39 /* Linux uses a negative return value to indicate syscall errors,
40 unlike most Unices, which use the condition codes' carry flag.
42 Since version 2.1 the return value of a system call might be
43 negative even if the call succeeded. E.g., the `lseek' system call
44 might return a large offset. Therefore we must not anymore test
45 for < 0, but test for a real error by making sure the value in %eax
46 is a real error number. Linus said he will make sure the no syscall
47 returns a value in -1 .. -4095 as a valid result so we can savely
48 test with -4095. */
50 /* We don't want the label for the error handle to be global when we define
51 it here. */
52 #ifdef PIC
53 # define SYSCALL_ERROR_LABEL 0f
54 #else
55 # define SYSCALL_ERROR_LABEL syscall_error
56 #endif
58 #undef PSEUDO
59 #define PSEUDO(name, syscall_name, args) \
60 .text; \
61 ENTRY (name) \
62 DO_CALL (syscall_name, args); \
63 cmp -126,d0; \
64 bls L(pseudo_end); \
65 jmp SYSCALL_ERROR_LABEL; \
66 L(pseudo_end): \
67 mov d0,a0;
69 #undef PSEUDO_END
70 #define PSEUDO_END(name) \
71 SYSCALL_ERROR_HANDLER \
72 END (name)
74 #undef PSEUDO_NOERROR
75 #define PSEUDO_NOERRNO(name, syscall_name, args) \
76 .text; \
77 ENTRY (name) \
78 DO_CALL (syscall_name, args)
80 #undef PSEUDO_END_NOERRNO
81 #define PSEUDO_END_NOERRNO(name) \
82 END (name)
84 #define ret_NOERRNO ret
86 /* The function has to return the error code. */
87 #undef PSEUDO_ERRVAL
88 #define PSEUDO_ERRVAL(name, syscall_name, args) \
89 .text; \
90 ENTRY (name) \
91 DO_CALL (syscall_name, args); \
92 clr d1; \
93 sub d0,d1,d0
95 #undef PSEUDO_END_ERRVAL
96 #define PSEUDO_END_ERRVAL(name) \
97 END (name)
99 #define ret_ERRVAL ret
101 #ifndef PIC
102 #define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */
103 #else
104 /* Store (- d0) into errno through the GOT. */
105 #ifdef _LIBC_REENTRANT
106 #define SYSCALL_ERROR_HANDLER \
107 0:movm [d2,a2],(sp); \
108 add -12,sp; \
109 1:mov pc,a2; \
110 add _GLOBAL_OFFSET_TABLE_-(1b-.),a2; \
111 clr d2; \
112 sub d0,d2; \
113 call __errno_location@PLT,[],0; \
114 mov d2,(a0); \
115 add 12,sp; \
116 movm (sp),[d2,a2]; \
117 mov -1,d0; \
118 mov d0,a0; \
119 jmp L(pseudo_end);
120 /* A quick note: it is assumed that the call to `__errno_location' does
121 not modify the stack! */
122 #else
123 #define SYSCALL_ERROR_HANDLER \
124 0:mov pc,a0; \
125 add _GLOBAL_OFFSET_TABLE_-(0b-.),a0; \
126 clr d1; \
127 sub d0,d1; \
128 mov (errno@GOT,a0),a1; \
129 mov d1,(a0); \
130 mov -1,d0; \
131 mov d0,a0; \
132 jmp L(pseudo_end);
133 #endif /* _LIBC_REENTRANT */
134 #endif /* PIC */
136 /* Linux takes system call arguments in registers:
138 syscall number d0 call-clobbered
139 arg 1 a0 call-clobbered
140 arg 2 d1 call-clobbered
141 arg 3 a3 call-saved
142 arg 4 a2 call-saved
143 arg 5 d3 call-saved
144 arg 6 d2 call-saved
146 The stack layout upon entering the function is:
148 (24,sp) Arg# 6
149 (20,sp) Arg# 5
150 (16,sp) Arg# 4
151 (12,sp) Arg# 3
152 d1 Arg# 2
153 d0 Arg# 1
154 (sp) Return address
156 (Of course a function with say 3 arguments does not have entries for
157 arguments 4, 5 and 6.) */
159 #undef DO_CALL
160 #define DO_CALL(syscall_name, args) \
161 PUSHARGS_##args \
162 DOARGS_##args \
163 mov SYS_ify (syscall_name),d0; \
164 syscall 0 \
165 POPARGS_##args
167 #define PUSHARGS_0 /* No arguments to push. */
168 #define _DOARGS_0(N) /* No arguments to frob. */
169 #define DOARGS_0 /* No arguments to frob. */
170 #define POPARGS_0 /* No arguments to pop. */
172 #define PUSHARGS_1 /* No arguments to push. */
173 #define _DOARGS_1(N) _DOARGS_0 (N-4) mov d0,a0;
174 #define DOARGS_1 _DOARGS_1 (4)
175 #define POPARGS_1 /* No arguments to pop. */
177 #define PUSHARGS_2 /* No arguments to push. */
178 #define _DOARGS_2(N) _DOARGS_1 (N-4) /* Argument already in d1. */
179 #define DOARGS_2 _DOARGS_2 (8)
180 #define POPARGS_2 /* No arguments to pop. */
182 #define PUSHARGS_3 movm [a3],(sp);
183 #define _DOARGS_3(N) _DOARGS_2 (N-4) mov (N,sp),a3;
184 #define DOARGS_3 _DOARGS_3 (16)
185 #define POPARGS_3 ; movm (sp),[a3]
187 #define PUSHARGS_4 movm [a2,a3],(sp);
188 #define _DOARGS_4(N) _DOARGS_3 (N-4) mov (N,sp),a2;
189 #define DOARGS_4 _DOARGS_4 (24)
190 #define POPARGS_4 ; movm (sp),[a2,a3]
192 #define PUSHARGS_5 movm [d3,a2,a3],(sp);
193 #define _DOARGS_5(N) _DOARGS_4 (N-4) mov (N,sp),d3;
194 #define DOARGS_5 _DOARGS_5 (32)
195 #define POPARGS_5 ; movm (sp),[d3,a2,a3]
197 #define PUSHARGS_6 movm [d2,d3,a2,a3],(sp);
198 #define _DOARGS_6(N) _DOARGS_5 (N-4) mov (N,sp),d2;
199 #define DOARGS_6 _DOARGS_6 (40)
200 #define POPARGS_6 ; movm (sp),[d2,d3,a2,a3]
202 #else /* !__ASSEMBLER__ */
204 /* Define a macro which expands inline into the wrapper code for a system
205 call. */
206 #undef INLINE_SYSCALL
207 #define INLINE_SYSCALL(name, nr, args...) \
208 ({ \
209 unsigned int resultvar = INTERNAL_SYSCALL (name, , nr, args); \
210 if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (resultvar, ), 0)) \
212 __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, )); \
213 resultvar = 0xffffffff; \
215 (int) resultvar; })
217 #define INTERNAL_SYSCALL(name, err, nr, args...) \
218 ({ \
219 register long __sc0 asm ("d0") = __NR_##name; \
220 inline_syscall##nr(name, ## args); \
221 __sc0; \
224 #undef INTERNAL_SYSCALL_DECL
225 #define INTERNAL_SYSCALL_DECL(err) do { } while (0)
227 #undef INTERNAL_SYSCALL_ERROR_P
228 #define INTERNAL_SYSCALL_ERROR_P(val, err) \
229 ((unsigned int) (val) >= (unsigned long)-125)
231 #undef INTERNAL_SYSCALL_ERRNO
232 #define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))
234 #define inline_syscall0(name,dummy...) \
235 __asm__ __volatile__ ("syscall 0" \
236 : "+d" (__sc0) \
237 : : "memory")
239 #define inline_syscall1(name,arg1) \
240 register long __sc1 asm ("a0") = (long) (arg1); \
241 inline_syscall0 (name); \
242 __asm__ __volatile__ ("" : : "r" (__sc1))
244 #define inline_syscall2(name,arg1,arg2) \
245 register long __sc2 asm ("d1") = (long) (arg2); \
246 inline_syscall1 (name,(arg1)); \
247 __asm__ __volatile__ ("" : : "r" (__sc2))
249 /* We can't tell whether a3 is going to be eliminated in the enclosing
250 function, so we have to assume it isn't. We first load the value
251 of any arguments into their registers, except for a3 itself, that
252 may be needed to load the value of the other arguments. Then, we
253 save a3's value in some other register, and load the argument value
254 into a3. We have to force both a3 and its copy to be live in
255 different registers at the same time, to avoid having the copy
256 spilled and the value reloaded into the same register, in which
257 case we'd be unable to get the value of a3 back, should the stack
258 slot reference be (offset,a3). */
259 #define inline_syscall3(name,arg1,arg2,arg3) \
260 long __sc3v = (long) (arg3); \
261 register long __sc1 asm ("a0") = (long) (arg1); \
262 register long __sc2 asm ("d1") = (long) (arg2); \
263 register long __sc3 asm ("a3") = __sc3; \
264 register long __sc3c; \
265 __asm__ __volatile__ ("mov %1,%0" : "=&r" (__sc3c) : "r" (__sc3)); \
266 __sc3 = __sc3v; \
267 __asm__ __volatile__ ("" : : "r" (__sc3c), "r" (__sc3)); \
268 inline_syscall0 (name); \
269 __sc3 = __sc3c; \
270 __asm__ __volatile__ ("" : : "r" (__sc3), "r" (__sc2), "r" (__sc1))
272 #ifdef PIC
273 /* Since a2 is the PIC register, it requires similar handling as a3
274 when we're generating PIC, as a2's value may be needed to load
275 arguments whose values live in global variables. The difference is
276 that we don't need to require its value to be live in a register;
277 it may well be in a stack slot, as long as we save it before
278 clobbering a3 and restore it after restoring a3. */
279 #define inline_syscall4(name,arg1,arg2,arg3,arg4) \
280 long __sc4v = (long) (arg4); \
281 long __sc3v = (long) (arg3); \
282 register long __sc1 asm ("a0") = (long) (arg1); \
283 register long __sc2 asm ("d1") = (long) (arg2); \
284 register long __sc3 asm ("a3") = __sc3; \
285 register long __sc3c; \
286 register long __sc4 asm ("a2") = __sc4; \
287 long __sc4c = __sc4; \
288 __sc4 = __sc4v; \
289 __asm__ __volatile__ ("mov %1,%0" : "=&r" (__sc3c) : "r" (__sc3)); \
290 __sc3 = __sc3v; \
291 __asm__ __volatile__ ("" : : "r" (__sc3c), "r" (__sc3), "r" (__sc4)); \
292 inline_syscall0 (name); \
293 __sc3 = __sc3c; \
294 __sc4 = __sc4c; \
295 __asm__ __volatile__ ("" : : "r" (__sc4), "r" (__sc3), \
296 "r" (__sc2), "r" (__sc1))
297 #else
298 #define inline_syscall4(name,arg1,arg2,arg3,arg4) \
299 register long __sc4 asm ("a2") = (long) (arg4); \
300 inline_syscall3 (name,(arg1),(arg2),(arg3)); \
301 __asm__ __volatile__ ("" : : "r" (__sc4))
302 #endif
304 #define inline_syscall5(name,arg1,arg2,arg3,arg4,arg5) \
305 register long __sc5 asm ("d3") = (long) (arg5); \
306 inline_syscall4 (name,(arg1),(arg2),(arg3),(arg4)); \
307 __asm__ __volatile__ ("" : : "r" (__sc5))
309 #define inline_syscall6(name,arg1,arg2,arg3,arg4,arg5,arg6) \
310 register long __sc6 asm ("d2") = (long) (arg6); \
311 inline_syscall5 (name,(arg1),(arg2),(arg3),(arg4),(arg5)); \
312 __asm__ __volatile__ ("" : : "r" (__sc6))
314 #endif /* __ASSEMBLER__ */
316 #endif /* linux/am33/sysdep.h */