From 1b6a04ca5504955c571d1c97504fb45ea0befee4 Mon Sep 17 00:00:00 2001
From: Valentin Popov <valentin@popov.link>
Date: Mon, 8 Jan 2024 01:21:28 +0400
Subject: Initial vendor packages

Signed-off-by: Valentin Popov <valentin@popov.link>
---
 vendor/rustix/src/backend/linux_raw/arch/x86.rs | 489 ++++++++++++++++++++++++
 1 file changed, 489 insertions(+)
 create mode 100644 vendor/rustix/src/backend/linux_raw/arch/x86.rs

(limited to 'vendor/rustix/src/backend/linux_raw/arch/x86.rs')

diff --git a/vendor/rustix/src/backend/linux_raw/arch/x86.rs b/vendor/rustix/src/backend/linux_raw/arch/x86.rs
new file mode 100644
index 0000000..e789181
--- /dev/null
+++ b/vendor/rustix/src/backend/linux_raw/arch/x86.rs
@@ -0,0 +1,489 @@
+//! 32-bit x86 Linux system calls.
+//!
+//! There are two forms; `indirect_*` which take a callee, which allow calling
+//! through the vDSO when possible, and plain forms, which use the `int 0x80`
+//! instruction.
+//!
+//! Most `rustix` syscalls use the vsyscall mechanism rather than going using
+//! `int 0x80` sequences, as vsyscall is much faster.
+//!
+//! Syscalls made with `int 0x80` preserve the flags register, while syscalls
+//! made using vsyscall do not.
+
+#![allow(dead_code)]
+
+use crate::backend::reg::{
+    ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0,
+};
+use crate::backend::vdso_wrappers::SyscallType;
+use core::arch::asm;
+
+#[inline]
+pub(in crate::backend) unsafe fn indirect_syscall0(
+    callee: SyscallType,
+    nr: SyscallNumber<'_>,
+) -> RetReg<R0> {
+    let r0;
+    asm!(
+        "call {callee}",
+        callee = in(reg) callee,
+        inlateout("eax") nr.to_asm() => r0,
+    );
+    FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::backend) unsafe fn indirect_syscall1(
+    callee: SyscallType,
+    nr: SyscallNumber<'_>,
+    a0: ArgReg<'_, A0>,
+) -> RetReg<R0> {
+    let r0;
+    asm!(
+        "call {callee}",
+        callee = in(reg) callee,
+        inlateout("eax") nr.to_asm() => r0,
+        in("ebx") a0.to_asm(),
+    );
+    FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::backend) unsafe fn indirect_syscall1_noreturn(
+    callee: SyscallType,
+    nr: SyscallNumber<'_>,
+    a0: ArgReg<'_, A0>,
+) -> ! {
+    asm!(
+        "call {callee}",
+        callee = in(reg) callee,
+        in("eax") nr.to_asm(),
+        in("ebx") a0.to_asm(),
+        options(noreturn)
+    )
+}
+
+#[inline]
+pub(in crate::backend) unsafe fn indirect_syscall2(
+    callee: SyscallType,
+    nr: SyscallNumber<'_>,
+    a0: ArgReg<'_, A0>,
+    a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+    let r0;
+    asm!(
+        "call {callee}",
+        callee = in(reg) callee,
+        inlateout("eax") nr.to_asm() => r0,
+        in("ebx") a0.to_asm(),
+        in("ecx") a1.to_asm(),
+    );
+    FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::backend) unsafe fn indirect_syscall3(
+    callee: SyscallType,
+    nr: SyscallNumber<'_>,
+    a0: ArgReg<'_, A0>,
+    a1: ArgReg<'_, A1>,
+    a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+    let r0;
+    asm!(
+        "call {callee}",
+        callee = in(reg) callee,
+        inlateout("eax") nr.to_asm() => r0,
+        in("ebx") a0.to_asm(),
+        in("ecx") a1.to_asm(),
+        in("edx") a2.to_asm(),
+    );
+    FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::backend) unsafe fn indirect_syscall4(
+    callee: SyscallType,
+    nr: SyscallNumber<'_>,
+    a0: ArgReg<'_, A0>,
+    a1: ArgReg<'_, A1>,
+    a2: ArgReg<'_, A2>,
+    a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+    let r0;
+    // a3 should go in esi, but `asm!` won't let us use it as an operand.
+    // Temporarily swap it into place, and then swap it back afterward.
+    //
+    // We hard-code the callee operand to use edi instead of `in(reg)` because
+    // even though we can't name esi as an operand, the compiler can use esi to
+    // satisfy `in(reg)`.
+    asm!(
+        "xchg esi, {a3}",
+        "call edi",
+        "xchg esi, {a3}",
+        a3 = in(reg) a3.to_asm(),
+        in("edi") callee,
+        inlateout("eax") nr.to_asm() => r0,
+        in("ebx") a0.to_asm(),
+        in("ecx") a1.to_asm(),
+        in("edx") a2.to_asm(),
+    );
+    FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::backend) unsafe fn indirect_syscall5(
+    callee: SyscallType,
+    nr: SyscallNumber<'_>,
+    a0: ArgReg<'_, A0>,
+    a1: ArgReg<'_, A1>,
+    a2: ArgReg<'_, A2>,
+    a3: ArgReg<'_, A3>,
+    a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+    let r0;
+    // Oof. a3 should go in esi, and `asm!` won't let us use that register as
+    // an operand. And we can't request stack slots. And there are no other
+    // registers free. Use eax as a temporary pointer to a slice, since it gets
+    // clobbered as the return value anyway.
+    asm!(
+        "push esi",
+        "push [eax + 0]",
+        "mov esi, [eax + 4]",
+        "mov eax, [eax + 8]",
+        "call [esp]",
+        "pop esi",
+        "pop esi",
+        inout("eax") &[callee as _, a3.to_asm(), nr.to_asm()] => r0,
+        in("ebx") a0.to_asm(),
+        in("ecx") a1.to_asm(),
+        in("edx") a2.to_asm(),
+        in("edi") a4.to_asm(),
+    );
+    FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::backend) unsafe fn indirect_syscall6(
+    callee: SyscallType,
+    nr: SyscallNumber<'_>,
+    a0: ArgReg<'_, A0>,
+    a1: ArgReg<'_, A1>,
+    a2: ArgReg<'_, A2>,
+    a3: ArgReg<'_, A3>,
+    a4: ArgReg<'_, A4>,
+    a5: ArgReg<'_, A5>,
+) -> RetReg<R0> {
+    let r0;
+    // Oof again. a3 should go in esi, and a5 should go in ebp, and `asm!`
+    // won't let us use either of those registers as operands. And we can't
+    // request stack slots. And there are no other registers free. Use eax as a
+    // temporary pointer to a slice, since it gets clobbered as the return
+    // value anyway.
+    //
+    // This is another reason that syscalls should be compiler intrinsics
+    // rather than inline asm.
+    asm!(
+        "push ebp",
+        "push esi",
+        "push [eax + 0]",
+        "mov esi, [eax + 4]",
+        "mov ebp, [eax + 8]",
+        "mov eax, [eax + 12]",
+        "call [esp]",
+        "pop esi",
+        "pop esi",
+        "pop ebp",
+        inout("eax") &[callee as _, a3.to_asm(), a5.to_asm(), nr.to_asm()] => r0,
+        in("ebx") a0.to_asm(),
+        in("ecx") a1.to_asm(),
+        in("edx") a2.to_asm(),
+        in("edi") a4.to_asm(),
+    );
+    FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::backend) unsafe fn syscall0_readonly(nr: SyscallNumber<'_>) -> RetReg<R0> {
+    let r0;
+    asm!(
+        "int $$0x80",
+        inlateout("eax") nr.to_asm() => r0,
+        options(nostack, preserves_flags, readonly)
+    );
+    FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::backend) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
+    let r0;
+    asm!(
+        "int $$0x80",
+        inlateout("eax") nr.to_asm() => r0,
+        in("ebx") a0.to_asm(),
+        options(nostack, preserves_flags)
+    );
+    FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::backend) unsafe fn syscall1_readonly(
+    nr: SyscallNumber<'_>,
+    a0: ArgReg<'_, A0>,
+) -> RetReg<R0> {
+    let r0;
+    asm!(
+        "int $$0x80",
+        inlateout("eax") nr.to_asm() => r0,
+        in("ebx") a0.to_asm(),
+        options(nostack, preserves_flags, readonly)
+    );
+    FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
+    asm!(
+        "int $$0x80",
+        in("eax") nr.to_asm(),
+        in("ebx") a0.to_asm(),
+        options(nostack, noreturn)
+    )
+}
+
+#[inline]
+pub(in crate::backend) unsafe fn syscall2(
+    nr: SyscallNumber<'_>,
+    a0: ArgReg<'_, A0>,
+    a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+    let r0;
+    asm!(
+        "int $$0x80",
+        inlateout("eax") nr.to_asm() => r0,
+        in("ebx") a0.to_asm(),
+        in("ecx") a1.to_asm(),
+        options(nostack, preserves_flags)
+    );
+    FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::backend) unsafe fn syscall2_readonly(
+    nr: SyscallNumber<'_>,
+    a0: ArgReg<'_, A0>,
+    a1: ArgReg<'_, A1>,
+) -> RetReg<R0> {
+    let r0;
+    asm!(
+        "int $$0x80",
+        inlateout("eax") nr.to_asm() => r0,
+        in("ebx") a0.to_asm(),
+        in("ecx") a1.to_asm(),
+        options(nostack, preserves_flags, readonly)
+    );
+    FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::backend) unsafe fn syscall3(
+    nr: SyscallNumber<'_>,
+    a0: ArgReg<'_, A0>,
+    a1: ArgReg<'_, A1>,
+    a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+    let r0;
+    asm!(
+        "int $$0x80",
+        inlateout("eax") nr.to_asm() => r0,
+        in("ebx") a0.to_asm(),
+        in("ecx") a1.to_asm(),
+        in("edx") a2.to_asm(),
+        options(nostack, preserves_flags)
+    );
+    FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::backend) unsafe fn syscall3_readonly(
+    nr: SyscallNumber<'_>,
+    a0: ArgReg<'_, A0>,
+    a1: ArgReg<'_, A1>,
+    a2: ArgReg<'_, A2>,
+) -> RetReg<R0> {
+    let r0;
+    asm!(
+        "int $$0x80",
+        inlateout("eax") nr.to_asm() => r0,
+        in("ebx") a0.to_asm(),
+        in("ecx") a1.to_asm(),
+        in("edx") a2.to_asm(),
+        options(nostack, preserves_flags, readonly)
+    );
+    FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::backend) unsafe fn syscall4(
+    nr: SyscallNumber<'_>,
+    a0: ArgReg<'_, A0>,
+    a1: ArgReg<'_, A1>,
+    a2: ArgReg<'_, A2>,
+    a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+    let r0;
+    // a3 should go in esi, but `asm!` won't let us use it as an operand.
+    // Temporarily swap it into place, and then swap it back afterward.
+    asm!(
+        "xchg esi, {a3}",
+        "int $$0x80",
+        "xchg esi, {a3}",
+        a3 = in(reg) a3.to_asm(),
+        inlateout("eax") nr.to_asm() => r0,
+        in("ebx") a0.to_asm(),
+        in("ecx") a1.to_asm(),
+        in("edx") a2.to_asm(),
+        options(nostack, preserves_flags)
+    );
+    FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::backend) unsafe fn syscall4_readonly(
+    nr: SyscallNumber<'_>,
+    a0: ArgReg<'_, A0>,
+    a1: ArgReg<'_, A1>,
+    a2: ArgReg<'_, A2>,
+    a3: ArgReg<'_, A3>,
+) -> RetReg<R0> {
+    let r0;
+    asm!(
+        "xchg esi, {a3}",
+        "int $$0x80",
+        "xchg esi, {a3}",
+        a3 = in(reg) a3.to_asm(),
+        inlateout("eax") nr.to_asm() => r0,
+        in("ebx") a0.to_asm(),
+        in("ecx") a1.to_asm(),
+        in("edx") a2.to_asm(),
+        options(nostack, preserves_flags, readonly)
+    );
+    FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::backend) unsafe fn syscall5(
+    nr: SyscallNumber<'_>,
+    a0: ArgReg<'_, A0>,
+    a1: ArgReg<'_, A1>,
+    a2: ArgReg<'_, A2>,
+    a3: ArgReg<'_, A3>,
+    a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+    let r0;
+    // As in `syscall4`, use xchg to handle a3. a4 should go in edi, and we can
+    // use that register as an operand. Unlike in `indirect_syscall5`, we don't
+    // have a `callee` operand taking up a register, so we have enough
+    // registers and don't need to use a slice.
+    asm!(
+        "xchg esi, {a3}",
+        "int $$0x80",
+        "xchg esi, {a3}",
+        a3 = in(reg) a3.to_asm(),
+        inlateout("eax") nr.to_asm() => r0,
+        in("ebx") a0.to_asm(),
+        in("ecx") a1.to_asm(),
+        in("edx") a2.to_asm(),
+        in("edi") a4.to_asm(),
+        options(nostack, preserves_flags)
+    );
+    FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::backend) unsafe fn syscall5_readonly(
+    nr: SyscallNumber<'_>,
+    a0: ArgReg<'_, A0>,
+    a1: ArgReg<'_, A1>,
+    a2: ArgReg<'_, A2>,
+    a3: ArgReg<'_, A3>,
+    a4: ArgReg<'_, A4>,
+) -> RetReg<R0> {
+    let r0;
+    // See the comments in `syscall5`.
+    asm!(
+        "xchg esi, {a3}",
+        "int $$0x80",
+        "xchg esi, {a3}",
+        a3 = in(reg) a3.to_asm(),
+        inlateout("eax") nr.to_asm() => r0,
+        in("ebx") a0.to_asm(),
+        in("ecx") a1.to_asm(),
+        in("edx") a2.to_asm(),
+        in("edi") a4.to_asm(),
+        options(nostack, preserves_flags, readonly)
+    );
+    FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::backend) 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> {
+    let r0;
+    // See the comments in `indirect_syscall6`.
+    asm!(
+        "push ebp",
+        "push esi",
+        "mov esi, [eax + 0]",
+        "mov ebp, [eax + 4]",
+        "mov eax, [eax + 8]",
+        "int $$0x80",
+        "pop esi",
+        "pop ebp",
+        inout("eax") &[a3.to_asm(), a5.to_asm(), nr.to_asm()] => r0,
+        in("ebx") a0.to_asm(),
+        in("ecx") a1.to_asm(),
+        in("edx") a2.to_asm(),
+        in("edi") a4.to_asm(),
+        options(preserves_flags)
+    );
+    FromAsm::from_asm(r0)
+}
+
+#[inline]
+pub(in crate::backend) unsafe fn syscall6_readonly(
+    nr: SyscallNumber<'_>,
+    a0: ArgReg<'_, A0>,
+    a1: ArgReg<'_, A1>,
+    a2: ArgReg<'_, A2>,
+    a3: ArgReg<'_, A3>,
+    a4: ArgReg<'_, A4>,
+    a5: ArgReg<'_, A5>,
+) -> RetReg<R0> {
+    let r0;
+    // See the comments in `indirect_syscall6`.
+    asm!(
+        "push ebp",
+        "push esi",
+        "mov esi, [eax + 0]",
+        "mov ebp, [eax + 4]",
+        "mov eax, [eax + 8]",
+        "int $$0x80",
+        "pop esi",
+        "pop ebp",
+        inout("eax") &[a3.to_asm(), a5.to_asm(), nr.to_asm()] => r0,
+        in("ebx") a0.to_asm(),
+        in("ecx") a1.to_asm(),
+        in("edx") a2.to_asm(),
+        in("edi") a4.to_asm(),
+        options(preserves_flags, readonly)
+    );
+    FromAsm::from_asm(r0)
+}
-- 
cgit v1.2.3