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