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},
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<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)]
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<u32, DetailedBusError> {
) -> Result<u32, InsExecError> {
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<u32, DetailedBusError> {
fn read_address(&mut self, address: u32, size: Size) -> Result<u32, InsExecError> {
// 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<u8, DetailedBusError> {
fn read_byte(&mut self, address: u32) -> Result<u8, InsExecError> {
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<u16, DetailedBusError> {
fn read_word(&mut self, address: u32) -> Result<u16, 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);
@ -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<u32, DetailedBusError> {
fn effective_address(&mut self, ea: EffectiveAddress) -> Result<u32, InsExecError> {
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<u32, DetailedBusError> {
fn pop(&mut self, size: Size) -> Result<u32, InsExecError> {
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)?;