Abort instruction processing on misaligned address trap

This commit is contained in:
pjht 2023-11-06 11:06:54 -06:00
parent f5df45499a
commit 2110bfbab8
Signed by: pjht
GPG Key ID: CA239FC6934E6F3A

View File

@ -9,7 +9,7 @@ use crate::{
disas::{self, DisassemblyError}, disas::{self, DisassemblyError},
instruction::{ instruction::{
ArithType, BitInsType, EffectiveAddress, Instruction, MoveDirection, ShiftDirection, 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<DetailedBusError, Self> {
if let Self::BusError(v) = self {
Ok(v)
} else {
Err(self)
}
}
}
impl From<DetailedBusError> for InsExecError {
fn from(v: DetailedBusError) -> Self {
Self::BusError(v)
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct M68K { pub struct M68K {
dregs: [u32; 8], dregs: [u32; 8],
@ -222,15 +247,26 @@ impl M68K {
disas::disasm(loc, &mut |addr| { disas::disasm(loc, &mut |addr| {
self.read_word(addr).map_err(|err| DetailedBusError { self.read_word(addr).map_err(|err| DetailedBusError {
cause: BusErrorCause::ReadingInstruction, cause: BusErrorCause::ReadingInstruction,
..err ..err.try_into_bus_error().unwrap()
}) })
}) })
} }
pub fn step(&mut self) { pub fn step(&mut self) {
let Err(bus_error) = self.step_ret_berr() else { let bus_error = match self.step_ret_berr() {
self.stored_mem_cycles.clear(); Ok(_) => {
return; 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 { if self.handling_bus_error {
println!("{} while handling bus error, halting", 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), 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.stopped = true;
self.stored_mem_cycles.clear(); self.stored_mem_cycles.clear();
self.use_stored_mem_cycles = false; 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 { if self.stopped {
return Ok(()); return Ok(());
} }
@ -281,7 +317,7 @@ impl M68K {
let (ins, new_pc) = match self.disassemble(self.pc) { let (ins, new_pc) = match self.disassemble(self.pc) {
Ok(ins) => ins, Ok(ins) => ins,
Err(DisassemblyError::InvalidInstruction) => panic!("Invalid instruction"), 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; self.pc = new_pc;
match ins { match ins {
@ -961,8 +997,8 @@ impl M68K {
Instruction::Shift(typ, size, dir, rot, dst) => { Instruction::Shift(typ, size, dir, rot, dst) => {
let dst_val = self.read_effective(dst, size)?; let dst_val = self.read_effective(dst, size)?;
let rotation = match rot { let rotation = match rot {
crate::instruction::Rotation::Immediate(rot) => rot, Rotation::Immediate(rot) => rot,
crate::instruction::Rotation::Register(dreg) => { Rotation::Register(dreg) => {
self.read_effective(EffectiveAddress::DataReg(dreg), Size::Byte)? as u8 self.read_effective(EffectiveAddress::DataReg(dreg), Size::Byte)? as u8
} }
}; };
@ -1053,7 +1089,7 @@ impl M68K {
src: EffectiveAddress, src: EffectiveAddress,
mut size: Size, mut size: Size,
typ: ArithType, typ: ArithType,
) -> Result<(), DetailedBusError> { ) -> Result<(), InsExecError> {
let ext = match typ { let ext = match typ {
ArithType::Ext => (self.sr & 0x0010) > 0, ArithType::Ext => (self.sr & 0x0010) > 0,
_ => false, _ => false,
@ -1129,7 +1165,7 @@ impl M68K {
src: EffectiveAddress, src: EffectiveAddress,
mut size: Size, mut size: Size,
typ: ArithType, typ: ArithType,
) -> Result<(), DetailedBusError> { ) -> Result<(), InsExecError> {
let ext = match typ { let ext = match typ {
ArithType::Ext => (self.sr & 0x0010) > 0, ArithType::Ext => (self.sr & 0x0010) > 0,
_ => false, _ => false,
@ -1204,7 +1240,7 @@ impl M68K {
dst: EffectiveAddress, dst: EffectiveAddress,
src: EffectiveAddress, src: EffectiveAddress,
size: Size, size: Size,
) -> Result<(), DetailedBusError> { ) -> Result<(), InsExecError> {
let src_val = self.read_effective(src, size)?; let src_val = self.read_effective(src, size)?;
let dst_val = self.read_effective(dst, size)?; let dst_val = self.read_effective(dst, size)?;
let res; let res;
@ -1253,7 +1289,7 @@ impl M68K {
&mut self, &mut self,
effective_address: EffectiveAddress, effective_address: EffectiveAddress,
size: Size, size: Size,
) -> Result<u32, DetailedBusError> { ) -> Result<u32, InsExecError> {
match effective_address { match effective_address {
EffectiveAddress::Immediate(x) => Ok(x), EffectiveAddress::Immediate(x) => Ok(x),
EffectiveAddress::DataReg(x) => Ok(Self::trim_excess(self.dregs[x as usize], size)), EffectiveAddress::DataReg(x) => Ok(Self::trim_excess(self.dregs[x as usize], size)),
@ -1276,10 +1312,10 @@ impl M68K {
EffectiveAddress::AddressPostinc(x) => { EffectiveAddress::AddressPostinc(x) => {
let mut address = let mut address =
self.read_effective(EffectiveAddress::AddressReg(x), Size::Long)?; 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())); address = address.wrapping_add(u32::from(size.byte_size()));
self.write_effective(EffectiveAddress::AddressReg(x), address, Size::Long)?; self.write_effective(EffectiveAddress::AddressReg(x), address, Size::Long)?;
val Ok(val)
} }
EffectiveAddress::AddressPredec(x) => { EffectiveAddress::AddressPredec(x) => {
let address = self let address = self
@ -1330,7 +1366,7 @@ impl M68K {
effective_address: EffectiveAddress, effective_address: EffectiveAddress,
data: u32, data: u32,
size: Size, size: Size,
) -> Result<(), DetailedBusError> { ) -> Result<(), InsExecError> {
match effective_address { match effective_address {
EffectiveAddress::DataReg(x) => { EffectiveAddress::DataReg(x) => {
self.dregs[x as usize] = Self::set_with_size(self.dregs[x as usize], data, size); self.dregs[x as usize] = Self::set_with_size(self.dregs[x as usize], data, size);
@ -1408,7 +1444,7 @@ impl M68K {
Ok(()) Ok(())
} }
fn read_address(&mut self, address: u32, size: Size) -> Result<u32, DetailedBusError> { fn read_address(&mut self, address: u32, size: Size) -> Result<u32, InsExecError> {
// println!("READ {:x}, {:?}", address, size); // println!("READ {:x}, {:?}", address, size);
let address = address & 0xFF_FFFF; let address = address & 0xFF_FFFF;
match size { match size {
@ -1426,7 +1462,7 @@ impl M68K {
address: u32, address: u32,
data: u32, data: u32,
size: Size, size: Size,
) -> Result<(), DetailedBusError> { ) -> Result<(), InsExecError> {
// println!("WRITE {:x}, {:?}, data {:x}", address, size, data); // println!("WRITE {:x}, {:?}, data {:x}", address, size, data);
match size { match size {
Size::Byte => self.write_byte(address, data as u8)?, Size::Byte => self.write_byte(address, data as u8)?,
@ -1439,7 +1475,7 @@ impl M68K {
Ok(()) Ok(())
} }
fn read_byte(&mut self, address: u32) -> Result<u8, DetailedBusError> { fn read_byte(&mut self, address: u32) -> Result<u8, InsExecError> {
let address = address & 0xFF_FFFF; let address = address & 0xFF_FFFF;
if self.use_stored_mem_cycles { if self.use_stored_mem_cycles {
let cycle = self.stored_mem_cycles.remove(0); let cycle = self.stored_mem_cycles.remove(0);
@ -1449,7 +1485,7 @@ impl M68K {
} = cycle } = cycle
{ {
if stored_address == address { if stored_address == address {
return result; return Ok(result?);
} else { } else {
panic!("Stored bus cycle has wrong address when reading byte (reading {:#x}, stored {:#x})", address, stored_address); 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: 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; let address = address & 0xFF_FFFF;
if self.use_stored_mem_cycles { if self.use_stored_mem_cycles {
let cycle = self.stored_mem_cycles.remove(0); let cycle = self.stored_mem_cycles.remove(0);
@ -1482,7 +1518,7 @@ impl M68K {
} = cycle } = cycle
{ {
if stored_address == address && stored_data == data { if stored_address == address && stored_data == data {
return result; return Ok(result?);
} else if stored_address != address { } else if stored_address != address {
panic!("Stored bus cycle has wrong address when writing byte (reading {:#x}, stored {:#x})", address, stored_address); panic!("Stored bus cycle has wrong address when writing byte (reading {:#x}, stored {:#x})", address, stored_address);
} else if stored_data != data { } else if stored_data != data {
@ -1507,13 +1543,14 @@ impl M68K {
result: result.clone(), result: result.clone(),
}); });
}; };
result Ok(result?)
} }
fn read_word(&mut self, address: u32) -> Result<u16, DetailedBusError> { fn read_word(&mut self, address: u32) -> Result<u16, InsExecError> {
let address = address & 0xFF_FFFF; let address = address & 0xFF_FFFF;
if address & 0x1 != 0 { if address & 0x1 != 0 {
self.trap(3)?; self.trap(3)?;
return Err(InsExecError::AbnormalTrap);
} }
if self.use_stored_mem_cycles { if self.use_stored_mem_cycles {
let cycle = self.stored_mem_cycles.remove(0); let cycle = self.stored_mem_cycles.remove(0);
@ -1523,7 +1560,7 @@ impl M68K {
} = cycle } = cycle
{ {
if stored_address == address { if stored_address == address {
return result; return Ok(result?);
} else { } else {
panic!("Stored bus cycle has wrong address when reading word (reading {:#x}, stored {:#x})", address, stored_address); 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: 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; let address = address & 0xFF_FFFF;
if address & 0x1 != 0 { if address & 0x1 != 0 {
self.trap(3)?; self.trap(3)?;
return Err(InsExecError::AbnormalTrap);
} }
if self.use_stored_mem_cycles { if self.use_stored_mem_cycles {
let cycle = self.stored_mem_cycles.remove(0); let cycle = self.stored_mem_cycles.remove(0);
@ -1559,7 +1597,7 @@ impl M68K {
} = cycle } = cycle
{ {
if stored_address == address && stored_data == data { if stored_address == address && stored_data == data {
return result; return Ok(result?);
} else if stored_address != address { } else if stored_address != address {
panic!("Stored bus cycle has wrong address when writing word (reading {:#x}, stored {:#x})", address, stored_address); panic!("Stored bus cycle has wrong address when writing word (reading {:#x}, stored {:#x})", address, stored_address);
} else if stored_data != data { } else if stored_data != data {
@ -1584,7 +1622,7 @@ impl M68K {
result: result.clone(), result: result.clone(),
}); });
}; };
result Ok(result?)
} }
fn trim_excess(num: u32, size: Size) -> u32 { fn trim_excess(num: u32, size: Size) -> u32 {
@ -1603,7 +1641,7 @@ impl M68K {
} }
} }
fn effective_address(&mut self, ea: EffectiveAddress) -> Result<u32, DetailedBusError> { fn effective_address(&mut self, ea: EffectiveAddress) -> Result<u32, InsExecError> {
match ea { match ea {
EffectiveAddress::Address(x) => { EffectiveAddress::Address(x) => {
Ok(self.read_effective(EffectiveAddress::AddressReg(x), Size::Long)?) 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) self.write_effective(EffectiveAddress::AddressPredec(7), data, size)
} }
fn pop(&mut self, size: Size) -> Result<u32, DetailedBusError> { fn pop(&mut self, size: Size) -> Result<u32, InsExecError> {
self.read_effective(EffectiveAddress::AddressPostinc(7), size) self.read_effective(EffectiveAddress::AddressPostinc(7), size)
} }
@ -1654,7 +1692,7 @@ impl M68K {
(self.sr & 0x2000) > 0 (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)?; let new_pc = self.read_address((u32::from(vector) * 4) + self.vbr, Size::Long)?;
self.push(u32::from(vector), Size::Word)?; self.push(u32::from(vector), Size::Word)?;
self.push(self.pc, Size::Long)?; self.push(self.pc, Size::Long)?;
@ -1671,7 +1709,7 @@ impl M68K {
byte_access: bool, byte_access: bool,
fault_addr: u32, fault_addr: u32,
write_data: u16, write_data: u16,
) -> Result<(), DetailedBusError> { ) -> Result<(), InsExecError> {
let new_pc = self.read_address(2 * 4 + self.vbr, Size::Long)?; let new_pc = self.read_address(2 * 4 + self.vbr, Size::Long)?;
// Version & internal information // Version & internal information
self.push(0, Size::Long)?; self.push(0, Size::Long)?;