This repository has been archived on 2024-12-14. You can view files and clone it, but cannot push or open issues or pull requests.
rustboyadvance-ng/src/arm7tdmi/psr.rs

155 lines
3.3 KiB
Rust
Raw Normal View History

2019-06-26 22:45:53 +01:00
/// The program status register
use std::fmt;
use crate::bit::BitIndex;
use crate::num_traits::FromPrimitive;
use super::{CpuMode, CpuState};
2019-06-26 22:45:53 +01:00
2019-06-27 13:13:38 +01:00
use colored::*;
2019-06-26 22:45:53 +01:00
impl From<CpuState> for bool {
fn from(state: CpuState) -> bool {
match state {
CpuState::ARM => false,
CpuState::THUMB => true,
}
}
}
impl From<bool> for CpuState {
fn from(flag: bool) -> CpuState {
if flag {
CpuState::THUMB
} else {
CpuState::ARM
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct RegPSR {
raw: u32,
}
const RESERVED_BIT_MASK: u32 = 0x0fffff00;
fn clear_reserved(n: u32) -> u32 {
n & !RESERVED_BIT_MASK
}
2019-06-27 13:13:38 +01:00
impl Default for RegPSR {
fn default() -> RegPSR {
let mut psr = RegPSR {
raw: clear_reserved(0),
};
2019-06-26 22:45:53 +01:00
psr.set_mode(CpuMode::Supervisor);
psr
}
2019-06-27 13:13:38 +01:00
}
2019-06-26 22:45:53 +01:00
2019-06-27 13:13:38 +01:00
impl RegPSR {
2019-06-26 22:45:53 +01:00
pub fn get(&self) -> u32 {
self.raw
}
pub fn set(&mut self, psr: u32) {
self.raw = clear_reserved(psr);
}
pub fn state(&self) -> CpuState {
self.raw.bit(5).into()
}
pub fn set_state(&mut self, state: CpuState) {
self.raw.set_bit(5, state.into());
}
pub fn mode(&self) -> CpuMode {
2019-06-27 13:03:44 +01:00
CpuMode::from_u32(self.raw.bit_range(0..5)).unwrap()
2019-06-26 22:45:53 +01:00
}
pub fn set_mode(&mut self, mode: CpuMode) {
2019-06-27 13:03:44 +01:00
self.raw.set_bit_range(0..5, (mode as u32) & 0b1_1111);
2019-06-26 22:45:53 +01:00
}
pub fn irq_disabled(&self) -> bool {
self.raw.bit(7)
}
pub fn set_irq_disabled(&mut self, disabled: bool) {
self.raw.set_bit(7, disabled);
}
pub fn fiq_disabled(&self) -> bool {
self.raw.bit(6)
}
pub fn set_fiq_disabled(&mut self, disabled: bool) {
self.raw.set_bit(6, disabled);
}
#[allow(non_snake_case)]
pub fn N(&self) -> bool {
self.raw.bit(31)
}
#[allow(non_snake_case)]
pub fn set_N(&mut self, flag: bool) {
self.raw.set_bit(31, flag);
}
#[allow(non_snake_case)]
pub fn Z(&self) -> bool {
self.raw.bit(30)
}
#[allow(non_snake_case)]
pub fn set_Z(&mut self, flag: bool) {
self.raw.set_bit(30, flag);
}
#[allow(non_snake_case)]
pub fn C(&self) -> bool {
self.raw.bit(29)
}
#[allow(non_snake_case)]
pub fn set_C(&mut self, flag: bool) {
self.raw.set_bit(29, flag);
}
#[allow(non_snake_case)]
pub fn V(&self) -> bool {
self.raw.bit(28)
}
#[allow(non_snake_case)]
pub fn set_V(&mut self, flag: bool) {
self.raw.set_bit(28, flag);
}
}
impl fmt::Display for RegPSR {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let disabled_string = |disabled: bool| -> ColoredString {
if disabled {
"disabled".bright_red()
} else {
"enabled".bright_green()
}
};
write!(
f,
"{{ mode: {mode}, state: {state}, irq: {irq}, fiq: {fiq}, condition_flags: (N={N} Z={Z} C={C} V={V}) }}",
mode = self.mode(),
state = self.state(),
irq = disabled_string(self.irq_disabled()),
fiq = disabled_string(self.irq_disabled()),
N = self.N() as u8,
Z = self.Z() as u8,
C = self.C() as u8,
V = self.V() as u8,
)
}
}