(INLINE_SYSCALL): Undefined before defining.
[kopensolaris-gnu/glibc.git] / sysdeps / unix / alpha / sysdep.h
1 /* Copyright (C) 1992, 1995, 1996, 2000, 2003 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Brendan Kehoe (brendan@zen.org).
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 #include <sysdeps/unix/sysdep.h>
21
22 #ifdef __ASSEMBLER__
23
24 #ifdef __linux__
25 # include <alpha/regdef.h>
26 #else
27 # include <regdef.h>
28 #endif
29
30 #include <tls.h>                /* Defines USE___THREAD.  */
31
32 #ifdef IS_IN_rtld
33 # include <dl-sysdep.h>         /* Defines RTLD_PRIVATE_ERRNO.  */
34 #endif
35
36
37 #ifdef __STDC__
38 #define __LABEL(x)      x##:
39 #else
40 #define __LABEL(x)      x/**/:
41 #endif
42
43 #define LEAF(name, framesize)                   \
44   .globl name;                                  \
45   .align 3;                                     \
46   .ent name, 0;                                 \
47   __LABEL(name)                                 \
48   .frame sp, framesize, ra
49
50 #define ENTRY(name)                             \
51   .globl name;                                  \
52   .align 3;                                     \
53   .ent name, 0;                                 \
54   __LABEL(name)                                 \
55   .frame sp, 0, ra
56
57 /* Mark the end of function SYM.  */
58 #undef END
59 #define END(sym)        .end sym
60
61 #ifdef PROF
62 # define PSEUDO_PROLOGUE                        \
63         .frame sp, 0, ra;                       \
64         ldgp    gp,0(pv);                       \
65         .set noat;                              \
66         lda     AT,_mcount;                     \
67         jsr     AT,(AT),_mcount;                \
68         .set at;                                \
69         .prologue 1
70 #elif defined PIC
71 # define PSEUDO_PROLOGUE                        \
72         .frame sp, 0, ra;                       \
73         .prologue 0
74 #else
75 # define PSEUDO_PROLOGUE                        \
76         .frame sp, 0, ra;                       \
77         ldgp    gp,0(pv);                       \
78         .prologue 1
79 #endif /* PROF */
80
81 #if RTLD_PRIVATE_ERRNO
82 # define SYSCALL_ERROR_LABEL    $syscall_error
83 # define SYSCALL_ERROR_HANDLER                  \
84         stl     v0, errno(gp)   !gprel;         \
85         lda     v0, -1;                         \
86         ret
87 #elif defined(PIC)
88 # define SYSCALL_ERROR_LABEL    __syscall_error
89 # define SYSCALL_ERROR_HANDLER \
90         br      $31, __syscall_error !samegp
91 #else
92 # define SYSCALL_ERROR_LABEL    $syscall_error
93 # define SYSCALL_ERROR_HANDLER \
94         jmp     $31, __syscall_error
95 #endif /* RTLD_PRIVATE_ERRNO */
96
97 /* Overridden by specific syscalls.  */
98 #undef PSEUDO_PREPARE_ARGS
99 #define PSEUDO_PREPARE_ARGS     /* Nothing.  */
100
101 #define PSEUDO(name, syscall_name, args)        \
102         .globl name;                            \
103         .align 4;                               \
104         .ent name,0;                            \
105 __LABEL(name)                                   \
106         PSEUDO_PROLOGUE;                        \
107         PSEUDO_PREPARE_ARGS                     \
108         lda     v0, SYS_ify(syscall_name);      \
109         call_pal PAL_callsys;                   \
110         bne     a3, SYSCALL_ERROR_LABEL
111
112 #undef PSEUDO_END
113 #if defined(PIC) && !RTLD_PRIVATE_ERRNO
114 # define PSEUDO_END(sym)  END(sym)
115 #else
116 # define PSEUDO_END(sym)                        \
117 $syscall_error:                                 \
118         SYSCALL_ERROR_HANDLER;                  \
119         END(sym)
120 #endif
121
122 #define r0      v0
123 #define r1      a4
124
125 #define MOVE(x,y)       mov x,y
126
127 #else /* !ASSEMBLER */
128
129 /* ??? Linux needs to be able to override INLINE_SYSCALL for one
130    particular special case.  Make this easy.  */
131
132 #undef INLINE_SYSCALL
133 #define INLINE_SYSCALL(name, nr, args...) \
134         INLINE_SYSCALL1(name, nr, args)
135
136 #define INLINE_SYSCALL1(name, nr, args...)      \
137 ({                                              \
138         long _sc_ret, _sc_err;                  \
139         inline_syscall##nr(name, args);         \
140         if (_sc_err)                            \
141           {                                     \
142             __set_errno (_sc_ret);              \
143             _sc_ret = -1L;                      \
144           }                                     \
145         _sc_ret;                                \
146 })
147
148 #define INTERNAL_SYSCALL(name, err_out, nr, args...) \
149         INTERNAL_SYSCALL1(name, err_out, nr, args)
150
151 #define INTERNAL_SYSCALL1(name, err_out, nr, args...)   \
152 ({                                                      \
153         long _sc_ret, _sc_err;                          \
154         inline_syscall##nr(name, args);                 \
155         err_out = _sc_err;                              \
156         _sc_ret;                                        \
157 })
158
159 #define INTERNAL_SYSCALL_DECL(err)              long int err
160 #define INTERNAL_SYSCALL_ERROR_P(val, err)      err
161 #define INTERNAL_SYSCALL_ERRNO(val, err)        val
162
163 #define inline_syscall_clobbers                         \
164         "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", \
165         "$22", "$23", "$24", "$25", "$27", "$28", "memory"
166
167 /* If TLS is in use, we have a conflict between the PAL_rduniq primitive,
168    as modeled within GCC, and explicit use of the R0 register.  If we use
169    the register via the asm, the scheduler may place the PAL_rduniq insn
170    before we've copied the data from R0 into _sc_ret.  If this happens 
171    we'll get a reload abort, since R0 is live at the same time it is 
172    needed for the PAL_rduniq.
173
174    Solve this by using the "v" constraint instead of an asm for the syscall
175    output.  We don't do this unconditionally to allow compilation with
176    older compilers.  */
177
178 #ifdef USE_TLS
179 #define inline_syscall_r0_asm
180 #define inline_syscall_r0_out_constraint        "=v"
181 #else
182 #define inline_syscall_r0_asm                   __asm__("$0")
183 #define inline_syscall_r0_out_constraint        "=r"
184 #endif
185
186 /* It is moderately important optimization-wise to limit the lifetime
187    of the hard-register variables as much as possible.  Thus we copy
188    in/out as close to the asm as possible.  */
189
190 #define inline_syscall0(name, args...)                          \
191 {                                                               \
192         register long _sc_0 inline_syscall_r0_asm;              \
193         register long _sc_19 __asm__("$19");                    \
194                                                                 \
195         _sc_0 = __NR_##name;                                    \
196         __asm__("callsys # %0 %1 <= %2"                         \
197                 : inline_syscall_r0_out_constraint (_sc_0),     \
198                   "=r"(_sc_19)                                  \
199                 : "0"(_sc_0)                                    \
200                 : inline_syscall_clobbers,                      \
201                   "$16", "$17", "$18", "$20", "$21");           \
202         _sc_ret = _sc_0, _sc_err = _sc_19;                      \
203 }
204
205 #define inline_syscall1(name,arg1)                              \
206 {                                                               \
207         register long _sc_0 inline_syscall_r0_asm;              \
208         register long _sc_16 __asm__("$16");                    \
209         register long _sc_19 __asm__("$19");                    \
210                                                                 \
211         _sc_0 = __NR_##name;                                    \
212         _sc_16 = (long) (arg1);                                 \
213         __asm__("callsys # %0 %1 <= %2 %3"                      \
214                 : inline_syscall_r0_out_constraint (_sc_0),     \
215                   "=r"(_sc_19), "=r"(_sc_16)                    \
216                 : "0"(_sc_0), "2"(_sc_16)                       \
217                 : inline_syscall_clobbers,                      \
218                   "$17", "$18", "$20", "$21");                  \
219         _sc_ret = _sc_0, _sc_err = _sc_19;                      \
220 }
221
222 #define inline_syscall2(name,arg1,arg2)                         \
223 {                                                               \
224         register long _sc_0 inline_syscall_r0_asm;              \
225         register long _sc_16 __asm__("$16");                    \
226         register long _sc_17 __asm__("$17");                    \
227         register long _sc_19 __asm__("$19");                    \
228                                                                 \
229         _sc_0 = __NR_##name;                                    \
230         _sc_16 = (long) (arg1);                                 \
231         _sc_17 = (long) (arg2);                                 \
232         __asm__("callsys # %0 %1 <= %2 %3 %4"                   \
233                 : inline_syscall_r0_out_constraint (_sc_0),     \
234                   "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17)      \
235                 : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17)          \
236                 : inline_syscall_clobbers,                      \
237                   "$18", "$20", "$21");                         \
238         _sc_ret = _sc_0, _sc_err = _sc_19;                      \
239 }
240
241 #define inline_syscall3(name,arg1,arg2,arg3)                    \
242 {                                                               \
243         register long _sc_0 inline_syscall_r0_asm;              \
244         register long _sc_16 __asm__("$16");                    \
245         register long _sc_17 __asm__("$17");                    \
246         register long _sc_18 __asm__("$18");                    \
247         register long _sc_19 __asm__("$19");                    \
248                                                                 \
249         _sc_0 = __NR_##name;                                    \
250         _sc_16 = (long) (arg1);                                 \
251         _sc_17 = (long) (arg2);                                 \
252         _sc_18 = (long) (arg3);                                 \
253         __asm__("callsys # %0 %1 <= %2 %3 %4 %5"                \
254                 : inline_syscall_r0_out_constraint (_sc_0),     \
255                   "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17),     \
256                   "=r"(_sc_18)                                  \
257                 : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17),         \
258                   "4"(_sc_18)                                   \
259                 : inline_syscall_clobbers, "$20", "$21");       \
260         _sc_ret = _sc_0, _sc_err = _sc_19;                      \
261 }
262
263 #define inline_syscall4(name,arg1,arg2,arg3,arg4)               \
264 {                                                               \
265         register long _sc_0 inline_syscall_r0_asm;              \
266         register long _sc_16 __asm__("$16");                    \
267         register long _sc_17 __asm__("$17");                    \
268         register long _sc_18 __asm__("$18");                    \
269         register long _sc_19 __asm__("$19");                    \
270                                                                 \
271         _sc_0 = __NR_##name;                                    \
272         _sc_16 = (long) (arg1);                                 \
273         _sc_17 = (long) (arg2);                                 \
274         _sc_18 = (long) (arg3);                                 \
275         _sc_19 = (long) (arg4);                                 \
276         __asm__("callsys # %0 %1 <= %2 %3 %4 %5 %6"             \
277                 : inline_syscall_r0_out_constraint (_sc_0),     \
278                   "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17),     \
279                   "=r"(_sc_18)                                  \
280                 : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17),         \
281                   "4"(_sc_18), "1"(_sc_19)                      \
282                 : inline_syscall_clobbers, "$20", "$21");       \
283         _sc_ret = _sc_0, _sc_err = _sc_19;                      \
284 }
285
286 #define inline_syscall5(name,arg1,arg2,arg3,arg4,arg5)          \
287 {                                                               \
288         register long _sc_0 inline_syscall_r0_asm;              \
289         register long _sc_16 __asm__("$16");                    \
290         register long _sc_17 __asm__("$17");                    \
291         register long _sc_18 __asm__("$18");                    \
292         register long _sc_19 __asm__("$19");                    \
293         register long _sc_20 __asm__("$20");                    \
294                                                                 \
295         _sc_0 = __NR_##name;                                    \
296         _sc_16 = (long) (arg1);                                 \
297         _sc_17 = (long) (arg2);                                 \
298         _sc_18 = (long) (arg3);                                 \
299         _sc_19 = (long) (arg4);                                 \
300         _sc_20 = (long) (arg5);                                 \
301         __asm__("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7"          \
302                 : inline_syscall_r0_out_constraint (_sc_0),     \
303                   "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17),     \
304                   "=r"(_sc_18), "=r"(_sc_20)                    \
305                 : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17),         \
306                   "4"(_sc_18), "1"(_sc_19), "5"(_sc_20)         \
307                 : inline_syscall_clobbers, "$21");              \
308         _sc_ret = _sc_0, _sc_err = _sc_19;                      \
309 }
310
311 #define inline_syscall6(name,arg1,arg2,arg3,arg4,arg5,arg6)     \
312 {                                                               \
313         register long _sc_0 inline_syscall_r0_asm;              \
314         register long _sc_16 __asm__("$16");                    \
315         register long _sc_17 __asm__("$17");                    \
316         register long _sc_18 __asm__("$18");                    \
317         register long _sc_19 __asm__("$19");                    \
318         register long _sc_20 __asm__("$20");                    \
319         register long _sc_21 __asm__("$21");                    \
320                                                                 \
321         _sc_0 = __NR_##name;                                    \
322         _sc_16 = (long) (arg1);                                 \
323         _sc_17 = (long) (arg2);                                 \
324         _sc_18 = (long) (arg3);                                 \
325         _sc_19 = (long) (arg4);                                 \
326         _sc_20 = (long) (arg5);                                 \
327         _sc_21 = (long) (arg6);                                 \
328         __asm__("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7 %8"       \
329                 : inline_syscall_r0_out_constraint (_sc_0),     \
330                   "=r"(_sc_19) "=r"(_sc_16), "=r"(_sc_17),      \
331                   "=r"(_sc_18), "=r"(_sc_20), "=r"(_sc_21)      \
332                 : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17),         \
333                   "4"(_sc_18), "1"(_sc_19), "5"(_sc_20),        \
334                   "6"(_sc_21)                                   \
335                 : inline_syscall_clobbers);                     \
336         _sc_ret = _sc_0, _sc_err = _sc_19;                      \
337 }
338
339 #endif /* ASSEMBLER */