181 lines
4.3 KiB
Rust
181 lines
4.3 KiB
Rust
use std::cmp::PartialEq;
|
|
use std::fmt;
|
|
|
|
// Sreg flags, ordered from bit 7 to bit 0.
|
|
#[derive(Copy, Clone, Debug)]
|
|
pub enum StatusFlag {
|
|
// I
|
|
GlobalInterruptEnable = 1 << 7,
|
|
// T
|
|
BitCopyStorage = 1 << 6,
|
|
// H
|
|
HalfCarry = 1 << 5,
|
|
// S
|
|
SignBit = 1 << 4,
|
|
// V
|
|
TwosComplementOverflow = 1 << 3,
|
|
// N
|
|
Negative = 1 << 2,
|
|
// Z
|
|
Zero = 1 << 1,
|
|
// C
|
|
Carry = 1 << 0,
|
|
}
|
|
|
|
impl fmt::Display for StatusFlag {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(
|
|
f,
|
|
"{}",
|
|
match *self {
|
|
StatusFlag::GlobalInterruptEnable => "I",
|
|
StatusFlag::BitCopyStorage => "T",
|
|
StatusFlag::HalfCarry => "H",
|
|
StatusFlag::SignBit => "S",
|
|
StatusFlag::TwosComplementOverflow => "V",
|
|
StatusFlag::Negative => "N",
|
|
StatusFlag::Zero => "Z",
|
|
StatusFlag::Carry => "C",
|
|
}
|
|
)
|
|
}
|
|
}
|
|
|
|
impl Into<u8> for StatusFlag {
|
|
fn into(self) -> u8 {
|
|
1 << match self {
|
|
StatusFlag::GlobalInterruptEnable => 7,
|
|
StatusFlag::BitCopyStorage => 6,
|
|
StatusFlag::HalfCarry => 5,
|
|
StatusFlag::SignBit => 4,
|
|
StatusFlag::TwosComplementOverflow => 3,
|
|
StatusFlag::Negative => 2,
|
|
StatusFlag::Zero => 1,
|
|
StatusFlag::Carry => 0,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl StatusFlag {
|
|
// the try_from is unstable, so use our own here.
|
|
pub fn try_from(i: u8) -> Result<Self, ()> {
|
|
match i {
|
|
0x80 => Ok(StatusFlag::GlobalInterruptEnable),
|
|
0x40 => Ok(StatusFlag::BitCopyStorage),
|
|
0x20 => Ok(StatusFlag::HalfCarry),
|
|
0x10 => Ok(StatusFlag::SignBit),
|
|
0x08 => Ok(StatusFlag::TwosComplementOverflow),
|
|
0x04 => Ok(StatusFlag::Negative),
|
|
0x02 => Ok(StatusFlag::Zero),
|
|
0x01 => Ok(StatusFlag::Carry),
|
|
_ => Err(()),
|
|
}
|
|
}
|
|
|
|
pub fn try_from_idx(i: u8) -> Result<Self, ()> {
|
|
if i > 7 {
|
|
Err(())
|
|
} else {
|
|
Ok([
|
|
StatusFlag::Carry,
|
|
StatusFlag::Zero,
|
|
StatusFlag::Negative,
|
|
StatusFlag::TwosComplementOverflow,
|
|
StatusFlag::SignBit,
|
|
StatusFlag::HalfCarry,
|
|
StatusFlag::BitCopyStorage,
|
|
StatusFlag::GlobalInterruptEnable,
|
|
][i as usize])
|
|
}
|
|
}
|
|
}
|
|
|
|
// type GeneralPurposeRegister = struct(u8);
|
|
#[derive(Debug)]
|
|
pub struct GeneralPurposeRegister(u8);
|
|
impl From<u8> for GeneralPurposeRegister {
|
|
fn from(v: u8) -> Self {
|
|
if v > 31 {
|
|
unreachable!();
|
|
}
|
|
Self { 0: v }
|
|
}
|
|
}
|
|
|
|
impl Into<u8> for GeneralPurposeRegister {
|
|
fn into(self) -> u8 {
|
|
self.0
|
|
}
|
|
}
|
|
|
|
impl Into<usize> for GeneralPurposeRegister {
|
|
fn into(self) -> usize {
|
|
self.0 as usize
|
|
}
|
|
}
|
|
|
|
impl GeneralPurposeRegister {
|
|
pub fn as_usize(&self) -> usize {
|
|
self.0 as usize
|
|
}
|
|
}
|
|
|
|
impl PartialEq for GeneralPurposeRegister {
|
|
fn eq(&self, other: &GeneralPurposeRegister) -> bool {
|
|
self.0 == other.0
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for GeneralPurposeRegister {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(f, "R{}", self.0)
|
|
}
|
|
}
|
|
|
|
// Mostly the same as above, but we want to make it a different type.
|
|
// type GeneralPurposeRegisterPair = struct(u8);
|
|
#[derive(Debug)]
|
|
pub struct GeneralPurposeRegisterPair(u8);
|
|
impl From<u8> for GeneralPurposeRegisterPair {
|
|
fn from(v: u8) -> Self {
|
|
if v > 30 {
|
|
println!("v={}", v);
|
|
unreachable!();
|
|
}
|
|
Self { 0: v }
|
|
}
|
|
}
|
|
|
|
impl Into<u8> for GeneralPurposeRegisterPair {
|
|
fn into(self) -> u8 {
|
|
self.0
|
|
}
|
|
}
|
|
|
|
impl PartialEq for GeneralPurposeRegisterPair {
|
|
fn eq(&self, other: &GeneralPurposeRegisterPair) -> bool {
|
|
self.0 == other.0
|
|
}
|
|
}
|
|
|
|
impl GeneralPurposeRegisterPair {
|
|
pub fn low(&self) -> usize {
|
|
self.0 as usize
|
|
}
|
|
|
|
pub fn high(&self) -> usize {
|
|
self.0 as usize + 1
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for GeneralPurposeRegisterPair {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(f, "R{}:R{}", self.high(), self.low())
|
|
}
|
|
}
|
|
|
|
pub type PC = u32;
|
|
|
|
// TODO: Struct :)
|
|
pub type IORegister = u16;
|