Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid redundant instructions in x86 inline asm #233

Merged
merged 3 commits into from
Feb 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 10 additions & 32 deletions src/imp/linux_raw/arch/inline/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,14 @@
//! much like regular calls, with custom calling conventions, and calling
//! conventions are otherwise the compiler's job. But for now, use inline asm.

#[cfg(target_arch = "aarch64")]
mod aarch64;
#[cfg(target_arch = "arm")]
mod arm;
#[cfg(target_arch = "mips")]
mod mips;
#[cfg(target_arch = "mips64")]
mod mips64;
#[cfg(target_arch = "powerpc64")]
mod powerpc64;
#[cfg(target_arch = "riscv64")]
mod riscv64;
#[cfg(target_arch = "x86")]
mod x86;
#[cfg(target_arch = "x86_64")]
mod x86_64;
#[cfg_attr(target_arch = "aarch64", path = "aarch64.rs")]
#[cfg_attr(target_arch = "arm", path = "arm.rs")]
#[cfg_attr(target_arch = "mips", path = "mips.rs")]
#[cfg_attr(target_arch = "mips64", path = "mips64.rs")]
#[cfg_attr(target_arch = "powerpc64", path = "powerpc64.rs")]
#[cfg_attr(target_arch = "riscv64", path = "riscv64.rs")]
#[cfg_attr(target_arch = "x86", path = "x86.rs")]
#[cfg_attr(target_arch = "x86_64", path = "x86_64.rs")]
mod target_arch;

#[cfg(target_arch = "aarch64")]
pub(in crate::imp) use self::aarch64::*;
#[cfg(target_arch = "arm")]
pub(in crate::imp) use self::arm::*;
#[cfg(target_arch = "mips")]
pub(in crate::imp) use self::mips::*;
#[cfg(target_arch = "mips64")]
pub(in crate::imp) use self::mips64::*;
#[cfg(target_arch = "powerpc64")]
pub(in crate::imp) use self::powerpc64::*;
#[cfg(target_arch = "riscv64")]
pub(in crate::imp) use self::riscv64::*;
#[cfg(target_arch = "x86")]
pub(in crate::imp) use self::x86::*;
#[cfg(target_arch = "x86_64")]
pub(in crate::imp) use self::x86_64::*;
pub(in crate::imp) use self::target_arch::*;
19 changes: 7 additions & 12 deletions src/imp/linux_raw/arch/inline/x86.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,15 +153,13 @@ pub(in crate::imp) unsafe fn indirect_syscall5(
// registers free. Use eax as a temporary pointer to a slice, since it
// gets clobbered as the return value anyway.
asm!(
"push ebp",
"push esi",
"push DWORD PTR [eax + 0]",
"mov esi, DWORD PTR [eax + 4]",
"mov eax, DWORD PTR [eax + 8]",
"call DWORD PTR [esp]",
"pop esi",
"pop esi",
"pop ebp",
inout("eax") &[callee as usize, a3.to_asm(), nr.to_asm()] => r0,
in("ebx") a0.to_asm(),
in("ecx") a1.to_asm(),
Expand Down Expand Up @@ -402,8 +400,10 @@ pub(in crate::imp) unsafe fn syscall5(
a4: ArgReg<'_, A4>,
) -> RetReg<R0> {
let r0;
// As in syscall 4, use xchg to handle a3. a4 should go in edi, and
// we can use that register as an operand.
// 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",
Expand All @@ -430,6 +430,7 @@ pub(in crate::imp) unsafe fn syscall5_readonly(
a4: ArgReg<'_, A4>,
) -> RetReg<R0> {
let r0;
// See the comments in `syscall5`.
asm!(
"xchg esi, {a3}",
"int $$0x80",
Expand Down Expand Up @@ -457,14 +458,7 @@ pub(in crate::imp) unsafe fn syscall6(
a5: ArgReg<'_, A5>,
) -> RetReg<R0> {
let r0;
// Oof. 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.
// See the comments in `indirect_syscall6`.
asm!(
"push ebp",
"push esi",
Expand Down Expand Up @@ -496,6 +490,7 @@ pub(in crate::imp) unsafe fn syscall6_readonly(
a5: ArgReg<'_, A5>,
) -> RetReg<R0> {
let r0;
// See the comments in `indirect_syscall6`.
asm!(
"push ebp",
"push esi",
Expand Down