blob: b39a168474723f73154f8cb7e4c11e1368ccf5f1 [file] [log] [blame]
//! mipsel Linux system calls.
//!
//! On mipsel, Linux indicates success or failure using `$a3` rather
//! than by returning a negative error code as most other architectures do.
//!
//! Mips-family platforms have a special calling convention for `__NR_pipe`,
//! however we use `__NR_pipe2` instead to avoid having to implement it.
use crate::backend::reg::{
ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, A6, R0,
};
use core::arch::asm;
#[inline]
pub(in crate::backend) unsafe fn syscall0_readonly(nr: SyscallNumber) -> RetReg<R0> {
let x0;
let err: usize;
asm!(
"syscall",
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
lateout("$7" /*$a3*/) err,
lateout("$8" /*$t0*/) _,
lateout("$9" /*$t1*/) _,
lateout("$10" /*$t2*/) _,
lateout("$11" /*$t3*/) _,
lateout("$12" /*$t4*/) _,
lateout("$13" /*$t5*/) _,
lateout("$14" /*$t6*/) _,
lateout("$15" /*$t7*/) _,
lateout("$24" /*$t8*/) _,
lateout("$25" /*$t9*/) _,
options(nostack, preserves_flags, readonly)
);
FromAsm::from_asm(if err != 0 {
(x0 as usize).wrapping_neg() as *mut _
} else {
x0
})
}
#[inline]
pub(in crate::backend) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
let x0;
let err: usize;
asm!(
"syscall",
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
in("$4" /*$a0*/) a0.to_asm(),
lateout("$7" /*$a3*/) err,
lateout("$8" /*$t0*/) _,
lateout("$9" /*$t1*/) _,
lateout("$10" /*$t2*/) _,
lateout("$11" /*$t3*/) _,
lateout("$12" /*$t4*/) _,
lateout("$13" /*$t5*/) _,
lateout("$14" /*$t6*/) _,
lateout("$15" /*$t7*/) _,
lateout("$24" /*$t8*/) _,
lateout("$25" /*$t9*/) _,
options(nostack, preserves_flags)
);
FromAsm::from_asm(if err != 0 {
(x0 as usize).wrapping_neg() as *mut _
} else {
x0
})
}
#[inline]
pub(in crate::backend) unsafe fn syscall1_readonly(
nr: SyscallNumber<'_>,
a0: ArgReg<'_, A0>,
) -> RetReg<R0> {
let x0;
let err: usize;
asm!(
"syscall",
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
in("$4" /*$a0*/) a0.to_asm(),
lateout("$7" /*$a3*/) err,
lateout("$8" /*$t0*/) _,
lateout("$9" /*$t1*/) _,
lateout("$10" /*$t2*/) _,
lateout("$11" /*$t3*/) _,
lateout("$12" /*$t4*/) _,
lateout("$13" /*$t5*/) _,
lateout("$14" /*$t6*/) _,
lateout("$15" /*$t7*/) _,
lateout("$24" /*$t8*/) _,
lateout("$25" /*$t9*/) _,
options(nostack, preserves_flags, readonly)
);
FromAsm::from_asm(if err != 0 {
(x0 as usize).wrapping_neg() as *mut _
} else {
x0
})
}
#[inline]
pub(in crate::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
asm!(
"syscall",
in("$2" /*$v0*/) nr.to_asm(),
in("$4" /*$a0*/) a0.to_asm(),
options(noreturn)
)
}
#[inline]
pub(in crate::backend) unsafe fn syscall2(
nr: SyscallNumber<'_>,
a0: ArgReg<'_, A0>,
a1: ArgReg<'_, A1>,
) -> RetReg<R0> {
let x0;
let err: usize;
asm!(
"syscall",
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
in("$4" /*$a0*/) a0.to_asm(),
in("$5" /*$a1*/) a1.to_asm(),
lateout("$7" /*$a3*/) err,
lateout("$8" /*$t0*/) _,
lateout("$9" /*$t1*/) _,
lateout("$10" /*$t2*/) _,
lateout("$11" /*$t3*/) _,
lateout("$12" /*$t4*/) _,
lateout("$13" /*$t5*/) _,
lateout("$14" /*$t6*/) _,
lateout("$15" /*$t7*/) _,
lateout("$24" /*$t8*/) _,
lateout("$25" /*$t9*/) _,
options(nostack, preserves_flags)
);
FromAsm::from_asm(if err != 0 {
(x0 as usize).wrapping_neg() as *mut _
} else {
x0
})
}
#[inline]
pub(in crate::backend) unsafe fn syscall2_readonly(
nr: SyscallNumber<'_>,
a0: ArgReg<'_, A0>,
a1: ArgReg<'_, A1>,
) -> RetReg<R0> {
let x0;
let err: usize;
asm!(
"syscall",
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
in("$4" /*$a0*/) a0.to_asm(),
in("$5" /*$a1*/) a1.to_asm(),
lateout("$7" /*$a3*/) err,
lateout("$8" /*$t0*/) _,
lateout("$9" /*$t1*/) _,
lateout("$10" /*$t2*/) _,
lateout("$11" /*$t3*/) _,
lateout("$12" /*$t4*/) _,
lateout("$13" /*$t5*/) _,
lateout("$14" /*$t6*/) _,
lateout("$15" /*$t7*/) _,
lateout("$24" /*$t8*/) _,
lateout("$25" /*$t9*/) _,
options(nostack, preserves_flags, readonly)
);
FromAsm::from_asm(if err != 0 {
(x0 as usize).wrapping_neg() as *mut _
} else {
x0
})
}
#[inline]
pub(in crate::backend) unsafe fn syscall3(
nr: SyscallNumber<'_>,
a0: ArgReg<'_, A0>,
a1: ArgReg<'_, A1>,
a2: ArgReg<'_, A2>,
) -> RetReg<R0> {
let x0;
let err: usize;
asm!(
"syscall",
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
in("$4" /*$a0*/) a0.to_asm(),
in("$5" /*$a1*/) a1.to_asm(),
in("$6" /*$a2*/) a2.to_asm(),
lateout("$7" /*$a3*/) err,
lateout("$8" /*$t0*/) _,
lateout("$9" /*$t1*/) _,
lateout("$10" /*$t2*/) _,
lateout("$11" /*$t3*/) _,
lateout("$12" /*$t4*/) _,
lateout("$13" /*$t5*/) _,
lateout("$14" /*$t6*/) _,
lateout("$15" /*$t7*/) _,
lateout("$24" /*$t8*/) _,
lateout("$25" /*$t9*/) _,
options(nostack, preserves_flags)
);
FromAsm::from_asm(if err != 0 {
(x0 as usize).wrapping_neg() as *mut _
} else {
x0
})
}
#[inline]
pub(in crate::backend) unsafe fn syscall3_readonly(
nr: SyscallNumber<'_>,
a0: ArgReg<'_, A0>,
a1: ArgReg<'_, A1>,
a2: ArgReg<'_, A2>,
) -> RetReg<R0> {
let x0;
let err: usize;
asm!(
"syscall",
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
in("$4" /*$a0*/) a0.to_asm(),
in("$5" /*$a1*/) a1.to_asm(),
in("$6" /*$a2*/) a2.to_asm(),
lateout("$7" /*$a3*/) err,
lateout("$8" /*$t0*/) _,
lateout("$9" /*$t1*/) _,
lateout("$10" /*$t2*/) _,
lateout("$11" /*$t3*/) _,
lateout("$12" /*$t4*/) _,
lateout("$13" /*$t5*/) _,
lateout("$14" /*$t6*/) _,
lateout("$15" /*$t7*/) _,
lateout("$24" /*$t8*/) _,
lateout("$25" /*$t9*/) _,
options(nostack, preserves_flags, readonly)
);
FromAsm::from_asm(if err != 0 {
(x0 as usize).wrapping_neg() as *mut _
} else {
x0
})
}
#[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 x0;
let err: usize;
asm!(
"syscall",
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
in("$4" /*$a0*/) a0.to_asm(),
in("$5" /*$a1*/) a1.to_asm(),
in("$6" /*$a2*/) a2.to_asm(),
inlateout("$7" /*$a3*/) a3.to_asm() => err,
lateout("$8" /*$t0*/) _,
lateout("$9" /*$t1*/) _,
lateout("$10" /*$t2*/) _,
lateout("$11" /*$t3*/) _,
lateout("$12" /*$t4*/) _,
lateout("$13" /*$t5*/) _,
lateout("$14" /*$t6*/) _,
lateout("$15" /*$t7*/) _,
lateout("$24" /*$t8*/) _,
lateout("$25" /*$t9*/) _,
options(nostack, preserves_flags)
);
FromAsm::from_asm(if err != 0 {
(x0 as usize).wrapping_neg() as *mut _
} else {
x0
})
}
#[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 x0;
let err: usize;
asm!(
"syscall",
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
in("$4" /*$a0*/) a0.to_asm(),
in("$5" /*$a1*/) a1.to_asm(),
in("$6" /*$a2*/) a2.to_asm(),
inlateout("$7" /*$a3*/) a3.to_asm() => err,
lateout("$8" /*$t0*/) _,
lateout("$9" /*$t1*/) _,
lateout("$10" /*$t2*/) _,
lateout("$11" /*$t3*/) _,
lateout("$12" /*$t4*/) _,
lateout("$13" /*$t5*/) _,
lateout("$14" /*$t6*/) _,
lateout("$15" /*$t7*/) _,
lateout("$24" /*$t8*/) _,
lateout("$25" /*$t9*/) _,
options(nostack, preserves_flags, readonly)
);
FromAsm::from_asm(if err != 0 {
(x0 as usize).wrapping_neg() as *mut _
} else {
x0
})
}
#[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 x0;
let err: usize;
asm!(
".set noat",
"subu $sp, 32",
"sw {}, 16($sp)",
"syscall",
"addu $sp, 32",
".set at",
in(reg) a4.to_asm(),
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
in("$4" /*$a0*/) a0.to_asm(),
in("$5" /*$a1*/) a1.to_asm(),
in("$6" /*$a2*/) a2.to_asm(),
inlateout("$7" /*$a3*/) a3.to_asm() => err,
lateout("$8" /*$t0*/) _,
lateout("$9" /*$t1*/) _,
lateout("$10" /*$t2*/) _,
lateout("$11" /*$t3*/) _,
lateout("$12" /*$t4*/) _,
lateout("$13" /*$t5*/) _,
lateout("$14" /*$t6*/) _,
lateout("$15" /*$t7*/) _,
lateout("$24" /*$t8*/) _,
lateout("$25" /*$t9*/) _,
options(preserves_flags)
);
FromAsm::from_asm(if err != 0 {
(x0 as usize).wrapping_neg() as *mut _
} else {
x0
})
}
#[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 x0;
let err: usize;
asm!(
".set noat",
"subu $sp, 32",
"sw {}, 16($sp)",
"syscall",
"addu $sp, 32",
".set at",
in(reg) a4.to_asm(),
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
in("$4" /*$a0*/) a0.to_asm(),
in("$5" /*$a1*/) a1.to_asm(),
in("$6" /*$a2*/) a2.to_asm(),
inlateout("$7" /*$a3*/) a3.to_asm() => err,
lateout("$8" /*$t0*/) _,
lateout("$9" /*$t1*/) _,
lateout("$10" /*$t2*/) _,
lateout("$11" /*$t3*/) _,
lateout("$12" /*$t4*/) _,
lateout("$13" /*$t5*/) _,
lateout("$14" /*$t6*/) _,
lateout("$15" /*$t7*/) _,
lateout("$24" /*$t8*/) _,
lateout("$25" /*$t9*/) _,
options(preserves_flags, readonly)
);
FromAsm::from_asm(if err != 0 {
(x0 as usize).wrapping_neg() as *mut _
} else {
x0
})
}
#[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 x0;
let err: usize;
asm!(
".set noat",
"subu $sp, 32",
"sw {}, 16($sp)",
"sw {}, 20($sp)",
"syscall",
"addu $sp, 32",
".set at",
in(reg) a4.to_asm(),
in(reg) a5.to_asm(),
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
in("$4" /*$a0*/) a0.to_asm(),
in("$5" /*$a1*/) a1.to_asm(),
in("$6" /*$a2*/) a2.to_asm(),
inlateout("$7" /*$a3*/) a3.to_asm() => err,
lateout("$8" /*$t0*/) _,
lateout("$9" /*$t1*/) _,
lateout("$10" /*$t2*/) _,
lateout("$11" /*$t3*/) _,
lateout("$12" /*$t4*/) _,
lateout("$13" /*$t5*/) _,
lateout("$14" /*$t6*/) _,
lateout("$15" /*$t7*/) _,
lateout("$24" /*$t8*/) _,
lateout("$25" /*$t9*/) _,
options(preserves_flags)
);
FromAsm::from_asm(if err != 0 {
(x0 as usize).wrapping_neg() as *mut _
} else {
x0
})
}
#[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 x0;
let err: usize;
asm!(
".set noat",
"subu $sp, 32",
"sw {}, 16($sp)",
"sw {}, 20($sp)",
"syscall",
"addu $sp, 32",
".set at",
in(reg) a4.to_asm(),
in(reg) a5.to_asm(),
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
in("$4" /*$a0*/) a0.to_asm(),
in("$5" /*$a1*/) a1.to_asm(),
in("$6" /*$a2*/) a2.to_asm(),
inlateout("$7" /*$a3*/) a3.to_asm() => err,
lateout("$8" /*$t0*/) _,
lateout("$9" /*$t1*/) _,
lateout("$10" /*$t2*/) _,
lateout("$11" /*$t3*/) _,
lateout("$12" /*$t4*/) _,
lateout("$13" /*$t5*/) _,
lateout("$14" /*$t6*/) _,
lateout("$15" /*$t7*/) _,
lateout("$24" /*$t8*/) _,
lateout("$25" /*$t9*/) _,
options(preserves_flags, readonly)
);
FromAsm::from_asm(if err != 0 {
(x0 as usize).wrapping_neg() as *mut _
} else {
x0
})
}
#[inline]
pub(in crate::backend) unsafe fn syscall7_readonly(
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> {
let x0;
let err: usize;
asm!(
".set noat",
"subu $sp, 32",
"sw {}, 16($sp)",
"sw {}, 20($sp)",
"sw {}, 24($sp)",
"syscall",
"addu $sp, 32",
".set at",
in(reg) a4.to_asm(),
in(reg) a5.to_asm(),
in(reg) a6.to_asm(),
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
in("$4" /*$a0*/) a0.to_asm(),
in("$5" /*$a1*/) a1.to_asm(),
in("$6" /*$a2*/) a2.to_asm(),
inlateout("$7" /*$a3*/) a3.to_asm() => err,
lateout("$8" /*$t0*/) _,
lateout("$9" /*$t1*/) _,
lateout("$10" /*$t2*/) _,
lateout("$11" /*$t3*/) _,
lateout("$12" /*$t4*/) _,
lateout("$13" /*$t5*/) _,
lateout("$14" /*$t6*/) _,
lateout("$15" /*$t7*/) _,
lateout("$24" /*$t8*/) _,
lateout("$25" /*$t9*/) _,
options(preserves_flags, readonly)
);
FromAsm::from_asm(if err != 0 {
(x0 as usize).wrapping_neg() as *mut _
} else {
x0
})
}