o1vm/interpreters/mips/
registers.rs

1use serde::{Deserialize, Serialize};
2use std::ops::{Index, IndexMut};
3
4pub const REGISTER_HI: usize = 32;
5pub const REGISTER_LO: usize = 33;
6pub const REGISTER_CURRENT_IP: usize = 34;
7pub const REGISTER_NEXT_IP: usize = 35;
8pub const REGISTER_HEAP_POINTER: usize = 36;
9pub const REGISTER_PREIMAGE_KEY_START: usize = 37;
10pub const REGISTER_PREIMAGE_KEY_END: usize = REGISTER_PREIMAGE_KEY_START + 8 /* 37 + 8 = 45 */;
11pub const REGISTER_PREIMAGE_OFFSET: usize = 45;
12
13pub const NUM_REGISTERS: usize = 46;
14
15/// This represents the internal state of the virtual machine.
16#[derive(Clone, Default, Debug, Serialize, Deserialize)]
17pub struct Registers<T> {
18    pub general_purpose: [T; 32],
19    pub hi: T,
20    pub lo: T,
21    pub current_instruction_pointer: T,
22    pub next_instruction_pointer: T,
23    pub heap_pointer: T,
24    pub preimage_key: [T; 8],
25    pub preimage_offset: T,
26}
27
28impl<T> Registers<T> {
29    pub fn iter(&self) -> impl Iterator<Item = &T> {
30        self.general_purpose
31            .iter()
32            .chain([
33                &self.hi,
34                &self.lo,
35                &self.current_instruction_pointer,
36                &self.next_instruction_pointer,
37                &self.heap_pointer,
38            ])
39            .chain(self.preimage_key.iter())
40            .chain([&self.preimage_offset])
41    }
42}
43
44impl<T: Clone> Index<usize> for Registers<T> {
45    type Output = T;
46
47    fn index(&self, index: usize) -> &Self::Output {
48        if index < 32 {
49            &self.general_purpose[index]
50        } else if index == REGISTER_HI {
51            &self.hi
52        } else if index == REGISTER_LO {
53            &self.lo
54        } else if index == REGISTER_CURRENT_IP {
55            &self.current_instruction_pointer
56        } else if index == REGISTER_NEXT_IP {
57            &self.next_instruction_pointer
58        } else if index == REGISTER_HEAP_POINTER {
59            &self.heap_pointer
60        } else if (REGISTER_PREIMAGE_KEY_START..REGISTER_PREIMAGE_KEY_END).contains(&index) {
61            &self.preimage_key[index - REGISTER_PREIMAGE_KEY_START]
62        } else if index == REGISTER_PREIMAGE_OFFSET {
63            &self.preimage_offset
64        } else {
65            panic!("Index out of bounds");
66        }
67    }
68}
69
70impl<T: Clone> IndexMut<usize> for Registers<T> {
71    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
72        if index < 32 {
73            &mut self.general_purpose[index]
74        } else if index == REGISTER_HI {
75            &mut self.hi
76        } else if index == REGISTER_LO {
77            &mut self.lo
78        } else if index == REGISTER_CURRENT_IP {
79            &mut self.current_instruction_pointer
80        } else if index == REGISTER_NEXT_IP {
81            &mut self.next_instruction_pointer
82        } else if index == REGISTER_HEAP_POINTER {
83            &mut self.heap_pointer
84        } else if (REGISTER_PREIMAGE_KEY_START..REGISTER_PREIMAGE_KEY_END).contains(&index) {
85            &mut self.preimage_key[index - REGISTER_PREIMAGE_KEY_START]
86        } else if index == REGISTER_PREIMAGE_OFFSET {
87            &mut self.preimage_offset
88        } else {
89            panic!("Index out of bounds");
90        }
91    }
92}