187 lines
5.2 KiB
Rust
187 lines
5.2 KiB
Rust
use crate::memory::Memory;
|
|
|
|
#[derive(Default)]
|
|
pub(crate) struct Psw {
|
|
pub a: u8,
|
|
pub sign: bool,
|
|
pub zero: bool,
|
|
pub auxiliary_carry: bool,
|
|
pub parity: bool,
|
|
pub carry: bool,
|
|
}
|
|
|
|
/*
|
|
* PSW is: A for the high byte and the flags for the low byte, in order,
|
|
* sign, zero, auxiliary carry, parity, carry:
|
|
*
|
|
* Bit: 7 6 5 4 3 2 1 0
|
|
* Flag: S Z 0 AC 0 P 1 C
|
|
*/
|
|
impl Psw {
|
|
pub(crate) fn to_u8(f: bool) -> u16 { if f { 1 } else { 0 } }
|
|
pub(crate) fn to_bool(v: u8) -> bool { if v == 0 { false } else { true }}
|
|
|
|
pub(crate) fn set_flags(&mut self, value: u8) {
|
|
self.sign = Psw::to_bool(value & (1 << 7));
|
|
self.zero = Psw::to_bool(value & (1 << 6));
|
|
self.auxiliary_carry = Psw::to_bool(value & (1 << 4));
|
|
self.parity = Psw::to_bool(value & (1 << 2));
|
|
self.carry = Psw::to_bool(value & 1);
|
|
}
|
|
|
|
pub(crate) fn value(&self) -> u16 {
|
|
(self.a as u16) << 8 |
|
|
Psw::to_u8(self.sign) << 7 |
|
|
Psw::to_u8(self.zero) << 6 |
|
|
Psw::to_u8(self.auxiliary_carry) << 4 |
|
|
Psw::to_u8(self.parity) << 2 |
|
|
1 << 1 |
|
|
Psw::to_u8(self.carry)
|
|
}
|
|
|
|
pub(crate) fn disassemble(&self) -> String {
|
|
format!("[C={} P={} S={} Z={}]",
|
|
Psw::to_u8(self.carry),
|
|
Psw::to_u8(self.parity),
|
|
Psw::to_u8(self.sign),
|
|
Psw::to_u8(self.zero))
|
|
}
|
|
}
|
|
|
|
#[derive(Default)]
|
|
pub(crate) struct State {
|
|
pub b: u8,
|
|
pub c: u8,
|
|
pub d: u8,
|
|
pub e: u8,
|
|
pub h: u8,
|
|
pub l: u8,
|
|
pub psw: Psw,
|
|
pub pc: usize,
|
|
pub sp: usize,
|
|
pub enable_interrupts: bool,
|
|
}
|
|
|
|
impl State {
|
|
pub(crate) fn new(pc: usize) -> State {
|
|
State {
|
|
pc,
|
|
.. Default::default()
|
|
}
|
|
}
|
|
|
|
pub fn m(&self) -> usize {
|
|
Memory::to_word(self.l, self.h)
|
|
}
|
|
|
|
pub fn disassemble(&self) -> String {
|
|
format!("a:{:02x} b:{:02x} c:{:02x} d:{:02x} e:{:02x} lh:{:04x} pc:{:04x} sp:{:04x} {}",
|
|
self.psw.a, self.b, self.c, self.d, self.e, ((self.h as u16) << 8) | self.l as u16,
|
|
self.pc, self.sp,
|
|
self.psw.disassemble())
|
|
}
|
|
|
|
pub fn set_logic_flags(&mut self, value: i16) {
|
|
self.psw.zero = value == 0;
|
|
self.psw.sign = 0x80 == (value & 0x80);
|
|
self.psw.parity = (value & 0xff).count_ones() % 2 == 0;
|
|
self.psw.carry = false;
|
|
// state.psw.auxiliary_carry = (state.psw.a < byte1);
|
|
}
|
|
|
|
pub fn set_arithmetic_flags(&mut self, value: i16) {
|
|
self.psw.zero = (value & 0xff) == 0;
|
|
self.psw.sign = 0x80 == (value & 0x80);
|
|
self.psw.parity = (value & 0xff).count_ones() % 2 == 0;
|
|
self.psw.carry = value < 0 || value > 0xff;
|
|
self.psw.auxiliary_carry = self.psw.carry;
|
|
}
|
|
|
|
pub fn jump_if_flag(&mut self, word: usize, flag: bool) -> bool {
|
|
if flag {
|
|
self.pc = word;
|
|
true
|
|
} else {
|
|
false
|
|
}
|
|
}
|
|
|
|
pub fn call(&mut self, memory: &mut Memory, target_pc: usize) {
|
|
let ret = self.pc + 3;
|
|
memory.write(self.sp - 1, ((ret >> 8) as u8) & 0xff);
|
|
memory.write(self.sp - 2, (ret & 0xff) as u8);
|
|
self.sp -= 2;
|
|
self.pc = target_pc;
|
|
}
|
|
|
|
pub fn ret(&mut self, memory: &Memory, flag: bool) -> bool {
|
|
if flag {
|
|
self.pc = Memory::to_word(memory.read(self.sp), memory.read(self.sp + 1));
|
|
self.sp += 2;
|
|
}
|
|
flag
|
|
}
|
|
|
|
pub fn dec(&mut self, n: u8) -> u8 {
|
|
let value = if n == 0 {
|
|
self.psw.carry = true;
|
|
self.psw.auxiliary_carry = true;
|
|
0xff
|
|
} else {
|
|
n - 1
|
|
};
|
|
self.set_arithmetic_flags(value as i16);
|
|
value
|
|
}
|
|
|
|
pub fn xra(&mut self, value: u8) -> u8 {
|
|
let value = self.psw.a ^ value;
|
|
self.set_arithmetic_flags(value as i16);
|
|
value
|
|
}
|
|
|
|
pub fn and(&mut self, value: u8) -> u8 {
|
|
let value = self.psw.a & value;
|
|
self.set_arithmetic_flags(value as i16);
|
|
value
|
|
}
|
|
|
|
pub fn or(&mut self, value: u8) -> u8 {
|
|
let value = self.psw.a | value;
|
|
self.set_arithmetic_flags(value as i16);
|
|
value
|
|
}
|
|
|
|
pub fn add(&mut self, value: u8, carry: u16) {
|
|
let value = self.psw.a as u16 + value as u16 + carry;
|
|
self.set_arithmetic_flags(value as i16);
|
|
self.psw.a = value as u8 & 0xff;
|
|
}
|
|
|
|
pub fn sub(&mut self, value: u8, carry: u16) {
|
|
let value = self.psw.a as i16 - value as i16 - carry as i16;
|
|
self.set_arithmetic_flags(value as i16);
|
|
self.psw.a = value as u8 & 0xff;
|
|
}
|
|
|
|
pub fn cmp(&mut self, n: u8) {
|
|
let value: i16 = self.psw.a as i16 - n as i16;
|
|
self.set_arithmetic_flags(value);
|
|
}
|
|
|
|
pub fn inr(&mut self, n: u8) -> u8 {
|
|
let value = if n == 0xff { 0 } else { n + 1 };
|
|
self.set_arithmetic_flags(value as i16);
|
|
value
|
|
}
|
|
|
|
pub fn add_hl(&mut self, b0: u8, b1: u8) {
|
|
let hl = Memory::to_word(self.l, self.h) as u32;
|
|
let v = Memory::to_word(b0, b1) as u32;
|
|
let result: u32 = hl + v;
|
|
self.psw.carry = result > 0xffff;
|
|
self.h = ((result & 0xff00) >> 8) as u8;
|
|
self.l = (result & 0xff) as u8;
|
|
}
|
|
}
|