use femtos::{Instant, Duration}; use moa_core::{System, Error, Address, Steppable, Addressable, Interruptable, Debuggable, Transmutable, read_beu16, write_beu16}; use crate::instructions::{ Condition, Instruction, LoadTarget, Target, Register, InterruptMode, RegisterPair, IndexRegister, SpecialRegister, IndexRegisterHalf, Size, Direction, UndocumentedCopy, }; use crate::state::{Z80, Z80Error, Status, Flags}; use crate::timing::Z80InstructionCycles; const FLAGS_NUMERIC: u8 = 0xC0; const FLAGS_ARITHMETIC: u8 = 0x17; const FLAGS_CARRY_HALF_CARRY: u8 = 0x11; enum RotateType { Bit8, Bit9, } impl Steppable for Z80 { fn step(&mut self, system: &System) -> Result { let clocks = if self.reset.get() { self.reset()? } else if self.bus_request.get() { 4 } else { self.step_internal(system)? }; Ok(self.frequency.period_duration() * clocks as u64) } fn on_error(&mut self, system: &System) { self.dump_state(system.clock); } } impl Interruptable for Z80 {} impl Transmutable for Z80 { fn as_steppable(&mut self) -> Option<&mut dyn Steppable> { Some(self) } fn as_interruptable(&mut self) -> Option<&mut dyn Interruptable> { Some(self) } fn as_debuggable(&mut self) -> Option<&mut dyn Debuggable> { Some(self) } } impl From for Error { fn from(err: Z80Error) -> Self { match err { Z80Error::Halted => Self::Other("cpu halted".to_string()), Z80Error::Breakpoint => Self::Breakpoint("breakpoint".to_string()), Z80Error::Unimplemented(instruction) => Self::new(format!("unimplemented instruction {:?}", instruction)), Z80Error::BusError(msg) => Self::Other(msg), } } } impl From for Z80Error { fn from(err: Error) -> Self { match err { Error::Processor(ex) => Z80Error::BusError(format!("processor error {}", ex)), Error::Breakpoint(_) => Z80Error::Breakpoint, Error::Other(msg) | Error::Assertion(msg) | Error::Emulator(_, msg) => Z80Error::BusError(msg.to_string()), } } } #[derive(Clone)] pub struct Z80Executor { pub current_clock: Instant, pub took_branch: bool, } impl Z80Executor { pub fn at_time(current_clock: Instant) -> Self { Self { current_clock, took_branch: false, } } } impl Z80 { pub fn step_internal(&mut self, system: &System) -> Result { self.executor = Z80Executor::at_time(system.clock); match self.state.status { Status::Init => self.init(), Status::Halted => Err(Z80Error::Halted), Status::Running => match self.cycle_one() { Ok(clocks) => Ok(clocks), Err(err) => Err(err), }, } } pub fn init(&mut self) -> Result { self.state.pc = 0; self.state.status = Status::Running; Ok(16) } pub fn reset(&mut self) -> Result { self.clear_state(); Ok(16) } pub fn cycle_one(&mut self) -> Result { self.check_breakpoints()?; self.decode_next()?; self.execute_current()?; Ok( Z80InstructionCycles::from_instruction(&self.decoder.instruction, self.decoder.extra_instruction_bytes)? .calculate_cycles(self.executor.took_branch), ) } pub fn decode_next(&mut self) -> Result<(), Z80Error> { self.decoder .decode_at(&mut self.port, self.executor.current_clock, self.state.pc)?; self.increment_refresh(self.decoder.end.saturating_sub(self.decoder.start) as u8); self.state.pc = self.decoder.end; Ok(()) } pub fn execute_current(&mut self) -> Result<(), Z80Error> { match self.decoder.instruction { Instruction::ADCa(target) => self.execute_adca(target), Instruction::ADC16(dest_pair, src_pair) => self.execute_adc16(dest_pair, src_pair), Instruction::ADDa(target) => self.execute_adda(target), Instruction::ADD16(dest_pair, src_pair) => self.execute_add16(dest_pair, src_pair), Instruction::AND(target) => self.execute_and(target), Instruction::BIT(bit, target) => self.execute_bit(bit, target), Instruction::CALL(addr) => self.execute_call(addr), Instruction::CALLcc(cond, addr) => self.execute_callcc(cond, addr), Instruction::CCF => self.execute_ccf(), Instruction::CP(target) => self.execute_cp(target), //Instruction::CPD => { //}, //Instruction::CPDR => { //}, //Instruction::CPI => { //}, //Instruction::CPIR => { //}, Instruction::CPL => self.execute_cpl(), Instruction::DAA => self.execute_daa(), Instruction::DEC16(regpair) => self.execute_dec16(regpair), Instruction::DEC8(target) => self.execute_dec8(target), Instruction::DI => self.execute_di(), Instruction::DJNZ(offset) => self.execute_djnz(offset), Instruction::EI => self.execute_ei(), Instruction::EXX => self.execute_exx(), Instruction::EXafaf => self.execute_ex_af_af(), Instruction::EXhlde => self.execute_ex_hl_de(), Instruction::EXsp(regpair) => self.execute_ex_sp(regpair), Instruction::HALT => self.execute_halt(), Instruction::IM(mode) => self.execute_im(mode), Instruction::INC16(regpair) => self.execute_inc16(regpair), Instruction::INC8(target) => self.execute_inc8(target), //Instruction::IND => { //}, //Instruction::INDR => { //}, Instruction::INI => self.execute_ini(), //Instruction::INIR => { //}, Instruction::INic(reg) => self.execute_inic(reg), //Instruction::INicz => { //}, Instruction::INx(n) => self.execute_inx(n), Instruction::JP(addr) => self.execute_jp(addr), Instruction::JPIndirect(regpair) => self.execute_jp_indirect(regpair), Instruction::JPcc(cond, addr) => self.execute_jpcc(cond, addr), Instruction::JR(offset) => self.execute_jr(offset), Instruction::JRcc(cond, offset) => self.execute_jrcc(cond, offset), Instruction::LD(dest, src) => self.execute_ld(dest, src), Instruction::LDsr(special_reg, dir) => self.execute_ldsr(special_reg, dir), Instruction::LDD | Instruction::LDDR | Instruction::LDI | Instruction::LDIR => self.execute_ldx(), Instruction::NEG => self.execute_neg(), Instruction::NOP => Ok(()), Instruction::OR(target) => self.execute_or(target), //Instruction::OTDR => { //}, //Instruction::OTIR => { //}, //Instruction::OUTD => { //}, //Instruction::OUTI => { //}, Instruction::OUTic(reg) => self.execute_outic(reg), //Instruction::OUTicz => { //}, Instruction::OUTx(n) => self.execute_outx(n), Instruction::POP(regpair) => self.execute_pop(regpair), Instruction::PUSH(regpair) => self.execute_push(regpair), Instruction::RES(bit, target, opt_copy) => self.execute_res(bit, target, opt_copy), Instruction::RET => self.execute_ret(), Instruction::RETI => self.execute_reti(), Instruction::RETN => self.execute_retn(), Instruction::RETcc(cond) => self.execute_retcc(cond), Instruction::RL(target, opt_copy) => self.execute_rl(target, opt_copy), Instruction::RLA => self.execute_rla(), Instruction::RLC(target, opt_copy) => self.execute_rlc(target, opt_copy), Instruction::RLCA => self.execute_rlca(), Instruction::RLD => self.execute_rld(), Instruction::RR(target, opt_copy) => self.execute_rr(target, opt_copy), Instruction::RRA => self.execute_rra(), Instruction::RRC(target, opt_copy) => self.execute_rrc(target, opt_copy), Instruction::RRCA => self.execute_rrca(), Instruction::RRD => self.execute_rrd(), Instruction::RST(addr) => self.execute_rst(addr), Instruction::SBCa(target) => self.execute_sbca(target), Instruction::SBC16(dest_pair, src_pair) => self.execute_sbc16(dest_pair, src_pair), Instruction::SCF => self.execute_scf(), Instruction::SET(bit, target, opt_copy) => self.execute_set(bit, target, opt_copy), Instruction::SLA(target, opt_copy) => self.execute_sla(target, opt_copy), Instruction::SLL(target, opt_copy) => self.execute_sll(target, opt_copy), Instruction::SRA(target, opt_copy) => self.execute_sra(target, opt_copy), Instruction::SRL(target, opt_copy) => self.execute_srl(target, opt_copy), Instruction::SUB(target) => self.execute_sub(target), Instruction::XOR(target) => self.execute_xor(target), _ => Err(Z80Error::Unimplemented(self.decoder.instruction.clone())), } } fn execute_adca(&mut self, target: Target) -> Result<(), Z80Error> { let src = self.get_target_value(target)?; let acc = self.get_register_value(Register::A); let (result1, carry1, overflow1, half_carry1) = add_bytes(acc, self.get_flag(Flags::Carry) as u8); let (result2, carry2, overflow2, half_carry2) = add_bytes(result1, src); self.set_arithmetic_op_flags( result2 as u16, Size::Byte, false, carry1 | carry2, overflow1 ^ overflow2, half_carry1 | half_carry2, ); self.set_register_value(Register::A, result2); Ok(()) } fn execute_adc16(&mut self, dest_pair: RegisterPair, src_pair: RegisterPair) -> Result<(), Z80Error> { let src = self.get_register_pair_value(src_pair); let dest = self.get_register_pair_value(dest_pair); let (result1, carry1, overflow1, half_carry1) = add_words(dest, src); let (result2, carry2, overflow2, half_carry2) = add_words(result1, self.get_flag(Flags::Carry) as u16); self.set_arithmetic_op_flags(result2, Size::Word, false, carry1 | carry2, overflow1 ^ overflow2, half_carry1 | half_carry2); self.set_register_pair_value(dest_pair, result2); Ok(()) } fn execute_adda(&mut self, target: Target) -> Result<(), Z80Error> { let src = self.get_target_value(target)?; let acc = self.get_register_value(Register::A); let (result, carry, overflow, half_carry) = add_bytes(acc, src); self.set_arithmetic_op_flags(result as u16, Size::Byte, false, carry, overflow, half_carry); self.set_register_value(Register::A, result); Ok(()) } fn execute_add16(&mut self, dest_pair: RegisterPair, src_pair: RegisterPair) -> Result<(), Z80Error> { let src = self.get_register_pair_value(src_pair); let dest = self.get_register_pair_value(dest_pair); let (result, carry, _, half_carry) = add_words(dest, src); self.set_flag(Flags::AddSubtract, false); self.set_flag(Flags::Carry, carry); self.set_flag(Flags::HalfCarry, half_carry); self.set_register_pair_value(dest_pair, result); Ok(()) } fn execute_and(&mut self, target: Target) -> Result<(), Z80Error> { let acc = self.get_register_value(Register::A); let value = self.get_target_value(target)?; let result = acc & value; self.set_register_value(Register::A, result); self.set_logic_op_flags(result, false, true); Ok(()) } fn execute_bit(&mut self, bit: u8, target: Target) -> Result<(), Z80Error> { let value = self.get_target_value(target)?; let result = value & (1 << bit); self.set_flag(Flags::Zero, result == 0); self.set_flag(Flags::Sign, bit == 7 && result != 0); self.set_flag(Flags::Parity, result == 0); self.set_flag(Flags::AddSubtract, false); self.set_flag(Flags::HalfCarry, true); Ok(()) } fn execute_call(&mut self, addr: u16) -> Result<(), Z80Error> { self.push_word(self.decoder.end)?; self.state.pc = addr; Ok(()) } fn execute_callcc(&mut self, cond: Condition, addr: u16) -> Result<(), Z80Error> { if self.get_current_condition(cond) { self.executor.took_branch = true; self.push_word(self.decoder.end)?; self.state.pc = addr; } Ok(()) } fn execute_ccf(&mut self) -> Result<(), Z80Error> { self.set_flag(Flags::AddSubtract, false); self.set_flag(Flags::HalfCarry, self.get_flag(Flags::Carry)); self.set_flag(Flags::Carry, !self.get_flag(Flags::Carry)); Ok(()) } fn execute_cp(&mut self, target: Target) -> Result<(), Z80Error> { let src = self.get_target_value(target)?; let acc = self.get_register_value(Register::A); let (result, carry, overflow, half_carry) = sub_bytes(acc, src); self.set_arithmetic_op_flags(result as u16, Size::Byte, true, carry, overflow, half_carry); Ok(()) } //Instruction::CPD => { //} //Instruction::CPDR => { //} //Instruction::CPI => { //} //Instruction::CPIR => { //} fn execute_cpl(&mut self) -> Result<(), Z80Error> { let value = self.get_register_value(Register::A); self.set_register_value(Register::A, !value); self.set_flag(Flags::HalfCarry, true); self.set_flag(Flags::AddSubtract, true); Ok(()) } fn execute_daa(&mut self) -> Result<(), Z80Error> { // From // if the least significant four bits of A contain a non-BCD digit (i. e. it is // greater than 9) or the H flag is set, then $06 is added to the register. Then // the four most significant bits are checked. If this more significant digit // also happens to be greater than 9 or the C flag is set, then $60 is added. // From // // CF | high | HF | low | diff // | nibble | | nibble | //---------------------------------- // 0 | 0-9 | 0 | 0-9 | 00 // 0 | 0-9 | 1 | 0-9 | 06 // 0 | 0-8 | * | a-f | 06 // 0 | a-f | 0 | 0-9 | 60 // 1 | * | 0 | 0-9 | 60 // 1 | * | 1 | 0-9 | 66 // 1 | * | * | a-f | 66 // 0 | 9-f | * | a-f | 66 // 0 | a-f | 1 | 0-9 | 66 let mut value = self.get_register_value(Register::A); let mut carry = false; let mut half_carry = false; if (value & 0x0F) > 9 || self.get_flag(Flags::HalfCarry) { let (result, _, _, half_carry1) = add_bytes(value, 6); value = result; half_carry = half_carry1; } if (value & 0xF0) > 0x90 || self.get_flag(Flags::Carry) { let (result, _, _, half_carry2) = add_bytes(value, 0x60); value = result; half_carry |= half_carry2; carry = true; } self.set_register_value(Register::A, value); self.set_numeric_flags(value as u16, Size::Byte); self.set_parity_flags(value); self.set_flag(Flags::HalfCarry, half_carry); self.set_flag(Flags::Carry, carry); Ok(()) } fn execute_dec16(&mut self, regpair: RegisterPair) -> Result<(), Z80Error> { let value = self.get_register_pair_value(regpair); let (result, _, _, _) = sub_words(value, 1); self.set_register_pair_value(regpair, result); Ok(()) } fn execute_dec8(&mut self, target: Target) -> Result<(), Z80Error> { let value = self.get_target_value(target)?; let (result, _, overflow, half_carry) = sub_bytes(value, 1); let carry = self.get_flag(Flags::Carry); // Preserve the carry bit, according to Z80 reference self.set_arithmetic_op_flags(result as u16, Size::Byte, true, carry, overflow, half_carry); self.set_target_value(target, result)?; Ok(()) } fn execute_di(&mut self) -> Result<(), Z80Error> { self.state.iff1 = false; self.state.iff2 = false; Ok(()) } fn execute_djnz(&mut self, offset: i8) -> Result<(), Z80Error> { let value = self.get_register_value(Register::B); let result = value.wrapping_sub(1); self.set_register_value(Register::B, result); if result != 0 { self.executor.took_branch = true; self.state.pc = self.state.pc.wrapping_add_signed(offset as i16); } Ok(()) } fn execute_ei(&mut self) -> Result<(), Z80Error> { self.state.iff1 = true; self.state.iff2 = true; Ok(()) } fn execute_exx(&mut self) -> Result<(), Z80Error> { for i in 0..6 { let (normal, shadow) = (self.state.reg[i], self.state.shadow_reg[i]); self.state.reg[i] = shadow; self.state.shadow_reg[i] = normal; } Ok(()) } fn execute_ex_af_af(&mut self) -> Result<(), Z80Error> { for i in 6..8 { let (normal, shadow) = (self.state.reg[i], self.state.shadow_reg[i]); self.state.reg[i] = shadow; self.state.shadow_reg[i] = normal; } Ok(()) } fn execute_ex_hl_de(&mut self) -> Result<(), Z80Error> { let (hl, de) = (self.get_register_pair_value(RegisterPair::HL), self.get_register_pair_value(RegisterPair::DE)); self.set_register_pair_value(RegisterPair::DE, hl); self.set_register_pair_value(RegisterPair::HL, de); Ok(()) } fn execute_ex_sp(&mut self, regpair: RegisterPair) -> Result<(), Z80Error> { let reg_value = self.get_register_pair_value(regpair); let sp = self.get_register_pair_value(RegisterPair::SP); let sp_value = self.read_port_u16(sp)?; self.set_register_pair_value(regpair, sp_value); self.write_port_u16(sp, reg_value)?; Ok(()) } fn execute_halt(&mut self) -> Result<(), Z80Error> { self.state.status = Status::Halted; self.state.pc -= 1; Ok(()) } fn execute_im(&mut self, mode: InterruptMode) -> Result<(), Z80Error> { self.state.im = mode; Ok(()) } fn execute_inc16(&mut self, regpair: RegisterPair) -> Result<(), Z80Error> { let value = self.get_register_pair_value(regpair); let (result, _, _, _) = add_words(value, 1); self.set_register_pair_value(regpair, result); Ok(()) } fn execute_inc8(&mut self, target: Target) -> Result<(), Z80Error> { let value = self.get_target_value(target)?; let (result, _, overflow, half_carry) = add_bytes(value, 1); let carry = self.get_flag(Flags::Carry); // Preserve the carry bit, according to Z80 reference self.set_arithmetic_op_flags(result as u16, Size::Byte, false, carry, overflow, half_carry); self.set_target_value(target, result)?; Ok(()) } //Instruction::IND => { //}, //Instruction::INDR => { //} fn execute_ini(&mut self) -> Result<(), Z80Error> { let b = self.get_register_value(Register::B); let c = self.get_register_value(Register::C); let value = self.read_ioport_value(b, c)?; self.set_load_target_value(LoadTarget::IndirectRegByte(RegisterPair::HL), value as u16)?; let hl = self.get_register_pair_value(RegisterPair::HL).wrapping_add(1); self.set_register_pair_value(RegisterPair::HL, hl); let b = self.get_register_value(Register::B).wrapping_sub(1); self.set_register_value(Register::B, b); Ok(()) } //Instruction::INIR => { //} fn execute_inic(&mut self, reg: Register) -> Result<(), Z80Error> { let b = self.get_register_value(Register::B); let c = self.get_register_value(Register::C); let value = self.read_ioport_value(b, c)?; self.set_register_value(reg, value); self.set_numeric_flags(value as u16, Size::Byte); self.set_parity_flags(value); self.set_flag(Flags::HalfCarry, false); self.set_flag(Flags::AddSubtract, false); Ok(()) } //Instruction::INicz => { //} fn execute_inx(&mut self, n: u8) -> Result<(), Z80Error> { let a = self.get_register_value(Register::A); let value = self.read_ioport_value(a, n)?; self.set_register_value(Register::A, value); Ok(()) } fn execute_jp(&mut self, addr: u16) -> Result<(), Z80Error> { self.state.pc = addr; Ok(()) } fn execute_jp_indirect(&mut self, regpair: RegisterPair) -> Result<(), Z80Error> { let value = self.get_register_pair_value(regpair); self.state.pc = value; Ok(()) } fn execute_jpcc(&mut self, cond: Condition, addr: u16) -> Result<(), Z80Error> { if self.get_current_condition(cond) { self.executor.took_branch = true; self.state.pc = addr; } Ok(()) } fn execute_jr(&mut self, offset: i8) -> Result<(), Z80Error> { self.state.pc = self.state.pc.wrapping_add_signed(offset as i16); Ok(()) } fn execute_jrcc(&mut self, cond: Condition, offset: i8) -> Result<(), Z80Error> { if self.get_current_condition(cond) { self.executor.took_branch = true; self.state.pc = self.state.pc.wrapping_add_signed(offset as i16); } Ok(()) } fn execute_ld(&mut self, dest: LoadTarget, src: LoadTarget) -> Result<(), Z80Error> { let src_value = self.get_load_target_value(src)?; self.set_load_target_value(dest, src_value)?; Ok(()) } fn execute_ldsr(&mut self, special_reg: SpecialRegister, dir: Direction) -> Result<(), Z80Error> { let addr = match special_reg { SpecialRegister::I => &mut self.state.i, SpecialRegister::R => &mut self.state.r, }; match dir { Direction::FromAcc => { *addr = self.state.reg[Register::A as usize]; }, Direction::ToAcc => { self.state.reg[Register::A as usize] = *addr; let value = self.state.reg[Register::A as usize]; self.set_numeric_flags(value as u16, Size::Byte); self.set_flag(Flags::Parity, self.state.iff2); self.set_flag(Flags::AddSubtract, false); self.set_flag(Flags::HalfCarry, false); }, } Ok(()) } fn execute_ldx(&mut self) -> Result<(), Z80Error> { let diff = if self.decoder.instruction == Instruction::LDI || self.decoder.instruction == Instruction::LDIR { 1 } else { -1 }; let src_value = self.get_load_target_value(LoadTarget::IndirectRegByte(RegisterPair::HL))?; self.set_load_target_value(LoadTarget::IndirectRegByte(RegisterPair::DE), src_value)?; self.add_to_regpair(RegisterPair::DE, diff); self.add_to_regpair(RegisterPair::HL, diff); let count = self.add_to_regpair(RegisterPair::BC, -1); let mask = (Flags::AddSubtract as u8) | (Flags::HalfCarry as u8) | (Flags::Parity as u8); let parity = if count != 0 { Flags::Parity as u8 } else { 0 }; self.set_flags(mask, parity); if (self.decoder.instruction == Instruction::LDIR || self.decoder.instruction == Instruction::LDDR) && count != 0 { self.executor.took_branch = true; self.state.pc -= 2; } Ok(()) } fn execute_neg(&mut self) -> Result<(), Z80Error> { let acc = self.get_register_value(Register::A); let (result, carry, overflow, half_carry) = sub_bytes(0, acc); self.set_arithmetic_op_flags(result as u16, Size::Byte, true, carry, overflow, half_carry); self.set_register_value(Register::A, result); Ok(()) } fn execute_or(&mut self, target: Target) -> Result<(), Z80Error> { let acc = self.get_register_value(Register::A); let value = self.get_target_value(target)?; let result = acc | value; self.set_register_value(Register::A, result); self.set_logic_op_flags(result, false, false); Ok(()) } //Instruction::OTDR => { //}, //Instruction::OTIR => { //}, //Instruction::OUTD => { //}, //Instruction::OUTI => { //} fn execute_outic(&mut self, reg: Register) -> Result<(), Z80Error> { let b = self.get_register_value(Register::B); let c = self.get_register_value(Register::C); let value = self.get_register_value(reg); self.write_ioport_value(b, c, value)?; Ok(()) } //Instruction::OUTicz => { //} fn execute_outx(&mut self, n: u8) -> Result<(), Z80Error> { let a = self.get_register_value(Register::A); let value = self.get_register_value(Register::A); self.write_ioport_value(a, n, value)?; Ok(()) } fn execute_pop(&mut self, regpair: RegisterPair) -> Result<(), Z80Error> { let value = self.pop_word()?; self.set_register_pair_value(regpair, value); Ok(()) } fn execute_push(&mut self, regpair: RegisterPair) -> Result<(), Z80Error> { let value = self.get_register_pair_value(regpair); self.push_word(value)?; Ok(()) } fn execute_res(&mut self, bit: u8, target: Target, opt_copy: UndocumentedCopy) -> Result<(), Z80Error> { let mut value = self.get_target_value(target)?; value &= !(1 << bit); self.set_target_value(target, value)?; if let Some(target) = opt_copy { self.set_target_value(target, value)?; } Ok(()) } fn execute_ret(&mut self) -> Result<(), Z80Error> { self.state.pc = self.pop_word()?; Ok(()) } fn execute_reti(&mut self) -> Result<(), Z80Error> { self.state.pc = self.pop_word()?; self.state.iff1 = self.state.iff2; Ok(()) } fn execute_retn(&mut self) -> Result<(), Z80Error> { self.state.pc = self.pop_word()?; self.state.iff1 = self.state.iff2; Ok(()) } fn execute_retcc(&mut self, cond: Condition) -> Result<(), Z80Error> { if self.get_current_condition(cond) { self.executor.took_branch = true; self.state.pc = self.pop_word()?; } Ok(()) } fn execute_rl(&mut self, target: Target, opt_copy: UndocumentedCopy) -> Result<(), Z80Error> { let value = self.get_target_value(target)?; let (result, out_bit) = self.rotate_left(value, RotateType::Bit9); self.set_logic_op_flags(result, out_bit, false); self.set_target_value(target, result)?; if let Some(target) = opt_copy { self.set_target_value(target, result)?; } Ok(()) } fn execute_rla(&mut self) -> Result<(), Z80Error> { let value = self.get_register_value(Register::A); let (result, out_bit) = self.rotate_left(value, RotateType::Bit9); self.set_flag(Flags::AddSubtract, false); self.set_flag(Flags::HalfCarry, false); self.set_flag(Flags::Carry, out_bit); self.set_register_value(Register::A, result); Ok(()) } fn execute_rlc(&mut self, target: Target, opt_copy: UndocumentedCopy) -> Result<(), Z80Error> { let value = self.get_target_value(target)?; let (result, out_bit) = self.rotate_left(value, RotateType::Bit8); self.set_logic_op_flags(result, out_bit, false); self.set_target_value(target, result)?; if let Some(target) = opt_copy { self.set_target_value(target, result)?; } Ok(()) } fn execute_rlca(&mut self) -> Result<(), Z80Error> { let value = self.get_register_value(Register::A); let (result, out_bit) = self.rotate_left(value, RotateType::Bit8); self.set_flag(Flags::AddSubtract, false); self.set_flag(Flags::HalfCarry, false); self.set_flag(Flags::Carry, out_bit); self.set_register_value(Register::A, result); Ok(()) } fn execute_rld(&mut self) -> Result<(), Z80Error> { let a = self.get_register_value(Register::A); let mem = self.get_load_target_value(LoadTarget::IndirectRegByte(RegisterPair::HL))? as u8; let lower_a = a & 0x0F; let a = (a & 0xF0) | (mem >> 4); let mem = (mem << 4) | lower_a; self.set_register_value(Register::A, a); self.set_load_target_value(LoadTarget::IndirectRegByte(RegisterPair::HL), mem as u16)?; self.set_numeric_flags(a as u16, Size::Byte); self.set_parity_flags(a); self.set_flag(Flags::HalfCarry, false); self.set_flag(Flags::AddSubtract, false); Ok(()) } fn execute_rr(&mut self, target: Target, opt_copy: UndocumentedCopy) -> Result<(), Z80Error> { let value = self.get_target_value(target)?; let (result, out_bit) = self.rotate_right(value, RotateType::Bit9); self.set_logic_op_flags(result, out_bit, false); self.set_target_value(target, result)?; if let Some(target) = opt_copy { self.set_target_value(target, result)?; } Ok(()) } fn execute_rra(&mut self) -> Result<(), Z80Error> { let value = self.get_register_value(Register::A); let (result, out_bit) = self.rotate_right(value, RotateType::Bit9); self.set_flag(Flags::AddSubtract, false); self.set_flag(Flags::HalfCarry, false); self.set_flag(Flags::Carry, out_bit); self.set_register_value(Register::A, result); Ok(()) } fn execute_rrc(&mut self, target: Target, opt_copy: UndocumentedCopy) -> Result<(), Z80Error> { let value = self.get_target_value(target)?; let (result, out_bit) = self.rotate_right(value, RotateType::Bit8); self.set_logic_op_flags(result, out_bit, false); self.set_target_value(target, result)?; if let Some(target) = opt_copy { self.set_target_value(target, result)?; } Ok(()) } fn execute_rrca(&mut self) -> Result<(), Z80Error> { let value = self.get_register_value(Register::A); let (result, out_bit) = self.rotate_right(value, RotateType::Bit8); self.set_flag(Flags::AddSubtract, false); self.set_flag(Flags::HalfCarry, false); self.set_flag(Flags::Carry, out_bit); self.set_register_value(Register::A, result); Ok(()) } fn execute_rrd(&mut self) -> Result<(), Z80Error> { let a = self.get_register_value(Register::A); let mem = self.get_load_target_value(LoadTarget::IndirectRegByte(RegisterPair::HL))? as u8; let lower_mem = mem & 0x0F; let mem = (a << 4) | (mem >> 4); let a = (a & 0xF0) | lower_mem; self.set_register_value(Register::A, a); self.set_load_target_value(LoadTarget::IndirectRegByte(RegisterPair::HL), mem as u16)?; self.set_numeric_flags(a as u16, Size::Byte); self.set_parity_flags(a); self.set_flag(Flags::HalfCarry, false); self.set_flag(Flags::AddSubtract, false); Ok(()) } fn execute_rst(&mut self, addr: u8) -> Result<(), Z80Error> { self.push_word(self.decoder.end)?; self.state.pc = addr as u16; Ok(()) } fn execute_sbca(&mut self, target: Target) -> Result<(), Z80Error> { let src = self.get_target_value(target)?; let acc = self.get_register_value(Register::A); let (result1, carry1, overflow1, half_carry1) = sub_bytes(acc, src); let (result2, carry2, overflow2, half_carry2) = sub_bytes(result1, self.get_flag(Flags::Carry) as u8); self.set_arithmetic_op_flags( result2 as u16, Size::Byte, true, carry1 | carry2, overflow1 ^ overflow2, half_carry1 | half_carry2, ); self.set_register_value(Register::A, result2); Ok(()) } fn execute_sbc16(&mut self, dest_pair: RegisterPair, src_pair: RegisterPair) -> Result<(), Z80Error> { let src = self.get_register_pair_value(src_pair); let dest = self.get_register_pair_value(dest_pair); let (result1, carry1, overflow1, half_carry1) = sub_words(dest, self.get_flag(Flags::Carry) as u16); let (result2, carry2, overflow2, half_carry2) = sub_words(result1, src); self.set_arithmetic_op_flags(result2, Size::Word, true, carry1 | carry2, overflow1 ^ overflow2, half_carry1 | half_carry2); self.set_register_pair_value(dest_pair, result2); Ok(()) } fn execute_scf(&mut self) -> Result<(), Z80Error> { self.set_flag(Flags::AddSubtract, false); self.set_flag(Flags::HalfCarry, false); self.set_flag(Flags::Carry, true); Ok(()) } fn execute_set(&mut self, bit: u8, target: Target, opt_copy: UndocumentedCopy) -> Result<(), Z80Error> { let mut value = self.get_target_value(target)?; value |= 1 << bit; self.set_target_value(target, value)?; if let Some(target) = opt_copy { self.set_target_value(target, value)?; } Ok(()) } fn execute_sla(&mut self, target: Target, opt_copy: UndocumentedCopy) -> Result<(), Z80Error> { let value = self.get_target_value(target)?; let out_bit = get_msb(value as u16, Size::Byte); let result = value << 1; self.set_logic_op_flags(result, out_bit, false); self.set_target_value(target, result)?; if let Some(target) = opt_copy { self.set_target_value(target, result)?; } Ok(()) } fn execute_sll(&mut self, target: Target, opt_copy: UndocumentedCopy) -> Result<(), Z80Error> { let value = self.get_target_value(target)?; let out_bit = get_msb(value as u16, Size::Byte); let result = (value << 1) | 0x01; self.set_logic_op_flags(result, out_bit, false); self.set_target_value(target, result)?; if let Some(target) = opt_copy { self.set_target_value(target, result)?; } Ok(()) } fn execute_sra(&mut self, target: Target, opt_copy: UndocumentedCopy) -> Result<(), Z80Error> { let value = self.get_target_value(target)?; let out_bit = (value & 0x01) != 0; let msb_mask = if get_msb(value as u16, Size::Byte) { 0x80 } else { 0 }; let result = (value >> 1) | msb_mask; self.set_logic_op_flags(result, out_bit, false); self.set_target_value(target, result)?; if let Some(target) = opt_copy { self.set_target_value(target, result)?; } Ok(()) } fn execute_srl(&mut self, target: Target, opt_copy: UndocumentedCopy) -> Result<(), Z80Error> { let value = self.get_target_value(target)?; let out_bit = (value & 0x01) != 0; let result = value >> 1; self.set_logic_op_flags(result, out_bit, false); self.set_target_value(target, result)?; if let Some(target) = opt_copy { self.set_target_value(target, result)?; } Ok(()) } fn execute_sub(&mut self, target: Target) -> Result<(), Z80Error> { let src = self.get_target_value(target)?; let acc = self.get_register_value(Register::A); let (result, carry, overflow, half_carry) = sub_bytes(acc, src); self.set_arithmetic_op_flags(result as u16, Size::Byte, true, carry, overflow, half_carry); self.set_register_value(Register::A, result); Ok(()) } fn execute_xor(&mut self, target: Target) -> Result<(), Z80Error> { let acc = self.get_register_value(Register::A); let value = self.get_target_value(target)?; let result = acc ^ value; self.set_register_value(Register::A, result); self.set_logic_op_flags(result, false, false); Ok(()) } fn rotate_left(&mut self, mut value: u8, rtype: RotateType) -> (u8, bool) { let out_bit = get_msb(value as u16, Size::Byte); let in_bit = match rtype { RotateType::Bit9 => self.get_flag(Flags::Carry), RotateType::Bit8 => out_bit, }; value <<= 1; value |= in_bit as u8; (value, out_bit) } fn rotate_right(&mut self, mut value: u8, rtype: RotateType) -> (u8, bool) { let out_bit = (value & 0x01) != 0; let in_bit = match rtype { RotateType::Bit9 => self.get_flag(Flags::Carry), RotateType::Bit8 => out_bit, }; value >>= 1; value |= if in_bit { 0x80 } else { 0 }; (value, out_bit) } fn add_to_regpair(&mut self, regpair: RegisterPair, value: i16) -> u16 { let addr = match regpair { RegisterPair::BC => &mut self.state.reg[0..2], RegisterPair::DE => &mut self.state.reg[2..4], RegisterPair::HL => &mut self.state.reg[4..6], RegisterPair::AF => &mut self.state.reg[6..8], _ => panic!("RegPair is not supported by inc/dec"), }; let result = (read_beu16(addr) as i16).wrapping_add(value) as u16; write_beu16(addr, result); result } fn push_word(&mut self, value: u16) -> Result<(), Z80Error> { self.state.sp = self.state.sp.wrapping_sub(1); self.write_port_u8(self.state.sp, (value >> 8) as u8)?; self.state.sp = self.state.sp.wrapping_sub(1); self.write_port_u8(self.state.sp, (value & 0x00FF) as u8)?; Ok(()) } fn pop_word(&mut self) -> Result { let mut value; value = self.read_port_u8(self.state.sp)? as u16; self.state.sp = self.state.sp.wrapping_add(1); value |= (self.read_port_u8(self.state.sp)? as u16) << 8; self.state.sp = self.state.sp.wrapping_add(1); Ok(value) } fn get_load_target_value(&mut self, target: LoadTarget) -> Result { let value = match target { LoadTarget::DirectRegByte(reg) => self.get_register_value(reg) as u16, LoadTarget::DirectRegHalfByte(reg) => self.get_index_register_half_value(reg) as u16, LoadTarget::DirectRegWord(regpair) => self.get_register_pair_value(regpair), LoadTarget::IndirectRegByte(regpair) => { let addr = self.get_register_pair_value(regpair); self.read_port_u8(addr)? as u16 }, LoadTarget::IndirectOffsetByte(index_reg, offset) => { let addr = self.get_index_register_value(index_reg); self.read_port_u8((addr as i16).wrapping_add(offset as i16) as u16)? as u16 }, LoadTarget::IndirectRegWord(regpair) => { let addr = self.get_register_pair_value(regpair); self.read_port_u16(addr)? }, LoadTarget::IndirectByte(addr) => self.read_port_u8(addr)? as u16, LoadTarget::IndirectWord(addr) => self.read_port_u16(addr)?, LoadTarget::ImmediateByte(data) => data as u16, LoadTarget::ImmediateWord(data) => data, _ => panic!("Unsupported LoadTarget for set"), }; Ok(value) } fn set_load_target_value(&mut self, target: LoadTarget, value: u16) -> Result<(), Z80Error> { match target { LoadTarget::DirectRegByte(reg) => self.set_register_value(reg, value as u8), LoadTarget::DirectRegHalfByte(reg) => self.set_index_register_half_value(reg, value as u8), LoadTarget::DirectRegWord(regpair) => self.set_register_pair_value(regpair, value), LoadTarget::IndirectRegByte(regpair) => { let addr = self.get_register_pair_value(regpair); self.write_port_u8(addr, value as u8)?; }, LoadTarget::IndirectOffsetByte(index_reg, offset) => { let addr = self.get_index_register_value(index_reg); self.write_port_u8((addr as i16).wrapping_add(offset as i16) as u16, value as u8)?; }, LoadTarget::IndirectRegWord(regpair) => { let addr = self.get_register_pair_value(regpair); self.write_port_u16(addr, value)?; }, LoadTarget::IndirectByte(addr) => { self.write_port_u8(addr, value as u8)?; }, LoadTarget::IndirectWord(addr) => { self.write_port_u16(addr, value)?; }, _ => panic!("Unsupported LoadTarget for set: {:?}", target), } Ok(()) } fn get_target_value(&mut self, target: Target) -> Result { match target { Target::DirectReg(reg) => Ok(self.get_register_value(reg)), Target::DirectRegHalf(reg) => Ok(self.get_index_register_half_value(reg)), Target::IndirectReg(regpair) => { let addr = self.get_register_pair_value(regpair); Ok(self.read_port_u8(addr)?) }, Target::IndirectOffset(reg, offset) => { let addr = self.get_index_register_value(reg).wrapping_add_signed(offset as i16); Ok(self.read_port_u8(addr)?) }, Target::Immediate(data) => Ok(data), } } fn set_target_value(&mut self, target: Target, value: u8) -> Result<(), Z80Error> { match target { Target::DirectReg(reg) => self.set_register_value(reg, value), Target::DirectRegHalf(reg) => self.set_index_register_half_value(reg, value), Target::IndirectReg(regpair) => { let addr = self.get_register_pair_value(regpair); self.write_port_u8(addr, value)?; }, Target::IndirectOffset(reg, offset) => { let addr = self.get_index_register_value(reg).wrapping_add_signed(offset as i16); self.write_port_u8(addr, value)?; }, _ => panic!("Unsupported LoadTarget for set"), } Ok(()) } fn increment_refresh(&mut self, count: u8) { self.state.r = (self.state.r & 0x80) | ((self.state.r + count) & 0x7F); } fn read_port_u8(&mut self, addr: u16) -> Result { self.increment_refresh(1); Ok(self.port.read_u8(self.executor.current_clock, addr as Address)?) } fn write_port_u8(&mut self, addr: u16, value: u8) -> Result<(), Z80Error> { self.increment_refresh(1); Ok(self.port.write_u8(self.executor.current_clock, addr as Address, value)?) } fn read_port_u16(&mut self, addr: u16) -> Result { self.increment_refresh(2); Ok(self.port.read_leu16(self.executor.current_clock, addr as Address)?) } fn write_port_u16(&mut self, addr: u16, value: u16) -> Result<(), Z80Error> { self.increment_refresh(2); Ok(self.port.write_leu16(self.executor.current_clock, addr as Address, value)?) } fn read_ioport_value(&mut self, upper: u8, lower: u8) -> Result { let addr = ((upper as Address) << 8) | (lower as Address); if let Some(io) = self.ioport.as_mut() { Ok(io.read_u8(self.executor.current_clock, addr)?) } else { Ok(0) } } fn write_ioport_value(&mut self, upper: u8, lower: u8, value: u8) -> Result<(), Z80Error> { let addr = ((upper as Address) << 8) | (lower as Address); if let Some(io) = self.ioport.as_mut() { io.write_u8(self.executor.current_clock, addr, value)? } Ok(()) } fn get_register_value(&mut self, reg: Register) -> u8 { self.state.reg[reg as usize] } fn set_register_value(&mut self, reg: Register, value: u8) { self.state.reg[reg as usize] = value; } fn get_index_register_half_value(&mut self, reg: IndexRegisterHalf) -> u8 { match reg { IndexRegisterHalf::IXH => (self.state.ix >> 8) as u8, IndexRegisterHalf::IXL => (self.state.ix & 0x00FF) as u8, IndexRegisterHalf::IYH => (self.state.iy >> 8) as u8, IndexRegisterHalf::IYL => (self.state.iy & 0x00FF) as u8, } } fn set_index_register_half_value(&mut self, reg: IndexRegisterHalf, value: u8) { match reg { IndexRegisterHalf::IXH => { self.state.ix = (self.state.ix & 0x00FF) | (value as u16) << 8; }, IndexRegisterHalf::IXL => { self.state.ix = (self.state.ix & 0xFF00) | value as u16; }, IndexRegisterHalf::IYH => { self.state.iy = (self.state.iy & 0x00FF) | (value as u16) << 8; }, IndexRegisterHalf::IYL => { self.state.iy = (self.state.iy & 0xFF00) | value as u16; }, } } fn get_register_pair_value(&mut self, regpair: RegisterPair) -> u16 { match regpair { RegisterPair::BC => read_beu16(&self.state.reg[0..2]), RegisterPair::DE => read_beu16(&self.state.reg[2..4]), RegisterPair::HL => read_beu16(&self.state.reg[4..6]), RegisterPair::AF => read_beu16(&self.state.reg[6..8]), RegisterPair::SP => self.state.sp, RegisterPair::IX => self.state.ix, RegisterPair::IY => self.state.iy, } } fn set_register_pair_value(&mut self, regpair: RegisterPair, value: u16) { match regpair { RegisterPair::BC => { write_beu16(&mut self.state.reg[0..2], value); }, RegisterPair::DE => { write_beu16(&mut self.state.reg[2..4], value); }, RegisterPair::HL => { write_beu16(&mut self.state.reg[4..6], value); }, RegisterPair::AF => { write_beu16(&mut self.state.reg[6..8], value); }, RegisterPair::SP => { self.state.sp = value; }, RegisterPair::IX => { self.state.ix = value; }, RegisterPair::IY => { self.state.iy = value; }, } } fn get_index_register_value(&mut self, reg: IndexRegister) -> u16 { match reg { IndexRegister::IX => self.state.ix, IndexRegister::IY => self.state.iy, } } fn get_current_condition(&mut self, cond: Condition) -> bool { match cond { Condition::NotZero => !self.get_flag(Flags::Zero), Condition::Zero => self.get_flag(Flags::Zero), Condition::NotCarry => !self.get_flag(Flags::Carry), Condition::Carry => self.get_flag(Flags::Carry), Condition::ParityOdd => !self.get_flag(Flags::Parity), Condition::ParityEven => self.get_flag(Flags::Parity), Condition::Positive => !self.get_flag(Flags::Sign), Condition::Negative => self.get_flag(Flags::Sign), } } fn set_numeric_flags(&mut self, value: u16, size: Size) { let sign = if get_msb(value, size) { Flags::Sign as u8 } else { 0 }; let zero = if value == 0 { Flags::Zero as u8 } else { 0 }; self.set_flags(FLAGS_NUMERIC, sign | zero); } fn set_parity_flags(&mut self, value: u8) { let parity = if (value.count_ones() & 0x01) == 0 { Flags::Parity as u8 } else { 0 }; self.set_flags(Flags::Parity as u8, parity); } fn set_arithmetic_op_flags(&mut self, value: u16, size: Size, addsub: bool, carry: bool, overflow: bool, half_carry: bool) { self.state.reg[Register::F as usize] = 0; self.set_numeric_flags(value, size); let addsub_flag = if addsub { Flags::AddSubtract as u8 } else { 0 }; let overflow_flag = if overflow { Flags::Parity as u8 } else { 0 }; let carry_flag = if carry { Flags::Carry as u8 } else { 0 }; let half_carry_flag = if half_carry { Flags::HalfCarry as u8 } else { 0 }; self.set_flags(FLAGS_ARITHMETIC, addsub_flag | overflow_flag | carry_flag | half_carry_flag); } fn set_logic_op_flags(&mut self, value: u8, carry: bool, half_carry: bool) { self.state.reg[Register::F as usize] = 0; self.set_numeric_flags(value as u16, Size::Byte); self.set_parity_flags(value); let carry_flag = if carry { Flags::Carry as u8 } else { 0 }; let half_carry_flag = if half_carry { Flags::HalfCarry as u8 } else { 0 }; self.set_flags(FLAGS_CARRY_HALF_CARRY, carry_flag | half_carry_flag); } fn get_flag(&self, flag: Flags) -> bool { self.get_flags() & (flag as u8) != 0 } fn set_flag(&mut self, flag: Flags, value: bool) { self.state.reg[Register::F as usize] &= !(flag as u8); if value { self.state.reg[Register::F as usize] |= flag as u8; } } fn get_flags(&self) -> u8 { self.state.reg[Register::F as usize] } fn set_flags(&mut self, mask: u8, values: u8) { self.state.reg[Register::F as usize] = (self.state.reg[Register::F as usize] & !mask) | values; } } fn add_bytes(operand1: u8, operand2: u8) -> (u8, bool, bool, bool) { let (result, carry) = operand1.overflowing_add(operand2); let overflow = (operand1 & 0x80) == (operand2 & 0x80) && (operand1 & 0x80) != (result & 0x80); let half_carry = (operand1 & 0x0F) + (operand2 & 0x0F) >= 0x10; (result, carry, overflow, half_carry) } fn add_words(operand1: u16, operand2: u16) -> (u16, bool, bool, bool) { let (result, carry) = operand1.overflowing_add(operand2); let overflow = (operand1 & 0x8000) == (operand2 & 0x8000) && (operand1 & 0x8000) != (result & 0x8000); let half_carry = (operand1 & 0x0FFF) + (operand2 & 0x0FFF) >= 0x1000; (result, carry, overflow, half_carry) } fn sub_bytes(operand1: u8, operand2: u8) -> (u8, bool, bool, bool) { let (result, carry) = operand1.overflowing_sub(operand2); let overflow = (operand1 & 0x80) != (operand2 & 0x80) && (operand1 & 0x80) != (result & 0x80); let half_carry = (operand1 & 0x0F) < (operand2 & 0x0F); (result, carry, overflow, half_carry) } fn sub_words(operand1: u16, operand2: u16) -> (u16, bool, bool, bool) { let (result, carry) = operand1.overflowing_sub(operand2); let overflow = (operand1 & 0x8000) != (operand2 & 0x8000) && (operand1 & 0x8000) != (result & 0x8000); let half_carry = (operand1 & 0x0FFF) < (operand2 & 0x0FFF); (result, carry, overflow, half_carry) } fn get_msb(value: u16, size: Size) -> bool { match size { Size::Byte => (value & 0x0080) != 0, Size::Word => (value & 0x8000) != 0, } }