diff --git a/src/arch/aarch64.rs b/src/arch/aarch64.rs index 23abe49a0d551c5d0f5c5d9eb27bf8e3937c2432..60e22386fea664d3ceec55fc86bf52bb1a4b7876 100644 --- a/src/arch/aarch64.rs +++ b/src/arch/aarch64.rs @@ -1,62 +1,129 @@ +use core::{mem, slice}; +use core::ops::{Deref, DerefMut}; + use super::error::{Error, Result}; -pub unsafe fn syscall0(mut a: usize) -> Result { - llvm_asm!("svc 0" - : "={x0}"(a) - : "{x8}"(a) - : "x0", "x8" - : "volatile"); +macro_rules! syscall { + ($($name:ident($a:ident, $($b:ident, $($c:ident, $($d:ident, $($e:ident, $($f:ident, )?)?)?)?)?);)+) => { + $( + pub unsafe fn $name(mut $a: usize, $(mut $b: usize, $($c: usize, $($d: usize, $($e: usize, $($f: usize)?)?)?)?)?) -> Result { + asm!( + "svc 0", + in("x8") $a, + $( + inout("x0") $b, + $( + in("x1") $c, + $( + in("x2") $d, + $( + in("x3") $e, + $( + in("x4") $f, + )? + )? + )? + )? + )? + options(nostack), + ); - Error::demux(a) + Error::demux($a) + } + )+ + }; } -pub unsafe fn syscall1(mut a: usize, b: usize) -> Result { - llvm_asm!("svc 0" - : "={x0}"(a) - : "{x8}"(a), "{x0}"(b) - : "x0", "x8" - : "volatile"); - - Error::demux(a) +syscall! { + syscall0(a,); + syscall1(a, b,); + syscall2(a, b, c,); + syscall3(a, b, c, d,); + syscall4(a, b, c, d, e,); + syscall5(a, b, c, d, e, f,); } -pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result { - llvm_asm!("svc 0" - : "={x0}"(a) - : "{x8}"(a), "{x0}"(b), "{x1}"(c) - : "x0", "x1", "x8" - : "volatile"); - - Error::demux(a) +#[derive(Copy, Clone, Debug, Default)] +#[repr(C)] +pub struct IntRegisters { + pub elr_el1: usize, + pub tpidr_el0: usize, + pub tpidrro_el0: usize, + pub spsr_el1: usize, + pub esr_el1: usize, + pub sp_el0: usize, // Shouldn't be used if interrupt occurred at EL1 + pub padding: usize, // To keep the struct even number aligned + pub x30: usize, + pub x29: usize, + pub x28: usize, + pub x27: usize, + pub x26: usize, + pub x25: usize, + pub x24: usize, + pub x23: usize, + pub x22: usize, + pub x21: usize, + pub x20: usize, + pub x19: usize, + pub x18: usize, + pub x17: usize, + pub x16: usize, + pub x15: usize, + pub x14: usize, + pub x13: usize, + pub x12: usize, + pub x11: usize, + pub x10: usize, + pub x9: usize, + pub x8: usize, + pub x7: usize, + pub x6: usize, + pub x5: usize, + pub x4: usize, + pub x3: usize, + pub x2: usize, + pub x1: usize, + pub x0: usize } -pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result { - llvm_asm!("svc 0" - : "={x0}"(a) - : "{x8}"(a), "{x0}"(b), "{x1}"(c), "{x2}"(d) - : "x0", "x1", "x2", "x8" - : "volatile"); - - Error::demux(a) +impl Deref for IntRegisters { + type Target = [u8]; + fn deref(&self) -> &[u8] { + unsafe { + slice::from_raw_parts(self as *const IntRegisters as *const u8, mem::size_of::()) + } + } } -pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result { - llvm_asm!("svc 0" - : "={x0}"(a) - : "{x8}"(a), "{x0}"(b), "{x1}"(c), "{x2}"(d), "{x3}"(e) - : "x0", "x1", "x2", "x3", "x8" - : "volatile"); +impl DerefMut for IntRegisters { + fn deref_mut(&mut self) -> &mut [u8] { + unsafe { + slice::from_raw_parts_mut(self as *mut IntRegisters as *mut u8, mem::size_of::()) + } + } +} - Error::demux(a) +#[derive(Clone, Copy, Debug, Default)] +#[repr(packed)] +pub struct FloatRegisters { + pub fp_simd_regs: [u128; 32], + pub fpsr: u32, + pub fpcr: u32 } -pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) - -> Result { - llvm_asm!("svc 0" - : "={x0}"(a) - : "{x8}"(a), "{x0}"(b), "{x1}"(c), "{x2}"(d), "{x3}"(e), "{x4}"(f) - : "x0", "x1", "x2", "x3", "x4", "x8" - : "volatile"); +impl Deref for FloatRegisters { + type Target = [u8]; + fn deref(&self) -> &[u8] { + unsafe { + slice::from_raw_parts(self as *const FloatRegisters as *const u8, mem::size_of::()) + } + } +} - Error::demux(a) +impl DerefMut for FloatRegisters { + fn deref_mut(&mut self) -> &mut [u8] { + unsafe { + slice::from_raw_parts_mut(self as *mut FloatRegisters as *mut u8, mem::size_of::()) + } + } }