use std::fmt;
pub(crate) const CC_C: u8 = 0x01; pub(crate) const CC_V: u8 = 0x02; pub(crate) const CC_Z: u8 = 0x04; pub(crate) const CC_N: u8 = 0x08; pub(crate) const CC_I: u8 = 0x10; pub(crate) const CC_H: u8 = 0x20; pub(crate) const CC_F: u8 = 0x40; pub(crate) const CC_E: u8 = 0x80;
#[repr(transparent)]
#[derive(Clone, Copy, Default, PartialEq, Eq)]
pub struct ConditionCodes(u8);
impl ConditionCodes {
pub const fn new() -> Self {
Self(0)
}
pub const fn from_byte(b: u8) -> Self {
Self(b)
}
pub const fn to_byte(self) -> u8 {
self.0
}
pub const fn carry(self) -> bool {
self.0 & CC_C != 0
}
pub const fn overflow(self) -> bool {
self.0 & CC_V != 0
}
pub const fn zero(self) -> bool {
self.0 & CC_Z != 0
}
pub const fn negative(self) -> bool {
self.0 & CC_N != 0
}
pub const fn irq_inhibit(self) -> bool {
self.0 & CC_I != 0
}
pub const fn half_carry(self) -> bool {
self.0 & CC_H != 0
}
pub const fn firq_inhibit(self) -> bool {
self.0 & CC_F != 0
}
pub const fn entire(self) -> bool {
self.0 & CC_E != 0
}
pub fn set_carry(&mut self, v: bool) {
self.set_bit(CC_C, v);
}
pub fn set_overflow(&mut self, v: bool) {
self.set_bit(CC_V, v);
}
pub fn set_zero(&mut self, v: bool) {
self.set_bit(CC_Z, v);
}
pub fn set_negative(&mut self, v: bool) {
self.set_bit(CC_N, v);
}
pub fn set_irq_inhibit(&mut self, v: bool) {
self.set_bit(CC_I, v);
}
pub fn set_half_carry(&mut self, v: bool) {
self.set_bit(CC_H, v);
}
pub fn set_firq_inhibit(&mut self, v: bool) {
self.set_bit(CC_F, v);
}
pub fn set_entire(&mut self, v: bool) {
self.set_bit(CC_E, v);
}
pub fn set_nz8(&mut self, val: u8) {
self.set_negative(val & 0x80 != 0);
self.set_zero(val == 0);
}
pub fn set_nz16(&mut self, val: u16) {
self.set_negative(val & 0x8000 != 0);
self.set_zero(val == 0);
}
pub fn or_with(&mut self, mask: u8) {
self.0 |= mask;
}
pub fn and_with(&mut self, mask: u8) {
self.0 &= mask;
}
fn set_bit(&mut self, mask: u8, v: bool) {
if v {
self.0 |= mask;
} else {
self.0 &= !mask;
}
}
}
impl fmt::Debug for ConditionCodes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"CC({:02X} {}{}{}{}{}{}{}{})",
self.0,
if self.entire() { 'E' } else { '.' },
if self.firq_inhibit() { 'F' } else { '.' },
if self.half_carry() { 'H' } else { '.' },
if self.irq_inhibit() { 'I' } else { '.' },
if self.negative() { 'N' } else { '.' },
if self.zero() { 'Z' } else { '.' },
if self.overflow() { 'V' } else { '.' },
if self.carry() { 'C' } else { '.' },
)
}
}
impl fmt::Display for ConditionCodes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self, f)
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct Registers {
pub d: u16,
pub x: u16,
pub y: u16,
pub u: u16,
pub s: u16,
pub pc: u16,
pub dp: u8,
pub cc: ConditionCodes,
}
impl Registers {
pub const fn new() -> Self {
Self {
d: 0,
x: 0,
y: 0,
u: 0,
s: 0,
pc: 0,
dp: 0,
cc: ConditionCodes::new(),
}
}
pub const fn a(self) -> u8 {
(self.d >> 8) as u8
}
pub const fn b(self) -> u8 {
self.d as u8
}
pub fn set_a(&mut self, val: u8) {
self.d = (self.d & 0x00FF) | ((val as u16) << 8);
}
pub fn set_b(&mut self, val: u8) {
self.d = (self.d & 0xFF00) | (val as u16);
}
}
impl fmt::Display for Registers {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"PC={:04X} A={:02X} B={:02X} X={:04X} Y={:04X} U={:04X} S={:04X} DP={:02X} {}",
self.pc,
self.a(),
self.b(),
self.x,
self.y,
self.u,
self.s,
self.dp,
self.cc,
)
}
}