Put function code in bus error status word
This commit is contained in:
parent
bf4d005ddd
commit
c40555ab03
114
src/m68k.rs
114
src/m68k.rs
@ -24,47 +24,37 @@ impl Display 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)]
|
||||
pub struct DetailedBusError {
|
||||
address: u32,
|
||||
cause: BusErrorCause,
|
||||
word: bool,
|
||||
write: bool,
|
||||
function: FunctionCode,
|
||||
}
|
||||
|
||||
impl Display for DetailedBusError {
|
||||
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!(
|
||||
"bus error {} 0x{:0>8x}",
|
||||
self.cause, self.address
|
||||
"{} 0x{:0>8x}",
|
||||
kind, self.address
|
||||
))
|
||||
}
|
||||
}
|
||||
@ -187,6 +177,16 @@ impl FunctionCode {
|
||||
pub fn is_supervisor(self) -> bool {
|
||||
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)]
|
||||
@ -288,13 +288,7 @@ impl M68K {
|
||||
loc: u32,
|
||||
) -> Result<(Instruction, u32), DisassemblyError<InsExecError>> {
|
||||
disas::disasm(loc, &mut |addr| {
|
||||
self.read_word(addr, FunctionCode::new(true, self.is_supervisor())).map_err(|err| match err {
|
||||
InsExecError::AbnormalTrap => InsExecError::AbnormalTrap,
|
||||
InsExecError::BusError(err) => InsExecError::BusError(DetailedBusError {
|
||||
cause: BusErrorCause::ReadingInstruction,
|
||||
..err
|
||||
}),
|
||||
})
|
||||
self.read_word(addr, FunctionCode::new(true, self.is_supervisor()))
|
||||
})
|
||||
}
|
||||
|
||||
@ -644,7 +638,7 @@ impl M68K {
|
||||
self.sr = (self.sr & 0xFFE0) | new_flags;
|
||||
}
|
||||
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 {
|
||||
Size::Byte => (dst_val & 0x80) > 0,
|
||||
Size::Word => (dst_val & 0x8000) > 0,
|
||||
@ -737,17 +731,10 @@ impl M68K {
|
||||
fault_address == last_cycle.address(),
|
||||
"Recorded fault address did not match cycle address"
|
||||
);
|
||||
let (expected_write, expected_ins, expected_byte_access) =
|
||||
match last_cycle.unwrap_err().cause {
|
||||
BusErrorCause::ReadingByte => (false, false, true),
|
||||
BusErrorCause::WritingByte => (true, false, true),
|
||||
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 err = last_cycle.unwrap_err();
|
||||
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);
|
||||
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());
|
||||
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);
|
||||
let input_buf = if ssw_ins {
|
||||
instruction_input_buf
|
||||
} else {
|
||||
@ -1575,8 +1562,10 @@ impl M68K {
|
||||
.bus
|
||||
.read_byte(address, function)
|
||||
.map_err(|_| DetailedBusError {
|
||||
word: false,
|
||||
write: false,
|
||||
function,
|
||||
address,
|
||||
cause: BusErrorCause::ReadingByte,
|
||||
});
|
||||
if self.store_mem_cycles {
|
||||
self.stored_mem_cycles
|
||||
@ -1611,8 +1600,10 @@ impl M68K {
|
||||
.bus
|
||||
.write_byte(address, data, function)
|
||||
.map_err(|_| DetailedBusError {
|
||||
word: false,
|
||||
write: true,
|
||||
function,
|
||||
address,
|
||||
cause: BusErrorCause::WritingByte,
|
||||
});
|
||||
if self.store_mem_cycles {
|
||||
self.stored_mem_cycles.push(MemCycleInfo::WriteByte {
|
||||
@ -1648,8 +1639,10 @@ impl M68K {
|
||||
.bus
|
||||
.read_word(address, function)
|
||||
.map_err(|_| DetailedBusError {
|
||||
word: true,
|
||||
write: false,
|
||||
function,
|
||||
address,
|
||||
cause: BusErrorCause::ReadingWord,
|
||||
});
|
||||
if self.store_mem_cycles {
|
||||
self.stored_mem_cycles
|
||||
@ -1688,8 +1681,10 @@ impl M68K {
|
||||
.bus
|
||||
.write_word(address, data, function)
|
||||
.map_err(|_| DetailedBusError {
|
||||
word: true,
|
||||
write: true,
|
||||
function,
|
||||
address,
|
||||
cause: BusErrorCause::WritingWord,
|
||||
});
|
||||
if self.store_mem_cycles {
|
||||
self.stored_mem_cycles.push(MemCycleInfo::WriteWord {
|
||||
@ -1818,9 +1813,10 @@ impl M68K {
|
||||
// Fault address
|
||||
self.push(bus_error.address, Size::Long)?;
|
||||
// Special status word
|
||||
let ins = bus_error.cause == BusErrorCause::ReadingInstruction;
|
||||
let special_status_word = (u16::from(bus_error.cause.is_write()) << 8)
|
||||
| (u16::from(bus_error.cause.is_byte()) << 9)
|
||||
let ins = bus_error.function.is_code();
|
||||
let special_status_word = bus_error.function.as_bits() as u16
|
||||
| (u16::from(bus_error.write) << 8)
|
||||
| (u16::from(!bus_error.word) << 9)
|
||||
| (((bus_error.address & 0x1) as u16) << 10)
|
||||
| (u16::from(!ins) << 12)
|
||||
| (u16::from(ins) << 13);
|
||||
|
Loading…
Reference in New Issue
Block a user