use core::arch::{asm, global_asm};
global_asm!(include_str!("trap.S"));
pub unsafe fn init() {
asm!(
"mtc0 {trap_entry}, $15, 1",
trap_entry = in(reg) trap_entry,
);
}
#[no_mangle]
#[linkage = "weak"]
extern "C" fn trap_handler(tf: &mut TrapFrame) {
unimplemented!("TRAP: tf={:#x?}", tf);
}
#[derive(Debug, Default, Clone, Copy)]
#[repr(C)]
pub struct TrapFrame {
pub tls: usize,
pub __reserved: usize,
pub status: usize,
pub cause: usize,
pub epc: usize,
pub vaddr: usize,
pub general: GeneralRegs,
}
#[derive(Debug, Default, Clone, Copy)]
#[repr(C)]
pub struct UserContext {
pub tls: usize,
pub __reserved: usize,
pub status: usize,
pub cause: usize,
pub epc: usize,
pub vaddr: usize,
pub general: GeneralRegs,
}
impl UserContext {
pub fn run(&mut self) {
unsafe { run_user(self) }
}
}
#[derive(Debug, Default, Clone, Copy)]
#[repr(C)]
pub struct GeneralRegs {
pub hi: usize,
pub lo: usize,
pub at: usize,
pub v0: usize,
pub v1: usize,
pub a0: usize,
pub a1: usize,
pub a2: usize,
pub a3: usize,
pub t0: usize,
pub t1: usize,
pub t2: usize,
pub t3: usize,
pub t4: usize,
pub t5: usize,
pub t6: usize,
pub t7: usize,
pub s0: usize,
pub s1: usize,
pub s2: usize,
pub s3: usize,
pub s4: usize,
pub s5: usize,
pub s6: usize,
pub s7: usize,
pub t8: usize,
pub t9: usize,
pub k0: usize,
pub k1: usize,
pub gp: usize,
pub sp: usize,
pub fp: usize,
pub ra: usize,
}
impl UserContext {
pub fn get_syscall_num(&self) -> usize {
self.general.v0
}
pub fn get_syscall_ret(&self) -> usize {
if self.general.a3 == 0 {
self.general.v0
} else {
(-(self.general.v0 as isize)) as usize
}
}
pub fn set_syscall_ret(&mut self, ret: usize) {
if (ret as isize) < 0 {
self.general.v0 = (-(ret as isize)) as usize;
self.general.a3 = 1;
} else {
self.general.v0 = ret as usize;
self.general.a3 = 0;
}
}
pub fn get_syscall_args(&self) -> [usize; 6] {
[
self.general.a0,
self.general.a1,
self.general.a2,
self.general.a3,
self.general.t0,
self.general.t1,
]
}
pub fn set_ip(&mut self, ip: usize) {
self.epc = 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.tls = tls;
}
}
#[allow(improper_ctypes)]
extern "C" {
fn trap_entry();
fn run_user(regs: &mut UserContext);
}