use super::{Cpu, Wide, high_byte, low_byte, wide_value};
use crate::control::{bus, step};
use crate::mcode::IndexState;
impl Cpu {
pub(super) fn accumulator(&self) -> u8 {
high_byte(self.registers.af)
}
pub(super) fn flags(&self) -> u8 {
low_byte(self.registers.af)
}
pub(super) fn index_register(&self) -> Wide {
match self.index_state {
IndexState::Iy => Wide::Iy,
_ => Wide::Ix,
}
}
pub(super) fn addressed_pair(&self, field: u8, substitute_index: bool) -> Wide {
let indexed = substitute_index
&& !self.index_displaced()
&& !matches!(self.index_state, IndexState::None);
match field & 0b11 {
0b00 => Wide::Bc,
0b01 => Wide::De,
0b10 => {
if indexed {
self.index_register()
} else {
Wide::Hl
}
}
_ => Wide::Ix,
}
}
pub(super) fn wide(&self, register: Wide) -> u16 {
match register {
Wide::Bc => self.registers.bc,
Wide::De => self.registers.de,
Wide::Hl => self.registers.hl,
Wide::Ix => self.registers.ix,
Wide::Iy => self.registers.iy,
}
}
pub(super) fn set_wide(&mut self, register: Wide, value: u16) {
let slot = match register {
Wide::Bc => &mut self.registers.bc,
Wide::De => &mut self.registers.de,
Wide::Hl => &mut self.registers.hl,
Wide::Ix => &mut self.registers.ix,
Wide::Iy => &mut self.registers.iy,
};
*slot = value;
}
pub(super) fn set_wide_high(&mut self, register: Wide, value: u8) {
let low = low_byte(self.wide(register));
self.set_wide(register, wide_value(value, low));
}
pub(super) fn set_wide_low(&mut self, register: Wide, value: u8) {
let high = high_byte(self.wide(register));
self.set_wide(register, wide_value(high, value));
}
pub(super) fn first_operand(&self, selector: u8) -> u8 {
let pair = self.wide(self.addressed_pair(selector >> 1, true));
match selector & bus::MASK {
0..=bus::REGISTER_LAST => {
if selector & 1 == 1 {
low_byte(pair)
} else {
high_byte(pair)
}
}
bus::DATA_LATCH => self.data_latch,
bus::ACCUMULATOR => self.accumulator(),
bus::STACK_LOW => low_byte(self.registers.sp),
bus::STACK_HIGH => high_byte(self.registers.sp),
_ => 0x00,
}
}
pub(super) fn second_operand(&self, selector: u8) -> u8 {
let pair = self.wide(self.addressed_pair(selector >> 1, true));
match selector & bus::MASK {
0..=bus::REGISTER_LAST => {
if selector & 1 == 1 {
low_byte(pair)
} else {
high_byte(pair)
}
}
bus::DATA_LATCH => self.data_latch,
bus::ACCUMULATOR => self.accumulator(),
bus::STACK_LOW => low_byte(self.registers.sp),
bus::STACK_HIGH => high_byte(self.registers.sp),
bus::ONE => 1,
bus::FLAGS => self.flags(),
bus::PROGRAM_COUNTER_LOW => low_byte(self.registers.pc),
bus::PROGRAM_COUNTER_HIGH => high_byte(self.registers.pc),
_ => 0x00,
}
}
pub(super) fn operands(&self, first: u8, second: u8, displaced_bit: bool) -> (u8, u8) {
if displaced_bit {
(self.data_latch, self.data_latch)
} else {
(self.first_operand(first), self.second_operand(second))
}
}
pub(super) fn step_pair(&mut self, control: u8) {
if !step::enabled(control) {
return;
}
let field = step::pair(control);
let decrement = step::counts_down(control);
if step::is_stack_pointer(control) {
self.registers.sp = if decrement {
self.registers.sp.wrapping_sub(1)
} else {
self.registers.sp.wrapping_add(1)
};
return;
}
let register = self.addressed_pair(field, true);
let stepped = if decrement {
self.wide(register).wrapping_sub(1)
} else {
self.wide(register).wrapping_add(1)
};
self.set_wide(register, stepped);
}
}