mirror of
https://github.com/FranLMSP/rultra64.git
synced 2026-10-03 07:55:20 -04:00
Getters and setters for CPU registers
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
use crate::registers::{CPURegisters};
|
||||||
|
|
||||||
|
pub struct CPU {
|
||||||
|
registers: CPURegisters,
|
||||||
|
}
|
||||||
@@ -1 +1,2 @@
|
|||||||
pub mod registers;
|
pub mod registers;
|
||||||
|
pub mod cpu;
|
||||||
|
|||||||
+120
-70
@@ -1,77 +1,127 @@
|
|||||||
pub struct Register<T: PartialOrd + Copy>(T);
|
pub trait Register<T: PartialOrd + Copy> {
|
||||||
|
fn get(&self) -> T;
|
||||||
|
fn set(&mut self, val: T);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct Fixed<T>(T);
|
||||||
|
impl<T: PartialOrd + Copy> Register<T> for Fixed<T> {
|
||||||
|
fn get(&self) -> T {self.0}
|
||||||
|
fn set(&mut self, _: T) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct Generic<T>(T);
|
||||||
|
impl<T: PartialOrd + Copy> Register<T> for Generic<T> {
|
||||||
|
fn get(&self) -> T {self.0}
|
||||||
|
fn set(&mut self, val: T) {self.0 = val}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const CPU_REGISTER_NAMES: [&'static str; 32] = [
|
||||||
|
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", "t0", "t1", "t2",
|
||||||
|
"t3", "t4", "t5", "t6", "t7", "s0", "s1", "s2", "s3", "s4", "s5",
|
||||||
|
"s6", "s7", "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
|
||||||
|
];
|
||||||
|
|
||||||
pub struct CPURegisters {
|
pub struct CPURegisters {
|
||||||
zero: Register<u64>,
|
registers: [Box<dyn Register<i64>>; 32],
|
||||||
at: Register<u64>,
|
program_counter: Generic<i64>,
|
||||||
v0: Register<u64>,
|
|
||||||
v1: Register<u64>,
|
|
||||||
a0: Register<u64>,
|
|
||||||
a1: Register<u64>,
|
|
||||||
a2: Register<u64>,
|
|
||||||
a3: Register<u64>,
|
|
||||||
t0: Register<u64>,
|
|
||||||
t1: Register<u64>,
|
|
||||||
t2: Register<u64>,
|
|
||||||
t3: Register<u64>,
|
|
||||||
t4: Register<u64>,
|
|
||||||
t5: Register<u64>,
|
|
||||||
t6: Register<u64>,
|
|
||||||
t7: Register<u64>,
|
|
||||||
s0: Register<u64>,
|
|
||||||
s1: Register<u64>,
|
|
||||||
s2: Register<u64>,
|
|
||||||
s3: Register<u64>,
|
|
||||||
s4: Register<u64>,
|
|
||||||
s5: Register<u64>,
|
|
||||||
s6: Register<u64>,
|
|
||||||
s7: Register<u64>,
|
|
||||||
t8: Register<u64>,
|
|
||||||
t9: Register<u64>,
|
|
||||||
k0: Register<u64>,
|
|
||||||
k1: Register<u64>,
|
|
||||||
gp: Register<u64>,
|
|
||||||
sp: Register<u64>,
|
|
||||||
s8: Register<u64>,
|
|
||||||
ra: Register<u64>,
|
|
||||||
|
|
||||||
program_counter: Register<u64>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct COP0Registers {
|
impl CPURegisters {
|
||||||
index: Register<u32>,
|
pub fn new() -> Self {
|
||||||
random: Register<u32>,
|
Self {
|
||||||
entry_lo_0: Register<u64>,
|
registers: [
|
||||||
entry_lo_1: Register<u64>,
|
Box::new(Fixed(0_i64)),
|
||||||
context: Register<u64>,
|
Box::new(Generic(0_i64)),
|
||||||
page_mask: Register<u32>,
|
Box::new(Generic(0_i64)),
|
||||||
wired: Register<u32>,
|
Box::new(Generic(0_i64)),
|
||||||
r7: Register<u64>,
|
Box::new(Generic(0_i64)),
|
||||||
bad_v_addr: Register<u64>,
|
Box::new(Generic(0_i64)),
|
||||||
count: Register<u32>,
|
Box::new(Generic(0_i64)),
|
||||||
entry_hi: Register<u64>,
|
Box::new(Generic(0_i64)),
|
||||||
compare: Register<u32>,
|
Box::new(Generic(0_i64)),
|
||||||
status: Register<u32>,
|
Box::new(Generic(0_i64)),
|
||||||
cause: Register<u32>,
|
Box::new(Generic(0_i64)),
|
||||||
epc: Register<u64>,
|
Box::new(Generic(0_i64)),
|
||||||
prid: Register<u32>,
|
Box::new(Generic(0_i64)),
|
||||||
config: Register<u32>,
|
Box::new(Generic(0_i64)),
|
||||||
ll_addr: Register<u32>,
|
Box::new(Generic(0_i64)),
|
||||||
watch_lo: Register<u32>,
|
Box::new(Generic(0_i64)),
|
||||||
watch_hi: Register<u32>,
|
Box::new(Generic(0_i64)),
|
||||||
x_context: Register<u64>,
|
Box::new(Generic(0_i64)),
|
||||||
r21: Register<u64>,
|
Box::new(Generic(0_i64)),
|
||||||
r22: Register<u64>,
|
Box::new(Generic(0_i64)),
|
||||||
r23: Register<u64>,
|
Box::new(Generic(0_i64)),
|
||||||
r24: Register<u64>,
|
Box::new(Generic(0_i64)),
|
||||||
r25: Register<u64>,
|
Box::new(Generic(0_i64)),
|
||||||
parity_error: Register<u32>,
|
Box::new(Generic(0_i64)),
|
||||||
cache_error: Register<u32>,
|
Box::new(Generic(0_i64)),
|
||||||
tag_lo: Register<u32>,
|
Box::new(Generic(0_i64)),
|
||||||
tag_hi: Register<u32>,
|
Box::new(Generic(0_i64)),
|
||||||
error_epc: Register<u64>,
|
Box::new(Generic(0_i64)),
|
||||||
r31: Register<u64>,
|
Box::new(Generic(0_i64)),
|
||||||
|
Box::new(Generic(0_i64)),
|
||||||
|
Box::new(Generic(0_i64)),
|
||||||
|
Box::new(Generic(0_i64)),
|
||||||
|
],
|
||||||
|
program_counter: Generic(0_i64),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct COP1Registers {
|
pub fn get_by_number(&self, index: usize) -> i64 {
|
||||||
registers: [Register<f32>; 32],
|
if index > 31 {
|
||||||
|
unreachable!("Register number {} not valid", index);
|
||||||
|
}
|
||||||
|
self.registers[index].get()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_by_name(&self, name: &'static str) -> i64 {
|
||||||
|
let index = CPU_REGISTER_NAMES.iter().position(|v| *v == name).unwrap();
|
||||||
|
self.registers[index].get()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_program_counter(&self) -> i64 {
|
||||||
|
self.program_counter.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_by_number(&mut self, index: usize, val: i64) {
|
||||||
|
if index > 31 {
|
||||||
|
unreachable!("Register number {} not valid", index);
|
||||||
|
}
|
||||||
|
self.registers[index].set(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_by_name(&mut self, name: &'static str, val: i64) {
|
||||||
|
let index = CPU_REGISTER_NAMES.iter().position(|v| *v == name).unwrap();
|
||||||
|
self.registers[index].set(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_program_counter(&mut self, val: i64) {
|
||||||
|
self.program_counter.set(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod cpu_registers_tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_set_by_number() {
|
||||||
|
let mut registers = CPURegisters::new();
|
||||||
|
registers.set_by_number(0, 20);
|
||||||
|
assert_eq!(registers.get_by_number(0), 0);
|
||||||
|
registers.set_by_number(5, 20);
|
||||||
|
assert_eq!(registers.get_by_number(5), 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_set_by_name() {
|
||||||
|
let mut registers = CPURegisters::new();
|
||||||
|
registers.set_by_name("zero", 20);
|
||||||
|
assert_eq!(registers.get_by_name("zero"), 0);
|
||||||
|
registers.set_by_name("a0", 20);
|
||||||
|
assert_eq!(registers.get_by_name("a0"), 20);
|
||||||
|
assert_eq!(registers.get_by_number(4), 20);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user