(INTERNAL_SYSCALL, INTERNAL_SYSCALL_ERROR_P, INTERNAL_SYSCALL_ERRNO):
[kopensolaris-gnu/glibc.git] / sysdeps / unix / sysv / linux / powerpc / powerpc32 / sysdep.h
1 /* Copyright (C) 1992,97,98,99,2000,01,02,03 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
18
19 #ifndef _LINUX_POWERPC_SYSDEP_H
20 #define _LINUX_POWERPC_SYSDEP_H 1
21
22 #include <sysdeps/unix/powerpc/sysdep.h>
23
24 /* Some systen calls got renamed over time, but retained the same semantics.
25    Handle them here so they can be catched by both C and assembler stubs in
26    glibc.  */
27
28 #ifdef __NR_pread64
29 # ifdef __NR_pread
30 #  error "__NR_pread and __NR_pread64 both defined???"
31 # endif
32 # define __NR_pread __NR_pread64
33 #endif
34
35 #ifdef __NR_pwrite64
36 # ifdef __NR_pwrite
37 #  error "__NR_pwrite and __NR_pwrite64 both defined???"
38 # endif
39 # define __NR_pwrite __NR_pwrite64
40 #endif
41
42 /* For Linux we can use the system call table in the header file
43         /usr/include/asm/unistd.h
44    of the kernel.  But these symbols do not follow the SYS_* syntax
45    so we have to redefine the `SYS_ify' macro here.  */
46 #undef SYS_ify
47 #ifdef __STDC__
48 # define SYS_ify(syscall_name)  __NR_##syscall_name
49 #else
50 # define SYS_ify(syscall_name)  __NR_/**/syscall_name
51 #endif
52
53 #ifndef __ASSEMBLER__
54
55 # include <errno.h>
56
57 /* On powerpc a system call basically clobbers the same registers like a
58    function call, with the exception of LR (which is needed for the
59    "sc; bnslr" sequence) and CR (where only CR0.SO is clobbered to signal
60    an error return status).  */
61
62 # undef INLINE_SYSCALL
63 # define INLINE_SYSCALL(name, nr, args...)                              \
64   ({                                                                    \
65     register long r0  __asm__ ("r0");                                   \
66     register long r3  __asm__ ("r3");                                   \
67     register long r4  __asm__ ("r4");                                   \
68     register long r5  __asm__ ("r5");                                   \
69     register long r6  __asm__ ("r6");                                   \
70     register long r7  __asm__ ("r7");                                   \
71     register long r8  __asm__ ("r8");                                   \
72     register long r9  __asm__ ("r9");                                   \
73     register long r10 __asm__ ("r10");                                  \
74     register long r11 __asm__ ("r11");                                  \
75     register long r12 __asm__ ("r12");                                  \
76     long ret, err;                                                      \
77     LOADARGS_##nr(name, args);                                          \
78     __asm__ __volatile__                                                \
79       ("sc\n\t"                                                         \
80        "mfcr    %0"                                                     \
81        : "=&r" (r0),                                                    \
82          "=&r" (r3), "=&r" (r4), "=&r" (r5),  "=&r" (r6),  "=&r" (r7),  \
83          "=&r" (r8), "=&r" (r9), "=&r" (r10), "=&r" (r11), "=&r" (r12)  \
84        : ASM_INPUT_##nr                                                 \
85        : "cr0", "ctr", "memory");                                       \
86     err = r0;                                                           \
87     ret = r3;                                                           \
88     if (__builtin_expect (err & (1 << 28), 0))                          \
89       {                                                                 \
90         __set_errno (ret);                                              \
91         ret = -1L;                                                      \
92       }                                                                 \
93     ret;                                                                \
94   })
95
96 /* Define a macro which expands inline into the wrapper code for a system
97    call. This use is for internal calls that do not need to handle errors
98    normally. It will never touch errno. This returns just what the kernel
99    gave back in the non-error (CR0.SO cleared) case, otherwise (CR0.SO set)
100    the negation of the return value in the kernel gets reverted.  */
101
102 # undef INTERNAL_SYSCALL_DECL
103 # define INTERNAL_SYSCALL_DECL(err) do { } while (0)
104
105 # undef INTERNAL_SYSCALL
106 # define INTERNAL_SYSCALL(name, err, nr, args...)                       \
107   ({                                                                    \
108     register long r0  __asm__ ("r0");                                   \
109     register long r3  __asm__ ("r3");                                   \
110     register long r4  __asm__ ("r4");                                   \
111     register long r5  __asm__ ("r5");                                   \
112     register long r6  __asm__ ("r6");                                   \
113     register long r7  __asm__ ("r7");                                   \
114     register long r8  __asm__ ("r8");                                   \
115     register long r9  __asm__ ("r9");                                   \
116     register long r10 __asm__ ("r10");                                  \
117     register long r11 __asm__ ("r11");                                  \
118     register long r12 __asm__ ("r12");                                  \
119     LOADARGS_##nr(name, args);                                          \
120     __asm__ __volatile__                                                \
121       ("sc\n\t"                                                         \
122        "bns+    0f\n\t"                                                 \
123        "neg     %1,%1\n"                                                \
124        "0:"                                                             \
125        : "=&r" (r0),                                                    \
126          "=&r" (r3), "=&r" (r4), "=&r" (r5),  "=&r" (r6),  "=&r" (r7),  \
127          "=&r" (r8), "=&r" (r9), "=&r" (r10), "=&r" (r11), "=&r" (r12)  \
128        : ASM_INPUT_##nr                                                 \
129        : "cr0", "ctr", "memory");                                       \
130     (int) r3;                                                           \
131   })
132
133 # undef INTERNAL_SYSCALL_ERROR_P
134 # define INTERNAL_SYSCALL_ERROR_P(val, err) \
135   ((unsigned long) (val) >= 0xfffff001u)
136
137 # undef INTERNAL_SYSCALL_ERRNO
138 # define INTERNAL_SYSCALL_ERRNO(val, err)     (-(val))
139
140 # define LOADARGS_0(name, dummy) \
141         r0 = __NR_##name
142 # define LOADARGS_1(name, arg1) \
143         LOADARGS_0(name, 0); \
144         extern void __illegally_sized_syscall_##name##_arg1 (void); \
145         if (sizeof (arg1) > 4) __illegally_sized_syscall_##name##_arg1 (); \
146         r3 = (long) (arg1)
147 # define LOADARGS_2(name, arg1, arg2) \
148         LOADARGS_1(name, arg1); \
149         extern void __illegally_sized_syscall_##name##_arg2 (void); \
150         if (sizeof (arg2) > 4) __illegally_sized_syscall_##name##_arg2 (); \
151         r4 = (long) (arg2)
152 # define LOADARGS_3(name, arg1, arg2, arg3) \
153         LOADARGS_2(name, arg1, arg2); \
154         extern void __illegally_sized_syscall_##name##_arg3 (void); \
155         if (sizeof (arg3) > 4) __illegally_sized_syscall_##name##_arg3 (); \
156         r5 = (long) (arg3)
157 # define LOADARGS_4(name, arg1, arg2, arg3, arg4) \
158         LOADARGS_3(name, arg1, arg2, arg3); \
159         extern void __illegally_sized_syscall_##name##_arg4 (void); \
160         if (sizeof (arg4) > 4) __illegally_sized_syscall_##name##_arg4 (); \
161         r6 = (long) (arg4)
162 # define LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5) \
163         LOADARGS_4(name, arg1, arg2, arg3, arg4); \
164         extern void __illegally_sized_syscall_##name##_arg5 (void); \
165         if (sizeof (arg5) > 4) __illegally_sized_syscall_##name##_arg5 (); \
166         r7 = (long) (arg5)
167 # define LOADARGS_6(name, arg1, arg2, arg3, arg4, arg5, arg6) \
168         LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5); \
169         extern void __illegally_sized_syscall_##name##_arg6 (void); \
170         if (sizeof (arg6) > 4) __illegally_sized_syscall_##name##_arg6 (); \
171         r8 = (long) (arg6)
172
173 # define ASM_INPUT_0 "0" (r0)
174 # define ASM_INPUT_1 ASM_INPUT_0, "1" (r3)
175 # define ASM_INPUT_2 ASM_INPUT_1, "2" (r4)
176 # define ASM_INPUT_3 ASM_INPUT_2, "3" (r5)
177 # define ASM_INPUT_4 ASM_INPUT_3, "4" (r6)
178 # define ASM_INPUT_5 ASM_INPUT_4, "5" (r7)
179 # define ASM_INPUT_6 ASM_INPUT_5, "6" (r8)
180
181 #endif /* __ASSEMBLER__ */
182
183
184 #endif /* linux/powerpc/sysdep.h */