use core::arch::asm;
use super::{OperationNumber, ParamRegR, ParamRegW, RetReg};
macro_rules! trap {
() => {
"hlt 0xF000" };
}
#[inline]
pub unsafe fn syscall(number: OperationNumber, parameter: ParamRegW<'_>) -> RetReg {
let ret;
unsafe {
asm!(
trap!(),
in("w0") number.0, inout("x1") parameter.0 => _, lateout("x0") ret, options(nostack, preserves_flags),
);
}
RetReg(ret)
}
#[inline]
pub unsafe fn syscall_readonly(number: OperationNumber, parameter: ParamRegR<'_>) -> RetReg {
let ret;
unsafe {
asm!(
trap!(),
in("w0") number.0, inout("x1") parameter.0 => _, lateout("x0") ret, options(nostack, preserves_flags, readonly),
);
}
RetReg(ret)
}
#[inline]
pub(crate) unsafe fn syscall_param_unchanged(
number: OperationNumber,
parameter: ParamRegW<'_>,
) -> RetReg {
let ret;
#[cfg(not(debug_assertions))]
unsafe {
asm!(
trap!(),
in("w0") number.0, in("x1") parameter.0, lateout("x0") ret, options(nostack, preserves_flags),
);
}
#[cfg(debug_assertions)]
unsafe {
let param_new;
asm!(
trap!(),
in("w0") number.0, inout("x1") parameter.0 => param_new, lateout("x0") ret, options(nostack, preserves_flags),
);
assert_eq!(parameter.0, param_new);
}
RetReg(ret)
}
#[inline]
pub(crate) unsafe fn syscall_param_unchanged_readonly(
number: OperationNumber,
parameter: ParamRegR<'_>,
) -> RetReg {
let ret;
#[cfg(not(debug_assertions))]
unsafe {
asm!(
trap!(),
in("w0") number.0, in("x1") parameter.0, lateout("x0") ret, options(nostack, preserves_flags, readonly),
);
}
#[cfg(debug_assertions)]
unsafe {
let param_new;
asm!(
trap!(),
in("w0") number.0, inout("x1") parameter.0 => param_new, lateout("x0") ret, options(nostack, preserves_flags, readonly),
);
assert_eq!(parameter.0, param_new);
}
RetReg(ret)
}
#[inline]
pub(crate) unsafe fn syscall_noreturn_readonly(
number: OperationNumber,
parameter: ParamRegR<'_>,
) -> ! {
unsafe {
asm!(
trap!(),
"2:",
"b 2b",
in("w0") number.0, in("x1") parameter.0, options(nostack, noreturn, preserves_flags, readonly),
)
}
}