use core::arch::{asm, global_asm};
use crate::Pod;
#[cfg(target_arch = "riscv32")]
global_asm!(
r"
.equ XLENB, 4
.macro LOAD_SP a1, a2
lw \a1, \a2*XLENB(sp)
.endm
.macro STORE_SP a1, a2
sw \a1, \a2*XLENB(sp)
.endm
"
);
#[cfg(target_arch = "riscv64")]
global_asm!(
r"
.equ XLENB, 8
.macro LOAD_SP a1, a2
ld \a1, \a2*XLENB(sp)
.endm
.macro STORE_SP a1, a2
sd \a1, \a2*XLENB(sp)
.endm
"
);
global_asm!(include_str!("trap.S"));
pub unsafe fn init() {
asm!("csrw sscratch, zero");
asm!("csrw stvec, {}", in(reg) trap_entry as usize);
}
#[derive(Debug, Default, Clone, Copy)]
#[repr(C)]
pub struct TrapFrame {
pub general: GeneralRegs,
pub sstatus: usize,
pub sepc: usize,
}
#[derive(Debug, Default, Clone, Copy, Pod)]
#[repr(C)]
pub struct UserContext {
pub general: GeneralRegs,
pub sstatus: usize,
pub sepc: usize,
}
impl UserContext {
pub fn run(&mut self) {
unsafe { run_user(self) }
}
}
#[derive(Debug, Default, Clone, Copy, Pod)]
#[repr(C)]
#[allow(missing_docs)]
pub struct GeneralRegs {
pub zero: usize,
pub ra: usize,
pub sp: usize,
pub gp: usize,
pub tp: usize,
pub t0: usize,
pub t1: usize,
pub t2: usize,
pub s0: usize,
pub s1: usize,
pub a0: usize,
pub a1: usize,
pub a2: usize,
pub a3: usize,
pub a4: usize,
pub a5: usize,
pub a6: usize,
pub a7: usize,
pub s2: usize,
pub s3: usize,
pub s4: usize,
pub s5: usize,
pub s6: usize,
pub s7: usize,
pub s8: usize,
pub s9: usize,
pub s10: usize,
pub s11: usize,
pub t3: usize,
pub t4: usize,
pub t5: usize,
pub t6: usize,
}
impl UserContext {
pub fn get_syscall_num(&self) -> usize {
self.general.a7
}
pub fn get_syscall_ret(&self) -> usize {
self.general.a0
}
pub fn set_syscall_ret(&mut self, ret: usize) {
self.general.a0 = ret;
}
pub fn get_syscall_args(&self) -> [usize; 6] {
[
self.general.a0,
self.general.a1,
self.general.a2,
self.general.a3,
self.general.a4,
self.general.a5,
]
}
pub fn set_ip(&mut self, ip: usize) {
self.sepc = ip;
}
pub fn set_sp(&mut self, sp: usize) {
self.general.sp = sp;
}
pub fn get_sp(&self) -> usize {
self.general.sp
}
pub fn set_tls(&mut self, tls: usize) {
self.general.gp = tls;
}
}
#[allow(improper_ctypes)]
extern "C" {
fn trap_entry();
fn run_user(regs: &mut UserContext);
}