From 2110bfbab815087a9eda678c6f1a74231962e7a6 Mon Sep 17 00:00:00 2001 From: pjht Date: Mon, 6 Nov 2023 11:06:54 -0600 Subject: [PATCH] Abort instruction processing on misaligned address trap --- src/m68k.rs | 110 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 74 insertions(+), 36 deletions(-) diff --git a/src/m68k.rs b/src/m68k.rs index b05fd73..1617eb2 100644 --- a/src/m68k.rs +++ b/src/m68k.rs @@ -9,7 +9,7 @@ use crate::{ disas::{self, DisassemblyError}, instruction::{ ArithType, BitInsType, EffectiveAddress, Instruction, MoveDirection, ShiftDirection, - ShiftType, Size, ControlRegister, + ShiftType, Size, ControlRegister, Rotation, }, }; @@ -122,6 +122,31 @@ impl MemCycleInfo { } } +#[derive(Debug)] +pub enum InsExecError { + BusError(DetailedBusError), + AbnormalTrap, +} + +impl InsExecError { + pub fn try_into_bus_error(self) -> Result { + if let Self::BusError(v) = self { + Ok(v) + } else { + Err(self) + } + } +} + +impl From for InsExecError { + fn from(v: DetailedBusError) -> Self { + Self::BusError(v) + } +} + + + + #[derive(Debug)] pub struct M68K { dregs: [u32; 8], @@ -222,15 +247,26 @@ impl M68K { disas::disasm(loc, &mut |addr| { self.read_word(addr).map_err(|err| DetailedBusError { cause: BusErrorCause::ReadingInstruction, - ..err + ..err.try_into_bus_error().unwrap() }) }) } pub fn step(&mut self) { - let Err(bus_error) = self.step_ret_berr() else { - self.stored_mem_cycles.clear(); - return; + let bus_error = match self.step_ret_berr() { + Ok(_) => { + self.stored_mem_cycles.clear(); + return; + }, + Err(e) => { + match e { + InsExecError::BusError(e) => e, + InsExecError::AbnormalTrap => { + self.stored_mem_cycles.clear(); + return; + }, + } + }, }; if self.handling_bus_error { println!("{} while handling bus error, halting", bus_error); @@ -261,7 +297,7 @@ impl M68K { last_cycle.try_get_write_data().unwrap_or(0), ) { - println!("{} while trapping to bus error handler for {}, halting", snd_bus_error, bus_error); + println!("{} while trapping to bus error handler for {}, halting", snd_bus_error.try_into_bus_error().unwrap(), bus_error); self.stopped = true; self.stored_mem_cycles.clear(); self.use_stored_mem_cycles = false; @@ -271,7 +307,7 @@ impl M68K { } } - fn step_ret_berr(&mut self) -> Result<(), DetailedBusError> { + fn step_ret_berr(&mut self) -> Result<(), InsExecError> { if self.stopped { return Ok(()); } @@ -281,7 +317,7 @@ impl M68K { let (ins, new_pc) = match self.disassemble(self.pc) { Ok(ins) => ins, Err(DisassemblyError::InvalidInstruction) => panic!("Invalid instruction"), - Err(DisassemblyError::ReadError(e)) => return Err(e), + Err(DisassemblyError::ReadError(e)) => return Err(e.into()), }; self.pc = new_pc; match ins { @@ -961,8 +997,8 @@ impl M68K { Instruction::Shift(typ, size, dir, rot, dst) => { let dst_val = self.read_effective(dst, size)?; let rotation = match rot { - crate::instruction::Rotation::Immediate(rot) => rot, - crate::instruction::Rotation::Register(dreg) => { + Rotation::Immediate(rot) => rot, + Rotation::Register(dreg) => { self.read_effective(EffectiveAddress::DataReg(dreg), Size::Byte)? as u8 } }; @@ -1053,7 +1089,7 @@ impl M68K { src: EffectiveAddress, mut size: Size, typ: ArithType, - ) -> Result<(), DetailedBusError> { + ) -> Result<(), InsExecError> { let ext = match typ { ArithType::Ext => (self.sr & 0x0010) > 0, _ => false, @@ -1129,7 +1165,7 @@ impl M68K { src: EffectiveAddress, mut size: Size, typ: ArithType, - ) -> Result<(), DetailedBusError> { + ) -> Result<(), InsExecError> { let ext = match typ { ArithType::Ext => (self.sr & 0x0010) > 0, _ => false, @@ -1204,7 +1240,7 @@ impl M68K { dst: EffectiveAddress, src: EffectiveAddress, size: Size, - ) -> Result<(), DetailedBusError> { + ) -> Result<(), InsExecError> { let src_val = self.read_effective(src, size)?; let dst_val = self.read_effective(dst, size)?; let res; @@ -1253,7 +1289,7 @@ impl M68K { &mut self, effective_address: EffectiveAddress, size: Size, - ) -> Result { + ) -> Result { match effective_address { EffectiveAddress::Immediate(x) => Ok(x), EffectiveAddress::DataReg(x) => Ok(Self::trim_excess(self.dregs[x as usize], size)), @@ -1276,10 +1312,10 @@ impl M68K { EffectiveAddress::AddressPostinc(x) => { let mut address = self.read_effective(EffectiveAddress::AddressReg(x), Size::Long)?; - let val = self.read_address(address, size); + let val = self.read_address(address, size)?; address = address.wrapping_add(u32::from(size.byte_size())); self.write_effective(EffectiveAddress::AddressReg(x), address, Size::Long)?; - val + Ok(val) } EffectiveAddress::AddressPredec(x) => { let address = self @@ -1330,7 +1366,7 @@ impl M68K { effective_address: EffectiveAddress, data: u32, size: Size, - ) -> Result<(), DetailedBusError> { + ) -> Result<(), InsExecError> { match effective_address { EffectiveAddress::DataReg(x) => { self.dregs[x as usize] = Self::set_with_size(self.dregs[x as usize], data, size); @@ -1408,7 +1444,7 @@ impl M68K { Ok(()) } - fn read_address(&mut self, address: u32, size: Size) -> Result { + fn read_address(&mut self, address: u32, size: Size) -> Result { // println!("READ {:x}, {:?}", address, size); let address = address & 0xFF_FFFF; match size { @@ -1426,7 +1462,7 @@ impl M68K { address: u32, data: u32, size: Size, - ) -> Result<(), DetailedBusError> { + ) -> Result<(), InsExecError> { // println!("WRITE {:x}, {:?}, data {:x}", address, size, data); match size { Size::Byte => self.write_byte(address, data as u8)?, @@ -1439,7 +1475,7 @@ impl M68K { Ok(()) } - fn read_byte(&mut self, address: u32) -> Result { + fn read_byte(&mut self, address: u32) -> Result { let address = address & 0xFF_FFFF; if self.use_stored_mem_cycles { let cycle = self.stored_mem_cycles.remove(0); @@ -1449,7 +1485,7 @@ impl M68K { } = cycle { if stored_address == address { - return result; + return Ok(result?); } else { panic!("Stored bus cycle has wrong address when reading byte (reading {:#x}, stored {:#x})", address, stored_address); } @@ -1468,10 +1504,10 @@ impl M68K { result: result.clone(), }); }; - result + Ok(result?) } - fn write_byte(&mut self, address: u32, data: u8) -> Result<(), DetailedBusError> { + fn write_byte(&mut self, address: u32, data: u8) -> Result<(), InsExecError> { let address = address & 0xFF_FFFF; if self.use_stored_mem_cycles { let cycle = self.stored_mem_cycles.remove(0); @@ -1482,7 +1518,7 @@ impl M68K { } = cycle { if stored_address == address && stored_data == data { - return result; + return Ok(result?); } else if stored_address != address { panic!("Stored bus cycle has wrong address when writing byte (reading {:#x}, stored {:#x})", address, stored_address); } else if stored_data != data { @@ -1507,13 +1543,14 @@ impl M68K { result: result.clone(), }); }; - result + Ok(result?) } - fn read_word(&mut self, address: u32) -> Result { + fn read_word(&mut self, address: u32) -> Result { let address = address & 0xFF_FFFF; if address & 0x1 != 0 { self.trap(3)?; + return Err(InsExecError::AbnormalTrap); } if self.use_stored_mem_cycles { let cycle = self.stored_mem_cycles.remove(0); @@ -1523,7 +1560,7 @@ impl M68K { } = cycle { if stored_address == address { - return result; + return Ok(result?); } else { panic!("Stored bus cycle has wrong address when reading word (reading {:#x}, stored {:#x})", address, stored_address); } @@ -1542,13 +1579,14 @@ impl M68K { result: result.clone(), }); }; - result + Ok(result?) } - fn write_word(&mut self, address: u32, data: u16) -> Result<(), DetailedBusError> { + fn write_word(&mut self, address: u32, data: u16) -> Result<(), InsExecError> { let address = address & 0xFF_FFFF; if address & 0x1 != 0 { self.trap(3)?; + return Err(InsExecError::AbnormalTrap); } if self.use_stored_mem_cycles { let cycle = self.stored_mem_cycles.remove(0); @@ -1559,7 +1597,7 @@ impl M68K { } = cycle { if stored_address == address && stored_data == data { - return result; + return Ok(result?); } else if stored_address != address { panic!("Stored bus cycle has wrong address when writing word (reading {:#x}, stored {:#x})", address, stored_address); } else if stored_data != data { @@ -1584,7 +1622,7 @@ impl M68K { result: result.clone(), }); }; - result + Ok(result?) } fn trim_excess(num: u32, size: Size) -> u32 { @@ -1603,7 +1641,7 @@ impl M68K { } } - fn effective_address(&mut self, ea: EffectiveAddress) -> Result { + fn effective_address(&mut self, ea: EffectiveAddress) -> Result { match ea { EffectiveAddress::Address(x) => { Ok(self.read_effective(EffectiveAddress::AddressReg(x), Size::Long)?) @@ -1642,11 +1680,11 @@ impl M68K { } } - fn push(&mut self, data: u32, size: Size) -> Result<(), DetailedBusError> { + fn push(&mut self, data: u32, size: Size) -> Result<(), InsExecError> { self.write_effective(EffectiveAddress::AddressPredec(7), data, size) } - fn pop(&mut self, size: Size) -> Result { + fn pop(&mut self, size: Size) -> Result { self.read_effective(EffectiveAddress::AddressPostinc(7), size) } @@ -1654,7 +1692,7 @@ impl M68K { (self.sr & 0x2000) > 0 } - fn trap(&mut self, vector: u8) -> Result<(), DetailedBusError> { + fn trap(&mut self, vector: u8) -> Result<(), InsExecError> { let new_pc = self.read_address((u32::from(vector) * 4) + self.vbr, Size::Long)?; self.push(u32::from(vector), Size::Word)?; self.push(self.pc, Size::Long)?; @@ -1671,7 +1709,7 @@ impl M68K { byte_access: bool, fault_addr: u32, write_data: u16, - ) -> Result<(), DetailedBusError> { + ) -> Result<(), InsExecError> { let new_pc = self.read_address(2 * 4 + self.vbr, Size::Long)?; // Version & internal information self.push(0, Size::Long)?;