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 {}
|
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user