1use std::ops::{Index, IndexMut};
4
5use log::*;
6#[cfg(feature = "serde")]
7use serde::{Deserialize, Serialize};
8
9use crate::mode::Mode;
10use crate::util::bit::BitUtilExt;
11
12pub type Reg = u8;
13
14const NUM_RGSR: usize = 37;
15
16pub const SP: Reg = 13;
18pub const LR: Reg = 14;
20pub const PC: Reg = 15;
22pub const CPSR: Reg = 16;
24pub const SPSR: Reg = 17;
26
27pub(crate) mod cpsr {
28 use super::Reg;
29
30 pub const N: Reg = 31;
31 pub const Z: Reg = 30;
32 pub const C: Reg = 29;
33 pub const V: Reg = 28;
34
35 pub const T: Reg = 5;
36}
37
38#[rustfmt::skip]
39const REG_MAP: [[usize; 18]; 6] = [
40 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16], [0, 1, 2, 3, 4, 5, 6, 7, 17, 18, 19, 20, 21, 22, 23, 15, 16, 24], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 16, 27], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 28, 29, 15, 16, 30], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 31, 32, 15, 16, 33], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 34, 35, 15, 16, 36], ];
47
48#[cfg(feature = "serde")]
49mod big_array {
50 use serde_big_array::big_array;
51 big_array! { BigArray; +super::NUM_RGSR }
52}
53
54#[derive(Copy, Clone)]
55#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
56pub(crate) struct RegFile {
57 #[cfg_attr(feature = "serde", serde(with = "big_array::BigArray"))]
58 reg: [u32; NUM_RGSR],
59 bank: usize,
60}
61
62impl PartialEq for RegFile {
63 fn eq(&self, other: &Self) -> bool {
64 self.reg[..] == other.reg[..] && self.bank == other.bank
65 }
66}
67
68impl Eq for RegFile {}
69
70impl std::fmt::Debug for RegFile {
73 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
74 let mut builder = fmt.debug_struct("RegFile");
75 builder.field("cur_bank", &self.bank);
76 for (bank, map) in REG_MAP.iter().enumerate() {
77 let mut regs = Vec::new();
78 for (i, reg) in map.iter().copied().enumerate() {
79 match i as u8 {
80 SP => regs.push(("SP".to_string(), self.reg[reg])),
81 LR => regs.push(("LR".to_string(), self.reg[reg])),
82 PC => regs.push(("PC".to_string(), self.reg[reg])),
83 CPSR => regs.push(("CPSR".to_string(), self.reg[reg])),
84 SPSR => regs.push(("SPSR".to_string(), self.reg[reg])),
85 _ => regs.push((format!("r{}", i), self.reg[reg])),
86 };
87 }
88 builder.field(
89 match bank {
90 0 => "user ",
91 1 => "fiq ",
92 2 => "irq ",
93 3 => "supervisor ",
94 4 => "abort ",
95 5 => "undefined ",
96 _ => unreachable!(),
97 },
98 &format!("{:08x?}", regs).replace("\"", ""),
99 );
100 }
101 builder.finish()
102 }
103}
104
105impl RegFile {
106 pub fn new_empty() -> RegFile {
107 RegFile {
108 reg: [0; NUM_RGSR],
109 bank: 0,
110 }
111 }
112
113 #[inline]
114 pub fn mode(&self) -> Mode {
115 Mode::from_bits(self.reg[CPSR as usize].extract(0, 5) as u8)
118 .expect("CPSR contained invalid mode bits")
119 }
120
121 #[inline]
122 pub fn update_bank(&mut self) {
123 self.bank = self.mode().reg_bank();
124 }
125
126 #[inline]
127 pub fn set(&mut self, bank: usize, reg: Reg, mut val: u32) {
128 if reg == CPSR {
129 let bits = val.extract(0, 5) as u8;
130 let mode = Mode::from_bits(bits);
131 if mode.is_none() {
132 error!(
141 "Attempted to write to CPSR with invalid mode bits: {:#x}",
142 bits
143 );
144
145 let oldval = self.reg[CPSR as usize];
146 val = (val & !0x1f) | (oldval & 0x1f);
147 }
148 }
149
150 self.reg[REG_MAP[bank][reg as usize]] = val;
151 if reg == CPSR {
152 self.update_bank()
153 }
154 }
155
156 #[inline]
157 pub fn get(&self, bank: usize, reg: Reg) -> u32 {
158 self.reg[REG_MAP[bank][reg as usize]]
159 }
160}
161
162impl Index<Reg> for RegFile {
163 type Output = u32;
164 #[inline]
165 fn index(&self, idx: Reg) -> &u32 {
166 &self.reg[REG_MAP[self.bank][idx as usize]]
167 }
168}
169
170impl IndexMut<Reg> for RegFile {
171 #[inline]
172 fn index_mut(&mut self, idx: Reg) -> &mut u32 {
173 &mut self.reg[REG_MAP[self.bank][idx as usize]]
174 }
175}