summaryrefslogtreecommitdiffstats
path: root/vendor/rustix/src/imp/linux_raw/arch/outline/nr_last.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rustix/src/imp/linux_raw/arch/outline/nr_last.rs')
-rw-r--r--vendor/rustix/src/imp/linux_raw/arch/outline/nr_last.rs166
1 files changed, 166 insertions, 0 deletions
diff --git a/vendor/rustix/src/imp/linux_raw/arch/outline/nr_last.rs b/vendor/rustix/src/imp/linux_raw/arch/outline/nr_last.rs
new file mode 100644
index 000000000..fdcd11021
--- /dev/null
+++ b/vendor/rustix/src/imp/linux_raw/arch/outline/nr_last.rs
@@ -0,0 +1,166 @@
+//! Syscall wrappers for platforms which pass the syscall number specially.
+//!
+//! Rustix aims to minimize the amount of assembly code it needs. To that end,
+//! this code reorders syscall arguments as close as feasible to the actual
+//! syscall convention before calling the assembly functions.
+//!
+//! Many architectures use a convention where the syscall number is passed in a
+//! special register, with the regular syscall arguments passed in either the
+//! same or similar registers as the platform C convention. This code
+//! approximates that order by passing the regular syscall arguments first, and
+//! the syscall number last. That way, the outline assembly code typically just
+//! needs to move the syscall number to its special register, and leave the
+//! other arguments mostly as they are.
+
+#[cfg(target_arch = "mips")]
+use crate::imp::reg::A6;
+use crate::imp::reg::{ArgReg, RetReg, SyscallNumber, A0, A1, A2, A3, A4, A5, R0};
+
+// First we declare the actual assembly routines with `*_nr_last` names and
+// reordered arguments. If the signatures or calling conventions are ever
+// changed, the symbol names should also be updated accordingly, to avoid
+// collisions with other versions of this crate.
+//
+// We don't define `_readonly` versions of these because we have no way to tell
+// Rust that calls to our outline assembly are readonly.
+extern "C" {
+ fn rustix_syscall0_nr_last(nr: SyscallNumber<'_>) -> RetReg<R0>;
+ fn rustix_syscall1_nr_last(a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>) -> RetReg<R0>;
+ fn rustix_syscall1_noreturn_nr_last(a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>) -> !;
+ fn rustix_syscall2_nr_last(
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ nr: SyscallNumber<'_>,
+ ) -> RetReg<R0>;
+ fn rustix_syscall3_nr_last(
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ nr: SyscallNumber<'_>,
+ ) -> RetReg<R0>;
+ fn rustix_syscall4_nr_last(
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ nr: SyscallNumber<'_>,
+ ) -> RetReg<R0>;
+ fn rustix_syscall5_nr_last(
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ nr: SyscallNumber<'_>,
+ ) -> RetReg<R0>;
+ fn rustix_syscall6_nr_last(
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+ nr: SyscallNumber<'_>,
+ ) -> RetReg<R0>;
+ #[cfg(target_arch = "mips")]
+ fn rustix_syscall7_nr_last(
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+ a6: ArgReg<'_, A6>,
+ nr: SyscallNumber<'_>,
+ ) -> RetReg<R0>;
+}
+
+// Then we define inline wrapper functions that do the reordering.
+
+#[inline]
+pub(in crate::imp) unsafe fn syscall0(nr: SyscallNumber<'_>) -> RetReg<R0> {
+ rustix_syscall0_nr_last(nr)
+}
+#[inline]
+pub(in crate::imp) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
+ rustix_syscall1_nr_last(a0, nr)
+}
+#[inline]
+pub(in crate::imp) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
+ rustix_syscall1_noreturn_nr_last(a0, nr)
+}
+#[inline]
+pub(in crate::imp) unsafe fn syscall2(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+ rustix_syscall2_nr_last(a0, a1, nr)
+}
+#[inline]
+pub(in crate::imp) unsafe fn syscall3(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+ rustix_syscall3_nr_last(a0, a1, a2, nr)
+}
+#[inline]
+pub(in crate::imp) unsafe fn syscall4(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+ rustix_syscall4_nr_last(a0, a1, a2, a3, nr)
+}
+#[inline]
+pub(in crate::imp) unsafe fn syscall5(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+ rustix_syscall5_nr_last(a0, a1, a2, a3, a4, nr)
+}
+#[inline]
+pub(in crate::imp) unsafe fn syscall6(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+) -> RetReg<R0> {
+ rustix_syscall6_nr_last(a0, a1, a2, a3, a4, a5, nr)
+}
+#[cfg(target_arch = "mips")]
+#[inline]
+pub(in crate::imp) unsafe fn syscall7(
+ nr: SyscallNumber<'_>,
+ a0: ArgReg<'_, A0>,
+ a1: ArgReg<'_, A1>,
+ a2: ArgReg<'_, A2>,
+ a3: ArgReg<'_, A3>,
+ a4: ArgReg<'_, A4>,
+ a5: ArgReg<'_, A5>,
+ a6: ArgReg<'_, A6>,
+) -> RetReg<R0> {
+ rustix_syscall7_nr_last(a0, a1, a2, a3, a4, a5, a6, nr)
+}
+
+// Then we define the `_readonly` versions of the wrappers. We don't have
+// separate `_readonly` implementations, so these can just be aliases to
+// their non-`_readonly` counterparts.
+#[cfg(target_arch = "mips")]
+pub(in crate::imp) use syscall7 as syscall7_readonly;
+pub(in crate::imp) use {
+ syscall0 as syscall0_readonly, syscall1 as syscall1_readonly, syscall2 as syscall2_readonly,
+ syscall3 as syscall3_readonly, syscall4 as syscall4_readonly, syscall5 as syscall5_readonly,
+ syscall6 as syscall6_readonly,
+};