diff --git a/src/cpus/m68k/decode.rs b/src/cpus/m68k/decode.rs index 80aa39c..13b9286 100644 --- a/src/cpus/m68k/decode.rs +++ b/src/cpus/m68k/decode.rs @@ -435,7 +435,7 @@ impl M68kDecoder { let dest = get_high_reg(ins); match (ins & 0x08) == 0 { true => Ok(Instruction::SUBX(Target::DirectDReg(src), Target::DirectDReg(dest), size)), - false => Ok(Instruction::SUBX(Target::IndirectARegDec(src), Target::DirectDReg(dest), size)), + false => Ok(Instruction::SUBX(Target::IndirectARegDec(src), Target::IndirectARegDec(dest), size)), } } else { let target = self.decode_lower_effective_address(memory, ins, Some(size))?; diff --git a/src/cpus/m68k/execute.rs b/src/cpus/m68k/execute.rs index 6195aa0..f69c238 100644 --- a/src/cpus/m68k/execute.rs +++ b/src/cpus/m68k/execute.rs @@ -180,7 +180,7 @@ impl M68k { self.timing.reset(); self.timer.decode.start(); - self.start_request(self.state.pc, Size::Word, MemAccess::Read, MemType::Program)?; + self.start_instruction_request(self.state.pc)?; self.decoder.decode_at(&mut self.port, self.state.pc)?; self.timer.decode.end(); @@ -230,8 +230,16 @@ impl M68k { let (result1, carry1) = overflowing_add_sized(existing, value, size); let (result2, carry2) = overflowing_add_sized(result1, extend, size); let overflow = get_add_overflow(existing, value, result2, size); + + // Handle flags + let zero = self.get_flag(Flags::Zero); self.set_compare_flags(result2, size, carry1 || carry2, overflow); + if self.get_flag(Flags::Zero) { + // ADDX can only clear the zero flag, so if it's set, restore it to whatever it was before + self.set_flag(Flags::Zero, zero); + } self.set_flag(Flags::Extend, carry1 || carry2); + self.set_target_value(dest, result2, size, Used::Twice)?; }, Instruction::AND(src, dest, size) => { @@ -460,7 +468,7 @@ impl M68k { self.set_logic_flags(result, size); }, Instruction::EORtoCCR(value) => { - self.state.sr = (self.state.sr & 0xFF00) | ((self.state.sr & 0x00FF) ^ (value as u16)); + self.set_sr((self.state.sr & 0xFF00) | ((self.state.sr & 0x00FF) ^ (value as u16))); }, Instruction::EORtoSR(value) => { self.require_supervisor()?; @@ -762,8 +770,16 @@ impl M68k { let (result1, carry1) = overflowing_sub_sized(existing, value, size); let (result2, carry2) = overflowing_sub_sized(result1, extend, size); let overflow = get_sub_overflow(existing, value, result2, size); + + // Handle flags + let zero = self.get_flag(Flags::Zero); self.set_compare_flags(result2, size, carry1 || carry2, overflow); + if self.get_flag(Flags::Zero) { + // SUBX can only clear the zero flag, so if it's set, restore it to whatever it was before + self.set_flag(Flags::Zero, zero); + } self.set_flag(Flags::Extend, carry1 || carry2); + self.set_target_value(dest, result2, size, Used::Twice)?; }, Instruction::SWAP(reg) => { @@ -1056,7 +1072,17 @@ impl M68k { *reg_addr } + pub fn start_instruction_request(&mut self, addr: u32) -> Result { + self.state.request.is_instruction = true; + self.state.request.code = FunctionCode::program(self.state.sr); + self.state.request.access = MemAccess::Read; + self.state.request.address = addr; + + validate_address(addr) + } + pub fn start_request(&mut self, addr: u32, size: Size, access: MemAccess, mtype: MemType) -> Result { + self.state.request.is_instruction = false; self.state.request.code = match mtype { MemType::Program => FunctionCode::program(self.state.sr), MemType::Data => FunctionCode::data(self.state.sr), @@ -1065,10 +1091,10 @@ impl M68k { self.state.request.access = access; self.state.request.address = addr; - if size == Size::Byte || addr & 0x1 == 0 { + if size == Size::Byte { Ok(addr) } else { - Err(Error::processor(Exceptions::AddressError as u32)) + validate_address(addr) } } @@ -1293,6 +1319,14 @@ impl M68k { } } +fn validate_address(addr: u32) -> Result { + if addr & 0x1 == 0 { + Ok(addr) + } else { + Err(Error::processor(Exceptions::AddressError as u32)) + } +} + fn overflowing_add_sized(operand1: u32, operand2: u32, size: Size) -> (u32, bool) { match size { Size::Byte => { diff --git a/src/cpus/m68k/state.rs b/src/cpus/m68k/state.rs index f3b9f5b..73afe94 100644 --- a/src/cpus/m68k/state.rs +++ b/src/cpus/m68k/state.rs @@ -98,6 +98,7 @@ pub enum MemAccess { #[derive(Copy, Clone, Debug, PartialEq)] pub struct MemoryRequest { + pub is_instruction: bool, pub access: MemAccess, pub code: FunctionCode, pub size: Size, @@ -180,11 +181,10 @@ impl M68k { println!("PC: {:#010x}", self.state.pc); println!("SR: {:#06x}", self.state.sr); for i in 0..7 { - println!("D{}: {:#010x} A{}: {:#010x}", i, self.state.d_reg[i as usize], i, self.state.a_reg[i as usize]); + println!("D{}: {:#010x} A{}: {:#010x}", i, self.state.d_reg[i as usize], i, self.state.a_reg[i as usize]); } - println!("D7: {:#010x}", self.state.d_reg[7]); - println!("SSP: {:#010x}", self.state.ssp); - println!("USP: {:#010x}", self.state.usp); + println!("D7: {:#010x} USP: {:#010x}", self.state.d_reg[7], self.state.ssp); + println!(" SSP: {:#010x}", self.state.ssp); println!("Current Instruction: {:#010x} {:?}", self.decoder.start, self.decoder.instruction); println!(""); @@ -229,6 +229,7 @@ impl FunctionCode { impl MemoryRequest { pub fn new() -> Self { Self { + is_instruction: false, access: MemAccess::Read, code: FunctionCode::Reserved0, size: Size::Word, @@ -237,10 +238,9 @@ impl MemoryRequest { } pub fn get_type_code(&self) -> u16 { - let ins = match self.code { - // TODO this is wrong (should be opposite results), but is a temporary hack - FunctionCode::SupervisorProgram | FunctionCode::UserProgram => 0x0008, - _ => 0x0000, + let ins = match self.is_instruction { + true => 0x0000, + false => 0x0008, }; let rw = match self.access {