1 //! mips64el Linux system calls.
2 //!
3 //! On mips64el, Linux indicates success or failure using `$a3` (`$7`) rather
4 //! than by returning a negative error code as most other architectures do.
5 //!
6 //! Mips-family platforms have a special calling convention for `__NR_pipe`,
7 //! however we use `__NR_pipe2` instead to avoid having to implement it.
8 
9 use crate::backend::reg::{
10     ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0,
11 };
12 use core::arch::asm;
13 
14 #[inline]
syscall0_readonly(nr: SyscallNumber) -> RetReg<R0>15 pub(in crate::backend) unsafe fn syscall0_readonly(nr: SyscallNumber) -> RetReg<R0> {
16     let x0;
17     let err: usize;
18     asm!(
19         "syscall",
20         inlateout("$2" /*$v0*/) nr.to_asm() => x0,
21         lateout("$7" /*$a3*/) err,
22         lateout("$8" /*$a4*/) _,
23         lateout("$9" /*$a5*/) _,
24         lateout("$10" /*$a6*/) _,
25         lateout("$11" /*$a7*/) _,
26         lateout("$12" /*$t0*/) _,
27         lateout("$13" /*$t1*/) _,
28         lateout("$14" /*$t2*/) _,
29         lateout("$15" /*$t3*/) _,
30         lateout("$24" /*$t8*/) _,
31         lateout("$25" /*$t9*/) _,
32         options(nostack, preserves_flags, readonly)
33     );
34     FromAsm::from_asm(if err != 0 {
35         (x0 as usize).wrapping_neg() as *mut _
36     } else {
37         x0
38     })
39 }
40 
41 #[inline]
syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0>42 pub(in crate::backend) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
43     let x0;
44     let err: usize;
45     asm!(
46         "syscall",
47         inlateout("$2" /*$v0*/) nr.to_asm() => x0,
48         in("$4" /*$a0*/) a0.to_asm(),
49         lateout("$7" /*$a3*/) err,
50         lateout("$8" /*$a4*/) _,
51         lateout("$9" /*$a5*/) _,
52         lateout("$10" /*$a6*/) _,
53         lateout("$11" /*$a7*/) _,
54         lateout("$12" /*$t0*/) _,
55         lateout("$13" /*$t1*/) _,
56         lateout("$14" /*$t2*/) _,
57         lateout("$15" /*$t3*/) _,
58         lateout("$24" /*$t8*/) _,
59         lateout("$25" /*$t9*/) _,
60         options(nostack, preserves_flags)
61     );
62     FromAsm::from_asm(if err != 0 {
63         (x0 as usize).wrapping_neg() as *mut _
64     } else {
65         x0
66     })
67 }
68 
69 #[inline]
syscall1_readonly( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, ) -> RetReg<R0>70 pub(in crate::backend) unsafe fn syscall1_readonly(
71     nr: SyscallNumber<'_>,
72     a0: ArgReg<'_, A0>,
73 ) -> RetReg<R0> {
74     let x0;
75     let err: usize;
76     asm!(
77         "syscall",
78         inlateout("$2" /*$v0*/) nr.to_asm() => x0,
79         in("$4" /*$a0*/) a0.to_asm(),
80         lateout("$7" /*$a3*/) err,
81         lateout("$8" /*$a4*/) _,
82         lateout("$9" /*$a5*/) _,
83         lateout("$10" /*$a6*/) _,
84         lateout("$11" /*$a7*/) _,
85         lateout("$12" /*$t0*/) _,
86         lateout("$13" /*$t1*/) _,
87         lateout("$14" /*$t2*/) _,
88         lateout("$15" /*$t3*/) _,
89         lateout("$24" /*$t8*/) _,
90         lateout("$25" /*$t9*/) _,
91         options(nostack, preserves_flags, readonly)
92     );
93     FromAsm::from_asm(if err != 0 {
94         (x0 as usize).wrapping_neg() as *mut _
95     } else {
96         x0
97     })
98 }
99 
100 #[inline]
syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> !101 pub(in crate::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
102     asm!(
103         "syscall",
104         in("$2" /*$v0*/) nr.to_asm(),
105         in("$4" /*$a0*/) a0.to_asm(),
106         options(nostack, noreturn)
107     )
108 }
109 
110 #[inline]
syscall2( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, ) -> RetReg<R0>111 pub(in crate::backend) unsafe fn syscall2(
112     nr: SyscallNumber<'_>,
113     a0: ArgReg<'_, A0>,
114     a1: ArgReg<'_, A1>,
115 ) -> RetReg<R0> {
116     let x0;
117     let err: usize;
118     asm!(
119         "syscall",
120         inlateout("$2" /*$v0*/) nr.to_asm() => x0,
121         in("$4" /*$a0*/) a0.to_asm(),
122         in("$5" /*$a1*/) a1.to_asm(),
123         lateout("$7" /*$a3*/) err,
124         lateout("$8" /*$a4*/) _,
125         lateout("$9" /*$a5*/) _,
126         lateout("$10" /*$a6*/) _,
127         lateout("$11" /*$a7*/) _,
128         lateout("$12" /*$t0*/) _,
129         lateout("$13" /*$t1*/) _,
130         lateout("$14" /*$t2*/) _,
131         lateout("$15" /*$t3*/) _,
132         lateout("$24" /*$t8*/) _,
133         lateout("$25" /*$t9*/) _,
134         options(nostack, preserves_flags)
135     );
136     FromAsm::from_asm(if err != 0 {
137         (x0 as usize).wrapping_neg() as *mut _
138     } else {
139         x0
140     })
141 }
142 
143 #[inline]
syscall2_readonly( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, ) -> RetReg<R0>144 pub(in crate::backend) unsafe fn syscall2_readonly(
145     nr: SyscallNumber<'_>,
146     a0: ArgReg<'_, A0>,
147     a1: ArgReg<'_, A1>,
148 ) -> RetReg<R0> {
149     let x0;
150     let err: usize;
151     asm!(
152         "syscall",
153         inlateout("$2" /*$v0*/) nr.to_asm() => x0,
154         in("$4" /*$a0*/) a0.to_asm(),
155         in("$5" /*$a1*/) a1.to_asm(),
156         lateout("$7" /*$a3*/) err,
157         lateout("$8" /*$a4*/) _,
158         lateout("$9" /*$a5*/) _,
159         lateout("$10" /*$a6*/) _,
160         lateout("$11" /*$a7*/) _,
161         lateout("$12" /*$t0*/) _,
162         lateout("$13" /*$t1*/) _,
163         lateout("$14" /*$t2*/) _,
164         lateout("$15" /*$t3*/) _,
165         lateout("$24" /*$t8*/) _,
166         lateout("$25" /*$t9*/) _,
167         options(nostack, preserves_flags, readonly)
168     );
169     FromAsm::from_asm(if err != 0 {
170         (x0 as usize).wrapping_neg() as *mut _
171     } else {
172         x0
173     })
174 }
175 
176 #[inline]
syscall3( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, ) -> RetReg<R0>177 pub(in crate::backend) unsafe fn syscall3(
178     nr: SyscallNumber<'_>,
179     a0: ArgReg<'_, A0>,
180     a1: ArgReg<'_, A1>,
181     a2: ArgReg<'_, A2>,
182 ) -> RetReg<R0> {
183     let x0;
184     let err: usize;
185     asm!(
186         "syscall",
187         inlateout("$2" /*$v0*/) nr.to_asm() => x0,
188         in("$4" /*$a0*/) a0.to_asm(),
189         in("$5" /*$a1*/) a1.to_asm(),
190         in("$6" /*$a2*/) a2.to_asm(),
191         lateout("$7" /*$a3*/) err,
192         lateout("$8" /*$a4*/) _,
193         lateout("$9" /*$a5*/) _,
194         lateout("$10" /*$a6*/) _,
195         lateout("$11" /*$a7*/) _,
196         lateout("$12" /*$t0*/) _,
197         lateout("$13" /*$t1*/) _,
198         lateout("$14" /*$t2*/) _,
199         lateout("$15" /*$t3*/) _,
200         lateout("$24" /*$t8*/) _,
201         lateout("$25" /*$t9*/) _,
202         options(nostack, preserves_flags)
203     );
204     FromAsm::from_asm(if err != 0 {
205         (x0 as usize).wrapping_neg() as *mut _
206     } else {
207         x0
208     })
209 }
210 
211 #[inline]
syscall3_readonly( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, ) -> RetReg<R0>212 pub(in crate::backend) unsafe fn syscall3_readonly(
213     nr: SyscallNumber<'_>,
214     a0: ArgReg<'_, A0>,
215     a1: ArgReg<'_, A1>,
216     a2: ArgReg<'_, A2>,
217 ) -> RetReg<R0> {
218     let x0;
219     let err: usize;
220     asm!(
221         "syscall",
222         inlateout("$2" /*$v0*/) nr.to_asm() => x0,
223         in("$4" /*$a0*/) a0.to_asm(),
224         in("$5" /*$a1*/) a1.to_asm(),
225         in("$6" /*$a2*/) a2.to_asm(),
226         lateout("$7" /*$a3*/) err,
227         lateout("$8" /*$a4*/) _,
228         lateout("$9" /*$a5*/) _,
229         lateout("$10" /*$a6*/) _,
230         lateout("$11" /*$a7*/) _,
231         lateout("$12" /*$t0*/) _,
232         lateout("$13" /*$t1*/) _,
233         lateout("$14" /*$t2*/) _,
234         lateout("$15" /*$t3*/) _,
235         lateout("$24" /*$t8*/) _,
236         lateout("$25" /*$t9*/) _,
237         options(nostack, preserves_flags, readonly)
238     );
239     FromAsm::from_asm(if err != 0 {
240         (x0 as usize).wrapping_neg() as *mut _
241     } else {
242         x0
243     })
244 }
245 
246 #[inline]
syscall4( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, ) -> RetReg<R0>247 pub(in crate::backend) unsafe fn syscall4(
248     nr: SyscallNumber<'_>,
249     a0: ArgReg<'_, A0>,
250     a1: ArgReg<'_, A1>,
251     a2: ArgReg<'_, A2>,
252     a3: ArgReg<'_, A3>,
253 ) -> RetReg<R0> {
254     let x0;
255     let err: usize;
256     asm!(
257         "syscall",
258         inlateout("$2" /*$v0*/) nr.to_asm() => x0,
259         in("$4" /*$a0*/) a0.to_asm(),
260         in("$5" /*$a1*/) a1.to_asm(),
261         in("$6" /*$a2*/) a2.to_asm(),
262         inlateout("$7" /*$a3*/) a3.to_asm() => err,
263         lateout("$8" /*$a4*/) _,
264         lateout("$9" /*$a5*/) _,
265         lateout("$10" /*$a6*/) _,
266         lateout("$11" /*$a7*/) _,
267         lateout("$12" /*$t0*/) _,
268         lateout("$13" /*$t1*/) _,
269         lateout("$14" /*$t2*/) _,
270         lateout("$15" /*$t3*/) _,
271         lateout("$24" /*$t8*/) _,
272         lateout("$25" /*$t9*/) _,
273         options(nostack, preserves_flags)
274     );
275     FromAsm::from_asm(if err != 0 {
276         (x0 as usize).wrapping_neg() as *mut _
277     } else {
278         x0
279     })
280 }
281 
282 #[inline]
syscall4_readonly( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, ) -> RetReg<R0>283 pub(in crate::backend) unsafe fn syscall4_readonly(
284     nr: SyscallNumber<'_>,
285     a0: ArgReg<'_, A0>,
286     a1: ArgReg<'_, A1>,
287     a2: ArgReg<'_, A2>,
288     a3: ArgReg<'_, A3>,
289 ) -> RetReg<R0> {
290     let x0;
291     let err: usize;
292     asm!(
293         "syscall",
294         inlateout("$2" /*$v0*/) nr.to_asm() => x0,
295         in("$4" /*$a0*/) a0.to_asm(),
296         in("$5" /*$a1*/) a1.to_asm(),
297         in("$6" /*$a2*/) a2.to_asm(),
298         inlateout("$7" /*$a3*/) a3.to_asm() => err,
299         lateout("$8" /*$a4*/) _,
300         lateout("$9" /*$a5*/) _,
301         lateout("$10" /*$a6*/) _,
302         lateout("$11" /*$a7*/) _,
303         lateout("$12" /*$t0*/) _,
304         lateout("$13" /*$t1*/) _,
305         lateout("$14" /*$t2*/) _,
306         lateout("$15" /*$t3*/) _,
307         lateout("$24" /*$t8*/) _,
308         lateout("$25" /*$t9*/) _,
309         options(nostack, preserves_flags, readonly)
310     );
311     FromAsm::from_asm(if err != 0 {
312         (x0 as usize).wrapping_neg() as *mut _
313     } else {
314         x0
315     })
316 }
317 
318 #[inline]
syscall5( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, ) -> RetReg<R0>319 pub(in crate::backend) unsafe fn syscall5(
320     nr: SyscallNumber<'_>,
321     a0: ArgReg<'_, A0>,
322     a1: ArgReg<'_, A1>,
323     a2: ArgReg<'_, A2>,
324     a3: ArgReg<'_, A3>,
325     a4: ArgReg<'_, A4>,
326 ) -> RetReg<R0> {
327     let x0;
328     let err: usize;
329     asm!(
330         "syscall",
331         inlateout("$2" /*$v0*/) nr.to_asm() => x0,
332         in("$4" /*$a0*/) a0.to_asm(),
333         in("$5" /*$a1*/) a1.to_asm(),
334         in("$6" /*$a2*/) a2.to_asm(),
335         inlateout("$7" /*$a3*/) a3.to_asm() => err,
336         inlateout("$8" /*$a4*/) a4.to_asm() => _,
337         lateout("$9" /*$a5*/) _,
338         lateout("$10" /*$a6*/) _,
339         lateout("$11" /*$a7*/) _,
340         lateout("$12" /*$t0*/) _,
341         lateout("$13" /*$t1*/) _,
342         lateout("$14" /*$t2*/) _,
343         lateout("$15" /*$t3*/) _,
344         lateout("$24" /*$t8*/) _,
345         lateout("$25" /*$t9*/) _,
346         options(nostack, preserves_flags)
347     );
348     FromAsm::from_asm(if err != 0 {
349         (x0 as usize).wrapping_neg() as *mut _
350     } else {
351         x0
352     })
353 }
354 
355 #[inline]
syscall5_readonly( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, ) -> RetReg<R0>356 pub(in crate::backend) unsafe fn syscall5_readonly(
357     nr: SyscallNumber<'_>,
358     a0: ArgReg<'_, A0>,
359     a1: ArgReg<'_, A1>,
360     a2: ArgReg<'_, A2>,
361     a3: ArgReg<'_, A3>,
362     a4: ArgReg<'_, A4>,
363 ) -> RetReg<R0> {
364     let x0;
365     let err: usize;
366     asm!(
367         "syscall",
368         inlateout("$2" /*$v0*/) nr.to_asm() => x0,
369         in("$4" /*$a0*/) a0.to_asm(),
370         in("$5" /*$a1*/) a1.to_asm(),
371         in("$6" /*$a2*/) a2.to_asm(),
372         inlateout("$7" /*$a3*/) a3.to_asm() => err,
373         inlateout("$8" /*$a4*/) a4.to_asm() => _,
374         lateout("$9" /*$a5*/) _,
375         lateout("$10" /*$a6*/) _,
376         lateout("$11" /*$a7*/) _,
377         lateout("$12" /*$t0*/) _,
378         lateout("$13" /*$t1*/) _,
379         lateout("$14" /*$t2*/) _,
380         lateout("$15" /*$t3*/) _,
381         lateout("$24" /*$t8*/) _,
382         lateout("$25" /*$t9*/) _,
383         options(nostack, preserves_flags, readonly)
384     );
385     FromAsm::from_asm(if err != 0 {
386         (x0 as usize).wrapping_neg() as *mut _
387     } else {
388         x0
389     })
390 }
391 
392 #[inline]
syscall6( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, a5: ArgReg<'_, A5>, ) -> RetReg<R0>393 pub(in crate::backend) unsafe fn syscall6(
394     nr: SyscallNumber<'_>,
395     a0: ArgReg<'_, A0>,
396     a1: ArgReg<'_, A1>,
397     a2: ArgReg<'_, A2>,
398     a3: ArgReg<'_, A3>,
399     a4: ArgReg<'_, A4>,
400     a5: ArgReg<'_, A5>,
401 ) -> RetReg<R0> {
402     let x0;
403     let err: usize;
404     asm!(
405         "syscall",
406         inlateout("$2" /*$v0*/) nr.to_asm() => x0,
407         in("$4" /*$a0*/) a0.to_asm(),
408         in("$5" /*$a1*/) a1.to_asm(),
409         in("$6" /*$a2*/) a2.to_asm(),
410         inlateout("$7" /*$a3*/) a3.to_asm() => err,
411         inlateout("$8" /*$a4*/) a4.to_asm() => _,
412         inlateout("$9" /*$a5*/) a5.to_asm() => _,
413         lateout("$10" /*$a6*/) _,
414         lateout("$11" /*$a7*/) _,
415         lateout("$12" /*$t0*/) _,
416         lateout("$13" /*$t1*/) _,
417         lateout("$14" /*$t2*/) _,
418         lateout("$15" /*$t3*/) _,
419         lateout("$24" /*$t8*/) _,
420         lateout("$25" /*$t9*/) _,
421         options(nostack, preserves_flags)
422     );
423     FromAsm::from_asm(if err != 0 {
424         (x0 as usize).wrapping_neg() as *mut _
425     } else {
426         x0
427     })
428 }
429 
430 #[inline]
syscall6_readonly( nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>, a1: ArgReg<'_, A1>, a2: ArgReg<'_, A2>, a3: ArgReg<'_, A3>, a4: ArgReg<'_, A4>, a5: ArgReg<'_, A5>, ) -> RetReg<R0>431 pub(in crate::backend) unsafe fn syscall6_readonly(
432     nr: SyscallNumber<'_>,
433     a0: ArgReg<'_, A0>,
434     a1: ArgReg<'_, A1>,
435     a2: ArgReg<'_, A2>,
436     a3: ArgReg<'_, A3>,
437     a4: ArgReg<'_, A4>,
438     a5: ArgReg<'_, A5>,
439 ) -> RetReg<R0> {
440     let x0;
441     let err: usize;
442     asm!(
443         "syscall",
444         inlateout("$2" /*$v0*/) nr.to_asm() => x0,
445         in("$4" /*$a0*/) a0.to_asm(),
446         in("$5" /*$a1*/) a1.to_asm(),
447         in("$6" /*$a2*/) a2.to_asm(),
448         inlateout("$7" /*$a3*/) a3.to_asm() => err,
449         inlateout("$8" /*$a4*/) a4.to_asm() => _,
450         inlateout("$9" /*$a5*/) a5.to_asm() => _,
451         lateout("$10" /*$a6*/) _,
452         lateout("$11" /*$a7*/) _,
453         lateout("$12" /*$t0*/) _,
454         lateout("$13" /*$t1*/) _,
455         lateout("$14" /*$t2*/) _,
456         lateout("$15" /*$t3*/) _,
457         lateout("$24" /*$t8*/) _,
458         lateout("$25" /*$t9*/) _,
459         options(nostack, preserves_flags, readonly)
460     );
461     FromAsm::from_asm(if err != 0 {
462         (x0 as usize).wrapping_neg() as *mut _
463     } else {
464         x0
465     })
466 }
467