Test for stack alignment.
[glibc.git] / sysdeps / unix / sysv / linux / hppa / sysdep.h
blob4cfe63c556d4cc73537b2da555d9c69a232dff56
1 /* Assembler macros for PA-RISC.
2 Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper, <drepper@cygnus.com>, August 1999.
5 Linux/PA-RISC changes by Philipp Rumpf, <prumpf@tux.org>, March 2000.
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with the GNU C Library; if not, write to the Free
19 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307 USA. */
22 #include <asm/unistd.h>
23 #include <sysdeps/generic/sysdep.h>
24 #include <sys/syscall.h>
25 #include "config.h"
27 #ifndef ASM_LINE_SEP
28 # define ASM_LINE_SEP ;
29 #endif
31 #undef SYS_ify
32 #define SYS_ify(syscall_name) (__NR_##syscall_name)
34 #ifdef PIC
35 /* WARNING: CANNOT BE USED IN A NOP! */
36 # define STW_PIC stw %r19, -32(%sr0, %sp) ASM_LINE_SEP
37 # define LDW_PIC ldw -32(%sr0, %sp), %r19 ASM_LINE_SEP
38 # define STW_ASM_PIC " copy %%r19, %%r4\n"
39 # define LDW_ASM_PIC " copy %%r4, %%r19\n"
40 # define USING_GR4 "%r4",
41 #else
42 # define STW_PIC ASM_LINE_SEP
43 # define LDW_PIC ASM_LINE_SEP
44 # define STW_ASM_PIC " \n"
45 # define LDW_ASM_PIC " \n"
46 # define USING_GR4
47 #endif
49 #ifdef __ASSEMBLER__
51 /* Syntactic details of assembler. */
53 #define ALIGNARG(log2) log2
55 /* For Linux we can use the system call table in the header file
56 /usr/include/asm/unistd.h
57 of the kernel. But these symbols do not follow the SYS_* syntax
58 so we have to redefine the `SYS_ify' macro here. */
59 #undef SYS_ify
60 #define SYS_ify(syscall_name) __NR_##syscall_name
62 /* ELF-like local names start with `.L'. */
63 #undef L
64 #define L(name) .L##name
66 /* Linux uses a negative return value to indicate syscall errors,
67 unlike most Unices, which use the condition codes' carry flag.
69 Since version 2.1 the return value of a system call might be
70 negative even if the call succeeded. E.g., the `lseek' system call
71 might return a large offset. Therefore we must not anymore test
72 for < 0, but test for a real error by making sure the value in %eax
73 is a real error number. Linus said he will make sure the no syscall
74 returns a value in -1 .. -4095 as a valid result so we can safely
75 test with -4095. */
77 /* We don't want the label for the error handle to be global when we define
78 it here. */
79 #ifdef PIC
80 # define SYSCALL_ERROR_LABEL 0f
81 #else
82 # define SYSCALL_ERROR_LABEL syscall_error
83 #endif
85 /* Define an entry point visible from C.
87 There is currently a bug in gdb which prevents us from specifying
88 incomplete stabs information. Fake some entries here which specify
89 the current source file. */
90 #define ENTRY(name) \
91 .text ASM_LINE_SEP \
92 .export C_SYMBOL_NAME(name) ASM_LINE_SEP \
93 .type C_SYMBOL_NAME(name),@function ASM_LINE_SEP \
94 C_LABEL(name) ASM_LINE_SEP \
95 CALL_MCOUNT ASM_LINE_SEP
97 #undef END
98 #define END(name) \
99 1: ASM_LINE_SEP \
100 .size C_SYMBOL_NAME(name),1b-C_SYMBOL_NAME(name) ASM_LINE_SEP
102 /* If compiled for profiling, call `mcount' at the start of each function. */
103 /* No, don't bother. gcc will put the call in for us. */
104 #define CALL_MCOUNT /* Do nothing. */
106 /* syscall wrappers consist of
107 #include <sysdep.h>
108 PSEUDO(...)
110 PSEUDO_END(...)
112 which means
113 ENTRY(name)
114 DO_CALL(...)
116 bv 0(2)
120 #define PSEUDO(name, syscall_name, args) \
121 ENTRY (name) \
122 DO_CALL(syscall_name, args) ASM_LINE_SEP \
123 nop ASM_LINE_SEP
125 #define ret \
126 /* Return value set by ERRNO code */ ASM_LINE_SEP \
127 bv 0(2) ASM_LINE_SEP \
128 nop ASM_LINE_SEP
130 #undef PSEUDO_END
131 #define PSEUDO_END(name) \
132 END (name)
134 /* We don't set the errno on the return from the syscall */
135 #define PSEUDO_NOERRNO(name, syscall_name, args) \
136 ENTRY (name) \
137 DO_CALL_NOERRNO(syscall_name, args) ASM_LINE_SEP \
138 nop ASM_LINE_SEP
140 #define ret_NOERRNO ret
142 #undef PSEUDO_END_NOERRNO
143 #define PSEUDO_END_NOERRNO(name) \
144 END (name)
146 /* This has to return the error value */
147 #undef PSEUDO_ERRVAL
148 #define PSEUDO_ERRVAL(name, syscall_name, args) \
149 ENTRY(name) \
150 DO_CALL_ERRVAL(syscall_name, args) ASM_LINE_SEP \
151 nop ASM_LINE_SEP
153 #define ret_ERRVAL ret
155 #undef PSEUDO_END_ERRVAL
156 #define PSEUDO_END_ERRVAL(name) \
157 END(name)
159 #undef JUMPTARGET
160 #define JUMPTARGET(name) name
161 #define SYSCALL_PIC_SETUP /* Nothing. */
164 /* All the syscall assembly macros rely on finding the approriate
165 SYSCALL_ERROR_LABEL or rather HANDLER. */
167 /* int * __errno_location(void) so you have to store your value
168 into the return address! */
169 #define DEFAULT_SYSCALL_ERROR_HANDLER \
170 .import __errno_location,code ASM_LINE_SEP \
171 /* branch to errno handler */ ASM_LINE_SEP \
172 bl __errno_location,%rp ASM_LINE_SEP
174 /* Here are the myriad of configuration options that the above can
175 work for... what we've done is provide the framework for future
176 changes if required to each section */
178 #ifdef PIC
179 # if RTLD_PRIVATE_ERRNO
180 # define SYSCALL_ERROR_HANDLER DEFAULT_SYSCALL_ERROR_HANDLER
181 # else /* !RTLD_PRIVATE_ERRNO */
182 # if defined _LIBC_REENTRANT
183 # define SYSCALL_ERROR_HANDLER DEFAULT_SYSCALL_ERROR_HANDLER
184 # else /* !_LIBC_REENTRANT */
185 # define SYSCALL_ERROR_HANDLER DEFAULT_SYSCALL_ERROR_HANDLER
186 # endif /* _LIBC_REENTRANT */
187 # endif /* RTLD_PRIVATE_ERRNO */
188 #else
189 # ifndef _LIBC_REENTRANT
190 # define SYSCALL_ERROR_HANDLER DEFAULT_SYSCALL_ERROR_HANDLER
191 # else
192 # define SYSCALL_ERROR_HANDLER DEFAULT_SYSCALL_ERROR_HANDLER
193 # endif
194 #endif
197 /* Linux takes system call arguments in registers:
198 syscall number gr20
199 arg 1 gr26
200 arg 2 gr25
201 arg 3 gr24
202 arg 4 gr23
203 arg 5 gr22
204 arg 6 gr21
206 The compiler calls us by the C convention:
207 syscall number in the DO_CALL macro
208 arg 1 gr26
209 arg 2 gr25
210 arg 3 gr24
211 arg 4 gr23
212 arg 5 -52(gr30)
213 arg 6 -56(gr30)
215 gr22 and gr21 are caller-saves, so we can just load the arguments
216 there and generally be happy. */
218 /* the cmpb...no_error code below inside DO_CALL
219 * is intended to mimic the if (__sys_res...)
220 * code inside INLINE_SYSCALL
223 #undef DO_CALL
224 #define DO_CALL(syscall_name, args) \
225 DOARGS_##args ASM_LINE_SEP \
226 STW_PIC ASM_LINE_SEP \
227 /* Do syscall, delay loads # */ ASM_LINE_SEP \
228 ble 0x100(%sr2,%r0) ASM_LINE_SEP \
229 ldi SYS_ify (syscall_name), %r20 ASM_LINE_SEP \
230 ldi -0x1000,%r1 ASM_LINE_SEP \
231 cmpb,>>=,n %r1,%ret0,0f ASM_LINE_SEP \
232 /* save rp or we get lost */ ASM_LINE_SEP \
233 stw %rp, -20(%sr0,%sp) ASM_LINE_SEP \
234 /* Restore r19 from frame */ ASM_LINE_SEP \
235 LDW_PIC ASM_LINE_SEP \
236 stw %ret0, -24(%sr0,%sp) ASM_LINE_SEP \
237 SYSCALL_ERROR_HANDLER ASM_LINE_SEP \
238 /* create frame */ ASM_LINE_SEP \
239 ldo 64(%sp), %sp ASM_LINE_SEP \
240 ldo -64(%sp), %sp ASM_LINE_SEP \
241 /* OPTIMIZE: Don't reload r19 */ ASM_LINE_SEP \
242 /* do a -1*syscall_ret0 */ ASM_LINE_SEP \
243 ldw -24(%sr0,%sp), %r26 ASM_LINE_SEP \
244 sub %r0, %r26, %r26 ASM_LINE_SEP \
245 /* Store into errno location */ ASM_LINE_SEP \
246 stw %r26, 0(%sr0,%ret0) ASM_LINE_SEP \
247 /* return -1 as error */ ASM_LINE_SEP \
248 ldo -1(%r0), %ret0 ASM_LINE_SEP \
249 ldw -20(%sr0,%sp), %rp ASM_LINE_SEP \
250 0: ASM_LINE_SEP \
251 UNDOARGS_##args ASM_LINE_SEP
253 /* We do nothing with the return, except hand it back to someone else */
254 #undef DO_CALL_NOERRNO
255 #define DO_CALL_NOERRNO(syscall_name, args) \
256 DOARGS_##args \
257 /* No need to store r19 */ ASM_LINE_SEP \
258 ble 0x100(%sr2,%r0) ASM_LINE_SEP \
259 ldi SYS_ify (syscall_name), %r20 ASM_LINE_SEP \
260 /* Caller will restore r19 */ ASM_LINE_SEP \
261 UNDOARGS_##args
263 /* Here, we return the ERRVAL in assembly, note we don't call the
264 error handler function, but we do 'negate' the return _IF_
265 it's an error. Not sure if this is the right semantic. */
267 #undef DO_CALL_ERRVAL
268 #define DO_CALL_ERRVAL(syscall_name, args) \
269 DOARGS_##args ASM_LINE_SEP \
270 /* No need to store r19 */ ASM_LINE_SEP \
271 ble 0x100(%sr2,%r0) ASM_LINE_SEP \
272 ldi SYS_ify (syscall_name), %r20 ASM_LINE_SEP \
273 /* Caller will restore r19 */ ASM_LINE_SEP \
274 ldi -0x1000,%r1 ASM_LINE_SEP \
275 cmpb,>>=,n %r1,%ret0,0f ASM_LINE_SEP \
276 sub %r0, %ret0, %ret0 ASM_LINE_SEP \
277 0: ASM_LINE_SEP \
278 UNDOARGS_##args ASM_LINE_SEP
280 #define DOARGS_0 /* nothing */
281 #define DOARGS_1 /* nothing */
282 #define DOARGS_2 /* nothing */
283 #define DOARGS_3 /* nothing */
284 #define DOARGS_4 /* nothing */
285 #define DOARGS_5 ldw -52(%r30), %r22 ASM_LINE_SEP
286 #define DOARGS_6 ldw -52(%r30), %r22 ASM_LINE_SEP \
287 ldw -56(%r30), %r21 ASM_LINE_SEP
290 #define UNDOARGS_0 /* nothing */
291 #define UNDOARGS_1 /* nothing */
292 #define UNDOARGS_2 /* nothing */
293 #define UNDOARGS_3 /* nothing */
294 #define UNDOARGS_4 /* nothing */
295 #define UNDOARGS_5 /* nothing */
296 #define UNDOARGS_6 /* nothing */
298 #else
300 /* GCC has to be warned that a syscall may clobber all the ABI
301 registers listed as "caller-saves", see page 8, Table 2
302 in section 2.2.6 of the PA-RISC RUN-TIME architecture
303 document. However! r28 is the result and will conflict with
304 the clobber list so it is left out. Also the input arguments
305 registers r20 -> r26 will conflict with the list so they
306 are treated specially. Although r19 is clobbered by the syscall
307 we cannot say this because it would violate ABI, thus we say
308 r4 is clobbered and use that register to save/restore r19
309 across the syscall. */
311 #define CALL_CLOB_REGS "%r1", "%r2", USING_GR4 \
312 "%r20", "%r29", "%r31"
314 #undef INLINE_SYSCALL
315 #define INLINE_SYSCALL(name, nr, args...) ({ \
316 long __sys_res; \
318 register unsigned long __res asm("r28"); \
319 LOAD_ARGS_##nr(args) \
320 /* FIXME: HACK stw/ldw r19 around syscall */ \
321 asm volatile( \
322 STW_ASM_PIC \
323 " ble 0x100(%%sr2, %%r0)\n" \
324 " ldi %1, %%r20\n" \
325 LDW_ASM_PIC \
326 : "=r" (__res) \
327 : "i" (SYS_ify(name)) ASM_ARGS_##nr \
328 : CALL_CLOB_REGS CLOB_ARGS_##nr \
329 ); \
330 __sys_res = (long)__res; \
332 if ( (unsigned long)__sys_res >= (unsigned long)-4095 ){ \
333 __set_errno(-__sys_res); \
334 __sys_res = -1; \
336 __sys_res; \
339 /* INTERNAL_SYSCALL_DECL - Allows us to setup some function static
340 value to use within the context of the syscall
341 INTERNAL_SYSCALL_ERROR_P - Returns 0 if it wasn't an error, 1 otherwise
342 You are allowed to use the syscall result (val) and the DECL error variable
343 to determine what went wrong.
344 INTERLAL_SYSCALL_ERRNO - Munges the val/err pair into the error number.
345 In our case we just flip the sign. */
347 #undef INTERNAL_SYSCALL_DECL
348 #define INTERNAL_SYSCALL_DECL(err) do { } while (0)
350 /* Equivalent to (val < 0)&&(val > -4095) which is what we want */
351 #undef INTERNAL_SYSCALL_ERROR_P
352 #define INTERNAL_SYSCALL_ERROR_P(val, err) \
353 ((unsigned long)val >= (unsigned long)-4095)
355 #undef INTERNAL_SYSCALL_ERRNO
356 #define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))
358 /* Similar to INLINE_SYSCALL but we don't set errno */
359 #undef INTERNAL_SYSCALL
360 #define INTERNAL_SYSCALL(name, err, nr, args...) \
361 ({ \
362 long __sys_res; \
364 register unsigned long __res asm("r28"); \
365 LOAD_ARGS_##nr(args) \
366 /* FIXME: HACK stw/ldw r19 around syscall */ \
367 asm volatile( \
368 STW_ASM_PIC \
369 " ble 0x100(%%sr2, %%r0)\n" \
370 " ldi %1, %%r20\n" \
371 LDW_ASM_PIC \
372 : "=r" (__res) \
373 : "i" (SYS_ify(name)) ASM_ARGS_##nr \
374 : CALL_CLOB_REGS CLOB_ARGS_##nr \
375 ); \
376 __sys_res = (long)__res; \
378 __sys_res; \
381 #define LOAD_ARGS_0()
382 #define LOAD_ARGS_1(r26) \
383 register unsigned long __r26 __asm__("r26") = (unsigned long)(r26); \
384 LOAD_ARGS_0()
385 #define LOAD_ARGS_2(r26,r25) \
386 register unsigned long __r25 __asm__("r25") = (unsigned long)(r25); \
387 LOAD_ARGS_1(r26)
388 #define LOAD_ARGS_3(r26,r25,r24) \
389 register unsigned long __r24 __asm__("r24") = (unsigned long)(r24); \
390 LOAD_ARGS_2(r26,r25)
391 #define LOAD_ARGS_4(r26,r25,r24,r23) \
392 register unsigned long __r23 __asm__("r23") = (unsigned long)(r23); \
393 LOAD_ARGS_3(r26,r25,r24)
394 #define LOAD_ARGS_5(r26,r25,r24,r23,r22) \
395 register unsigned long __r22 __asm__("r22") = (unsigned long)(r22); \
396 LOAD_ARGS_4(r26,r25,r24,r23)
397 #define LOAD_ARGS_6(r26,r25,r24,r23,r22,r21) \
398 register unsigned long __r21 __asm__("r21") = (unsigned long)(r21); \
399 LOAD_ARGS_5(r26,r25,r24,r23,r22)
401 /* Even with zero args we use r20 for the syscall number */
402 #define ASM_ARGS_0
403 #define ASM_ARGS_1 ASM_ARGS_0, "r" (__r26)
404 #define ASM_ARGS_2 ASM_ARGS_1, "r" (__r25)
405 #define ASM_ARGS_3 ASM_ARGS_2, "r" (__r24)
406 #define ASM_ARGS_4 ASM_ARGS_3, "r" (__r23)
407 #define ASM_ARGS_5 ASM_ARGS_4, "r" (__r22)
408 #define ASM_ARGS_6 ASM_ARGS_5, "r" (__r21)
410 /* The registers not listed as inputs but clobbered */
411 #define CLOB_ARGS_6
412 #define CLOB_ARGS_5 CLOB_ARGS_6, "%r21"
413 #define CLOB_ARGS_4 CLOB_ARGS_5, "%r22"
414 #define CLOB_ARGS_3 CLOB_ARGS_4, "%r23"
415 #define CLOB_ARGS_2 CLOB_ARGS_3, "%r24"
416 #define CLOB_ARGS_1 CLOB_ARGS_2, "%r25"
417 #define CLOB_ARGS_0 CLOB_ARGS_1, "%r26"
419 #endif /* __ASSEMBLER__ */