ee6eec1956223cdc932e90122336c8947ea6848b
[kopensolaris-gnu/glibc.git] / sysdeps / unix / sysv / linux / sh / sysdep.h
1 /* Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>, August 1995.
4    Changed by Kaz Kojima, <kkojima@rr.iij4u.or.jp>.
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 #ifndef _LINUX_SH_SYSDEP_H
22 #define _LINUX_SH_SYSDEP_H 1
23
24 /* There is some commonality.  */
25 #include <sysdeps/unix/sh/sysdep.h>
26
27 /* For Linux we can use the system call table in the header file
28         /usr/include/asm/unistd.h
29    of the kernel.  But these symbols do not follow the SYS_* syntax
30    so we have to redefine the `SYS_ify' macro here.  */
31 #undef SYS_ify
32 #define SYS_ify(syscall_name)   (__NR_##syscall_name)
33
34
35 #ifdef __ASSEMBLER__
36
37 /* Linux uses a negative return value to indicate syscall errors,
38    unlike most Unices, which use the condition codes' carry flag.
39
40    Since version 2.1 the return value of a system call might be
41    negative even if the call succeeded.  E.g., the `lseek' system call
42    might return a large offset.  Therefore we must not anymore test
43    for < 0, but test for a real error by making sure the value in R0
44    is a real error number.  Linus said he will make sure the no syscall
45    returns a value in -1 .. -4095 as a valid result so we can savely
46    test with -4095.  */
47
48 #define _IMM1 #-1
49 #define _IMM12 #-12
50 #undef  PSEUDO
51 #define PSEUDO(name, syscall_name, args) \
52  .text; \
53  ENTRY (name); \
54     DO_CALL (syscall_name, args); \
55     mov r0,r1; \
56     mov _IMM12,r2; \
57     shad r2,r1; \
58     not r1,r1; \
59     tst r1,r1; \
60     bf .Lpseudo_end; \
61     SYSCALL_ERROR_HANDLER; \
62  .Lpseudo_end:
63
64 #undef  PSEUDO_END
65 #define PSEUDO_END(name) \
66   END (name)
67
68 #undef  PSEUDO_NOERRNO
69 #define PSEUDO_NOERRNO(name, syscall_name, args) \
70  .text; \
71  ENTRY (name); \
72     DO_CALL (syscall_name, args)
73
74 #undef  PSEUDO_END_NOERRNO
75 #define PSEUDO_END_NOERRNO(name) \
76   END (name)
77
78 #define ret_NOERRNO ret
79
80 #define PSEUDO_ERRVAL(name, syscall_name, args) \
81  .text; \
82  ENTRY (name); \
83     DO_CALL (syscall_name, args);
84
85 #undef  PSEUDO_END_ERRVAL
86 #define PSEUDO_END_ERRVAL(name) \
87   END (name)
88
89 #define ret_ERRVAL ret
90
91 #ifndef PIC
92 # define SYSCALL_ERROR_HANDLER  \
93         mov.l 0f,r1; \
94         jmp @r1; \
95          mov r0,r4; \
96         .align 2; \
97      0: .long __syscall_error
98 #else
99 # if RTLD_PRIVATE_ERRNO
100 #  define SYSCALL_ERROR_HANDLER \
101         neg r0,r1; \
102         mov.l 0f,r12; \
103         mova 0f,r0; \
104         add r0,r12; \
105         mov.l 1f,r0; \
106         mov.l r1,@(r0,r12)
107         bra .Lpseudo_end; \
108          mov _IMM1,r0; \
109         .align 2; \
110      0: .long _GLOBAL_OFFSET_TABLE_; \
111      1: .long errno@GOTOFF
112
113 # elif defined _LIBC_REENTRANT
114
115 #  if USE___THREAD
116 #   ifndef NOT_IN_libc
117 #    define SYSCALL_ERROR_ERRNO __libc_errno
118 #   else
119 #    define SYSCALL_ERROR_ERRNO errno
120 #   endif
121 #   define SYSCALL_ERROR_HANDLER \
122         neg r0,r1; \
123         mov r12,r2; \
124         mov.l 0f,r12; \
125         mova 0f,r0; \
126         add r0,r12; \
127         mov.l 1f,r0; \
128         stc gbr, r4; \
129         mov.l @(r0,r12),r0; \
130         mov r2,r12; \
131         add r4,r0; \
132         mov.l r1,@r0; \
133         bra .Lpseudo_end; \
134          mov _IMM1,r0; \
135         .align 2; \
136      0: .long _GLOBAL_OFFSET_TABLE_; \
137      1: .long SYSCALL_ERROR_ERRNO@GOTTPOFF
138 #  else
139 #   define SYSCALL_ERROR_HANDLER \
140         neg r0,r1; \
141         mov.l r14,@-r15; \
142         mov.l r12,@-r15; \
143         mov.l r1,@-r15; \
144         mov.l 0f,r12; \
145         mova 0f,r0; \
146         add r0,r12; \
147         sts.l pr,@-r15; \
148         mov r15,r14; \
149         mov.l 1f,r1; \
150         bsrf r1; \
151          nop; \
152      2: mov r14,r15; \
153         lds.l @r15+,pr; \
154         mov.l @r15+,r1; \
155         mov.l r1,@r0; \
156         mov.l @r15+,r12; \
157         mov.l @r15+,r14; \
158         bra .Lpseudo_end; \
159          mov _IMM1,r0; \
160         .align 2; \
161      0: .long _GLOBAL_OFFSET_TABLE_; \
162      1: .long PLTJMP(C_SYMBOL_NAME(__errno_location))-(2b+2-.)
163 /* A quick note: it is assumed that the call to `__errno_location' does
164    not modify the stack!  */
165 #  endif
166 # else
167 /* Store (-r0) into errno through the GOT.  */
168 #  define SYSCALL_ERROR_HANDLER                                               \
169         neg r0,r1; \
170         mov r12,r2; \
171         mov.l 0f,r12; \
172         mova 0f,r0; \
173         add r0,r12; \
174         mov.l 1f,r0; \
175         mov.l @(r0,r12),r0; \
176         mov r2,r12; \
177         mov.l r1,@r0; \
178         bra .Lpseudo_end; \
179          mov _IMM1,r0; \
180         .align 2; \
181      0: .long _GLOBAL_OFFSET_TABLE_; \
182      1: .long errno@GOT
183 # endif /* _LIBC_REENTRANT */
184 #endif  /* PIC */
185
186 #define SYSCALL_INST0   trapa #0x10
187 #define SYSCALL_INST1   trapa #0x11
188 #define SYSCALL_INST2   trapa #0x12
189 #define SYSCALL_INST3   trapa #0x13
190 #define SYSCALL_INST4   trapa #0x14
191 #define SYSCALL_INST5   mov.l @(0,r15),r0; trapa #0x15
192 #define SYSCALL_INST6   mov.l @(0,r15),r0; mov.l @(4,r15),r1; trapa #0x16
193
194 #undef  DO_CALL
195 #define DO_CALL(syscall_name, args)     \
196     mov.l 1f,r3;                        \
197     SYSCALL_INST##args;                 \
198     bra 2f;                             \
199      nop;                               \
200     .align 2;                           \
201  1: .long SYS_ify (syscall_name);       \
202  2:
203
204 # ifdef NEED_SYSCALL_INST_PAD
205 #  define SYSCALL_INST_PAD \
206         or r0,r0; or r0,r0; or r0,r0; or r0,r0; or r0,r0
207 # else
208 #  define SYSCALL_INST_PAD
209 # endif
210
211 #else /* not __ASSEMBLER__ */
212
213 #define SYSCALL_INST_STR0       "trapa #0x10\n\t"
214 #define SYSCALL_INST_STR1       "trapa #0x11\n\t"
215 #define SYSCALL_INST_STR2       "trapa #0x12\n\t"
216 #define SYSCALL_INST_STR3       "trapa #0x13\n\t"
217 #define SYSCALL_INST_STR4       "trapa #0x14\n\t"
218 #define SYSCALL_INST_STR5       "trapa #0x15\n\t"
219 #define SYSCALL_INST_STR6       "trapa #0x16\n\t"
220
221 # ifdef NEED_SYSCALL_INST_PAD
222 #  define SYSCALL_INST_PAD "\
223         or r0,r0; or r0,r0; or r0,r0; or r0,r0; or r0,r0"
224 # else
225 #  define SYSCALL_INST_PAD
226 # endif
227
228 #define ASMFMT_0
229 #define ASMFMT_1 \
230         , "r" (r4)
231 #define ASMFMT_2 \
232         , "r" (r4), "r" (r5)
233 #define ASMFMT_3 \
234         , "r" (r4), "r" (r5), "r" (r6)
235 #define ASMFMT_4 \
236         , "r" (r4), "r" (r5), "r" (r6), "r" (r7)
237 #define ASMFMT_5 \
238         , "r" (r4), "r" (r5), "r" (r6), "r" (r7), "0" (r0)
239 #define ASMFMT_6 \
240         , "r" (r4), "r" (r5), "r" (r6), "r" (r7), "0" (r0), "r" (r1)
241 #define ASMFMT_7 \
242         , "r" (r4), "r" (r5), "r" (r6), "r" (r7), "0" (r0), "r" (r1), "r" (r2)
243
244 #define SUBSTITUTE_ARGS_0()
245 #define SUBSTITUTE_ARGS_1(arg1)                                 \
246         register long r4 asm ("%r4") = (long)(arg1)
247 #define SUBSTITUTE_ARGS_2(arg1, arg2)                           \
248         register long r4 asm ("%r4") = (long)(arg1);            \
249         register long r5 asm ("%r5") = (long)(arg2)
250 #define SUBSTITUTE_ARGS_3(arg1, arg2, arg3)                     \
251         register long r4 asm ("%r4") = (long)(arg1);            \
252         register long r5 asm ("%r5") = (long)(arg2);            \
253         register long r6 asm ("%r6") = (long)(arg3)
254 #define SUBSTITUTE_ARGS_4(arg1, arg2, arg3, arg4)               \
255         register long r4 asm ("%r4") = (long)(arg1);            \
256         register long r5 asm ("%r5") = (long)(arg2);            \
257         register long r6 asm ("%r6") = (long)(arg3);            \
258         register long r7 asm ("%r7") = (long)(arg4)
259 #define SUBSTITUTE_ARGS_5(arg1, arg2, arg3, arg4, arg5)         \
260         register long r4 asm ("%r4") = (long)(arg1);            \
261         register long r5 asm ("%r5") = (long)(arg2);            \
262         register long r6 asm ("%r6") = (long)(arg3);            \
263         register long r7 asm ("%r7") = (long)(arg4);            \
264         register long r0 asm ("%r0") = (long)(arg5)
265 #define SUBSTITUTE_ARGS_6(arg1, arg2, arg3, arg4, arg5, arg6)           \
266         register long r4 asm ("%r4") = (long)(arg1);                    \
267         register long r5 asm ("%r5") = (long)(arg2);                    \
268         register long r6 asm ("%r6") = (long)(arg3);                    \
269         register long r7 asm ("%r7") = (long)(arg4);                    \
270         register long r0 asm ("%r0") = (long)(arg5);                    \
271         register long r1 asm ("%r1") = (long)(arg6)
272 #define SUBSTITUTE_ARGS_7(arg1, arg2, arg3, arg4, arg5, arg6, arg7)     \
273         register long r4 asm ("%r4") = (long)(arg1);                    \
274         register long r5 asm ("%r5") = (long)(arg2);                    \
275         register long r6 asm ("%r6") = (long)(arg3);                    \
276         register long r7 asm ("%r7") = (long)(arg4);                    \
277         register long r0 asm ("%r0") = (long)(arg5)                     \
278         register long r1 asm ("%r1") = (long)(arg6);                    \
279         register long r2 asm ("%r2") = (long)(arg7)
280
281 #undef INLINE_SYSCALL
282 #define INLINE_SYSCALL(name, nr, args...) \
283   ({                                                                          \
284     unsigned int resultvar = INTERNAL_SYSCALL (name, , nr, args);             \
285     if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (resultvar, ), 0))         \
286       {                                                                       \
287         __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, ));                   \
288         resultvar = 0xffffffff;                                               \
289       }                                                                       \
290     (int) resultvar; })
291
292 #undef INTERNAL_SYSCALL
293 #define INTERNAL_SYSCALL(name, err, nr, args...) \
294   ({                                                            \
295     unsigned long resultvar;                                    \
296     register long r3 asm ("%r3") = SYS_ify (name);              \
297     SUBSTITUTE_ARGS_##nr(args);                                 \
298                                                                 \
299     asm volatile (SYSCALL_INST_STR##nr SYSCALL_INST_PAD         \
300                   : "=z" (resultvar)                            \
301                   : "r" (r3) ASMFMT_##nr                        \
302                   : "memory");                                  \
303                                                                 \
304     (int) resultvar; })
305
306 #undef INTERNAL_SYSCALL_DECL
307 #define INTERNAL_SYSCALL_DECL(err) do { } while (0)
308
309 #undef INTERNAL_SYSCALL_ERROR_P
310 #define INTERNAL_SYSCALL_ERROR_P(val, err) \
311   ((unsigned int) (val) >= 0xfffff001u)
312
313 #undef INTERNAL_SYSCALL_ERRNO
314 #define INTERNAL_SYSCALL_ERRNO(val, err)        (-(val))
315
316 #endif  /* __ASSEMBLER__ */
317
318 #endif /* linux/sh/sysdep.h */