use core::arch::asm;
use super::ExceptionCause;
#[repr(C)]
#[allow(non_snake_case)]
#[derive(Debug, Clone, Copy)]
pub struct Context {
pub PC: u32,
pub PS: u32,
pub A0: u32,
pub A1: u32,
pub A2: u32,
pub A3: u32,
pub A4: u32,
pub A5: u32,
pub A6: u32,
pub A7: u32,
pub A8: u32,
pub A9: u32,
pub A10: u32,
pub A11: u32,
pub A12: u32,
pub A13: u32,
pub A14: u32,
pub A15: u32,
pub SAR: u32,
pub EXCCAUSE: u32,
pub EXCVADDR: u32,
pub LBEG: u32,
pub LEND: u32,
pub LCOUNT: u32,
pub THREADPTR: u32,
pub SCOMPARE1: u32,
pub BR: u32,
pub ACCLO: u32,
pub ACCHI: u32,
pub M0: u32,
pub M1: u32,
pub M2: u32,
pub M3: u32,
pub F64R_LO: u32,
pub F64R_HI: u32,
pub F64S: u32,
pub FCR: u32,
pub FSR: u32,
pub F0: u32,
pub F1: u32,
pub F2: u32,
pub F3: u32,
pub F4: u32,
pub F5: u32,
pub F6: u32,
pub F7: u32,
pub F8: u32,
pub F9: u32,
pub F10: u32,
pub F11: u32,
pub F12: u32,
pub F13: u32,
pub F14: u32,
pub F15: u32,
}
extern "Rust" {
fn __exception(cause: ExceptionCause, save_frame: &mut Context);
fn __user_exception(cause: ExceptionCause, save_frame: &mut Context);
fn __double_exception(cause: ExceptionCause, save_frame: &mut Context);
fn __level_1_interrupt(level: u32, save_frame: &mut Context);
fn __level_2_interrupt(level: u32, save_frame: &mut Context);
fn __level_3_interrupt(level: u32, save_frame: &mut Context);
fn __level_4_interrupt(level: u32, save_frame: &mut Context);
fn __level_5_interrupt(level: u32, save_frame: &mut Context);
fn __level_6_interrupt(level: u32, save_frame: &mut Context);
fn __level_7_interrupt(level: u32, save_frame: &mut Context);
}
#[no_mangle]
#[link_section = ".rwtext"]
unsafe extern "C" fn __default_exception(cause: ExceptionCause, save_frame: &mut Context) {
__user_exception(cause, save_frame)
}
#[no_mangle]
#[link_section = ".rwtext"]
extern "C" fn __default_user_exception(cause: ExceptionCause, save_frame: &Context) {
panic!("Exception: {:?}, {:08x?}", cause, save_frame)
}
#[no_mangle]
#[link_section = ".rwtext"]
extern "C" fn __default_interrupt(level: u32, save_frame: &Context) {
panic!("Interrupt: {:?}, {:08x?}", level, save_frame)
}
#[no_mangle]
#[link_section = ".rwtext"]
extern "C" fn __default_double_exception(cause: ExceptionCause, save_frame: &Context) {
panic!("Double Exception: {:?}, {:08x?}", cause, save_frame)
}
#[naked]
#[no_mangle]
#[link_section = ".KernelExceptionVector.text"]
unsafe extern "C" fn _KernelExceptionVector() {
asm!(
"
wsr a0, EXCSAVE1 // preserve a0
rsr a0, EXCCAUSE // get exception cause
beqi a0, 5, .AllocAException
call0 __naked_kernel_exception
",
options(noreturn)
);
}
#[naked]
#[no_mangle]
#[link_section = ".UserExceptionVector.text"]
unsafe extern "C" fn _UserExceptionVector() {
asm!(
"
wsr a0, EXCSAVE1 // preserve a0
rsr a0, EXCCAUSE // get exception cause
beqi a0, 5, .AllocAException
call0 __naked_user_exception
.AllocAException:
call0 _AllocAException
",
options(noreturn)
);
}
#[naked]
#[no_mangle]
#[link_section = ".DoubleExceptionVector.text"]
unsafe extern "C" fn _DoubleExceptionVector() {
asm!(
"
wsr a0, EXCSAVE1 // preserve a0 (EXCSAVE1 can be reused as long as there
// is no double exception in the first exception until
// EXCSAVE1 is stored to the stack.)
call0 __naked_double_exception // used as long jump
",
options(noreturn)
);
}
#[naked]
#[no_mangle]
#[link_section = ".Level2InterruptVector.text"]
unsafe extern "C" fn _Level2InterruptVector() {
asm!(
"
wsr a0, EXCSAVE2 // preserve a0
call0 __naked_level_2_interrupt // used as long jump
",
options(noreturn)
);
}
#[naked]
#[no_mangle]
#[link_section = ".Level3InterruptVector.text"]
unsafe extern "C" fn _Level3InterruptVector() {
asm!(
"
wsr a0, EXCSAVE3 // preserve a0
call0 __naked_level_3_interrupt // used as long jump
",
options(noreturn)
);
}
#[naked]
#[no_mangle]
#[link_section = ".Level4InterruptVector.text"]
unsafe extern "C" fn _Level4InterruptVector() {
asm!(
"
wsr a0, EXCSAVE4 // preserve a0
call0 __naked_level_4_interrupt // used as long jump
",
options(noreturn)
);
}
#[naked]
#[no_mangle]
#[link_section = ".Level5InterruptVector.text"]
unsafe extern "C" fn _Level5InterruptVector() {
asm!(
"
wsr a0, EXCSAVE5 // preserve a0
call0 __naked_level_5_interrupt // used as long jump
",
options(noreturn)
);
}
#[naked]
#[no_mangle]
#[link_section = ".DebugExceptionVector.text"]
unsafe extern "C" fn _Level6InterruptVector() {
asm!(
"
wsr a0, EXCSAVE6 // preserve a0
call0 __naked_level_6_interrupt // used as long jump
",
options(noreturn)
);
}
#[naked]
#[no_mangle]
#[link_section = ".NMIExceptionVector.text"]
unsafe extern "C" fn _Level7InterruptVector() {
asm!(
"
wsr a0, EXCSAVE7 // preserve a0
call0 __naked_level_7_interrupt // used as long jump
",
options(noreturn)
);
}
#[naked]
#[no_mangle]
#[link_section = ".WindowOverflow4.text"]
unsafe extern "C" fn _WindowOverflow4() {
asm!(
"
s32e a0, a5, -16
s32e a1, a5, -12
s32e a2, a5, -8
s32e a3, a5, -4
rfwo
",
options(noreturn)
);
}
#[naked]
#[no_mangle]
#[link_section = ".WindowUnderflow4.text"]
unsafe extern "C" fn _WindowUnderflow4() {
asm!(
"
l32e a0, a5, -16
l32e a1, a5, -12
l32e a2, a5, -8
l32e a3, a5, -4
rfwu
// inline the _AllocAException saves on the ret.w for WindowUnderflow4
// this makes that it just fits, which is needed for the bbci instructions
.align 4
_AllocAException:
rsr a0, WINDOWBASE // grab WINDOWBASE before rotw changes it
rotw -1 // WINDOWBASE goes to a4, new a0-a3 are scratch
rsr a2, PS
extui a3, a2, 8, 4 // XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS
xor a3, a3, a4 // bits changed from old to current windowbase
rsr a4, EXCSAVE1 // restore original a0 (now in a4)
slli a3, a3, 8 // XCHAL_PS_OWB_SHIFT
xor a2, a2, a3 // flip changed bits in old window base
wsr a2, PS // update PS.OWB to new window base
rsync
bbci a4, 31, _WindowUnderflow4
rotw -1 // original a0 goes to a8
bbci a8, 30, _WindowUnderflow8
rotw -1
j _WindowUnderflow12
",
options(noreturn)
);
}
#[naked]
#[no_mangle]
#[link_section = ".WindowOverflow8.text"]
unsafe extern "C" fn _WindowOverflow8() {
asm!(
"
s32e a0, a9, -16
l32e a0, a1, -12
s32e a1, a9, -12
s32e a2, a9, -8
s32e a3, a9, -4
s32e a4, a0, -32
s32e a5, a0, -28
s32e a6, a0, -24
s32e a7, a0, -20
rfwo
",
options(noreturn)
);
}
#[naked]
#[no_mangle]
#[link_section = ".WindowUnderflow8.text"]
unsafe extern "C" fn _WindowUnderflow8() {
asm!(
"
l32e a0, a9, -16
l32e a1, a9, -12
l32e a2, a9, -8
l32e a7, a1, -12
l32e a3, a9, -4
l32e a4, a7, -32
l32e a5, a7, -28
l32e a6, a7, -24
l32e a7, a7, -20
rfwu
",
options(noreturn)
);
}
#[naked]
#[no_mangle]
#[link_section = ".WindowOverflow12.text"]
unsafe extern "C" fn _WindowOverflow12() {
asm!(
"
s32e a0, a13, -16
l32e a0, a1, -12
s32e a1, a13, -12
s32e a2, a13, -8
s32e a3, a13, -4
s32e a4, a0, -48
s32e a5, a0, -44
s32e a6, a0, -40
s32e a7, a0, -36
s32e a8, a0, -32
s32e a9, a0, -28
s32e a10, a0, -24
s32e a11, a0, -20
rfwo
",
options(noreturn)
);
}
#[naked]
#[no_mangle]
#[link_section = ".WindowUnderflow12.text"]
unsafe extern "C" fn _WindowUnderflow12() {
asm!(
"
l32e a0, a13, -16
l32e a1, a13, -12
l32e a2, a13, -8
l32e a11, a1, -12
l32e a3, a13, -4
l32e a4, a11, -48
l32e a5, a11, -44
l32e a6, a11, -40
l32e a7, a11, -36
l32e a8, a11, -32
l32e a9, a11, -28
l32e a10, a11, -24
l32e a11, a11, -20
rfwu
",
options(noreturn)
);
}