use crate::interpreter::{utils::unlikely, Error};
pub const CPU_REGISTER_COUNT: u8 = 32;
#[repr(u8)]
#[derive(Debug)]
pub enum CPURegister {
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,
}
#[derive(Debug, Default, PartialEq, Copy, Clone)]
pub struct CPURegisters {
pub(crate) inner: [i32; CPU_REGISTER_COUNT as usize],
}
impl CPURegisters {
#[inline]
pub fn get(&self, index: u8) -> Result<i32, Error> {
if unlikely(index >= CPU_REGISTER_COUNT) {
return Err(Error::InvalidCPURegister(index));
}
Ok(self.inner[index as usize])
}
#[inline]
pub fn get_mut(&mut self, index: u8) -> Result<&mut i32, Error> {
if unlikely(index >= CPU_REGISTER_COUNT) {
return Err(Error::InvalidCPURegister(index));
}
Ok(&mut self.inner[index as usize])
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn get_cpu_register() {
let mut registers = CPURegisters::default();
assert_eq!(registers.get(0), Ok(0));
assert_eq!(registers.get(CPU_REGISTER_COUNT - 1), Ok(0));
assert_eq!(registers.get_mut(0).map(|x| *x), Ok(0));
assert_eq!(registers.get_mut(CPU_REGISTER_COUNT - 1).map(|x| *x), Ok(0));
}
#[test]
fn get_cpu_register_out_of_bounds() {
let mut registers = CPURegisters::default();
assert!(matches!(
registers.get(CPU_REGISTER_COUNT),
Err(Error::InvalidCPURegister(_))
));
assert!(matches!(
registers.get_mut(CPU_REGISTER_COUNT).map(|x| *x),
Err(Error::InvalidCPURegister(_))
));
}
}