Additional makefile for Unix on Alpha.
[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 PSEUDO_NOERRNO(name, syscall_name, args)        \
123         .globl name;                                    \
124         .align 4;                                       \
125         .ent name,0;                                    \
126 __LABEL(name)                                           \
127         PSEUDO_PROLOGUE;                                \
128         PSEUDO_PREPARE_ARGS                             \
129         lda     v0, SYS_ify(syscall_name);              \
130         call_pal PAL_callsys;
131
132 #undef PSEUDO_END_NOERRNO
133 #define PSEUDO_END_NOERRNO(sym)  END(sym)
134
135 #define ret_NOERRNO ret
136
137 #define PSEUDO_ERRVAL(name, syscall_name, args) \
138         .globl name;                                    \
139         .align 4;                                       \
140         .ent name,0;                                    \
141 __LABEL(name)                                           \
142         PSEUDO_PROLOGUE;                                \
143         PSEUDO_PREPARE_ARGS                             \
144         lda     v0, SYS_ify(syscall_name);              \
145         call_pal PAL_callsys;
146
147 #undef PSEUDO_END_ERRVAL
148 #define PSEUDO_END_ERRVAL(sym)  END(sym)
149
150 #define ret_ERRVAL ret
151
152 #define r0      v0
153 #define r1      a4
154
155 #define MOVE(x,y)       mov x,y
156
157 #else /* !ASSEMBLER */
158
159 /* ??? Linux needs to be able to override INLINE_SYSCALL for one
160    particular special case.  Make this easy.  */
161
162 #undef INLINE_SYSCALL
163 #define INLINE_SYSCALL(name, nr, args...) \
164         INLINE_SYSCALL1(name, nr, args)
165
166 #define INLINE_SYSCALL1(name, nr, args...)      \
167 ({                                              \
168         long _sc_ret, _sc_err;                  \
169         inline_syscall##nr(name, args);         \
170         if (__builtin_expect (_sc_err, 0))      \
171           {                                     \
172             __set_errno (_sc_ret);              \
173             _sc_ret = -1L;                      \
174           }                                     \
175         _sc_ret;                                \
176 })
177
178 #define INTERNAL_SYSCALL(name, err_out, nr, args...) \
179         INTERNAL_SYSCALL1(name, err_out, nr, args)
180
181 #define INTERNAL_SYSCALL1(name, err_out, nr, args...)   \
182 ({                                                      \
183         long _sc_ret, _sc_err;                          \
184         inline_syscall##nr(name, args);                 \
185         err_out = _sc_err;                              \
186         _sc_ret;                                        \
187 })
188
189 #define INTERNAL_SYSCALL_DECL(err)              long int err
190 #define INTERNAL_SYSCALL_ERROR_P(val, err)      err
191 #define INTERNAL_SYSCALL_ERRNO(val, err)        val
192
193 #define inline_syscall_clobbers                         \
194         "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", \
195         "$22", "$23", "$24", "$25", "$27", "$28", "memory"
196
197 /* If TLS is in use, we have a conflict between the PAL_rduniq primitive,
198    as modeled within GCC, and explicit use of the R0 register.  If we use
199    the register via the asm, the scheduler may place the PAL_rduniq insn
200    before we've copied the data from R0 into _sc_ret.  If this happens
201    we'll get a reload abort, since R0 is live at the same time it is
202    needed for the PAL_rduniq.
203
204    Solve this by using the "v" constraint instead of an asm for the syscall
205    output.  We don't do this unconditionally to allow compilation with
206    older compilers.  */
207
208 #ifdef HAVE___THREAD
209 #define inline_syscall_r0_asm
210 #define inline_syscall_r0_out_constraint        "=v"
211 #else
212 #define inline_syscall_r0_asm                   __asm__("$0")
213 #define inline_syscall_r0_out_constraint        "=r"
214 #endif
215
216 /* It is moderately important optimization-wise to limit the lifetime
217    of the hard-register variables as much as possible.  Thus we copy
218    in/out as close to the asm as possible.  */
219
220 #define inline_syscall0(name, args...)                          \
221 {                                                               \
222         register long _sc_0 inline_syscall_r0_asm;              \
223         register long _sc_19 __asm__("$19");                    \
224                                                                 \
225         _sc_0 = __NR_##name;                                    \
226         __asm__ __volatile__                                    \
227           ("callsys # %0 %1 <= %2"                              \
228            : inline_syscall_r0_out_constraint (_sc_0),          \
229              "=r"(_sc_19)                                       \
230            : "0"(_sc_0)                                         \
231            : inline_syscall_clobbers,                           \
232              "$16", "$17", "$18", "$20", "$21");                \
233         _sc_ret = _sc_0, _sc_err = _sc_19;                      \
234 }
235
236 #define inline_syscall1(name,arg1)                              \
237 {                                                               \
238         register long _sc_0 inline_syscall_r0_asm;              \
239         register long _sc_16 __asm__("$16");                    \
240         register long _sc_19 __asm__("$19");                    \
241                                                                 \
242         _sc_0 = __NR_##name;                                    \
243         _sc_16 = (long) (arg1);                                 \
244         __asm__ __volatile__                                    \
245           ("callsys # %0 %1 <= %2 %3"                           \
246            : inline_syscall_r0_out_constraint (_sc_0),          \
247              "=r"(_sc_19), "=r"(_sc_16)                         \
248            : "0"(_sc_0), "2"(_sc_16)                            \
249            : inline_syscall_clobbers,                           \
250              "$17", "$18", "$20", "$21");                       \
251         _sc_ret = _sc_0, _sc_err = _sc_19;                      \
252 }
253
254 #define inline_syscall2(name,arg1,arg2)                         \
255 {                                                               \
256         register long _sc_0 inline_syscall_r0_asm;              \
257         register long _sc_16 __asm__("$16");                    \
258         register long _sc_17 __asm__("$17");                    \
259         register long _sc_19 __asm__("$19");                    \
260                                                                 \
261         _sc_0 = __NR_##name;                                    \
262         _sc_16 = (long) (arg1);                                 \
263         _sc_17 = (long) (arg2);                                 \
264         __asm__ __volatile__                                    \
265           ("callsys # %0 %1 <= %2 %3 %4"                        \
266            : inline_syscall_r0_out_constraint (_sc_0),          \
267              "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17)           \
268            : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17)               \
269            : inline_syscall_clobbers,                           \
270              "$18", "$20", "$21");                              \
271         _sc_ret = _sc_0, _sc_err = _sc_19;                      \
272 }
273
274 #define inline_syscall3(name,arg1,arg2,arg3)                    \
275 {                                                               \
276         register long _sc_0 inline_syscall_r0_asm;              \
277         register long _sc_16 __asm__("$16");                    \
278         register long _sc_17 __asm__("$17");                    \
279         register long _sc_18 __asm__("$18");                    \
280         register long _sc_19 __asm__("$19");                    \
281                                                                 \
282         _sc_0 = __NR_##name;                                    \
283         _sc_16 = (long) (arg1);                                 \
284         _sc_17 = (long) (arg2);                                 \
285         _sc_18 = (long) (arg3);                                 \
286         __asm__ __volatile__                                    \
287           ("callsys # %0 %1 <= %2 %3 %4 %5"                     \
288            : inline_syscall_r0_out_constraint (_sc_0),          \
289              "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17),          \
290              "=r"(_sc_18)                                       \
291            : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17),              \
292              "4"(_sc_18)                                        \
293            : inline_syscall_clobbers, "$20", "$21");            \
294         _sc_ret = _sc_0, _sc_err = _sc_19;                      \
295 }
296
297 #define inline_syscall4(name,arg1,arg2,arg3,arg4)               \
298 {                                                               \
299         register long _sc_0 inline_syscall_r0_asm;              \
300         register long _sc_16 __asm__("$16");                    \
301         register long _sc_17 __asm__("$17");                    \
302         register long _sc_18 __asm__("$18");                    \
303         register long _sc_19 __asm__("$19");                    \
304                                                                 \
305         _sc_0 = __NR_##name;                                    \
306         _sc_16 = (long) (arg1);                                 \
307         _sc_17 = (long) (arg2);                                 \
308         _sc_18 = (long) (arg3);                                 \
309         _sc_19 = (long) (arg4);                                 \
310         __asm__ __volatile__                                    \
311           ("callsys # %0 %1 <= %2 %3 %4 %5 %6"                  \
312            : inline_syscall_r0_out_constraint (_sc_0),          \
313              "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17),          \
314              "=r"(_sc_18)                                       \
315            : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17),              \
316              "4"(_sc_18), "1"(_sc_19)                           \
317            : inline_syscall_clobbers, "$20", "$21");            \
318         _sc_ret = _sc_0, _sc_err = _sc_19;                      \
319 }
320
321 #define inline_syscall5(name,arg1,arg2,arg3,arg4,arg5)          \
322 {                                                               \
323         register long _sc_0 inline_syscall_r0_asm;              \
324         register long _sc_16 __asm__("$16");                    \
325         register long _sc_17 __asm__("$17");                    \
326         register long _sc_18 __asm__("$18");                    \
327         register long _sc_19 __asm__("$19");                    \
328         register long _sc_20 __asm__("$20");                    \
329                                                                 \
330         _sc_0 = __NR_##name;                                    \
331         _sc_16 = (long) (arg1);                                 \
332         _sc_17 = (long) (arg2);                                 \
333         _sc_18 = (long) (arg3);                                 \
334         _sc_19 = (long) (arg4);                                 \
335         _sc_20 = (long) (arg5);                                 \
336         __asm__ __volatile__                                    \
337           ("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7"               \
338            : inline_syscall_r0_out_constraint (_sc_0),          \
339              "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17),          \
340              "=r"(_sc_18), "=r"(_sc_20)                         \
341            : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17),              \
342              "4"(_sc_18), "1"(_sc_19), "5"(_sc_20)              \
343            : inline_syscall_clobbers, "$21");                   \
344         _sc_ret = _sc_0, _sc_err = _sc_19;                      \
345 }
346
347 #define inline_syscall6(name,arg1,arg2,arg3,arg4,arg5,arg6)     \
348 {                                                               \
349         register long _sc_0 inline_syscall_r0_asm;              \
350         register long _sc_16 __asm__("$16");                    \
351         register long _sc_17 __asm__("$17");                    \
352         register long _sc_18 __asm__("$18");                    \
353         register long _sc_19 __asm__("$19");                    \
354         register long _sc_20 __asm__("$20");                    \
355         register long _sc_21 __asm__("$21");                    \
356                                                                 \
357         _sc_0 = __NR_##name;                                    \
358         _sc_16 = (long) (arg1);                                 \
359         _sc_17 = (long) (arg2);                                 \
360         _sc_18 = (long) (arg3);                                 \
361         _sc_19 = (long) (arg4);                                 \
362         _sc_20 = (long) (arg5);                                 \
363         _sc_21 = (long) (arg6);                                 \
364         __asm__ __volatile__                                    \
365           ("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7 %8"            \
366            : inline_syscall_r0_out_constraint (_sc_0),          \
367              "=r"(_sc_19) "=r"(_sc_16), "=r"(_sc_17),           \
368              "=r"(_sc_18), "=r"(_sc_20), "=r"(_sc_21)           \
369            : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17), "4"(_sc_18), \
370              "1"(_sc_19), "5"(_sc_20), "6"(_sc_21)              \
371            : inline_syscall_clobbers);                          \
372         _sc_ret = _sc_0, _sc_err = _sc_19;                      \
373 }
374
375 #endif /* ASSEMBLER */