1 #ifndef _BITS_SYSCALLS_H
2 #define _BITS_SYSCALLS_H
3 #ifndef _SYSCALL_H
4 # error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
5 #endif
6 
7 #include <sgidefs.h>
8 
9 #ifndef __ASSEMBLER__
10 
11 #include <errno.h>
12 
13 /*
14  * Import from:
15  *	glibc-ports/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
16  *	glibc-ports/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h
17  *	glibc-ports/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h
18  */
19 
20 /* Define a macro which expands into the inline wrapper code for a system
21    call.  */
22 #define INLINE_SYSCALL(name, nr, args...)                               \
23   ({ INTERNAL_SYSCALL_DECL(err);					\
24      long result_var = INTERNAL_SYSCALL(name, err, nr, args);		\
25      if ( INTERNAL_SYSCALL_ERROR_P (result_var, err) )			\
26        {								\
27 	 __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, err));	\
28 	 result_var = -1L;						\
29        }								\
30      result_var; })
31 
32 #define INLINE_SYSCALL_NOERR_NCS(name, nr, args...)			\
33 ({									\
34 	INTERNAL_SYSCALL_DECL(err);					\
35 	long res = INTERNAL_SYSCALL_NCS(name, err, nr, args);		\
36 	if (unlikely(INTERNAL_SYSCALL_ERROR_P(res, err))) {		\
37 	    res = -res;							\
38 	}								\
39         res;								\
40 })
41 
42 #define INTERNAL_SYSCALL_DECL(err) long err attribute_unused
43 
44 #define INTERNAL_SYSCALL_ERROR_P(val, err)   ((long) (err))
45 
46 #define INTERNAL_SYSCALL_ERRNO(val, err)     (val)
47 
48 #define INTERNAL_SYSCALL(name, err, nr, args...) \
49 	internal_syscall##nr (, "li\t$2, %2\t\t\t# " #name "\n\t",	\
50 			      "i" (SYS_ify (name)), err, args)
51 
52 #define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
53 	internal_syscall##nr (= number, , "r" (__v0), err, args)
54 
55 #if _MIPS_SIM == _ABIO32 || _MIPS_SIM == _ABI64
56 # define ARG_TYPE long
57 #else
58 # define ARG_TYPE long long
59 #endif
60 
61 #define internal_syscall0(ncs_init, cs_init, input, err, dummy...)	\
62 ({									\
63 	long _sys_result;						\
64 									\
65 	{								\
66 	register ARG_TYPE __v0 __asm__("$2") ncs_init;			\
67 	register ARG_TYPE __a3 __asm__("$7");				\
68 	__asm__ __volatile__ (						\
69 	".set\tnoreorder\n\t"						\
70 	cs_init								\
71 	"syscall\n\t"							\
72 	".set reorder"							\
73 	: "=r" (__v0), "=r" (__a3)					\
74 	: input								\
75 	: __SYSCALL_CLOBBERS);						\
76 	err = __a3;							\
77 	_sys_result = __v0;						\
78 	}								\
79 	_sys_result;							\
80 })
81 
82 #define internal_syscall1(ncs_init, cs_init, input, err, arg1)		\
83 ({									\
84 	long _sys_result;						\
85 									\
86 	{								\
87 	register ARG_TYPE __v0 __asm__("$2") ncs_init;			\
88 	register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1;		\
89 	register ARG_TYPE __a3 __asm__("$7");				\
90 	__asm__ __volatile__ (						\
91 	".set\tnoreorder\n\t"						\
92 	cs_init								\
93 	"syscall\n\t"							\
94 	".set reorder"							\
95 	: "=r" (__v0), "=r" (__a3)					\
96 	: input, "r" (__a0)						\
97 	: __SYSCALL_CLOBBERS);						\
98 	err = __a3;							\
99 	_sys_result = __v0;						\
100 	}								\
101 	_sys_result;							\
102 })
103 
104 #define internal_syscall2(ncs_init, cs_init, input, err, arg1, arg2)	\
105 ({									\
106 	long _sys_result;						\
107 									\
108 	{								\
109 	register ARG_TYPE __v0 __asm__("$2") ncs_init;			\
110 	register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1;		\
111 	register ARG_TYPE __a1 __asm__("$5") = (ARG_TYPE) arg2;		\
112 	register ARG_TYPE __a3 __asm__("$7");				\
113 	__asm__ __volatile__ (						\
114 	".set\tnoreorder\n\t"						\
115 	cs_init								\
116 	"syscall\n\t"							\
117 	".set\treorder"						\
118 	: "=r" (__v0), "=r" (__a3)					\
119 	: input, "r" (__a0), "r" (__a1)					\
120 	: __SYSCALL_CLOBBERS);						\
121 	err = __a3;							\
122 	_sys_result = __v0;						\
123 	}								\
124 	_sys_result;							\
125 })
126 
127 #define internal_syscall3(ncs_init, cs_init, input, err, arg1, arg2, arg3)\
128 ({									\
129 	long _sys_result;						\
130 									\
131 	{								\
132 	register ARG_TYPE __v0 __asm__("$2") ncs_init;			\
133 	register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1;		\
134 	register ARG_TYPE __a1 __asm__("$5") = (ARG_TYPE) arg2;		\
135 	register ARG_TYPE __a2 __asm__("$6") = (ARG_TYPE) arg3;		\
136 	register ARG_TYPE __a3 __asm__("$7");				\
137 	__asm__ __volatile__ (						\
138 	".set\tnoreorder\n\t"						\
139 	cs_init								\
140 	"syscall\n\t"							\
141 	".set\treorder"						\
142 	: "=r" (__v0), "=r" (__a3)					\
143 	: input, "r" (__a0), "r" (__a1), "r" (__a2)			\
144 	: __SYSCALL_CLOBBERS);						\
145 	err = __a3;							\
146 	_sys_result = __v0;						\
147 	}								\
148 	_sys_result;							\
149 })
150 
151 #define internal_syscall4(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4)\
152 ({									\
153 	long _sys_result;						\
154 									\
155 	{								\
156 	register ARG_TYPE __v0 __asm__("$2") ncs_init;			\
157 	register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1;		\
158 	register ARG_TYPE __a1 __asm__("$5") = (ARG_TYPE) arg2;		\
159 	register ARG_TYPE __a2 __asm__("$6") = (ARG_TYPE) arg3;		\
160 	register ARG_TYPE __a3 __asm__("$7") = (ARG_TYPE) arg4;		\
161 	__asm__ __volatile__ (						\
162 	".set\tnoreorder\n\t"						\
163 	cs_init								\
164 	"syscall\n\t"							\
165 	".set\treorder"						\
166 	: "=r" (__v0), "+r" (__a3)					\
167 	: input, "r" (__a0), "r" (__a1), "r" (__a2)			\
168 	: __SYSCALL_CLOBBERS);						\
169 	err = __a3;							\
170 	_sys_result = __v0;						\
171 	}								\
172 	_sys_result;							\
173 })
174 
175 #if _MIPS_SIM == _ABIO32
176 #include <alloca.h>
177 /* We need to use a frame pointer for the functions in which we
178    adjust $sp around the syscall, or debug information and unwind
179    information will be $sp relative and thus wrong during the syscall.  As
180    of GCC 3.4.3, this is sufficient.  */
181 #define FORCE_FRAME_POINTER alloca (4)
182 
183 #define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5)\
184 ({									\
185 	long _sys_result;						\
186 									\
187 	int* array = FORCE_FRAME_POINTER;				\
188 	{								\
189 	register long __v0 __asm__("$2") ncs_init;			\
190 	register long __a0 __asm__("$4") = (long) arg1;			\
191 	register long __a1 __asm__("$5") = (long) arg2;			\
192 	register long __a2 __asm__("$6") = (long) arg3;			\
193 	register long __a3 __asm__("$7") = (long) arg4;			\
194 	__asm__ __volatile__ (						\
195 	".set\tnoreorder\n\t"						\
196 	"subu\t$29, 32\n\t"                                             \
197 	"sw\t%6, 16($29)\n\t"						\
198 	cs_init								\
199 	"syscall\n\t"							\
200 	"addiu\t$29, 32\n\t"                                            \
201 	"addiu\t%7, %7, 0\n\t"						\
202 	".set\treorder"						        \
203 	: "=r" (__v0), "+r" (__a3)					\
204 	: input, "r" (__a0), "r" (__a1), "r" (__a2),			\
205 	  "r" ((long)arg5), "r" (array)					\
206 	: __SYSCALL_CLOBBERS);						\
207 	err = __a3;							\
208 	_sys_result = __v0;						\
209 	}								\
210 	_sys_result;							\
211 })
212 
213 #define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6)\
214 ({									\
215 	long _sys_result;						\
216 									\
217 	int* array = FORCE_FRAME_POINTER;				\
218 	{								\
219 	register long __v0 __asm__("$2") ncs_init;			\
220 	register long __a0 __asm__("$4") = (long) arg1;			\
221 	register long __a1 __asm__("$5") = (long) arg2;			\
222 	register long __a2 __asm__("$6") = (long) arg3;			\
223 	register long __a3 __asm__("$7") = (long) arg4;			\
224 	__asm__ __volatile__ (						\
225 	".set\tnoreorder\n\t"                                           \
226 	"subu\t$29, 32\n\t"                                             \
227 	"sw\t%6, 16($29)\n\t"						\
228 	"sw\t%7, 20($29)\n\t"						\
229 	cs_init								\
230 	"syscall\n\t"							\
231 	"addiu\t$29, 32\n\t"                                            \
232 	"addiu\t%8, %8, 0\n\t"						\
233 	".set\treorder"						        \
234 	: "=r" (__v0), "+r" (__a3)					\
235 	: input, "r" (__a0), "r" (__a1), "r" (__a2),			\
236 	  "r" ((long)arg5), "r" ((long)arg6), "r" (array)		\
237 	: __SYSCALL_CLOBBERS);						\
238 	err = __a3;							\
239 	_sys_result = __v0;						\
240 	}								\
241 	_sys_result;							\
242 })
243 
244 #define internal_syscall7(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\
245 ({									\
246 	long _sys_result;						\
247 									\
248 	int* array = FORCE_FRAME_POINTER;				\
249 	{								\
250 	register long __v0 __asm__("$2") ncs_init;			\
251 	register long __a0 __asm__("$4") = (long) arg1;			\
252 	register long __a1 __asm__("$5") = (long) arg2;			\
253 	register long __a2 __asm__("$6") = (long) arg3;			\
254 	register long __a3 __asm__("$7") = (long) arg4;			\
255 	__asm__ __volatile__ (						\
256 	".set\tnoreorder\n\t"						\
257 	"subu\t$29, 32\n\t"                                             \
258 	"sw\t%6, 16($29)\n\t"						\
259 	"sw\t%7, 20($29)\n\t"						\
260 	"sw\t%8, 24($29)\n\t"						\
261 	cs_init								\
262 	"syscall\n\t"							\
263 	"addiu\t$29, 32\n\t"                                            \
264 	"addiu\t%9, %9, 0\n\t"						\
265 	".set\treorder"							\
266 	: "=r" (__v0), "+r" (__a3)					\
267 	: input, "r" (__a0), "r" (__a1), "r" (__a2),			\
268 	  "r" ((long)arg5), "r" ((long)arg6), "r" ((long)arg7),		\
269 	  "r" (array)							\
270 	: __SYSCALL_CLOBBERS);						\
271 	err = __a3;							\
272 	_sys_result = __v0;						\
273 	}								\
274 	_sys_result;							\
275 })
276 
277 #if __mips_isa_rev >= 6
278 # define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \
279 	 "$14", "$15", "$24", "$25", "memory"
280 #else
281 # define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \
282 	 "$14", "$15", "$24", "$25", "hi", "lo", "memory"
283 #endif
284 
285 #else /* N32 || N64 */
286 
287 #define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5) \
288 ({ 									\
289 	long _sys_result;						\
290 									\
291 	{								\
292 	register ARG_TYPE __v0 __asm__("$2") ncs_init;			\
293 	register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1; 	\
294 	register ARG_TYPE __a1 __asm__("$5") = (ARG_TYPE) arg2; 	\
295 	register ARG_TYPE __a2 __asm__("$6") = (ARG_TYPE) arg3; 	\
296 	register ARG_TYPE __a3 __asm__("$7") = (ARG_TYPE) arg4; 	\
297 	register ARG_TYPE __a4 __asm__("$8") = (ARG_TYPE) arg5; 	\
298 	__asm__ __volatile__ ( 						\
299 	".set\tnoreorder\n\t" 						\
300 	cs_init								\
301 	"syscall\n\t" 							\
302 	".set\treorder" 						\
303 	: "=r" (__v0), "+r" (__a3) 					\
304 	: input, "r" (__a0), "r" (__a1), "r" (__a2), "r" (__a4)		\
305 	: __SYSCALL_CLOBBERS); 						\
306 	err = __a3;							\
307 	_sys_result = __v0;						\
308 	}								\
309 	_sys_result;							\
310 })
311 
312 #define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6) \
313 ({ 									\
314 	long _sys_result;						\
315 									\
316 	{								\
317 	register ARG_TYPE __v0 __asm__("$2") ncs_init;			\
318 	register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1; 	\
319 	register ARG_TYPE __a1 __asm__("$5") = (ARG_TYPE) arg2; 	\
320 	register ARG_TYPE __a2 __asm__("$6") = (ARG_TYPE) arg3; 	\
321 	register ARG_TYPE __a3 __asm__("$7") = (ARG_TYPE) arg4; 	\
322 	register ARG_TYPE __a4 __asm__("$8") = (ARG_TYPE) arg5; 	\
323 	register ARG_TYPE __a5 __asm__("$9") = (ARG_TYPE) arg6; 	\
324 	__asm__ __volatile__ ( 						\
325 	".set\tnoreorder\n\t" 						\
326 	cs_init								\
327 	"syscall\n\t" 							\
328 	".set\treorder" 						\
329 	: "=r" (__v0), "+r" (__a3) 					\
330 	: input, "r" (__a0), "r" (__a1), "r" (__a2), "r" (__a4),	\
331 	  "r" (__a5)							\
332 	: __SYSCALL_CLOBBERS); 						\
333 	err = __a3;							\
334 	_sys_result = __v0;						\
335 	}								\
336 	_sys_result;							\
337 })
338 
339 #if __mips_isa_rev >= 6
340 # define __SYSCALL_CLOBBERS "$1", "$3", "$10", "$11", "$12", "$13", \
341 	 "$14", "$15", "$24", "$25", "memory"
342 #else
343 # define __SYSCALL_CLOBBERS "$1", "$3", "$10", "$11", "$12", "$13", \
344 	 "$14", "$15", "$24", "$25", "hi", "lo", "memory"
345 #endif
346 
347 #endif
348 
349 #endif /* __ASSEMBLER__ */
350 #endif /* _BITS_SYSCALLS_H */
351