Abort instruction processing on misaligned address trap
This commit is contained in:
parent
f5df45499a
commit
2110bfbab8
110
src/m68k.rs
110
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<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)?;
|
||||
|
Loading…
Reference in New Issue
Block a user