143064261240d1e27ca0a318067994241f4d9d8e
[kopensolaris-gnu/glibc.git] / sysdeps / unix / sysv / linux / hppa / sysdep.h
1 /* Assembler macros for PA-RISC.
2    Copyright (C) 1999, 2001 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.
6
7    The GNU C Library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Library General Public License as
9    published by the Free Software Foundation; either version 2 of the
10    License, or (at your option) any later version.
11
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    Library General Public License for more details.
16
17    You should have received a copy of the GNU Library General Public
18    License along with the GNU C Library; see the file COPYING.LIB.  If not,
19    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.  */
21
22 #include <asm/unistd.h>
23 #include <sysdeps/generic/sysdep.h>
24 #include <sys/syscall.h>
25 #include "config.h"
26
27 #ifndef ASM_LINE_SEP
28 #define ASM_LINE_SEP ;
29 #endif
30
31 #undef SYS_ify
32 #define SYS_ify(syscall_name)   (__NR_##syscall_name)
33
34
35 #ifdef __ASSEMBLER__
36
37 /* Syntactic details of assembler.  */
38
39 #define ALIGNARG(log2) log2
40
41 /* For Linux we can use the system call table in the header file
42         /usr/include/asm/unistd.h
43    of the kernel.  But these symbols do not follow the SYS_* syntax
44    so we have to redefine the `SYS_ify' macro here.  */
45 #undef SYS_ify
46 #define SYS_ify(syscall_name)   __NR_##syscall_name
47
48 /* ELF-like local names start with `.L'.  */
49 #undef L
50 #define L(name) .L##name
51
52 /* Linux uses a negative return value to indicate syscall errors,
53    unlike most Unices, which use the condition codes' carry flag.
54
55    Since version 2.1 the return value of a system call might be
56    negative even if the call succeeded.  E.g., the `lseek' system call
57    might return a large offset.  Therefore we must not anymore test
58    for < 0, but test for a real error by making sure the value in %eax
59    is a real error number.  Linus said he will make sure the no syscall
60    returns a value in -1 .. -4095 as a valid result so we can safely
61    test with -4095.  */
62
63 /* We don't want the label for the error handle to be global when we define
64    it here.  */
65 #ifdef PIC
66 # define SYSCALL_ERROR_LABEL 0f
67 #else
68 # define SYSCALL_ERROR_LABEL syscall_error
69 #endif
70
71 /* Define an entry point visible from C.
72
73    There is currently a bug in gdb which prevents us from specifying
74    incomplete stabs information.  Fake some entries here which specify
75    the current source file.  */
76 #define ENTRY(name)                                             \
77         .text                                   ASM_LINE_SEP    \
78         .export C_SYMBOL_NAME(name)             ASM_LINE_SEP    \
79         .type   C_SYMBOL_NAME(name),@function   ASM_LINE_SEP    \
80         C_LABEL(name)                                           \
81         CALL_MCOUNT
82
83 #define ret \
84         bv 0(2)                                 ASM_LINE_SEP    \
85         nop
86
87 #undef  END
88 #define END(name)                                               \
89 1:      .size   C_SYMBOL_NAME(name),1b-C_SYMBOL_NAME(name)
90
91 /* If compiled for profiling, call `mcount' at the start of each function.  */
92 #ifdef  PROF
93 /* The mcount code relies on a normal frame pointer being on the stack
94    to locate our caller, so push one just for its benefit.  */
95 #define CALL_MCOUNT             /* XXX */
96 #else
97 #define CALL_MCOUNT             /* Do nothing.  */
98 #endif
99
100 /* syscall wrappers consist of
101         #include <sysdep.h>
102         PSEUDO(...)
103         ret
104         PSEUDO_END(...)
105
106    which means
107         ENTRY(name)
108         DO_CALL(...)
109         nop
110         bv 0(2)
111         nop
112 */
113
114 #define PSEUDO(name, syscall_name, args)                                      \
115   ENTRY (name)                                                                \
116   DO_CALL(args, syscall_name)                                   ASM_LINE_SEP  \
117   nop
118
119 #undef  PSEUDO_END
120 #define PSEUDO_END(name)                                                      \
121   END (name)
122
123 #define JUMPTARGET(name)        name
124 #define SYSCALL_PIC_SETUP       /* Nothing.  */
125
126 /* Linux takes system call arguments in registers:
127         syscall number  gr20
128         arg 1           gr26
129         arg 2           gr25
130         arg 3           gr24
131         arg 4           gr23
132         arg 5           gr22
133         arg 6           gr21
134
135    The compiler calls us by the C convention:
136         syscall number  in the DO_CALL macro
137         arg 1           gr26
138         arg 2           gr25
139         arg 3           gr24
140         arg 4           gr23
141         arg 5           -52(gr30)
142         arg 6           -56(gr30)
143
144    gr22 and gr21 are caller-saves, so we can just load the arguments
145    there and generally be happy. */
146
147 /* the cmpb...no_error code below inside DO_CALL
148  * is intended to mimic the if (__sys_res...)
149  * code inside INLINE_SYSCALL
150  */
151
152 #undef  DO_CALL
153 #define DO_CALL(args, syscall_name)                             \
154         DOARGS_##args                                           \
155         ble  0x100(%sr2,%r0)                    ASM_LINE_SEP    \
156         ldi SYS_ify (syscall_name), %r20        ASM_LINE_SEP    \
157         ldi -0x1000,%r1                         ASM_LINE_SEP    \
158         cmpb,>>=,n %r1,%ret0,0f                 ASM_LINE_SEP    \
159         stw %rp, -20(%sr0,%r30)                 ASM_LINE_SEP    \
160         stw %ret0, -24(%sr0,%r30)               ASM_LINE_SEP    \
161         .import __errno_location,code           ASM_LINE_SEP    \
162         bl __errno_location,%rp                 ASM_LINE_SEP    \
163         ldo 64(%r30), %r30                      ASM_LINE_SEP    \
164         ldo -64(%r30), %r30                     ASM_LINE_SEP    \
165         ldw -24(%r30), %r26                     ASM_LINE_SEP    \
166         sub %r0, %r26, %r26                     ASM_LINE_SEP    \
167         stw %r26, 0(%sr0,%ret0)                 ASM_LINE_SEP    \
168         ldo -1(%r0), %ret0                      ASM_LINE_SEP    \
169         ldw -20(%r30), %rp                      ASM_LINE_SEP    \
170 0:                                              ASM_LINE_SEP    \
171         UNDOARGS_##args
172
173 #define DOARGS_0 /* nothing */
174 #define DOARGS_1 /* nothing */
175 #define DOARGS_2 /* nothing */
176 #define DOARGS_3 /* nothing */
177 #define DOARGS_4 /* nothing */
178 #define DOARGS_5 ldw -52(%r30), %r22            ASM_LINE_SEP
179 #define DOARGS_6 ldw -52(%r30), %r22            ASM_LINE_SEP    \
180                  ldw -56(%r30), %r21            ASM_LINE_SEP
181
182
183 #define UNDOARGS_0 /* nothing */
184 #define UNDOARGS_1 /* nothing */
185 #define UNDOARGS_2 /* nothing */
186 #define UNDOARGS_3 /* nothing */
187 #define UNDOARGS_4 /* nothing */
188 #define UNDOARGS_5 /* nothing */
189 #define UNDOARGS_6 /* nothing */
190
191 #else
192
193 #undef INLINE_SYSCALL
194 #define INLINE_SYSCALL(name, nr, args...)       ({              \
195         long __sys_res;                                         \
196         {                                                       \
197                 register unsigned long __res asm("r28");        \
198                 LOAD_ARGS_##nr(args)                            \
199                 asm volatile(                                   \
200                         "ble  0x100(%%sr2, %%r0)\n\t"           \
201                         " ldi %1, %%r20"                        \
202                         : "=r" (__res)                          \
203                         : "i" (SYS_ify(name)) ASM_ARGS_##nr     \
204                          );                                     \
205                 __sys_res = __res;                              \
206         }                                                       \
207         if ((unsigned long)__sys_res >= (unsigned long)-4095) { \
208                 __set_errno(-__sys_res);                        \
209                 __sys_res = -1;                                 \
210         }                                                       \
211         __sys_res;                                              \
212 })
213
214 #define LOAD_ARGS_0()
215 #define LOAD_ARGS_1(r26)                                        \
216         register unsigned long __r26 __asm__("r26") = (unsigned long)r26;       \
217         LOAD_ARGS_0()
218 #define LOAD_ARGS_2(r26,r25)                                    \
219         register unsigned long __r25 __asm__("r25") = (unsigned long)r25;       \
220         LOAD_ARGS_1(r26)
221 #define LOAD_ARGS_3(r26,r25,r24)                                \
222         register unsigned long __r24 __asm__("r24") = (unsigned long)r24;       \
223         LOAD_ARGS_2(r26,r25)
224 #define LOAD_ARGS_4(r26,r25,r24,r23)                            \
225         register unsigned long __r23 __asm__("r23") = (unsigned long)r23;       \
226         LOAD_ARGS_3(r26,r25,r24)
227 #define LOAD_ARGS_5(r26,r25,r24,r23,r22)                        \
228         register unsigned long __r22 __asm__("r22") = (unsigned long)r22;       \
229         LOAD_ARGS_4(r26,r25,r24,r23)
230 #define LOAD_ARGS_6(r26,r25,r24,r23,r22,r21)                    \
231         register unsigned long __r21 __asm__("r21") = (unsigned long)r21;       \
232         LOAD_ARGS_5(r26,r25,r24,r23,r22)
233
234 #define ASM_ARGS_0 
235 #define ASM_ARGS_1 , "r" (__r26)
236 #define ASM_ARGS_2 , "r" (__r26), "r" (__r25)
237 #define ASM_ARGS_3 , "r" (__r26), "r" (__r25), "r" (__r24)
238 #define ASM_ARGS_4 , "r" (__r26), "r" (__r25), "r" (__r24), "r" (__r23)
239 #define ASM_ARGS_5 , "r" (__r26), "r" (__r25), "r" (__r24), "r" (__r23), "r" (__r22)
240 #define ASM_ARGS_6 , "r" (__r26), "r" (__r25), "r" (__r24), "r" (__r23), "r" (__r22), "r" (__r21)
241
242 #endif  /* __ASSEMBLER__ */