fdwalk should return 0 on an empty directory
[kopensolaris-gnu/glibc.git] / sysdeps / unix / alpha / sysdep.h
1 /* Copyright (C) 1992, 1995, 1996, 2000, 2003, 2004, 2006
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         register long _tmp_16 = (long) (arg1);                  \
246                                                                 \
247         _sc_0 = name;                                           \
248         _sc_16 = _tmp_16;                                       \
249         __asm__ __volatile__                                    \
250           ("callsys # %0 %1 <= %2 %3"                           \
251            : inline_syscall_r0_out_constraint (_sc_0),          \
252              "=r"(_sc_19), "=r"(_sc_16)                         \
253            : "0"(_sc_0), "2"(_sc_16)                            \
254            : inline_syscall_clobbers,                           \
255              "$17", "$18", "$20", "$21");                       \
256         _sc_ret = _sc_0, _sc_err = _sc_19;                      \
257 }
258
259 #define inline_syscall2(name,arg1,arg2)                         \
260 {                                                               \
261         register long _sc_0 inline_syscall_r0_asm;              \
262         register long _sc_16 __asm__("$16");                    \
263         register long _sc_17 __asm__("$17");                    \
264         register long _sc_19 __asm__("$19");                    \
265         register long _tmp_16 = (long) (arg1);                  \
266         register long _tmp_17 = (long) (arg2);                  \
267                                                                 \
268         _sc_0 = name;                                           \
269         _sc_16 = _tmp_16;                                       \
270         _sc_17 = _tmp_17;                                       \
271         __asm__ __volatile__                                    \
272           ("callsys # %0 %1 <= %2 %3 %4"                        \
273            : inline_syscall_r0_out_constraint (_sc_0),          \
274              "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17)           \
275            : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17)               \
276            : inline_syscall_clobbers,                           \
277              "$18", "$20", "$21");                              \
278         _sc_ret = _sc_0, _sc_err = _sc_19;                      \
279 }
280
281 #define inline_syscall3(name,arg1,arg2,arg3)                    \
282 {                                                               \
283         register long _sc_0 inline_syscall_r0_asm;              \
284         register long _sc_16 __asm__("$16");                    \
285         register long _sc_17 __asm__("$17");                    \
286         register long _sc_18 __asm__("$18");                    \
287         register long _sc_19 __asm__("$19");                    \
288         register long _tmp_16 = (long) (arg1);                  \
289         register long _tmp_17 = (long) (arg2);                  \
290         register long _tmp_18 = (long) (arg3);                  \
291                                                                 \
292         _sc_0 = name;                                           \
293         _sc_16 = _tmp_16;                                       \
294         _sc_17 = _tmp_17;                                       \
295         _sc_18 = _tmp_18;                                       \
296         __asm__ __volatile__                                    \
297           ("callsys # %0 %1 <= %2 %3 %4 %5"                     \
298            : inline_syscall_r0_out_constraint (_sc_0),          \
299              "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17),          \
300              "=r"(_sc_18)                                       \
301            : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17),              \
302              "4"(_sc_18)                                        \
303            : inline_syscall_clobbers, "$20", "$21");            \
304         _sc_ret = _sc_0, _sc_err = _sc_19;                      \
305 }
306
307 #define inline_syscall4(name,arg1,arg2,arg3,arg4)               \
308 {                                                               \
309         register long _sc_0 inline_syscall_r0_asm;              \
310         register long _sc_16 __asm__("$16");                    \
311         register long _sc_17 __asm__("$17");                    \
312         register long _sc_18 __asm__("$18");                    \
313         register long _sc_19 __asm__("$19");                    \
314         register long _tmp_16 = (long) (arg1);                  \
315         register long _tmp_17 = (long) (arg2);                  \
316         register long _tmp_18 = (long) (arg3);                  \
317         register long _tmp_19 = (long) (arg4);                  \
318                                                                 \
319         _sc_0 = name;                                           \
320         _sc_16 = _tmp_16;                                       \
321         _sc_17 = _tmp_17;                                       \
322         _sc_18 = _tmp_18;                                       \
323         _sc_19 = _tmp_19;                                       \
324         __asm__ __volatile__                                    \
325           ("callsys # %0 %1 <= %2 %3 %4 %5 %6"                  \
326            : inline_syscall_r0_out_constraint (_sc_0),          \
327              "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17),          \
328              "=r"(_sc_18)                                       \
329            : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17),              \
330              "4"(_sc_18), "1"(_sc_19)                           \
331            : inline_syscall_clobbers, "$20", "$21");            \
332         _sc_ret = _sc_0, _sc_err = _sc_19;                      \
333 }
334
335 #define inline_syscall5(name,arg1,arg2,arg3,arg4,arg5)          \
336 {                                                               \
337         register long _sc_0 inline_syscall_r0_asm;              \
338         register long _sc_16 __asm__("$16");                    \
339         register long _sc_17 __asm__("$17");                    \
340         register long _sc_18 __asm__("$18");                    \
341         register long _sc_19 __asm__("$19");                    \
342         register long _sc_20 __asm__("$20");                    \
343         register long _tmp_16 = (long) (arg1);                  \
344         register long _tmp_17 = (long) (arg2);                  \
345         register long _tmp_18 = (long) (arg3);                  \
346         register long _tmp_19 = (long) (arg4);                  \
347         register long _tmp_20 = (long) (arg5);                  \
348                                                                 \
349         _sc_0 = name;                                           \
350         _sc_16 = _tmp_16;                                       \
351         _sc_17 = _tmp_17;                                       \
352         _sc_18 = _tmp_18;                                       \
353         _sc_19 = _tmp_19;                                       \
354         _sc_20 = _tmp_20;                                       \
355         __asm__ __volatile__                                    \
356           ("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7"               \
357            : inline_syscall_r0_out_constraint (_sc_0),          \
358              "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17),          \
359              "=r"(_sc_18), "=r"(_sc_20)                         \
360            : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17),              \
361              "4"(_sc_18), "1"(_sc_19), "5"(_sc_20)              \
362            : inline_syscall_clobbers, "$21");                   \
363         _sc_ret = _sc_0, _sc_err = _sc_19;                      \
364 }
365
366 #define inline_syscall6(name,arg1,arg2,arg3,arg4,arg5,arg6)     \
367 {                                                               \
368         register long _sc_0 inline_syscall_r0_asm;              \
369         register long _sc_16 __asm__("$16");                    \
370         register long _sc_17 __asm__("$17");                    \
371         register long _sc_18 __asm__("$18");                    \
372         register long _sc_19 __asm__("$19");                    \
373         register long _sc_20 __asm__("$20");                    \
374         register long _sc_21 __asm__("$21");                    \
375         register long _tmp_16 = (long) (arg1);                  \
376         register long _tmp_17 = (long) (arg2);                  \
377         register long _tmp_18 = (long) (arg3);                  \
378         register long _tmp_19 = (long) (arg4);                  \
379         register long _tmp_20 = (long) (arg5);                  \
380         register long _tmp_21 = (long) (arg6);                  \
381                                                                 \
382         _sc_0 = name;                                           \
383         _sc_16 = _tmp_16;                                       \
384         _sc_17 = _tmp_17;                                       \
385         _sc_18 = _tmp_18;                                       \
386         _sc_19 = _tmp_19;                                       \
387         _sc_20 = _tmp_20;                                       \
388         _sc_21 = _tmp_21;                                       \
389         __asm__ __volatile__                                    \
390           ("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7 %8"            \
391            : inline_syscall_r0_out_constraint (_sc_0),          \
392              "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17),          \
393              "=r"(_sc_18), "=r"(_sc_20), "=r"(_sc_21)           \
394            : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17), "4"(_sc_18), \
395              "1"(_sc_19), "5"(_sc_20), "6"(_sc_21)              \
396            : inline_syscall_clobbers);                          \
397         _sc_ret = _sc_0, _sc_err = _sc_19;                      \
398 }
399
400 /* Pointer mangling support.  Note that tls access is slow enough that
401    we don't deoptimize things by placing the pointer check value there.  */
402
403 #include <stdint.h>
404
405 #if defined NOT_IN_libc && defined IS_IN_rtld
406 # ifdef __ASSEMBLER__
407 #  define PTR_MANGLE(dst, src, tmp)                             \
408         ldah    tmp, __pointer_chk_guard_local($29) !gprelhigh; \
409         ldq     tmp, __pointer_chk_guard_local(tmp) !gprellow;  \
410         xor     src, tmp, dst
411 #  define PTR_MANGLE2(dst, src, tmp)                            \
412         xor     src, tmp, dst
413 #  define PTR_DEMANGLE(dst, tmp)   PTR_MANGLE(dst, dst, tmp)
414 #  define PTR_DEMANGLE2(dst, tmp)  PTR_MANGLE2(dst, dst, tmp)
415 # else
416 extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden;
417 #  define PTR_MANGLE(var)       \
418   (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local)
419 #  define PTR_DEMANGLE(var)  PTR_MANGLE(var)
420 # endif
421 #elif defined PIC
422 # ifdef __ASSEMBLER__
423 #  define PTR_MANGLE(dst, src, tmp)             \
424         ldq     tmp, __pointer_chk_guard;       \
425         xor     src, tmp, dst
426 #  define PTR_MANGLE2(dst, src, tmp)            \
427         xor     src, tmp, dst
428 #  define PTR_DEMANGLE(dst, tmp)   PTR_MANGLE(dst, dst, tmp)
429 #  define PTR_DEMANGLE2(dst, tmp)  PTR_MANGLE2(dst, dst, tmp)
430 # else
431 extern uintptr_t __pointer_chk_guard attribute_relro;
432 #  define PTR_MANGLE(var)       \
433         (var) = (void *) ((uintptr_t) (var) ^ __pointer_chk_guard)
434 #  define PTR_DEMANGLE(var)  PTR_MANGLE(var)
435 # endif
436 #endif
437
438 #endif /* ASSEMBLER */