Line data Source code
1 : use std::error::Error;
2 :
3 : use log::{info, warn};
4 :
5 : use crate::component::reset::Reset;
6 : use crate::component::snapshot::Snapshot;
7 : use crate::util::bit_manipulation::{is_bit_set_32, set_bit_32};
8 :
9 : pub const SP_REG: usize = 13;
10 : pub const LP_REG: usize = 14;
11 : pub const PC_REG: usize = 15;
12 :
13 : const NUM_OF_REGISTERS: usize = 16;
14 :
15 : pub struct Registers {
16 : skip_bios: bool,
17 :
18 : registers: Box<[u32]>,
19 : r8: u32,
20 : r8_fiq: u32,
21 : r9: u32,
22 : r9_fiq: u32,
23 : r10: u32,
24 : r10_fiq: u32,
25 : r11: u32,
26 : r11_fiq: u32,
27 : r12: u32,
28 : r12_fiq: u32,
29 : r13: u32,
30 : r13_fiq: u32,
31 : r13_svc: u32,
32 : r13_abt: u32,
33 : r13_irq: u32,
34 : r13_und: u32,
35 : r14: u32,
36 : r14_fiq: u32,
37 : r14_svc: u32,
38 : r14_abt: u32,
39 : r14_irq: u32,
40 : r14_und: u32,
41 : r15: u32,
42 :
43 : cpsr: Cpsr,
44 :
45 : // Swappable spsr regs
46 : spsr: u32,
47 : spsr_fiq: u32,
48 : spsr_svc: u32,
49 : spsr_abt: u32,
50 : spsr_irq: u32,
51 : spsr_und: u32,
52 :
53 : null_spsr: u32,
54 : }
55 :
56 : /// The current program status register.
57 : ///
58 : /// Read more ARM9: <https://tinyurl.com/2wxzw232>.
59 : ///
60 : /// Read more ARM11: <https://tinyurl.com/ymcvpnme>.
61 : struct Cpsr {
62 : /// Indicates if the result of a logical or arithmetic operation is
63 : /// negative.
64 : sign_flag: bool,
65 : /// Indicates if the result of a logical or arithmetic operation is zero.
66 : zero_flag: bool,
67 : /// Indicates if a arithmetic operation produced a carry, borrow, or the
68 : /// last bit of a shifted out value. This value is normally left unchanged
69 : /// by non-addition/subtraction operations, but there are exceptions for
70 : /// some.
71 : carry_flag: bool,
72 : /// Indicates if a arithmetic operation produced an overflow. This value is
73 : /// normally left unchanged by non-addition/subtraction operations, but
74 : /// there are exceptions for some.
75 : overflow_flag: bool,
76 : /// Indicates if a overflow and/or saturation has occurred in some
77 : /// DSP-oriented instructions.
78 : sticky_overflow_flag: bool,
79 : /// ARM11 only: Indicates if the processor is in Jazelle state to support
80 : /// execution of Java bytecode. The Nintendo 3DS does not support
81 : /// Jazelle, if the processor attempts to enter Jazelle using the BXJ
82 : /// instruction, it will function as a normal BX instruction.
83 : /// See: <https://tinyurl.com/3y8aycz4>.
84 : jazelle_state: bool,
85 : /// ARM11 only: Set by SIMD instructions to indicate whether the result of a
86 : /// SIMD instruction is greater than or equal to the corresponding operand.
87 : /// Abbreviated as "GE" and composed of 4 bits, each bit corresponds to a
88 : /// halfword or byte in the result. These flags are later used to control
89 : /// a later SEL instruction.
90 : ///
91 : /// For instructions that operate on halfwords:
92 : /// - set or clear GE[3:2] together, based on the result on the top halfword
93 : /// calculation.
94 : /// - set or clear GE[1:0] together, based on the result on the bottom
95 : /// halfword calculation.
96 : ///
97 : /// For instructions that operate on bytes:
98 : /// - set or clear GE[3] based on the result on the top byte calculation.
99 : /// - set or clear GE[2] based on the result on the second byte calculation.
100 : /// - set or clear GE[1] based on the result on the third byte calculation.
101 : /// - set or clear GE[0] based on the result on the bottom byte calculation.
102 : ///
103 : /// Using the rules above, each bit are set or cleared if the results of the
104 : /// corresponding calculation are as follows:
105 : /// - for unsigned byte addition, if the result is greater than or equal to
106 : /// 2^8.
107 : /// - for unsigned halfword addition, of the result is greater than or equal
108 : /// to 2^16.
109 : /// - for unsigned subtraction, if the result is greater than or equal to
110 : /// zero.
111 : /// - for signed arithmetic, if the result is greater than or equal to zero.
112 : greater_than_or_equal_to: [bool; 4],
113 : /// ARM11 only: Controls the endianness of load and store instructions. This
114 : /// bit is ignored by instruction fetches. When set, load/store operates in
115 : /// big-endian, when cleared, load/store operates in little-endian.
116 : data_endianness_bit: bool,
117 : /// ARM11 only: Indicates whether to disable imprecise Data Aborts.
118 : imprecise_data_abort: bool,
119 : /// Whether to disable IRQ interrupts.
120 : irq_disabled: bool,
121 : /// Whether to disable FIQ interrupts.
122 : fiq_disabled: bool,
123 : /// Indicates if the processor is in THUMB when set or ARM state when
124 : /// cleared.
125 : thumb_state: bool,
126 : /// The operating mode the processor is currently in.
127 : mode: OperatingMode,
128 : }
129 :
130 0 : #[derive(Clone, Copy, PartialEq)]
131 : pub enum OperatingMode {
132 : Unknown,
133 : User = 0x10,
134 : Fiq = 0x11,
135 : Irq = 0x12,
136 : Supervisor = 0x13,
137 : Abort = 0x17,
138 : Undefined = 0x1B,
139 : System = 0x1F,
140 : }
141 :
142 : impl OperatingMode {
143 0 : pub fn to_string(self) -> &'static str {
144 0 : match self {
145 0 : OperatingMode::User => "User",
146 0 : OperatingMode::Fiq => "FIQ",
147 0 : OperatingMode::Irq => "IRQ",
148 0 : OperatingMode::Supervisor => "Supervisor",
149 0 : OperatingMode::Abort => "Abort",
150 0 : OperatingMode::Undefined => "Undefined",
151 0 : OperatingMode::System => "System",
152 0 : OperatingMode::Unknown => "Unknown",
153 : }
154 0 : }
155 :
156 0 : pub fn from_u32(val: u32) -> OperatingMode {
157 0 : match val {
158 0 : 0x10 => OperatingMode::User,
159 0 : 0x11 => OperatingMode::Fiq,
160 0 : 0x12 => OperatingMode::Irq,
161 0 : 0x13 => OperatingMode::Supervisor,
162 0 : 0x17 => OperatingMode::Abort,
163 0 : 0x1B => OperatingMode::Undefined,
164 0 : 0x1F => OperatingMode::System,
165 0 : _ => OperatingMode::Unknown,
166 : }
167 0 : }
168 : }
169 :
170 : impl Cpsr {
171 : const SIGN_FLAG_IDX: i32 = 31;
172 : const ZERO_FLAG_IDX: i32 = 30;
173 : const CARRY_FLAG_IDX: i32 = 29;
174 : const OVERFLOW_FLAG_IDX: i32 = 28;
175 : const STICKY_OVERFLOW_IDX: i32 = 27;
176 : const JAZELLE_STATE_IDX: i32 = 24;
177 : const GREATER_THAN_OR_EQUAL_TO_BIT_3_IDX: i32 = 22;
178 : const GREATER_THAN_OR_EQUAL_TO_BIT_2_IDX: i32 = 21;
179 : const GREATER_THAN_OR_EQUAL_TO_BIT_1_IDX: i32 = 20;
180 : const GREATER_THAN_OR_EQUAL_TO_BIT_0_IDX: i32 = 19;
181 : const E_BIT_IDX: i32 = 9;
182 : const A_BIT_IDX: i32 = 8;
183 : const IRQ_DISABLED_IDX: i32 = 7;
184 : const FIQ_DISABLED_IDX: i32 = 6;
185 : const THUMB_STATE_IDX: i32 = 5;
186 : const MODE_EXTRACT_BITS: u32 = 0x1F;
187 :
188 0 : fn new() -> Self {
189 0 : Self {
190 0 : sign_flag: false,
191 0 : zero_flag: false,
192 0 : carry_flag: false,
193 0 : overflow_flag: false,
194 0 : sticky_overflow_flag: false,
195 0 : jazelle_state: false,
196 0 : greater_than_or_equal_to: [false, false, false, false],
197 0 : data_endianness_bit: false,
198 0 : imprecise_data_abort: false,
199 0 : irq_disabled: false,
200 0 : fiq_disabled: false,
201 0 : thumb_state: false,
202 0 : mode: OperatingMode::User,
203 0 : }
204 0 : }
205 :
206 0 : fn get_mode(&self) -> OperatingMode {
207 0 : self.mode
208 0 : }
209 :
210 : /// Sets the value of the CPSR register.
211 : ///
212 : /// Be aware that this function updates the CPSR mode value, but does not
213 : /// swap banked registers. Be sure to call
214 : /// [Registers::switch_operating_mode] along side this function to
215 : /// properly update the operating mode registers.
216 0 : fn set(&mut self, val: u32) {
217 0 : self.sign_flag = is_bit_set_32(val, Cpsr::SIGN_FLAG_IDX);
218 0 : self.zero_flag = is_bit_set_32(val, Cpsr::ZERO_FLAG_IDX);
219 0 : self.carry_flag = is_bit_set_32(val, Cpsr::CARRY_FLAG_IDX);
220 0 : self.overflow_flag = is_bit_set_32(val, Cpsr::OVERFLOW_FLAG_IDX);
221 0 : self.sticky_overflow_flag = is_bit_set_32(val, Cpsr::STICKY_OVERFLOW_IDX);
222 0 : self.jazelle_state = is_bit_set_32(val, Cpsr::JAZELLE_STATE_IDX);
223 0 : self.greater_than_or_equal_to[3] =
224 0 : is_bit_set_32(val, Cpsr::GREATER_THAN_OR_EQUAL_TO_BIT_3_IDX);
225 0 : self.greater_than_or_equal_to[2] =
226 0 : is_bit_set_32(val, Cpsr::GREATER_THAN_OR_EQUAL_TO_BIT_2_IDX);
227 0 : self.greater_than_or_equal_to[1] =
228 0 : is_bit_set_32(val, Cpsr::GREATER_THAN_OR_EQUAL_TO_BIT_1_IDX);
229 0 : self.greater_than_or_equal_to[0] =
230 0 : is_bit_set_32(val, Cpsr::GREATER_THAN_OR_EQUAL_TO_BIT_0_IDX);
231 0 : self.data_endianness_bit = is_bit_set_32(val, Cpsr::E_BIT_IDX);
232 0 : self.imprecise_data_abort = is_bit_set_32(val, Cpsr::A_BIT_IDX);
233 0 : self.irq_disabled = is_bit_set_32(val, Cpsr::IRQ_DISABLED_IDX);
234 0 : self.fiq_disabled = is_bit_set_32(val, Cpsr::FIQ_DISABLED_IDX);
235 0 : self.thumb_state = is_bit_set_32(val, Cpsr::THUMB_STATE_IDX);
236 0 :
237 0 : let new_mode = OperatingMode::from_u32(val & Cpsr::MODE_EXTRACT_BITS);
238 0 : if new_mode != OperatingMode::Unknown {
239 0 : self.mode = new_mode;
240 0 : }
241 0 : }
242 :
243 0 : fn val(&self) -> u32 {
244 0 : let mut cpsr_val: u32 = 0;
245 0 : cpsr_val = set_bit_32(cpsr_val, Cpsr::SIGN_FLAG_IDX, self.sign_flag);
246 0 : cpsr_val = set_bit_32(cpsr_val, Cpsr::ZERO_FLAG_IDX, self.zero_flag);
247 0 : cpsr_val = set_bit_32(cpsr_val, Cpsr::CARRY_FLAG_IDX, self.carry_flag);
248 0 : cpsr_val = set_bit_32(cpsr_val, Cpsr::OVERFLOW_FLAG_IDX, self.overflow_flag);
249 0 : cpsr_val = set_bit_32(cpsr_val, Cpsr::STICKY_OVERFLOW_IDX, self.sticky_overflow_flag);
250 0 : cpsr_val = set_bit_32(cpsr_val, Cpsr::JAZELLE_STATE_IDX, self.jazelle_state);
251 0 : cpsr_val = set_bit_32(
252 0 : cpsr_val,
253 0 : Cpsr::GREATER_THAN_OR_EQUAL_TO_BIT_3_IDX,
254 0 : self.greater_than_or_equal_to[3],
255 0 : );
256 0 : cpsr_val = set_bit_32(
257 0 : cpsr_val,
258 0 : Cpsr::GREATER_THAN_OR_EQUAL_TO_BIT_2_IDX,
259 0 : self.greater_than_or_equal_to[2],
260 0 : );
261 0 : cpsr_val = set_bit_32(
262 0 : cpsr_val,
263 0 : Cpsr::GREATER_THAN_OR_EQUAL_TO_BIT_1_IDX,
264 0 : self.greater_than_or_equal_to[1],
265 0 : );
266 0 : cpsr_val = set_bit_32(
267 0 : cpsr_val,
268 0 : Cpsr::GREATER_THAN_OR_EQUAL_TO_BIT_0_IDX,
269 0 : self.greater_than_or_equal_to[0],
270 0 : );
271 0 : cpsr_val = set_bit_32(cpsr_val, Cpsr::E_BIT_IDX, self.data_endianness_bit);
272 0 : cpsr_val = set_bit_32(cpsr_val, Cpsr::A_BIT_IDX, self.imprecise_data_abort);
273 0 : cpsr_val = set_bit_32(cpsr_val, Cpsr::IRQ_DISABLED_IDX, self.irq_disabled);
274 0 : cpsr_val = set_bit_32(cpsr_val, Cpsr::FIQ_DISABLED_IDX, self.fiq_disabled);
275 0 : cpsr_val = set_bit_32(cpsr_val, Cpsr::THUMB_STATE_IDX, self.thumb_state);
276 0 : cpsr_val |= self.mode as u32;
277 0 : cpsr_val
278 0 : }
279 : }
280 :
281 : impl Reset for Cpsr {
282 : /// Resets the CPSR register to its default state.
283 : ///
284 : /// On reset, the CPSR enters [`OperatingMode::Supervisor`] and disabled
285 : /// data imprecise aborts, fiq, and irq bits. In our case, we will set all
286 : /// bits to false.
287 : ///
288 : /// See: <https://tinyurl.com/43kwv52u> and <https://tinyurl.com/2r9fmhyc>.
289 0 : fn reset(&mut self) {
290 0 : self.sign_flag = false;
291 0 : self.zero_flag = false;
292 0 : self.carry_flag = false;
293 0 : self.overflow_flag = false;
294 0 : self.sticky_overflow_flag = false;
295 0 : self.jazelle_state = false;
296 0 : self.greater_than_or_equal_to.fill(false);
297 0 : self.data_endianness_bit = false;
298 0 : self.imprecise_data_abort = false;
299 0 : self.irq_disabled = false;
300 0 : self.fiq_disabled = false;
301 0 : self.thumb_state = false;
302 0 : self.mode = OperatingMode::Supervisor;
303 0 : }
304 : }
305 :
306 : impl Registers {
307 0 : pub fn new(skip_bios: bool) -> Self {
308 0 : Self {
309 0 : skip_bios,
310 0 : registers: vec![0u32; NUM_OF_REGISTERS].into_boxed_slice(),
311 0 : r8: 0,
312 0 : r8_fiq: 0,
313 0 : r9: 0,
314 0 : r9_fiq: 0,
315 0 : r10: 0,
316 0 : r10_fiq: 0,
317 0 : r11: 0,
318 0 : r11_fiq: 0,
319 0 : r12: 0,
320 0 : r12_fiq: 0,
321 0 : r13: 0,
322 0 : r13_fiq: 0,
323 0 : r13_svc: 0,
324 0 : r13_abt: 0,
325 0 : r13_irq: 0,
326 0 : r13_und: 0,
327 0 : r14: 0,
328 0 : r14_fiq: 0,
329 0 : r14_svc: 0,
330 0 : r14_abt: 0,
331 0 : r14_irq: 0,
332 0 : r14_und: 0,
333 0 : r15: 0,
334 0 : cpsr: Cpsr::new(),
335 0 : spsr: 0,
336 0 : spsr_fiq: 0,
337 0 : spsr_svc: 0,
338 0 : spsr_abt: 0,
339 0 : spsr_irq: 0,
340 0 : spsr_und: 0,
341 0 : null_spsr: 0,
342 0 : }
343 0 : }
344 :
345 0 : pub fn read_register(&self, reg_idx: usize) -> u32 {
346 0 : self.registers[reg_idx]
347 0 : }
348 :
349 0 : pub fn write_register(&mut self, reg_idx: usize, val: u32) {
350 0 : self.registers[reg_idx] = val
351 0 : }
352 :
353 0 : pub fn spsr(&self) -> u32 {
354 0 : // Even if SPSR doesn't exist, it a "dummy" spsr can still be read.
355 0 : if !self.does_spsr_exist() {
356 0 : info!("[Register] Reading spsr in mode where it shouldn't exist");
357 0 : }
358 0 : self.spsr
359 0 : }
360 :
361 0 : pub fn set_spsr(&mut self, spsr: u32) {
362 0 : // Even if SPSR doesn't exist, it a "dummy" spsr can still be written.
363 0 : if !self.does_spsr_exist() {
364 0 : info!(
365 0 : "[Register] Writing to spsr in mode where it shouldn't exist with data: {:#X}",
366 : spsr
367 : );
368 0 : }
369 0 : self.spsr = spsr;
370 0 : }
371 :
372 : /// Returns if an spsr exists in the current [OperatingMode].
373 0 : fn does_spsr_exist(&self) -> bool {
374 0 : self.cpsr.get_mode() == OperatingMode::User || self.cpsr.get_mode() == OperatingMode::System
375 0 : }
376 :
377 0 : pub fn switch_operating_mode(&mut self, new_mode: OperatingMode) {
378 0 : let old_mode = self.cpsr.get_mode();
379 0 :
380 0 : // Ignore if invalid mode
381 0 : if new_mode == OperatingMode::Unknown {
382 0 : warn!("Tried to set to unknown mode");
383 0 : return;
384 0 : }
385 0 :
386 0 : // Ignore if already in new mode
387 0 : if new_mode == old_mode {
388 0 : return;
389 0 : }
390 0 :
391 0 : // Swap banked mode registers into their appropriate variables.
392 0 : match old_mode {
393 0 : OperatingMode::User | OperatingMode::System => {
394 0 : self.r8 = self.registers[8];
395 0 : self.r9 = self.registers[9];
396 0 : self.r10 = self.registers[10];
397 0 : self.r11 = self.registers[11];
398 0 : self.r12 = self.registers[12];
399 0 : self.r13 = self.registers[13];
400 0 : self.r14 = self.registers[14];
401 0 : self.null_spsr = self.spsr;
402 0 : }
403 : OperatingMode::Fiq => {
404 0 : self.r8_fiq = self.registers[8];
405 0 : self.r9_fiq = self.registers[9];
406 0 : self.r10_fiq = self.registers[10];
407 0 : self.r11_fiq = self.registers[11];
408 0 : self.r12_fiq = self.registers[12];
409 0 : self.r13_fiq = self.registers[13];
410 0 : self.r14_fiq = self.registers[14];
411 0 : self.spsr_fiq = self.spsr
412 : }
413 : OperatingMode::Irq => {
414 0 : self.r8 = self.registers[8];
415 0 : self.r9 = self.registers[9];
416 0 : self.r10 = self.registers[10];
417 0 : self.r11 = self.registers[11];
418 0 : self.r12 = self.registers[12];
419 0 : self.r13_irq = self.registers[13];
420 0 : self.r14_irq = self.registers[14];
421 0 : self.spsr_irq = self.spsr
422 : }
423 : OperatingMode::Supervisor => {
424 0 : self.r8 = self.registers[8];
425 0 : self.r9 = self.registers[9];
426 0 : self.r10 = self.registers[10];
427 0 : self.r11 = self.registers[11];
428 0 : self.r12 = self.registers[12];
429 0 : self.r13_svc = self.registers[13];
430 0 : self.r14_svc = self.registers[14];
431 0 : self.spsr_svc = self.spsr
432 : }
433 : OperatingMode::Abort => {
434 0 : self.r8 = self.registers[8];
435 0 : self.r9 = self.registers[9];
436 0 : self.r10 = self.registers[10];
437 0 : self.r11 = self.registers[11];
438 0 : self.r12 = self.registers[12];
439 0 : self.r13_abt = self.registers[13];
440 0 : self.r14_abt = self.registers[14];
441 0 : self.spsr_abt = self.spsr
442 : }
443 : OperatingMode::Undefined => {
444 0 : self.r8 = self.registers[8];
445 0 : self.r9 = self.registers[9];
446 0 : self.r10 = self.registers[10];
447 0 : self.r11 = self.registers[11];
448 0 : self.r12 = self.registers[12];
449 0 : self.r13_und = self.registers[13];
450 0 : self.r14_und = self.registers[14];
451 0 : self.spsr_und = self.spsr
452 : }
453 : _ => {
454 0 : warn!(
455 0 : "[Registers] Unable to switch operating mode because current mode is an invalid mode"
456 : )
457 : }
458 : }
459 :
460 0 : self.registers[8] = self.r8;
461 0 : self.registers[9] = self.r9;
462 0 : self.registers[10] = self.r10;
463 0 : self.registers[11] = self.r11;
464 0 : self.registers[12] = self.r12;
465 0 : self.registers[13] = self.r13;
466 0 : self.registers[14] = self.r14;
467 0 : self.spsr = self.null_spsr;
468 0 :
469 0 : match new_mode {
470 0 : OperatingMode::User | OperatingMode::System => {}
471 0 : OperatingMode::Fiq => {
472 0 : self.registers[8] = self.r8_fiq;
473 0 : self.registers[9] = self.r9_fiq;
474 0 : self.registers[10] = self.r10_fiq;
475 0 : self.registers[11] = self.r11_fiq;
476 0 : self.registers[12] = self.r12_fiq;
477 0 : self.registers[13] = self.r13_fiq;
478 0 : self.registers[14] = self.r14_fiq;
479 0 : self.spsr = self.spsr_fiq;
480 0 : }
481 0 : OperatingMode::Irq => {
482 0 : self.registers[13] = self.r13_irq;
483 0 : self.registers[14] = self.r14_irq;
484 0 : self.spsr = self.spsr_irq;
485 0 : }
486 0 : OperatingMode::Supervisor => {
487 0 : self.registers[13] = self.r13_svc;
488 0 : self.registers[14] = self.r14_svc;
489 0 : self.spsr = self.spsr_svc;
490 0 : }
491 0 : OperatingMode::Abort => {
492 0 : self.registers[13] = self.r13_abt;
493 0 : self.registers[14] = self.r14_abt;
494 0 : self.spsr = self.spsr_abt;
495 0 : }
496 0 : OperatingMode::Undefined => {
497 0 : self.registers[13] = self.r13_und;
498 0 : self.registers[14] = self.r14_und;
499 0 : self.spsr = self.spsr_und;
500 0 : }
501 : _ => {
502 : // TODO: Update logs in here.
503 0 : warn!("Can't update to invalid opearting mode: {:#X}", new_mode as i32);
504 : }
505 : }
506 :
507 0 : self.cpsr.mode = new_mode;
508 0 : }
509 :
510 0 : pub fn get_sign_flag(&self) -> bool {
511 0 : self.cpsr.sign_flag
512 0 : }
513 :
514 0 : pub fn set_sign_flag(&mut self, sign_flag_val: bool) {
515 0 : self.cpsr.sign_flag = sign_flag_val
516 0 : }
517 :
518 0 : pub fn get_zero_flag(&self) -> bool {
519 0 : self.cpsr.zero_flag
520 0 : }
521 :
522 0 : pub fn set_zero_flag(&mut self, zero_flag_val: bool) {
523 0 : self.cpsr.zero_flag = zero_flag_val
524 0 : }
525 :
526 0 : pub fn get_carry_flag(&self) -> bool {
527 0 : self.cpsr.carry_flag
528 0 : }
529 :
530 0 : pub fn set_carry_flag(&mut self, carry_flag_val: bool) {
531 0 : self.cpsr.carry_flag = carry_flag_val
532 0 : }
533 :
534 0 : pub fn get_overflow_flag(&self) -> bool {
535 0 : self.cpsr.overflow_flag
536 0 : }
537 :
538 0 : pub fn set_overflow_flag(&mut self, overflow_flag_val: bool) {
539 0 : self.cpsr.overflow_flag = overflow_flag_val
540 0 : }
541 :
542 0 : pub fn get_irq_disabled_flag(&self) -> bool {
543 0 : self.cpsr.irq_disabled
544 0 : }
545 :
546 0 : pub fn set_irq_disabled(&mut self, irq_disabled_val: bool) {
547 0 : self.cpsr.irq_disabled = irq_disabled_val
548 0 : }
549 :
550 0 : pub fn get_fiq_disabled(&self) -> bool {
551 0 : self.cpsr.fiq_disabled
552 0 : }
553 :
554 0 : pub fn set_fiq_disabled(&mut self, fiq_disabled_val: bool) {
555 0 : self.cpsr.fiq_disabled = fiq_disabled_val
556 0 : }
557 :
558 0 : pub fn get_thumb_state(&self) -> bool {
559 0 : self.cpsr.thumb_state
560 0 : }
561 :
562 0 : pub fn set_thumb_state(&mut self, thumb_state_val: bool) {
563 0 : self.cpsr.thumb_state = thumb_state_val
564 0 : }
565 :
566 0 : pub fn get_opearting_mode(&self) -> OperatingMode {
567 0 : self.cpsr.mode
568 0 : }
569 :
570 0 : pub fn cpsr(&self) -> u32 {
571 0 : self.cpsr.val()
572 0 : }
573 :
574 0 : pub fn set_cpsr(&mut self, cpsr: u32) {
575 0 : self.switch_operating_mode(OperatingMode::from_u32(cpsr & Cpsr::MODE_EXTRACT_BITS));
576 0 : self.cpsr.set(cpsr);
577 0 : }
578 : }
579 :
580 : impl Reset for Registers {
581 0 : fn reset(&mut self) {
582 0 : self.cpsr.reset();
583 0 :
584 0 : // Clear registers
585 0 : self.registers.fill(0);
586 0 : self.r8 = 0;
587 0 : self.r8_fiq = 0;
588 0 : self.r9 = 0;
589 0 : self.r9_fiq = 0;
590 0 : self.r10 = 0;
591 0 : self.r10_fiq = 0;
592 0 : self.r11 = 0;
593 0 : self.r11_fiq = 0;
594 0 : self.r12 = 0;
595 0 : self.r12_fiq = 0;
596 0 : self.r13 = 0;
597 0 : self.r13_fiq = 0;
598 0 : self.r13_svc = 0;
599 0 : self.r13_abt = 0;
600 0 : self.r13_irq = 0;
601 0 : self.r13_und = 0;
602 0 : self.r14 = 0;
603 0 : self.r14_fiq = 0;
604 0 : self.r14_svc = 0;
605 0 : self.r14_abt = 0;
606 0 : self.r14_irq = 0;
607 0 : self.r14_und = 0;
608 0 : // Reset vector
609 0 : self.r15 = 0;
610 0 : self.spsr = 0;
611 0 : self.spsr_fiq = 0;
612 0 : self.spsr_svc = 0;
613 0 : self.spsr_abt = 0;
614 0 : self.spsr_irq = 0;
615 0 : self.spsr_und = 0;
616 0 : self.null_spsr = 0;
617 0 : }
618 : }
619 :
620 : /* Snapshot memento */
621 : struct CpsrSnapshot {
622 : sign_flag: bool,
623 : zero_flag: bool,
624 : carry_flag: bool,
625 : overflow_flag: bool,
626 : sticky_overflow_flag: bool,
627 : jazelle_state: bool,
628 : greater_than_or_equal_to: [bool; 4],
629 : data_endianness_bit: bool,
630 : imprecise_data_abort: bool,
631 : irq_disabled: bool,
632 : fiq_disabled: bool,
633 : thumb_state: bool,
634 : mode: OperatingMode,
635 : }
636 :
637 : pub struct RegistersSnapshot {
638 : skip_bios: bool,
639 : registers: Box<[u32]>,
640 : r8: u32,
641 : r8_fiq: u32,
642 : r9: u32,
643 : r9_fiq: u32,
644 : r10: u32,
645 : r10_fiq: u32,
646 : r11: u32,
647 : r11_fiq: u32,
648 : r12: u32,
649 : r12_fiq: u32,
650 : r13: u32,
651 : r13_fiq: u32,
652 : r13_svc: u32,
653 : r13_abt: u32,
654 : r13_irq: u32,
655 : r13_und: u32,
656 : r14: u32,
657 : r14_fiq: u32,
658 : r14_svc: u32,
659 : r14_abt: u32,
660 : r14_irq: u32,
661 : r14_und: u32,
662 : r15: u32,
663 : cpsr: CpsrSnapshot,
664 : spsr: u32,
665 : spsr_fiq: u32,
666 : spsr_svc: u32,
667 : spsr_abt: u32,
668 : spsr_irq: u32,
669 : spsr_und: u32,
670 : null_spsr: u32,
671 : }
672 :
673 : impl Snapshot<RegistersSnapshot> for Registers {
674 0 : fn capture(self) -> Result<RegistersSnapshot, ()> {
675 0 : Ok(RegistersSnapshot {
676 0 : skip_bios: self.skip_bios.to_owned(),
677 0 : registers: self.registers.to_owned(),
678 0 : r8: self.r8.to_owned(),
679 0 : r8_fiq: self.r8_fiq.to_owned(),
680 0 : r9: self.r9.to_owned(),
681 0 : r9_fiq: self.r9_fiq.to_owned(),
682 0 : r10: self.r10.to_owned(),
683 0 : r10_fiq: self.r10_fiq.to_owned(),
684 0 : r11: self.r11.to_owned(),
685 0 : r11_fiq: self.r11_fiq.to_owned(),
686 0 : r12: self.r12.to_owned(),
687 0 : r12_fiq: self.r12_fiq.to_owned(),
688 0 : r13: self.r13.to_owned(),
689 0 : r13_fiq: self.r13_fiq.to_owned(),
690 0 : r13_svc: self.r13_svc.to_owned(),
691 0 : r13_abt: self.r13_abt.to_owned(),
692 0 : r13_irq: self.r13_irq.to_owned(),
693 0 : r13_und: self.r13_und.to_owned(),
694 0 : r14: self.r14.to_owned(),
695 0 : r14_fiq: self.r14_fiq.to_owned(),
696 0 : r14_svc: self.r14_svc.to_owned(),
697 0 : r14_abt: self.r14_abt.to_owned(),
698 0 : r14_irq: self.r14_irq.to_owned(),
699 0 : r14_und: self.r14_und.to_owned(),
700 0 : r15: self.r15.to_owned(),
701 0 : cpsr: CpsrSnapshot {
702 0 : sign_flag: self.cpsr.sign_flag.to_owned(),
703 0 : zero_flag: self.cpsr.zero_flag.to_owned(),
704 0 : carry_flag: self.cpsr.carry_flag.to_owned(),
705 0 : overflow_flag: self.cpsr.overflow_flag.to_owned(),
706 0 : sticky_overflow_flag: self.cpsr.sticky_overflow_flag.to_owned(),
707 0 : jazelle_state: self.cpsr.jazelle_state.to_owned(),
708 0 : greater_than_or_equal_to: self.cpsr.greater_than_or_equal_to.to_owned(),
709 0 : data_endianness_bit: self.cpsr.data_endianness_bit.to_owned(),
710 0 : imprecise_data_abort: self.cpsr.imprecise_data_abort.to_owned(),
711 0 : irq_disabled: self.cpsr.irq_disabled.to_owned(),
712 0 : fiq_disabled: self.cpsr.fiq_disabled.to_owned(),
713 0 : thumb_state: self.cpsr.thumb_state.to_owned(),
714 0 : mode: self.cpsr.mode.to_owned(),
715 0 : },
716 0 : spsr: self.spsr.to_owned(),
717 0 : spsr_fiq: self.spsr_fiq.to_owned(),
718 0 : spsr_svc: self.spsr_svc.to_owned(),
719 0 : spsr_abt: self.spsr_abt.to_owned(),
720 0 : spsr_irq: self.spsr_irq.to_owned(),
721 0 : spsr_und: self.spsr_und.to_owned(),
722 0 : null_spsr: self.null_spsr.to_owned(),
723 0 : })
724 0 : }
725 :
726 0 : fn restore(&mut self, snapshot: RegistersSnapshot) -> Result<(), Box<dyn Error>> {
727 0 : self.skip_bios = snapshot.skip_bios.to_owned();
728 0 : self.registers = snapshot.registers.to_owned();
729 0 : self.r8 = snapshot.r8.to_owned();
730 0 : self.r8_fiq = snapshot.r8_fiq.to_owned();
731 0 : self.r9 = snapshot.r9.to_owned();
732 0 : self.r9_fiq = snapshot.r9_fiq.to_owned();
733 0 : self.r10 = snapshot.r10.to_owned();
734 0 : self.r10_fiq = snapshot.r10_fiq.to_owned();
735 0 : self.r11 = snapshot.r11.to_owned();
736 0 : self.r11_fiq = snapshot.r11_fiq.to_owned();
737 0 : self.r12 = snapshot.r12.to_owned();
738 0 : self.r12_fiq = snapshot.r12_fiq.to_owned();
739 0 : self.r13 = snapshot.r13.to_owned();
740 0 : self.r13_fiq = snapshot.r13_fiq.to_owned();
741 0 : self.r13_svc = snapshot.r13_svc.to_owned();
742 0 : self.r13_abt = snapshot.r13_abt.to_owned();
743 0 : self.r13_irq = snapshot.r13_irq.to_owned();
744 0 : self.r13_und = snapshot.r13_und.to_owned();
745 0 : self.r14 = snapshot.r14.to_owned();
746 0 : self.r14_fiq = snapshot.r14_fiq.to_owned();
747 0 : self.r14_svc = snapshot.r14_svc.to_owned();
748 0 : self.r14_abt = snapshot.r14_abt.to_owned();
749 0 : self.r14_irq = snapshot.r14_irq.to_owned();
750 0 : self.r14_und = snapshot.r14_und.to_owned();
751 0 : self.r15 = snapshot.r15.to_owned();
752 0 :
753 0 : self.cpsr.sign_flag = snapshot.cpsr.sign_flag.to_owned();
754 0 : self.cpsr.zero_flag = snapshot.cpsr.zero_flag.to_owned();
755 0 : self.cpsr.carry_flag = snapshot.cpsr.carry_flag.to_owned();
756 0 : self.cpsr.overflow_flag = snapshot.cpsr.overflow_flag.to_owned();
757 0 : self.cpsr.irq_disabled = snapshot.cpsr.irq_disabled.to_owned();
758 0 : self.cpsr.fiq_disabled = snapshot.cpsr.fiq_disabled.to_owned();
759 0 : self.cpsr.thumb_state = snapshot.cpsr.thumb_state.to_owned();
760 0 : self.cpsr.mode = snapshot.cpsr.mode.to_owned();
761 0 :
762 0 : self.spsr = snapshot.spsr.to_owned();
763 0 : self.spsr_fiq = snapshot.spsr_fiq.to_owned();
764 0 : self.spsr_svc = snapshot.spsr_svc.to_owned();
765 0 : self.spsr_abt = snapshot.spsr_abt.to_owned();
766 0 : self.spsr_irq = snapshot.spsr_irq.to_owned();
767 0 : self.spsr_und = snapshot.spsr_und.to_owned();
768 0 : self.null_spsr = snapshot.null_spsr.to_owned();
769 0 :
770 0 : Ok(())
771 0 : }
772 : }
|