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