blob: 9de4f1acea259c15b42894c5a7efa08c220d2a72 [file] [log] [blame]
yuezonghe824eb0c2024-06-27 02:32:26 -07001/* Copyright (C) 1992, 1995, 1997, 1999, 2000, 2002, 2003, 2004
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#ifndef _LINUX_MIPS_SYSDEP_H
22#define _LINUX_MIPS_SYSDEP_H 1
23
24#include <sgidefs.h>
25#include <common/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
32#undef SYS_ify
33#ifdef __STDC__
34# define SYS_ify(syscall_name) __NR_##syscall_name
35#else
36# define SYS_ify(syscall_name) __NR_/**/syscall_name
37#endif
38
39#ifdef __ASSEMBLER__
40
41#include <sys/regdef.h>
42
43#define ENTRY(name) \
44 .globl name; \
45 .align 2; \
46 .ent name,0; \
47 name##:
48
49#undef END
50#define END(function) \
51 .end function; \
52 .size function,.-function
53
54#define ret j ra ; nop
55
56#undef PSEUDO_END
57#define PSEUDO_END(sym) .end sym; .size sym,.-sym
58
59#define PSEUDO_NOERRNO(name, syscall_name, args) \
60 .align 2; \
61 ENTRY(name) \
62 .set noreorder; \
63 li v0, SYS_ify(syscall_name); \
64 syscall
65
66#undef PSEUDO_END_NOERRNO
67#define PSEUDO_END_NOERRNO(sym) .end sym; .size sym,.-sym
68
69#define ret_NOERRNO ret
70
71#define PSEUDO_ERRVAL(name, syscall_name, args) \
72 .align 2; \
73 ENTRY(name) \
74 .set noreorder; \
75 li v0, SYS_ify(syscall_name); \
76 syscall
77
78#undef PSEUDO_END_ERRVAL
79#define PSEUDO_END_ERRVAL(sym) .end sym; .size sym,.-sym
80
81#define ret_ERRVAL ret
82
83#define r0 v0
84#define r1 v1
85/* The mips move insn is d,s. */
86#define MOVE(x,y) move y , x
87
88#if _MIPS_SIM == _ABIO32
89# define L(label) $L ## label
90#else
91# define L(label) .L ## label
92#endif
93
94/* Note that while it's better structurally, going back to call __syscall_error
95 can make things confusing if you're debugging---it looks like it's jumping
96 backwards into the previous fn. */
97
98#ifdef __PIC__
99#define PSEUDO(name, syscall_name, args) \
100 .align 2; \
101 99: move a0, v0; \
102 la t9,__syscall_error; \
103 jr t9; \
104 ENTRY(name) \
105 .set noreorder; \
106 .cpload t9; \
107 li v0, SYS_ify(syscall_name); \
108 syscall; \
109 .set reorder; \
110 bne a3, zero, 99b; \
111L(syse1):
112#else
113#define PSEUDO(name, syscall_name, args) \
114 .set noreorder; \
115 .align 2; \
116 99: move a0, v0; \
117 j __syscall_error; \
118 nop; \
119 ENTRY(name) \
120 .set noreorder; \
121 li v0, SYS_ify(syscall_name); \
122 syscall; \
123 .set reorder; \
124 bne a3, zero, 99b; \
125L(syse1):
126#endif
127
128/* We don't want the label for the error handler to be visible in the symbol
129 table when we define it here. */
130#ifdef __PIC__
131# define SYSCALL_ERROR_LABEL 99b
132#endif
133
134#else /* ! __ASSEMBLER__ */
135
136/* Define a macro which expands into the inline wrapper code for a system
137 call. */
138#undef INLINE_SYSCALL
139#define INLINE_SYSCALL(name, nr, args...) \
140 ({ INTERNAL_SYSCALL_DECL(err); \
141 long result_var = INTERNAL_SYSCALL (name, err, nr, args); \
142 if ( INTERNAL_SYSCALL_ERROR_P (result_var, err) ) \
143 { \
144 __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, err)); \
145 result_var = -1L; \
146 } \
147 result_var; })
148
149#undef INTERNAL_SYSCALL_DECL
150#define INTERNAL_SYSCALL_DECL(err) long err
151
152#undef INTERNAL_SYSCALL_ERROR_P
153#define INTERNAL_SYSCALL_ERROR_P(val, err) ((long) (err))
154
155#undef INTERNAL_SYSCALL_ERRNO
156#define INTERNAL_SYSCALL_ERRNO(val, err) (val)
157
158#undef INTERNAL_SYSCALL
159#define INTERNAL_SYSCALL(name, err, nr, args...) \
160 internal_syscall##nr (, "li\t$2, %2\t\t\t# " #name "\n\t", \
161 "i" (SYS_ify (name)), err, args)
162
163#undef INTERNAL_SYSCALL_NCS
164#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
165 internal_syscall##nr (= number, , "r" (__v0), err, args)
166#undef internal_syscall0
167#define internal_syscall0(ncs_init, cs_init, input, err, dummy...) \
168({ \
169 long _sys_result; \
170 \
171 { \
172 register long __v0 __asm__("$2") ncs_init; \
173 register long __a3 __asm__("$7"); \
174 __asm__ __volatile__ ( \
175 ".set\tnoreorder\n\t" \
176 cs_init \
177 "syscall\n\t" \
178 ".set reorder" \
179 : "=r" (__v0), "=r" (__a3) \
180 : input \
181 : __SYSCALL_CLOBBERS); \
182 err = __a3; \
183 _sys_result = __v0; \
184 } \
185 _sys_result; \
186})
187
188#undef internal_syscall1
189#define internal_syscall1(ncs_init, cs_init, input, err, arg1) \
190({ \
191 long _sys_result; \
192 \
193 { \
194 register long __v0 __asm__("$2") ncs_init; \
195 register long __a0 __asm__("$4") = (long) arg1; \
196 register long __a3 __asm__("$7"); \
197 __asm__ __volatile__ ( \
198 ".set\tnoreorder\n\t" \
199 cs_init \
200 "syscall\n\t" \
201 ".set reorder" \
202 : "=r" (__v0), "=r" (__a3) \
203 : input, "r" (__a0) \
204 : __SYSCALL_CLOBBERS); \
205 err = __a3; \
206 _sys_result = __v0; \
207 } \
208 _sys_result; \
209})
210
211#undef internal_syscall2
212#define internal_syscall2(ncs_init, cs_init, input, err, arg1, arg2) \
213({ \
214 long _sys_result; \
215 \
216 { \
217 register long __v0 __asm__("$2") ncs_init; \
218 register long __a0 __asm__("$4") = (long) arg1; \
219 register long __a1 __asm__("$5") = (long) arg2; \
220 register long __a3 __asm__("$7"); \
221 __asm__ __volatile__ ( \
222 ".set\tnoreorder\n\t" \
223 cs_init \
224 "syscall\n\t" \
225 ".set\treorder" \
226 : "=r" (__v0), "=r" (__a3) \
227 : input, "r" (__a0), "r" (__a1) \
228 : __SYSCALL_CLOBBERS); \
229 err = __a3; \
230 _sys_result = __v0; \
231 } \
232 _sys_result; \
233})
234
235#undef internal_syscall3
236#define internal_syscall3(ncs_init, cs_init, input, err, arg1, arg2, arg3)\
237({ \
238 long _sys_result; \
239 \
240 { \
241 register long __v0 __asm__("$2") ncs_init; \
242 register long __a0 __asm__("$4") = (long) arg1; \
243 register long __a1 __asm__("$5") = (long) arg2; \
244 register long __a2 __asm__("$6") = (long) arg3; \
245 register long __a3 __asm__("$7"); \
246 __asm__ __volatile__ ( \
247 ".set\tnoreorder\n\t" \
248 cs_init \
249 "syscall\n\t" \
250 ".set\treorder" \
251 : "=r" (__v0), "=r" (__a3) \
252 : input, "r" (__a0), "r" (__a1), "r" (__a2) \
253 : __SYSCALL_CLOBBERS); \
254 err = __a3; \
255 _sys_result = __v0; \
256 } \
257 _sys_result; \
258})
259
260#undef internal_syscall4
261#define internal_syscall4(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4)\
262({ \
263 long _sys_result; \
264 \
265 { \
266 register long __v0 __asm__("$2") ncs_init; \
267 register long __a0 __asm__("$4") = (long) arg1; \
268 register long __a1 __asm__("$5") = (long) arg2; \
269 register long __a2 __asm__("$6") = (long) arg3; \
270 register long __a3 __asm__("$7") = (long) arg4; \
271 __asm__ __volatile__ ( \
272 ".set\tnoreorder\n\t" \
273 cs_init \
274 "syscall\n\t" \
275 ".set\treorder" \
276 : "=r" (__v0), "+r" (__a3) \
277 : input, "r" (__a0), "r" (__a1), "r" (__a2) \
278 : __SYSCALL_CLOBBERS); \
279 err = __a3; \
280 _sys_result = __v0; \
281 } \
282 _sys_result; \
283})
284
285/* We need to use a frame pointer for the functions in which we
286 adjust $sp around the syscall, or debug information and unwind
287 information will be $sp relative and thus wrong during the syscall. As
288 of GCC 3.4.3, this is sufficient. */
289#define FORCE_FRAME_POINTER alloca (4)
290
291#undef internal_syscall5
292#define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5)\
293({ \
294 long _sys_result; \
295 \
296 FORCE_FRAME_POINTER; \
297 { \
298 register long __v0 __asm__("$2") ncs_init; \
299 register long __a0 __asm__("$4") = (long) arg1; \
300 register long __a1 __asm__("$5") = (long) arg2; \
301 register long __a2 __asm__("$6") = (long) arg3; \
302 register long __a3 __asm__("$7") = (long) arg4; \
303 __asm__ __volatile__ ( \
304 ".set\tnoreorder\n\t" \
305 "subu\t$29, 32\n\t" \
306 "sw\t%6, 16($29)\n\t" \
307 cs_init \
308 "syscall\n\t" \
309 "addiu\t$29, 32\n\t" \
310 ".set\treorder" \
311 : "=r" (__v0), "+r" (__a3) \
312 : input, "r" (__a0), "r" (__a1), "r" (__a2), \
313 "r" ((long)arg5) \
314 : __SYSCALL_CLOBBERS); \
315 err = __a3; \
316 _sys_result = __v0; \
317 } \
318 _sys_result; \
319})
320
321#undef internal_syscall6
322#define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6)\
323({ \
324 long _sys_result; \
325 \
326 FORCE_FRAME_POINTER; \
327 { \
328 register long __v0 __asm__("$2") ncs_init; \
329 register long __a0 __asm__("$4") = (long) arg1; \
330 register long __a1 __asm__("$5") = (long) arg2; \
331 register long __a2 __asm__("$6") = (long) arg3; \
332 register long __a3 __asm__("$7") = (long) arg4; \
333 __asm__ __volatile__ ( \
334 ".set\tnoreorder\n\t" \
335 "subu\t$29, 32\n\t" \
336 "sw\t%6, 16($29)\n\t" \
337 "sw\t%7, 20($29)\n\t" \
338 cs_init \
339 "syscall\n\t" \
340 "addiu\t$29, 32\n\t" \
341 ".set\treorder" \
342 : "=r" (__v0), "+r" (__a3) \
343 : input, "r" (__a0), "r" (__a1), "r" (__a2), \
344 "r" ((long)arg5), "r" ((long)arg6) \
345 : __SYSCALL_CLOBBERS); \
346 err = __a3; \
347 _sys_result = __v0; \
348 } \
349 _sys_result; \
350})
351
352#undef internal_syscall7
353#define internal_syscall7(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\
354({ \
355 long _sys_result; \
356 \
357 FORCE_FRAME_POINTER; \
358 { \
359 register long __v0 __asm__("$2") ncs_init; \
360 register long __a0 __asm__("$4") = (long) arg1; \
361 register long __a1 __asm__("$5") = (long) arg2; \
362 register long __a2 __asm__("$6") = (long) arg3; \
363 register long __a3 __asm__("$7") = (long) arg4; \
364 __asm__ __volatile__ ( \
365 ".set\tnoreorder\n\t" \
366 "subu\t$29, 32\n\t" \
367 "sw\t%6, 16($29)\n\t" \
368 "sw\t%7, 20($29)\n\t" \
369 "sw\t%8, 24($29)\n\t" \
370 cs_init \
371 "syscall\n\t" \
372 "addiu\t$29, 32\n\t" \
373 ".set\treorder" \
374 : "=r" (__v0), "+r" (__a3) \
375 : input, "r" (__a0), "r" (__a1), "r" (__a2), \
376 "r" ((long)arg5), "r" ((long)arg6), "r" ((long)arg7) \
377 : __SYSCALL_CLOBBERS); \
378 err = __a3; \
379 _sys_result = __v0; \
380 } \
381 _sys_result; \
382})
383
384#undef __SYSCALL_CLOBBERS
385#define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \
386 "$14", "$15", "$24", "$25", "memory"
387
388/* Pointer mangling is not yet supported for MIPS. */
389#define PTR_MANGLE(var) (void) (var)
390#define PTR_DEMANGLE(var) (void) (var)
391
392#endif /* __ASSEMBLER__ */
393#endif /* _LINUX_MIPS_SYSDEP_H */