]>
Commit | Line | Data |
---|---|---|
340f7976 JM |
1 | /* Copyright (C) 2000, 2002, 2003, 2004, 2005, |
2 | 2009 Free Software Foundation, Inc. | |
87af90e7 AJ |
3 | This file is part of the GNU C Library. |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
3214b89b AJ |
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. | |
87af90e7 AJ |
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 | |
3214b89b | 13 | Lesser General Public License for more details. |
87af90e7 | 14 | |
3214b89b AJ |
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. */ | |
87af90e7 | 19 | |
ef055a74 AO |
20 | #ifndef _LINUX_MIPS_MIPS32_SYSDEP_H |
21 | #define _LINUX_MIPS_MIPS32_SYSDEP_H 1 | |
87af90e7 AJ |
22 | |
23 | /* There is some commonality. */ | |
ef055a74 | 24 | #include <sysdeps/unix/mips/mips32/sysdep.h> |
87af90e7 | 25 | |
8c276674 DJ |
26 | #include <tls.h> |
27 | ||
340f7976 JM |
28 | /* In order to get __set_errno() definition in INLINE_SYSCALL. */ |
29 | #ifndef __ASSEMBLER__ | |
30 | #include <errno.h> | |
31 | #endif | |
32 | ||
87af90e7 AJ |
33 | /* For Linux we can use the system call table in the header file |
34 | /usr/include/asm/unistd.h | |
35 | of the kernel. But these symbols do not follow the SYS_* syntax | |
36 | so we have to redefine the `SYS_ify' macro here. */ | |
37 | #undef SYS_ify | |
38 | #ifdef __STDC__ | |
39 | # define SYS_ify(syscall_name) __NR_##syscall_name | |
40 | #else | |
41 | # define SYS_ify(syscall_name) __NR_/**/syscall_name | |
42 | #endif | |
43 | ||
63fb881a | 44 | #ifndef __ASSEMBLER__ |
9da3df10 UD |
45 | |
46 | /* Define a macro which expands into the inline wrapper code for a system | |
47 | call. */ | |
48 | #undef INLINE_SYSCALL | |
49 | #define INLINE_SYSCALL(name, nr, args...) \ | |
50 | ({ INTERNAL_SYSCALL_DECL(err); \ | |
e1ae85a5 AJ |
51 | long result_var = INTERNAL_SYSCALL (name, err, nr, args); \ |
52 | if ( INTERNAL_SYSCALL_ERROR_P (result_var, err) ) \ | |
53 | { \ | |
54 | __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, err)); \ | |
55 | result_var = -1L; \ | |
56 | } \ | |
9da3df10 UD |
57 | result_var; }) |
58 | ||
59 | #undef INTERNAL_SYSCALL_DECL | |
60 | #define INTERNAL_SYSCALL_DECL(err) long err | |
61 | ||
62 | #undef INTERNAL_SYSCALL_ERROR_P | |
63 | #define INTERNAL_SYSCALL_ERROR_P(val, err) ((long) (err)) | |
64 | ||
65 | #undef INTERNAL_SYSCALL_ERRNO | |
66 | #define INTERNAL_SYSCALL_ERRNO(val, err) (val) | |
67 | ||
68 | #undef INTERNAL_SYSCALL | |
e1ae85a5 AJ |
69 | #define INTERNAL_SYSCALL(name, err, nr, args...) \ |
70 | internal_syscall##nr (, "li\t$2, %2\t\t\t# " #name "\n\t", \ | |
71 | "i" (SYS_ify (name)), err, args) | |
9da3df10 | 72 | |
e1ae85a5 AJ |
73 | #undef INTERNAL_SYSCALL_NCS |
74 | #define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ | |
75 | internal_syscall##nr (= number, , "r" (__v0), err, args) | |
76 | ||
77 | #define internal_syscall0(ncs_init, cs_init, input, err, dummy...) \ | |
78 | ({ \ | |
9da3df10 UD |
79 | long _sys_result; \ |
80 | \ | |
81 | { \ | |
e1ae85a5 AJ |
82 | register long __v0 asm("$2") ncs_init; \ |
83 | register long __a3 asm("$7"); \ | |
84 | __asm__ volatile ( \ | |
85 | ".set\tnoreorder\n\t" \ | |
86 | cs_init \ | |
87 | "syscall\n\t" \ | |
88 | ".set reorder" \ | |
89 | : "=r" (__v0), "=r" (__a3) \ | |
90 | : input \ | |
91 | : __SYSCALL_CLOBBERS); \ | |
9da3df10 UD |
92 | err = __a3; \ |
93 | _sys_result = __v0; \ | |
94 | } \ | |
95 | _sys_result; \ | |
96 | }) | |
97 | ||
e1ae85a5 AJ |
98 | #define internal_syscall1(ncs_init, cs_init, input, err, arg1) \ |
99 | ({ \ | |
9da3df10 UD |
100 | long _sys_result; \ |
101 | \ | |
102 | { \ | |
e1ae85a5 AJ |
103 | register long __v0 asm("$2") ncs_init; \ |
104 | register long __a0 asm("$4") = (long) arg1; \ | |
105 | register long __a3 asm("$7"); \ | |
106 | __asm__ volatile ( \ | |
107 | ".set\tnoreorder\n\t" \ | |
108 | cs_init \ | |
109 | "syscall\n\t" \ | |
110 | ".set reorder" \ | |
111 | : "=r" (__v0), "=r" (__a3) \ | |
112 | : input, "r" (__a0) \ | |
113 | : __SYSCALL_CLOBBERS); \ | |
9da3df10 UD |
114 | err = __a3; \ |
115 | _sys_result = __v0; \ | |
116 | } \ | |
117 | _sys_result; \ | |
118 | }) | |
119 | ||
e1ae85a5 AJ |
120 | #define internal_syscall2(ncs_init, cs_init, input, err, arg1, arg2) \ |
121 | ({ \ | |
9da3df10 UD |
122 | long _sys_result; \ |
123 | \ | |
124 | { \ | |
e1ae85a5 AJ |
125 | register long __v0 asm("$2") ncs_init; \ |
126 | register long __a0 asm("$4") = (long) arg1; \ | |
127 | register long __a1 asm("$5") = (long) arg2; \ | |
128 | register long __a3 asm("$7"); \ | |
129 | __asm__ volatile ( \ | |
130 | ".set\tnoreorder\n\t" \ | |
131 | cs_init \ | |
132 | "syscall\n\t" \ | |
133 | ".set\treorder" \ | |
134 | : "=r" (__v0), "=r" (__a3) \ | |
135 | : input, "r" (__a0), "r" (__a1) \ | |
136 | : __SYSCALL_CLOBBERS); \ | |
9da3df10 UD |
137 | err = __a3; \ |
138 | _sys_result = __v0; \ | |
139 | } \ | |
140 | _sys_result; \ | |
141 | }) | |
142 | ||
e1ae85a5 AJ |
143 | #define internal_syscall3(ncs_init, cs_init, input, err, arg1, arg2, arg3)\ |
144 | ({ \ | |
9da3df10 UD |
145 | long _sys_result; \ |
146 | \ | |
147 | { \ | |
e1ae85a5 AJ |
148 | register long __v0 asm("$2") ncs_init; \ |
149 | register long __a0 asm("$4") = (long) arg1; \ | |
150 | register long __a1 asm("$5") = (long) arg2; \ | |
151 | register long __a2 asm("$6") = (long) arg3; \ | |
152 | register long __a3 asm("$7"); \ | |
153 | __asm__ volatile ( \ | |
154 | ".set\tnoreorder\n\t" \ | |
155 | cs_init \ | |
156 | "syscall\n\t" \ | |
157 | ".set\treorder" \ | |
158 | : "=r" (__v0), "=r" (__a3) \ | |
159 | : input, "r" (__a0), "r" (__a1), "r" (__a2) \ | |
160 | : __SYSCALL_CLOBBERS); \ | |
9da3df10 UD |
161 | err = __a3; \ |
162 | _sys_result = __v0; \ | |
163 | } \ | |
164 | _sys_result; \ | |
165 | }) | |
166 | ||
e1ae85a5 AJ |
167 | #define internal_syscall4(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4)\ |
168 | ({ \ | |
9da3df10 UD |
169 | long _sys_result; \ |
170 | \ | |
171 | { \ | |
e1ae85a5 AJ |
172 | register long __v0 asm("$2") ncs_init; \ |
173 | register long __a0 asm("$4") = (long) arg1; \ | |
174 | register long __a1 asm("$5") = (long) arg2; \ | |
175 | register long __a2 asm("$6") = (long) arg3; \ | |
176 | register long __a3 asm("$7") = (long) arg4; \ | |
177 | __asm__ volatile ( \ | |
178 | ".set\tnoreorder\n\t" \ | |
179 | cs_init \ | |
180 | "syscall\n\t" \ | |
181 | ".set\treorder" \ | |
182 | : "=r" (__v0), "+r" (__a3) \ | |
183 | : input, "r" (__a0), "r" (__a1), "r" (__a2) \ | |
184 | : __SYSCALL_CLOBBERS); \ | |
9da3df10 UD |
185 | err = __a3; \ |
186 | _sys_result = __v0; \ | |
187 | } \ | |
188 | _sys_result; \ | |
189 | }) | |
190 | ||
e1ae85a5 AJ |
191 | /* We need to use a frame pointer for the functions in which we |
192 | adjust $sp around the syscall, or debug information and unwind | |
193 | information will be $sp relative and thus wrong during the syscall. As | |
194 | of GCC 3.4.3, this is sufficient. */ | |
195 | #define FORCE_FRAME_POINTER alloca (4) | |
196 | ||
197 | #define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5)\ | |
198 | ({ \ | |
9da3df10 UD |
199 | long _sys_result; \ |
200 | \ | |
e1ae85a5 | 201 | FORCE_FRAME_POINTER; \ |
9da3df10 | 202 | { \ |
e1ae85a5 AJ |
203 | register long __v0 asm("$2") ncs_init; \ |
204 | register long __a0 asm("$4") = (long) arg1; \ | |
205 | register long __a1 asm("$5") = (long) arg2; \ | |
206 | register long __a2 asm("$6") = (long) arg3; \ | |
207 | register long __a3 asm("$7") = (long) arg4; \ | |
208 | __asm__ volatile ( \ | |
209 | ".set\tnoreorder\n\t" \ | |
210 | "subu\t$29, 32\n\t" \ | |
211 | "sw\t%6, 16($29)\n\t" \ | |
212 | cs_init \ | |
213 | "syscall\n\t" \ | |
214 | "addiu\t$29, 32\n\t" \ | |
215 | ".set\treorder" \ | |
216 | : "=r" (__v0), "+r" (__a3) \ | |
217 | : input, "r" (__a0), "r" (__a1), "r" (__a2), \ | |
218 | "r" ((long)arg5) \ | |
219 | : __SYSCALL_CLOBBERS); \ | |
9da3df10 UD |
220 | err = __a3; \ |
221 | _sys_result = __v0; \ | |
222 | } \ | |
223 | _sys_result; \ | |
224 | }) | |
225 | ||
e1ae85a5 AJ |
226 | #define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6)\ |
227 | ({ \ | |
9da3df10 UD |
228 | long _sys_result; \ |
229 | \ | |
e1ae85a5 | 230 | FORCE_FRAME_POINTER; \ |
9da3df10 | 231 | { \ |
e1ae85a5 AJ |
232 | register long __v0 asm("$2") ncs_init; \ |
233 | register long __a0 asm("$4") = (long) arg1; \ | |
234 | register long __a1 asm("$5") = (long) arg2; \ | |
235 | register long __a2 asm("$6") = (long) arg3; \ | |
236 | register long __a3 asm("$7") = (long) arg4; \ | |
237 | __asm__ volatile ( \ | |
238 | ".set\tnoreorder\n\t" \ | |
239 | "subu\t$29, 32\n\t" \ | |
240 | "sw\t%6, 16($29)\n\t" \ | |
241 | "sw\t%7, 20($29)\n\t" \ | |
242 | cs_init \ | |
243 | "syscall\n\t" \ | |
244 | "addiu\t$29, 32\n\t" \ | |
245 | ".set\treorder" \ | |
246 | : "=r" (__v0), "+r" (__a3) \ | |
247 | : input, "r" (__a0), "r" (__a1), "r" (__a2), \ | |
54316090 | 248 | "r" ((long)arg5), "r" ((long)arg6) \ |
e1ae85a5 | 249 | : __SYSCALL_CLOBBERS); \ |
9da3df10 UD |
250 | err = __a3; \ |
251 | _sys_result = __v0; \ | |
252 | } \ | |
253 | _sys_result; \ | |
254 | }) | |
255 | ||
e1ae85a5 AJ |
256 | #define internal_syscall7(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\ |
257 | ({ \ | |
9da3df10 UD |
258 | long _sys_result; \ |
259 | \ | |
e1ae85a5 | 260 | FORCE_FRAME_POINTER; \ |
9da3df10 | 261 | { \ |
e1ae85a5 AJ |
262 | register long __v0 asm("$2") ncs_init; \ |
263 | register long __a0 asm("$4") = (long) arg1; \ | |
264 | register long __a1 asm("$5") = (long) arg2; \ | |
265 | register long __a2 asm("$6") = (long) arg3; \ | |
266 | register long __a3 asm("$7") = (long) arg4; \ | |
267 | __asm__ volatile ( \ | |
268 | ".set\tnoreorder\n\t" \ | |
269 | "subu\t$29, 32\n\t" \ | |
270 | "sw\t%6, 16($29)\n\t" \ | |
271 | "sw\t%7, 20($29)\n\t" \ | |
272 | "sw\t%8, 24($29)\n\t" \ | |
273 | cs_init \ | |
274 | "syscall\n\t" \ | |
275 | "addiu\t$29, 32\n\t" \ | |
276 | ".set\treorder" \ | |
277 | : "=r" (__v0), "+r" (__a3) \ | |
278 | : input, "r" (__a0), "r" (__a1), "r" (__a2), \ | |
54316090 | 279 | "r" ((long)arg5), "r" ((long)arg6), "r" ((long)arg7) \ |
e1ae85a5 | 280 | : __SYSCALL_CLOBBERS); \ |
9da3df10 UD |
281 | err = __a3; \ |
282 | _sys_result = __v0; \ | |
283 | } \ | |
284 | _sys_result; \ | |
285 | }) | |
286 | ||
145f3f8a | 287 | #define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \ |
f1297d79 | 288 | "$14", "$15", "$24", "$25", "hi", "lo", "memory" |
9da3df10 UD |
289 | |
290 | #endif /* __ASSEMBLER__ */ | |
291 | ||
908afa83 DJ |
292 | /* Pointer mangling is not yet supported for MIPS. */ |
293 | #define PTR_MANGLE(var) (void) (var) | |
294 | #define PTR_DEMANGLE(var) (void) (var) | |
295 | ||
ef055a74 | 296 | #endif /* linux/mips/mips32/sysdep.h */ |