Put function code in bus error status word

This commit is contained in:
pjht 2024-03-18 08:24:18 -05:00
parent bf4d005ddd
commit c40555ab03
Signed by: pjht
GPG Key ID: 7B5F6AFBEC7EE78E

View File

@ -24,47 +24,37 @@ impl Display for BusError {
impl Error 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)] #[derive(Debug, Copy, Clone)]
pub struct DetailedBusError { pub struct DetailedBusError {
address: u32, address: u32,
cause: BusErrorCause, word: bool,
write: bool,
function: FunctionCode,
} }
impl Display for DetailedBusError { impl Display for DetailedBusError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 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!( f.write_fmt(format_args!(
"bus error {} 0x{:0>8x}", "{} 0x{:0>8x}",
self.cause, self.address kind, self.address
)) ))
} }
} }
@ -187,6 +177,16 @@ impl FunctionCode {
pub fn is_supervisor(self) -> bool { pub fn is_supervisor(self) -> bool {
self == Self::SupervisorData || self == Self::SupervisorProgram 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)] #[derive(Debug)]
@ -288,13 +288,7 @@ impl M68K {
loc: u32, loc: u32,
) -> Result<(Instruction, u32), DisassemblyError<InsExecError>> { ) -> Result<(Instruction, u32), DisassemblyError<InsExecError>> {
disas::disasm(loc, &mut |addr| { disas::disasm(loc, &mut |addr| {
self.read_word(addr, FunctionCode::new(true, self.is_supervisor())).map_err(|err| match err { self.read_word(addr, FunctionCode::new(true, self.is_supervisor()))
InsExecError::AbnormalTrap => InsExecError::AbnormalTrap,
InsExecError::BusError(err) => InsExecError::BusError(DetailedBusError {
cause: BusErrorCause::ReadingInstruction,
..err
}),
})
}) })
} }
@ -644,7 +638,7 @@ impl M68K {
self.sr = (self.sr & 0xFFE0) | new_flags; self.sr = (self.sr & 0xFFE0) | new_flags;
} }
Instruction::Tst(size, src) => { 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 { let neg = match size {
Size::Byte => (dst_val & 0x80) > 0, Size::Byte => (dst_val & 0x80) > 0,
Size::Word => (dst_val & 0x8000) > 0, Size::Word => (dst_val & 0x8000) > 0,
@ -737,17 +731,10 @@ impl M68K {
fault_address == last_cycle.address(), fault_address == last_cycle.address(),
"Recorded fault address did not match cycle address" "Recorded fault address did not match cycle address"
); );
let (expected_write, expected_ins, expected_byte_access) = let err = last_cycle.unwrap_err();
match last_cycle.unwrap_err().cause { 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);
BusErrorCause::ReadingByte => (false, false, true), 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());
BusErrorCause::WritingByte => (true, false, true), 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);
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 input_buf = if ssw_ins { let input_buf = if ssw_ins {
instruction_input_buf instruction_input_buf
} else { } else {
@ -1575,8 +1562,10 @@ impl M68K {
.bus .bus
.read_byte(address, function) .read_byte(address, function)
.map_err(|_| DetailedBusError { .map_err(|_| DetailedBusError {
word: false,
write: false,
function,
address, address,
cause: BusErrorCause::ReadingByte,
}); });
if self.store_mem_cycles { if self.store_mem_cycles {
self.stored_mem_cycles self.stored_mem_cycles
@ -1611,8 +1600,10 @@ impl M68K {
.bus .bus
.write_byte(address, data, function) .write_byte(address, data, function)
.map_err(|_| DetailedBusError { .map_err(|_| DetailedBusError {
word: false,
write: true,
function,
address, address,
cause: BusErrorCause::WritingByte,
}); });
if self.store_mem_cycles { if self.store_mem_cycles {
self.stored_mem_cycles.push(MemCycleInfo::WriteByte { self.stored_mem_cycles.push(MemCycleInfo::WriteByte {
@ -1648,8 +1639,10 @@ impl M68K {
.bus .bus
.read_word(address, function) .read_word(address, function)
.map_err(|_| DetailedBusError { .map_err(|_| DetailedBusError {
word: true,
write: false,
function,
address, address,
cause: BusErrorCause::ReadingWord,
}); });
if self.store_mem_cycles { if self.store_mem_cycles {
self.stored_mem_cycles self.stored_mem_cycles
@ -1688,8 +1681,10 @@ impl M68K {
.bus .bus
.write_word(address, data, function) .write_word(address, data, function)
.map_err(|_| DetailedBusError { .map_err(|_| DetailedBusError {
word: true,
write: true,
function,
address, address,
cause: BusErrorCause::WritingWord,
}); });
if self.store_mem_cycles { if self.store_mem_cycles {
self.stored_mem_cycles.push(MemCycleInfo::WriteWord { self.stored_mem_cycles.push(MemCycleInfo::WriteWord {
@ -1818,9 +1813,10 @@ impl M68K {
// Fault address // Fault address
self.push(bus_error.address, Size::Long)?; self.push(bus_error.address, Size::Long)?;
// Special status word // Special status word
let ins = bus_error.cause == BusErrorCause::ReadingInstruction; let ins = bus_error.function.is_code();
let special_status_word = (u16::from(bus_error.cause.is_write()) << 8) let special_status_word = bus_error.function.as_bits() as u16
| (u16::from(bus_error.cause.is_byte()) << 9) | (u16::from(bus_error.write) << 8)
| (u16::from(!bus_error.word) << 9)
| (((bus_error.address & 0x1) as u16) << 10) | (((bus_error.address & 0x1) as u16) << 10)
| (u16::from(!ins) << 12) | (u16::from(!ins) << 12)
| (u16::from(ins) << 13); | (u16::from(ins) << 13);