LCOV - code coverage report
Current view: top level - src/cpu - registers.rs (source / functions) Hit Total Coverage
Test: lcov Lines: 0 479 0.0 %
Date: 2023-12-07 18:49:03 Functions: 0 36 0.0 %
Legend: Lines: hit not hit

          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             : }

Generated by: LCOV version 1.16