1 //! Syscall wrappers for platforms which pass the syscall number specially.
3 //! Rustix aims to minimize the amount of assembly code it needs. To that end,
4 //! this code reorders syscall arguments as close as feasible to the actual
5 //! syscall convention before calling the assembly functions.
7 //! Many architectures use a convention where the syscall number is passed in a
8 //! special register, with the regular syscall arguments passed in either the
9 //! same or similar registers as the platform C convention. This code
10 //! approximates that order by passing the regular syscall arguments first, and
11 //! the syscall number last. That way, the outline assembly code typically just
12 //! needs to move the syscall number to its special register, and leave the
13 //! other arguments mostly as they are.
15 #[cfg(target_arch = "mips")]
16 use crate::backend
::reg
::A6
;
17 use crate::backend
::reg
::{ArgReg, RetReg, SyscallNumber, A0, A1, A2, A3, A4, A5, R0}
;
19 // First we declare the actual assembly routines with `*_nr_last` names and
20 // reordered arguments. If the signatures or calling conventions are ever
21 // changed, the symbol names should also be updated accordingly, to avoid
22 // collisions with other versions of this crate.
24 // We don't define `_readonly` versions of these because we have no way to tell
25 // Rust that calls to our outline assembly are readonly.
27 fn rustix_syscall0_nr_last(nr
: SyscallNumber
<'_
>) -> RetReg
<R0
>;
28 fn rustix_syscall1_nr_last(a0
: ArgReg
<'_
, A0
>, nr
: SyscallNumber
<'_
>) -> RetReg
<R0
>;
29 fn rustix_syscall1_noreturn_nr_last(a0
: ArgReg
<'_
, A0
>, nr
: SyscallNumber
<'_
>) -> !;
30 fn rustix_syscall2_nr_last(
33 nr
: SyscallNumber
<'_
>,
35 fn rustix_syscall3_nr_last(
39 nr
: SyscallNumber
<'_
>,
41 fn rustix_syscall4_nr_last(
46 nr
: SyscallNumber
<'_
>,
48 fn rustix_syscall5_nr_last(
54 nr
: SyscallNumber
<'_
>,
56 fn rustix_syscall6_nr_last(
63 nr
: SyscallNumber
<'_
>,
65 #[cfg(target_arch = "mips")]
66 fn rustix_syscall7_nr_last(
74 nr
: SyscallNumber
<'_
>,
78 // Then we define inline wrapper functions that do the reordering.
81 pub(in crate::backend
) unsafe fn syscall0(nr
: SyscallNumber
<'_
>) -> RetReg
<R0
> {
82 rustix_syscall0_nr_last(nr
)
85 pub(in crate::backend
) unsafe fn syscall1(nr
: SyscallNumber
<'_
>, a0
: ArgReg
<'_
, A0
>) -> RetReg
<R0
> {
86 rustix_syscall1_nr_last(a0
, nr
)
89 pub(in crate::backend
) unsafe fn syscall1_noreturn(nr
: SyscallNumber
<'_
>, a0
: ArgReg
<'_
, A0
>) -> ! {
90 rustix_syscall1_noreturn_nr_last(a0
, nr
)
93 pub(in crate::backend
) unsafe fn syscall2(
94 nr
: SyscallNumber
<'_
>,
98 rustix_syscall2_nr_last(a0
, a1
, nr
)
101 pub(in crate::backend
) unsafe fn syscall3(
102 nr
: SyscallNumber
<'_
>,
107 rustix_syscall3_nr_last(a0
, a1
, a2
, nr
)
110 pub(in crate::backend
) unsafe fn syscall4(
111 nr
: SyscallNumber
<'_
>,
117 rustix_syscall4_nr_last(a0
, a1
, a2
, a3
, nr
)
120 pub(in crate::backend
) unsafe fn syscall5(
121 nr
: SyscallNumber
<'_
>,
128 rustix_syscall5_nr_last(a0
, a1
, a2
, a3
, a4
, nr
)
131 pub(in crate::backend
) unsafe fn syscall6(
132 nr
: SyscallNumber
<'_
>,
140 rustix_syscall6_nr_last(a0
, a1
, a2
, a3
, a4
, a5
, nr
)
142 #[cfg(target_arch = "mips")]
144 pub(in crate::backend
) unsafe fn syscall7(
145 nr
: SyscallNumber
<'_
>,
154 rustix_syscall7_nr_last(a0
, a1
, a2
, a3
, a4
, a5
, a6
, nr
)
157 // Then we define the `_readonly` versions of the wrappers. We don't have
158 // separate `_readonly` implementations, so these can just be aliases to
159 // their non-`_readonly` counterparts.
160 #[cfg(target_arch = "mips")]
161 pub(in crate::backend
) use syscall7
as syscall7_readonly
;
162 pub(in crate::backend
) use {
163 syscall0
as syscall0_readonly
, syscall1
as syscall1_readonly
, syscall2
as syscall2_readonly
,
164 syscall3
as syscall3_readonly
, syscall4
as syscall4_readonly
, syscall5
as syscall5_readonly
,
165 syscall6
as syscall6_readonly
,