use crate::{core::Condition, core::ItState, helpers::BitAccess, instructions::DecodeHelper};
use core::panic;
use std::{
fmt::{self, Debug, Display},
ops::Index,
};
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum RegisterIndex {
R0,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R8,
R9,
R10,
R11,
R12,
Sp,
Lr,
Pc,
Apsr,
Iapsr,
Eapsr,
Xpsr,
Ipsr,
Epsr,
Iepsr,
Msp,
Psp,
Primask,
Basepri,
BasepriMax,
FaultMask,
Control,
}
impl RegisterIndex {
pub fn new_main(index: u32) -> Self {
match index {
0 => Self::R0,
1 => Self::R1,
2 => Self::R2,
3 => Self::R3,
4 => Self::R4,
5 => Self::R5,
6 => Self::R6,
7 => Self::R7,
8 => Self::R8,
9 => Self::R9,
10 => Self::R10,
11 => Self::R11,
12 => Self::R12,
13 => Self::Sp,
14 => Self::Lr,
15 => Self::Pc,
_ => panic!("invalid main register index"),
}
}
#[cfg(test)]
pub fn new_general_random() -> Self {
use rand::Rng;
let mut rng = rand::rng();
Self::new_main(rng.random_range(..=12))
}
#[cfg(test)]
pub fn pick_two_general_distinct() -> (Self, Self) {
use rand::Rng;
let mut rng = rand::rng();
let range = 0..=12;
let first = rng.random_range(range.clone());
let mut second = rng.random_range(range.clone());
while second == first {
second = rng.random_range(range.clone());
}
(Self::new_main(first), Self::new_main(second))
}
#[cfg(test)]
pub fn pick_four_general_distinct() -> (Self, Self, Self, Self) {
let mut rng = rand::rng();
let regs: Vec<_> = rand::seq::index::sample(&mut rng, 13, 4)
.into_iter()
.map(|i| Self::new_main(i as u32))
.collect();
(regs[0], regs[1], regs[2], regs[3])
}
pub fn new_sys(index: u32) -> Self {
match index {
0 => Self::Apsr,
1 => Self::Iapsr,
2 => Self::Eapsr,
3 => Self::Xpsr,
5 => Self::Ipsr,
6 => Self::Epsr,
7 => Self::Iepsr,
8 => Self::Msp,
9 => Self::Psp,
16 => Self::Primask,
17 => Self::Basepri,
18 => Self::BasepriMax,
19 => Self::FaultMask,
20 => Self::Control,
_ => panic!("invalid sys register index"),
}
}
pub fn index_main(&self) -> Option<u32> {
match self {
Self::R0 => Some(0),
Self::R1 => Some(1),
Self::R2 => Some(2),
Self::R3 => Some(3),
Self::R4 => Some(4),
Self::R5 => Some(5),
Self::R6 => Some(6),
Self::R7 => Some(7),
Self::R8 => Some(8),
Self::R9 => Some(9),
Self::R10 => Some(10),
Self::R11 => Some(11),
Self::R12 => Some(12),
Self::Sp => Some(13),
Self::Lr => Some(14),
Self::Pc => Some(15),
_ => None,
}
}
pub fn index_sys(&self) -> u32 {
match self {
RegisterIndex::Apsr => 0,
RegisterIndex::Iapsr => 1,
RegisterIndex::Eapsr => 2,
RegisterIndex::Xpsr => 3,
RegisterIndex::Ipsr => 5,
RegisterIndex::Epsr => 6,
RegisterIndex::Iepsr => 7,
RegisterIndex::Msp => 8,
RegisterIndex::Psp => 9,
RegisterIndex::Primask => 16,
RegisterIndex::Basepri => 17,
RegisterIndex::BasepriMax => 18,
RegisterIndex::FaultMask => 19,
RegisterIndex::Control => 20,
_ => panic!("not a sys register"),
}
}
pub fn is_sp(&self) -> bool {
*self == Self::Sp
}
pub fn is_pc(&self) -> bool {
*self == Self::Pc
}
pub fn is_sp_or_pc(&self) -> bool {
(*self == Self::Sp) || (*self == Self::Pc)
}
pub fn is_low(&self) -> bool {
matches!(
self,
Self::R0 | Self::R1 | Self::R2 | Self::R3 | Self::R4 | Self::R5 | Self::R6 | Self::R7
)
}
}
impl From<u32> for RegisterIndex {
fn from(value: u32) -> Self {
Self::new_main(value)
}
}
impl Display for RegisterIndex {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
Self::R0 => "r0",
Self::R1 => "r1",
Self::R2 => "r2",
Self::R3 => "r3",
Self::R4 => "r4",
Self::R5 => "r5",
Self::R6 => "r6",
Self::R7 => "r7",
Self::R8 => "r8",
Self::R9 => "r9",
Self::R10 => "r10",
Self::R11 => "r11",
Self::R12 => "r12",
Self::Sp => "sp",
Self::Lr => "lr",
Self::Pc => "pc",
Self::Apsr => "apsr",
Self::Iapsr => "iapsr",
Self::Eapsr => "eapsr",
Self::Xpsr => "xpsr",
Self::Ipsr => "ipsr",
Self::Epsr => "epsr",
Self::Iepsr => "iepsr",
Self::Msp => "msp",
Self::Psp => "psp",
Self::Primask => "primask",
Self::Basepri => "basepri",
Self::BasepriMax => "basepri_max",
Self::FaultMask => "faultmask",
Self::Control => "control",
};
write!(f, "{}", s)
}
}
#[derive(Debug, Copy, Clone)]
pub struct MainRegisterList(u16);
impl MainRegisterList {
pub fn new(bits: u16) -> MainRegisterList {
MainRegisterList(bits)
}
pub fn is_empty(&self) -> bool {
self.0 == 0
}
pub fn contains(&self, x: &RegisterIndex) -> bool {
if let Some(i) = x.index_main() {
self.0 & (1 << i) != 0
} else {
false
}
}
pub fn len(&self) -> usize {
let mut result = 0;
let mut x = self.0;
while x > 0 {
if x & 1 != 0 {
result += 1;
}
x >>= 1;
}
result
}
pub fn has_sp(&self) -> bool {
self.contains(&RegisterIndex::Sp)
}
pub fn has_lr(&self) -> bool {
self.contains(&RegisterIndex::Lr)
}
pub fn has_pc(&self) -> bool {
self.contains(&RegisterIndex::Pc)
}
pub fn iter(&self) -> MainRegisterListIterator {
MainRegisterListIterator {
list: self.0,
forward: 0,
backward: 15,
}
}
pub fn lowest(&self) -> Option<RegisterIndex> {
self.iter().next()
}
}
impl Display for MainRegisterList {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut first = true;
for reg in self.iter() {
if first {
first = false;
} else {
f.write_str(", ")?;
}
f.write_str(®.to_string())?;
}
Ok(())
}
}
pub struct MainRegisterListIterator {
list: u16,
forward: i8,
backward: i8,
}
impl Iterator for MainRegisterListIterator {
type Item = RegisterIndex;
fn next(&mut self) -> Option<Self::Item> {
loop {
if self.forward > self.backward {
return None;
} else {
let pos = self.forward;
self.forward += 1;
if self.list & (1 << pos) != 0 {
return Some(RegisterIndex::new_main(pos as u32));
}
}
}
}
}
impl DoubleEndedIterator for MainRegisterListIterator {
fn next_back(&mut self) -> Option<Self::Item> {
loop {
if self.backward < self.forward {
return None;
} else {
let pos = self.backward;
self.backward -= 1;
if self.list & (1 << pos) != 0 {
return Some(RegisterIndex::new_main(pos as u32));
}
}
}
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct ProgramStatusRegister(u32);
impl ProgramStatusRegister {
const APSR_MASK: u32 = 0xf80f0000;
const IPSR_MASK: u32 = 0x000001ff;
const EPSR_MASK: u32 = 0x0700fc00;
pub fn new() -> Self {
ProgramStatusRegister(0)
}
pub fn get(&self) -> u32 {
self.0
}
pub fn set(&mut self, value: u32) {
self.0 = value & 0xff0ffdff;
}
pub fn apsr(&self) -> u32 {
self.0 & Self::APSR_MASK
}
pub fn set_apsr(&mut self, value: u32) {
self.0 = self.0 & !Self::APSR_MASK | value & Self::APSR_MASK;
}
pub fn ipsr(&self) -> u32 {
self.0 & Self::IPSR_MASK
}
pub fn set_ipsr(&mut self, value: u32) {
self.0 = self.0 & !Self::IPSR_MASK | value & Self::IPSR_MASK;
}
pub fn epsr(&self) -> u32 {
self.0 & Self::EPSR_MASK
}
pub fn set_epsr(&mut self, value: u32) {
self.0 = self.0 & !Self::EPSR_MASK | value & Self::EPSR_MASK;
}
pub fn n(&self) -> bool {
self.0.bit(31)
}
pub fn set_n(&mut self, n: bool) -> &mut Self {
self.0.set_bit(31, n);
self
}
pub fn z(&self) -> bool {
self.0.bit(30)
}
pub fn set_z(&mut self, z: bool) -> &mut Self {
self.0.set_bit(30, z);
self
}
pub fn c(&self) -> bool {
self.0.bit(29)
}
pub fn set_c(&mut self, c: bool) -> &mut Self {
self.0.set_bit(29, c);
self
}
pub fn set_c_opt(&mut self, c: Option<bool>) -> &mut Self {
if let Some(c) = c {
self.set_c(c);
}
self
}
pub fn v(&self) -> bool {
self.0.bit(28)
}
pub fn set_v(&mut self, v: bool) -> &mut Self {
self.0.set_bit(28, v);
self
}
pub fn q(&self) -> bool {
self.0.bit(27)
}
pub fn set_q(&mut self, q: bool) -> &mut Self {
self.0.set_bit(27, q);
self
}
pub fn set_nz(&mut self, v: u32) -> &mut Self {
self.set_n(v >> 31 != 0).set_z(v == 0)
}
pub fn flags(&self) -> u8 {
(self.0 >> 27) as u8
}
pub fn set_flags(&mut self, flags: u8) {
debug_assert!(flags < 32);
self.0 = self.0 & 0x07ffffff | ((flags as u32) << 27);
}
pub fn ge(&self) -> u8 {
self.0.imm4(16) as u8
}
pub fn set_ge(&mut self, value: u8) {
debug_assert!(value <= 0xf);
self.0 = (self.0 & 0x000f0000) | ((value as u32 & 0xf) << 16);
}
pub fn ici_it(&self) -> u8 {
(((self.0 & 0x06000000) >> 19) | ((self.0 >> 10) & 0x3f)) as u8
}
pub fn set_ici_it(&mut self, value: u8) -> &mut Self {
let value = value as u32;
self.0 = self.0 & 0xf9ff03ff | ((value & 0xc0) << 19) | ((value & 0x3f) << 10);
self
}
pub fn t(&self) -> bool {
self.0.bit(24)
}
pub fn set_t(&mut self, value: bool) -> &mut Self {
self.0.set_bit(24, value);
self
}
pub fn exception_number(&self) -> u16 {
(self.0 & 0x1ff) as u16
}
pub fn set_exception_number(&mut self, number: u16) -> &mut Self {
debug_assert!(number <= 0x1ff);
self.set_ipsr(number as u32);
self
}
pub fn test(&self, cond: Condition) -> bool {
match cond {
Condition::Equal => self.z(),
Condition::NotEqual => !self.z(),
Condition::CarrySet => self.c(),
Condition::CarryClear => !self.c(),
Condition::Minus => self.n(),
Condition::Plus => !self.n(),
Condition::Overflow => self.v(),
Condition::NoOverflow => !self.v(),
Condition::Higher => self.c() && !self.z(),
Condition::LowerOrSame => !self.c() || self.z(),
Condition::GreaterThanOrEqual => self.n() == self.v(),
Condition::LessThan => self.n() != self.v(),
Condition::GreaterThan => !self.z() && self.n() == self.v(),
Condition::LessThanOrEqual => self.z() || self.n() != self.v(),
Condition::Always => true,
}
}
pub fn it_state(&self) -> ItState {
ItState((((self.0 >> 25) & 3) | (((self.0 >> 10) & 0x3f) << 2)) as u8)
}
pub fn set_it_state(&mut self, it: ItState) {
self.0 = (self.0 & 0xf9ff03ff) | (((it.0 & 3) as u32) << 25) | (((it.0 >> 2) as u32) << 10);
}
}
impl Default for ProgramStatusRegister {
fn default() -> Self {
Self::new()
}
}
impl Debug for ProgramStatusRegister {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Debug::fmt(&self.0, f)
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct MaskRegister(u32);
impl MaskRegister {
pub fn new() -> Self {
Self(0)
}
pub fn pm(&self) -> bool {
self.0.bit(0)
}
pub fn set_pm(&mut self, pm: bool) {
self.0.set_bit(0, pm)
}
}
impl Default for MaskRegister {
fn default() -> Self {
Self::new()
}
}
impl Debug for MaskRegister {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Debug::fmt(&self.0, f)
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct ControlRegister(u32);
impl ControlRegister {
pub fn new() -> Self {
Self(0)
}
pub fn read(&self) -> u32 {
self.0
}
pub fn privileged_bit(&self) -> bool {
self.0.bit(0)
}
pub fn set_privileged_bit(&mut self, value: bool) {
self.0.set_bit(0, value)
}
pub fn spsel(&self) -> bool {
self.0.bit(1)
}
pub fn set_spsel(&mut self, value: bool) {
self.0.set_bit(1, value)
}
}
impl Default for ControlRegister {
fn default() -> Self {
Self::new()
}
}
impl Debug for ControlRegister {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Debug::fmt(&self.0, f)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Mode {
Thread,
Handler,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct CoreRegisters {
pub r0: u32,
pub r1: u32,
pub r2: u32,
pub r3: u32,
pub r4: u32,
pub r5: u32,
pub r6: u32,
pub r7: u32,
pub r8: u32,
pub r9: u32,
pub r10: u32,
pub r11: u32,
pub r12: u32,
pub lr: u32,
pub pc: u32,
pub msp: u32,
pub psp: u32,
pub psr: ProgramStatusRegister,
pub primask: MaskRegister,
pub faultmask: MaskRegister,
pub control: ControlRegister,
pub mode: Mode,
pub event: bool,
}
impl CoreRegisters {
pub fn new() -> Self {
Self {
r0: 0,
r1: 0,
r2: 0,
r3: 0,
r4: 0,
r5: 0,
r6: 0,
r7: 0,
r8: 0,
r9: 0,
r10: 0,
r11: 0,
r12: 0,
lr: 0,
pc: 0,
msp: 0,
psp: 0,
psr: ProgramStatusRegister::new(),
primask: MaskRegister::new(),
faultmask: MaskRegister::new(),
control: ControlRegister::new(),
mode: Mode::Thread,
event: false,
}
}
pub fn translate_sp(&self) -> RegisterIndex {
match self.mode {
Mode::Handler => RegisterIndex::Msp,
Mode::Thread => {
if self.control.spsel() {
RegisterIndex::Psp
} else {
RegisterIndex::Msp
}
}
}
}
pub fn sp(&self) -> u32 {
self[self.translate_sp()]
}
pub fn sp_mut(&mut self) -> &mut u32 {
match self.translate_sp() {
RegisterIndex::Msp => &mut self.msp,
RegisterIndex::Psp => &mut self.psp,
_ => panic!(),
}
}
pub fn set(&mut self, index: RegisterIndex, value: u32) {
match index {
RegisterIndex::R0 => self.r0 = value,
RegisterIndex::R1 => self.r1 = value,
RegisterIndex::R2 => self.r2 = value,
RegisterIndex::R3 => self.r3 = value,
RegisterIndex::R4 => self.r4 = value,
RegisterIndex::R5 => self.r5 = value,
RegisterIndex::R6 => self.r6 = value,
RegisterIndex::R7 => self.r7 = value,
RegisterIndex::R8 => self.r8 = value,
RegisterIndex::R9 => self.r9 = value,
RegisterIndex::R10 => self.r10 = value,
RegisterIndex::R11 => self.r11 = value,
RegisterIndex::R12 => self.r12 = value,
RegisterIndex::Sp => match self.translate_sp() {
RegisterIndex::Msp => self.msp = value,
RegisterIndex::Psp => self.psp = value,
_ => panic!(),
},
RegisterIndex::Lr => self.lr = value,
RegisterIndex::Pc => self.pc = value,
RegisterIndex::Apsr => self.psr.set_apsr(value),
RegisterIndex::Iapsr => todo!(),
RegisterIndex::Eapsr => todo!(),
RegisterIndex::Xpsr => self.psr.set(value),
RegisterIndex::Ipsr => self.psr.set_ipsr(value),
RegisterIndex::Epsr => self.psr.set_epsr(value),
RegisterIndex::Iepsr => todo!(),
RegisterIndex::Msp => self.msp = value,
RegisterIndex::Psp => self.psp = value,
RegisterIndex::Primask => self.primask.0 = value,
RegisterIndex::Basepri => todo!(),
RegisterIndex::BasepriMax => todo!(),
RegisterIndex::FaultMask => self.faultmask.0 = value,
RegisterIndex::Control => self.control.0 = value,
}
}
}
impl Default for CoreRegisters {
fn default() -> Self {
Self::new()
}
}
impl Index<u32> for CoreRegisters {
type Output = u32;
fn index(&self, index: u32) -> &Self::Output {
&self[RegisterIndex::new_main(index)]
}
}
impl Index<RegisterIndex> for CoreRegisters {
type Output = u32;
fn index(&self, index: RegisterIndex) -> &Self::Output {
match index {
RegisterIndex::R0 => &self.r0,
RegisterIndex::R1 => &self.r1,
RegisterIndex::R2 => &self.r2,
RegisterIndex::R3 => &self.r3,
RegisterIndex::R4 => &self.r4,
RegisterIndex::R5 => &self.r5,
RegisterIndex::R6 => &self.r6,
RegisterIndex::R7 => &self.r7,
RegisterIndex::R8 => &self.r8,
RegisterIndex::R9 => &self.r9,
RegisterIndex::R10 => &self.r10,
RegisterIndex::R11 => &self.r11,
RegisterIndex::R12 => &self.r12,
RegisterIndex::Sp => match self.translate_sp() {
RegisterIndex::Msp => &self.msp,
RegisterIndex::Psp => &self.psp,
_ => panic!(),
},
RegisterIndex::Lr => &self.lr,
RegisterIndex::Pc => &self.pc,
RegisterIndex::Apsr => &self.psr.0,
RegisterIndex::Iapsr => todo!(),
RegisterIndex::Eapsr => todo!(),
RegisterIndex::Xpsr => todo!(),
RegisterIndex::Ipsr => todo!(),
RegisterIndex::Epsr => todo!(),
RegisterIndex::Iepsr => todo!(),
RegisterIndex::Msp => &self.msp,
RegisterIndex::Psp => &self.psp,
RegisterIndex::Primask => &self.primask.0,
RegisterIndex::Basepri => todo!(),
RegisterIndex::BasepriMax => todo!(),
RegisterIndex::FaultMask => &self.faultmask.0,
RegisterIndex::Control => &self.control.0,
}
}
}
#[cfg(test)]
mod tests {
use super::{MainRegisterList, ProgramStatusRegister};
use crate::registers::RegisterIndex;
#[test]
fn test_register_index_is_low() {
for i in 0..=15 {
assert_eq!(RegisterIndex::new_main(i).is_low(), i <= 7);
}
for i in (0..=3).chain(5..=9).chain(16..=20) {
assert!(!RegisterIndex::new_sys(i).is_low());
}
}
#[test]
fn test_main_register_list_iterator() {
assert!(MainRegisterList(0xaaaa)
.iter()
.eq((1..16).step_by(2).map(|i| RegisterIndex::new_main(i))));
assert!(MainRegisterList(0x5555)
.iter()
.eq((0..16).step_by(2).map(|i| RegisterIndex::new_main(i))));
assert!(MainRegisterList(0xff00)
.iter()
.eq((8..16).map(|i| RegisterIndex::new_main(i))));
assert!(MainRegisterList(0x00ff)
.iter()
.eq((0..8).map(|i| RegisterIndex::new_main(i))));
assert!(MainRegisterList(0xaaaa)
.iter()
.rev()
.eq((1..16).step_by(2).rev().map(|i| RegisterIndex::new_main(i))));
assert!(MainRegisterList(0x5555)
.iter()
.rev()
.eq((0..16).step_by(2).rev().map(|i| RegisterIndex::new_main(i))));
assert!(MainRegisterList(0xff00)
.iter()
.rev()
.eq((8..16).rev().map(|i| RegisterIndex::new_main(i))));
assert!(MainRegisterList(0x00ff)
.iter()
.rev()
.eq((0..8).rev().map(|i| RegisterIndex::new_main(i))));
}
#[test]
fn test_program_status_register_flags() {
let mut psr = ProgramStatusRegister::new();
for i in 0..32 {
psr.set_flags(i);
assert_eq!(psr.flags(), i);
assert_eq!(psr.n(), i & 0b10000 != 0);
assert_eq!(psr.z(), i & 0b01000 != 0);
assert_eq!(psr.c(), i & 0b00100 != 0);
assert_eq!(psr.v(), i & 0b00010 != 0);
assert_eq!(psr.q(), i & 0b00001 != 0);
psr.set_flags(0);
psr.set_n(i & 0b10000 != 0);
psr.set_z(i & 0b01000 != 0);
psr.set_c(i & 0b00100 != 0);
psr.set_v(i & 0b00010 != 0);
psr.set_q(i & 0b00001 != 0);
assert_eq!(psr.flags(), i);
}
}
}