pub use riscv::register::sstatus::{self, FS, Sstatus};
#[cfg(kernel_tls)]
pub use super::asm::{read_thread_pointer, write_thread_pointer};
pub use super::{
context::FpState,
local_state::{CpuEntryState, TaskEntryState},
};
#[repr(C)]
#[derive(Debug, Default, Clone, Copy)]
pub struct GeneralRegisters {
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,
}
#[repr(u32)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum GprIndex {
Zero = 0,
RA = 1,
SP = 2,
GP = 3,
TP = 4,
T0 = 5,
T1 = 6,
T2 = 7,
S0 = 8,
S1 = 9,
A0 = 10,
A1 = 11,
A2 = 12,
A3 = 13,
A4 = 14,
A5 = 15,
A6 = 16,
A7 = 17,
S2 = 18,
S3 = 19,
S4 = 20,
S5 = 21,
S6 = 22,
S7 = 23,
S8 = 24,
S9 = 25,
S10 = 26,
S11 = 27,
T3 = 28,
T4 = 29,
T5 = 30,
T6 = 31,
}
impl GprIndex {
pub const fn from_raw(raw: u32) -> Option<Self> {
match raw {
0 => Some(Self::Zero),
1 => Some(Self::RA),
2 => Some(Self::SP),
3 => Some(Self::GP),
4 => Some(Self::TP),
5 => Some(Self::T0),
6 => Some(Self::T1),
7 => Some(Self::T2),
8 => Some(Self::S0),
9 => Some(Self::S1),
10 => Some(Self::A0),
11 => Some(Self::A1),
12 => Some(Self::A2),
13 => Some(Self::A3),
14 => Some(Self::A4),
15 => Some(Self::A5),
16 => Some(Self::A6),
17 => Some(Self::A7),
18 => Some(Self::S2),
19 => Some(Self::S3),
20 => Some(Self::S4),
21 => Some(Self::S5),
22 => Some(Self::S6),
23 => Some(Self::S7),
24 => Some(Self::S8),
25 => Some(Self::S9),
26 => Some(Self::S10),
27 => Some(Self::S11),
28 => Some(Self::T3),
29 => Some(Self::T4),
30 => Some(Self::T5),
31 => Some(Self::T6),
_ => None,
}
}
pub const fn byte_offset(self) -> usize {
match self {
Self::Zero => core::mem::offset_of!(GeneralRegisters, zero),
Self::RA => core::mem::offset_of!(GeneralRegisters, ra),
Self::SP => core::mem::offset_of!(GeneralRegisters, sp),
Self::GP => core::mem::offset_of!(GeneralRegisters, gp),
Self::TP => core::mem::offset_of!(GeneralRegisters, tp),
Self::T0 => core::mem::offset_of!(GeneralRegisters, t0),
Self::T1 => core::mem::offset_of!(GeneralRegisters, t1),
Self::T2 => core::mem::offset_of!(GeneralRegisters, t2),
Self::S0 => core::mem::offset_of!(GeneralRegisters, s0),
Self::S1 => core::mem::offset_of!(GeneralRegisters, s1),
Self::A0 => core::mem::offset_of!(GeneralRegisters, a0),
Self::A1 => core::mem::offset_of!(GeneralRegisters, a1),
Self::A2 => core::mem::offset_of!(GeneralRegisters, a2),
Self::A3 => core::mem::offset_of!(GeneralRegisters, a3),
Self::A4 => core::mem::offset_of!(GeneralRegisters, a4),
Self::A5 => core::mem::offset_of!(GeneralRegisters, a5),
Self::A6 => core::mem::offset_of!(GeneralRegisters, a6),
Self::A7 => core::mem::offset_of!(GeneralRegisters, a7),
Self::S2 => core::mem::offset_of!(GeneralRegisters, s2),
Self::S3 => core::mem::offset_of!(GeneralRegisters, s3),
Self::S4 => core::mem::offset_of!(GeneralRegisters, s4),
Self::S5 => core::mem::offset_of!(GeneralRegisters, s5),
Self::S6 => core::mem::offset_of!(GeneralRegisters, s6),
Self::S7 => core::mem::offset_of!(GeneralRegisters, s7),
Self::S8 => core::mem::offset_of!(GeneralRegisters, s8),
Self::S9 => core::mem::offset_of!(GeneralRegisters, s9),
Self::S10 => core::mem::offset_of!(GeneralRegisters, s10),
Self::S11 => core::mem::offset_of!(GeneralRegisters, s11),
Self::T3 => core::mem::offset_of!(GeneralRegisters, t3),
Self::T4 => core::mem::offset_of!(GeneralRegisters, t4),
Self::T5 => core::mem::offset_of!(GeneralRegisters, t5),
Self::T6 => core::mem::offset_of!(GeneralRegisters, t6),
}
}
}
impl GeneralRegisters {
pub const fn reg(&self, index: GprIndex) -> usize {
match index {
GprIndex::Zero => 0,
GprIndex::RA => self.ra,
GprIndex::SP => self.sp,
GprIndex::GP => self.gp,
GprIndex::TP => self.tp,
GprIndex::T0 => self.t0,
GprIndex::T1 => self.t1,
GprIndex::T2 => self.t2,
GprIndex::S0 => self.s0,
GprIndex::S1 => self.s1,
GprIndex::A0 => self.a0,
GprIndex::A1 => self.a1,
GprIndex::A2 => self.a2,
GprIndex::A3 => self.a3,
GprIndex::A4 => self.a4,
GprIndex::A5 => self.a5,
GprIndex::A6 => self.a6,
GprIndex::A7 => self.a7,
GprIndex::S2 => self.s2,
GprIndex::S3 => self.s3,
GprIndex::S4 => self.s4,
GprIndex::S5 => self.s5,
GprIndex::S6 => self.s6,
GprIndex::S7 => self.s7,
GprIndex::S8 => self.s8,
GprIndex::S9 => self.s9,
GprIndex::S10 => self.s10,
GprIndex::S11 => self.s11,
GprIndex::T3 => self.t3,
GprIndex::T4 => self.t4,
GprIndex::T5 => self.t5,
GprIndex::T6 => self.t6,
}
}
pub fn set_reg(&mut self, index: GprIndex, value: usize) {
match index {
GprIndex::Zero => {}
GprIndex::RA => self.ra = value,
GprIndex::SP => self.sp = value,
GprIndex::GP => self.gp = value,
GprIndex::TP => self.tp = value,
GprIndex::T0 => self.t0 = value,
GprIndex::T1 => self.t1 = value,
GprIndex::T2 => self.t2 = value,
GprIndex::S0 => self.s0 = value,
GprIndex::S1 => self.s1 = value,
GprIndex::A0 => self.a0 = value,
GprIndex::A1 => self.a1 = value,
GprIndex::A2 => self.a2 = value,
GprIndex::A3 => self.a3 = value,
GprIndex::A4 => self.a4 = value,
GprIndex::A5 => self.a5 = value,
GprIndex::A6 => self.a6 = value,
GprIndex::A7 => self.a7 = value,
GprIndex::S2 => self.s2 = value,
GprIndex::S3 => self.s3 = value,
GprIndex::S4 => self.s4 = value,
GprIndex::S5 => self.s5 = value,
GprIndex::S6 => self.s6 = value,
GprIndex::S7 => self.s7 = value,
GprIndex::S8 => self.s8 = value,
GprIndex::S9 => self.s9 = value,
GprIndex::S10 => self.s10 = value,
GprIndex::S11 => self.s11 = value,
GprIndex::T3 => self.t3 = value,
GprIndex::T4 => self.t4 = value,
GprIndex::T5 => self.t5 = value,
GprIndex::T6 => self.t6 = value,
}
}
pub const fn a_regs(&self) -> [usize; 8] {
[
self.a0, self.a1, self.a2, self.a3, self.a4, self.a5, self.a6, self.a7,
]
}
}
#[inline]
pub fn read_tp() -> usize {
let value;
unsafe { core::arch::asm!("mv {}, tp", out(reg) value, options(nostack)) };
value
}
#[inline]
pub unsafe fn write_tp(value: usize) {
unsafe { core::arch::asm!("mv tp, {}", in(reg) value, options(nostack)) };
}
#[inline]
pub fn read_sscratch() -> usize {
let value;
unsafe { core::arch::asm!("csrr {}, sscratch", out(reg) value, options(nostack)) };
value
}
#[inline]
pub unsafe fn write_sscratch(value: usize) {
unsafe { core::arch::asm!("csrw sscratch, {}", in(reg) value, options(nostack)) };
}