Skip to main content

javm_exec/
regs.rs

1//! Register state: 13 general-purpose 64-bit registers + PC.
2//!
3//! Per JAM Gray Paper Appendix A / PVM spec: the PVM has 13 GPRs
4//! (φ₀..φ₁₂) plus an instruction pointer. v3 keeps the same layout
5//! since v3 doesn't change the PVM instruction set.
6
7/// Number of general-purpose registers.
8pub const REG_COUNT: usize = 13;
9
10/// Full register state: 13 GPRs + PC.
11#[derive(Clone, Debug, PartialEq, Eq)]
12pub struct Regs {
13    /// General-purpose registers φ₀..φ₁₂.
14    pub gpr: [u64; REG_COUNT],
15    /// Program counter (bytecode offset, not memory address).
16    pub pc: u64,
17}
18
19impl Regs {
20    /// All zeros, PC = 0.
21    pub fn new() -> Self {
22        Self::default()
23    }
24
25    /// Read register `i`. Returns 0 if `i >= REG_COUNT` (defensive;
26    /// callers should validate the opcode first).
27    pub fn read(&self, i: usize) -> u64 {
28        self.gpr.get(i).copied().unwrap_or(0)
29    }
30
31    /// Write register `i`. No-op if `i >= REG_COUNT`.
32    pub fn write(&mut self, i: usize, v: u64) {
33        if let Some(slot) = self.gpr.get_mut(i) {
34            *slot = v;
35        }
36    }
37}
38
39impl Default for Regs {
40    fn default() -> Self {
41        Self {
42            gpr: [0u64; REG_COUNT],
43            pc: 0,
44        }
45    }
46}
47
48#[cfg(test)]
49mod tests {
50    use super::*;
51
52    #[test]
53    fn new_is_zero() {
54        let r = Regs::new();
55        assert_eq!(r.pc, 0);
56        for i in 0..REG_COUNT {
57            assert_eq!(r.read(i), 0);
58        }
59    }
60
61    #[test]
62    fn read_write_round_trip() {
63        let mut r = Regs::new();
64        r.write(7, 0xDEAD_BEEF);
65        assert_eq!(r.read(7), 0xDEAD_BEEF);
66    }
67
68    #[test]
69    fn out_of_range_read_returns_zero() {
70        let r = Regs::new();
71        assert_eq!(r.read(99), 0);
72    }
73
74    #[test]
75    fn out_of_range_write_is_noop() {
76        let mut r = Regs::new();
77        r.write(99, 1);
78        // No panic; no state change.
79        for i in 0..REG_COUNT {
80            assert_eq!(r.read(i), 0);
81        }
82    }
83}