diff --git a/src/m68k.rs b/src/m68k.rs index f77b193..0fe4740 100644 --- a/src/m68k.rs +++ b/src/m68k.rs @@ -24,47 +24,37 @@ impl Display for BusError { impl Error for BusError {} -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum BusErrorCause { - ReadingByte, - ReadingWord, - WritingByte, - WritingWord, - ReadingInstruction, -} - -impl BusErrorCause { - fn is_write(self) -> bool { - self == Self::WritingByte || self == Self::WritingWord - } - fn is_byte(self) -> bool { - self == Self::ReadingByte || self == Self::WritingByte - } -} - -impl Display for BusErrorCause { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::ReadingByte => f.write_str("reading byte from"), - Self::ReadingWord => f.write_str("reading word from"), - Self::WritingByte => f.write_str("writing byte to"), - Self::WritingWord => f.write_str("writing word to"), - Self::ReadingInstruction => f.write_str("reading instruction at"), - } - } -} - #[derive(Debug, Copy, Clone)] pub struct DetailedBusError { address: u32, - cause: BusErrorCause, + word: bool, + write: bool, + function: FunctionCode, } impl Display for DetailedBusError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let kind = match (self.word, self.write, self.function) { + (false, false, FunctionCode::UserData) => "user bus error reading byte from", + (false, false, FunctionCode::UserProgram) => "user bus error reading instruction byte from", + (false, false, FunctionCode::SupervisorData) => "supervisor bus error reading byte from", + (false, false, FunctionCode::SupervisorProgram) => "supervisor bus error reading instruction byte from", + (false, true, FunctionCode::UserData) => "user bus error writing byte to", + (false, true, FunctionCode::UserProgram) => "user bus error writing instruction byte to", + (false, true, FunctionCode::SupervisorData) => "supervisor bus error writing byte to", + (false, true, FunctionCode::SupervisorProgram) => "supervisor bus error writing instruction byte to", + (true, false, FunctionCode::UserData) => "user bus error reading word from", + (true, false, FunctionCode::UserProgram) => "user bus error reading instruction word from", + (true, false, FunctionCode::SupervisorData) => "supervisor bus error reading word from", + (true, false, FunctionCode::SupervisorProgram) => "supervisor bus error reading instruction word from", + (true, true, FunctionCode::UserData) => "user bus error writing word to", + (true, true, FunctionCode::UserProgram) => "user bus error writing instruction word to", + (true, true, FunctionCode::SupervisorData) => "supervisor bus error writing word to", + (true, true, FunctionCode::SupervisorProgram) => "supervisor bus error writing instruction word to", + }; f.write_fmt(format_args!( - "bus error {} 0x{:0>8x}", - self.cause, self.address + "{} 0x{:0>8x}", + kind, self.address )) } } @@ -187,6 +177,16 @@ impl FunctionCode { pub fn is_supervisor(self) -> bool { self == Self::SupervisorData || self == Self::SupervisorProgram } + + pub fn as_bits(self) -> u8 { + match self { + Self::UserData => 0b001, + Self::UserProgram => 0b010, + Self::SupervisorData => 0b101, + Self::SupervisorProgram => 0b110, + } + } + } #[derive(Debug)] @@ -288,13 +288,7 @@ impl M68K { loc: u32, ) -> Result<(Instruction, u32), DisassemblyError> { disas::disasm(loc, &mut |addr| { - self.read_word(addr, FunctionCode::new(true, self.is_supervisor())).map_err(|err| match err { - InsExecError::AbnormalTrap => InsExecError::AbnormalTrap, - InsExecError::BusError(err) => InsExecError::BusError(DetailedBusError { - cause: BusErrorCause::ReadingInstruction, - ..err - }), - }) + self.read_word(addr, FunctionCode::new(true, self.is_supervisor())) }) } @@ -644,7 +638,7 @@ impl M68K { self.sr = (self.sr & 0xFFE0) | new_flags; } Instruction::Tst(size, src) => { - let dst_val = self.read_effective(src, Size::Byte)?; + let dst_val = self.read_effective(src, size)?; let neg = match size { Size::Byte => (dst_val & 0x80) > 0, Size::Word => (dst_val & 0x8000) > 0, @@ -737,17 +731,10 @@ impl M68K { fault_address == last_cycle.address(), "Recorded fault address did not match cycle address" ); - let (expected_write, expected_ins, expected_byte_access) = - match last_cycle.unwrap_err().cause { - BusErrorCause::ReadingByte => (false, false, true), - BusErrorCause::WritingByte => (true, false, true), - BusErrorCause::ReadingWord => (false, false, false), - BusErrorCause::WritingWord => (true, false, false), - BusErrorCause::ReadingInstruction => (false, true, false), - }; - assert!(ssw_write == expected_write, "Write flag in the SSW did not match kind of cycle when returning from handling bus error (got {ssw_write}, expected {expected_write})"); - assert!(ssw_ins == expected_ins, "Instruction flag in the SSW did not match kind of cycle when returning from handling bus error (got {ssw_ins}, expected {expected_ins})"); - assert!(ssw_byte_access == expected_byte_access, "Byte access flag in the SSW did not match kind of cycle when returning from handling bus error (got {ssw_byte_access}, expected {expected_byte_access})"); + let err = last_cycle.unwrap_err(); + assert!(ssw_write == err.write, "Write flag in the SSW did not match kind of cycle when returning from handling bus error (got {ssw_write}, expected {})", err.write); + assert!(ssw_ins == err.function.is_code(), "Instruction flag in the SSW did not match kind of cycle when returning from handling bus error (got {ssw_ins}, expected {})", err.function.is_code()); + assert!(ssw_byte_access == !err.word, "Byte access flag in the SSW did not match kind of cycle when returning from handling bus error (got {ssw_byte_access}, expected {})", !err.word); let input_buf = if ssw_ins { instruction_input_buf } else { @@ -1575,8 +1562,10 @@ impl M68K { .bus .read_byte(address, function) .map_err(|_| DetailedBusError { + word: false, + write: false, + function, address, - cause: BusErrorCause::ReadingByte, }); if self.store_mem_cycles { self.stored_mem_cycles @@ -1611,8 +1600,10 @@ impl M68K { .bus .write_byte(address, data, function) .map_err(|_| DetailedBusError { + word: false, + write: true, + function, address, - cause: BusErrorCause::WritingByte, }); if self.store_mem_cycles { self.stored_mem_cycles.push(MemCycleInfo::WriteByte { @@ -1648,8 +1639,10 @@ impl M68K { .bus .read_word(address, function) .map_err(|_| DetailedBusError { + word: true, + write: false, + function, address, - cause: BusErrorCause::ReadingWord, }); if self.store_mem_cycles { self.stored_mem_cycles @@ -1688,8 +1681,10 @@ impl M68K { .bus .write_word(address, data, function) .map_err(|_| DetailedBusError { + word: true, + write: true, + function, address, - cause: BusErrorCause::WritingWord, }); if self.store_mem_cycles { self.stored_mem_cycles.push(MemCycleInfo::WriteWord { @@ -1818,9 +1813,10 @@ impl M68K { // Fault address self.push(bus_error.address, Size::Long)?; // Special status word - let ins = bus_error.cause == BusErrorCause::ReadingInstruction; - let special_status_word = (u16::from(bus_error.cause.is_write()) << 8) - | (u16::from(bus_error.cause.is_byte()) << 9) + let ins = bus_error.function.is_code(); + let special_status_word = bus_error.function.as_bits() as u16 + | (u16::from(bus_error.write) << 8) + | (u16::from(!bus_error.word) << 9) | (((bus_error.address & 0x1) as u16) << 10) | (u16::from(!ins) << 12) | (u16::from(ins) << 13);