Fixed tests and clippy warnings

This commit is contained in:
transistor 2024-03-16 13:15:34 -07:00
parent c20d7afe6e
commit d0037c8125
26 changed files with 367 additions and 215 deletions

1
Cargo.lock generated
View File

@ -521,7 +521,6 @@ dependencies = [
"emulator-hal-memory",
"femtos",
"flate2",
"moa-core",
"moa-m68k",
"serde",
"serde_derive",

View File

@ -171,7 +171,7 @@ pub trait Debuggable {
fn remove_breakpoint(&mut self, addr: Address);
fn print_current_step(&mut self, system: &System) -> Result<(), Error>;
fn print_disassembly(&mut self, addr: Address, count: usize);
fn print_disassembly(&mut self, system: &System, addr: Address, count: usize);
fn run_command(&mut self, system: &System, args: &[&str]) -> Result<bool, Error>;
}

View File

@ -92,13 +92,14 @@ impl M68kDecoder {
Ok(())
}
pub fn dump_disassembly<Bus>(&mut self, bus: &mut Bus, memory: &mut M68kBusPort, start: u32, length: u32)
pub fn dump_disassembly<Bus>(&mut self, bus: &mut Bus, start: u32, length: u32)
where
Bus: BusAccess<M68kAddress, Instant>,
{
let mut memory = M68kBusPort::default();
let mut next = start;
while next < (start + length) {
match self.decode_at(bus, memory, self.is_supervisor, next) {
match self.decode_at(bus, &mut memory, self.is_supervisor, next) {
Ok(()) => {
self.dump_decoded(memory.current_clock, bus);
next = self.end;

View File

@ -142,7 +142,7 @@ impl M68kBusPort {
Self {
request: Default::default(),
data_bytewidth: info.data_width as usize / 8,
address_mask: 1_u32.wrapping_shl(info.address_width as u32).wrapping_sub(1),
address_mask: 1_u32.checked_shl(info.address_width as u32).unwrap_or(0).wrapping_sub(1),
cycle_start_clock: clock,
current_clock: clock,
}

View File

@ -16,7 +16,7 @@ impl Steppable for M68k {
let mut adapter: bus::BusAdapter<u32, u64, Instant, &mut dyn Addressable, Error> = bus::BusAdapter::new(
&mut *bus,
|addr| addr as u64,
|err| err.try_into().unwrap(),
|err| err,
);
let mut executor = cycle.begin(self, &mut adapter);
@ -24,7 +24,7 @@ impl Steppable for M68k {
executor.step()?;
let interrupt = system.get_interrupt_controller().check();
if let (priority, Some(ack)) = executor.check_pending_interrupts(interrupt)? {
if let (priority, Some(_)) = executor.check_pending_interrupts(interrupt)? {
log::debug!("interrupt: {:?} @ {} ns", priority, system.clock.as_duration().as_nanos());
system.get_interrupt_controller().acknowledge(priority as u8)?;
}
@ -35,7 +35,7 @@ impl Steppable for M68k {
fn on_error(&mut self, _system: &System) {
let mut output = String::with_capacity(256);
self.dump_state(&mut output);
let _ = self.dump_state(&mut output);
println!("{}", output);
}
}
@ -60,8 +60,8 @@ impl<BusError> From<Error> for M68kError<BusError> {
fn from(err: Error) -> Self {
match err {
Error::Processor(ex) => M68kError::Interrupt(ex as u8),
Error::Breakpoint(msg) => M68kError::Breakpoint,
Error::Other(msg) | Error::Assertion(msg) | Error::Emulator(_, msg) => M68kError::Other(format!("{}", msg)),
Error::Breakpoint(_) => M68kError::Breakpoint,
Error::Other(msg) | Error::Assertion(msg) | Error::Emulator(_, msg) => M68kError::Other(msg.to_string()),
}
}
}
@ -100,9 +100,17 @@ impl Debuggable for M68k {
Ok(())
}
fn print_disassembly(&mut self, addr: Address, count: usize) {
fn print_disassembly(&mut self, system: &System, addr: Address, count: usize) {
let mut decoder = M68kDecoder::new(self.info.chip, true, 0);
decoder.dump_disassembly(&mut self.bus, self.cycle.memory, addr as u32, count as u32);
let mut bus = system.bus.borrow_mut();
let mut adapter: bus::BusAdapter<u32, u64, Instant, &mut dyn Addressable, Error> = bus::BusAdapter::new(
&mut *bus,
|addr| addr as u64,
|err| err,
);
decoder.dump_disassembly(&mut adapter, addr as u32, count as u32);
}
fn run_command(&mut self, system: &System, args: &[&str]) -> Result<bool, Error> {

View File

@ -1,4 +1,4 @@
/(
#[cfg(test)]
mod decode_unit_tests {
use femtos::Instant;
@ -12,7 +12,10 @@ mod decode_unit_tests {
const INIT_ADDR: u32 = 0x00000000;
fn init_decode_test<'a>(cputype: M68kType) -> InstructionDecoding<'a, MemoryBlock<u32, Instant>> {
fn run_decode_test<F>(cputype: M68kType, mut test_func: F)
where
F: FnMut(&mut InstructionDecoding<'_, MemoryBlock<u32, Instant>>),
{
let mut memory = MemoryBlock::from(vec![0; 0x0000100]);
let mut decoder = M68kDecoder::new(cputype, true, 0);
let mut decoding = InstructionDecoding {
@ -20,7 +23,8 @@ mod decode_unit_tests {
memory: &mut M68kBusPort::default(),
decoder: &mut decoder,
};
decoding
test_func(&mut decoding);
}
//
@ -29,224 +33,224 @@ mod decode_unit_tests {
#[test]
fn target_direct_d() {
let mut decoder = init_decode_test(M68kType::MC68010);
run_decode_test(M68kType::MC68010, |decoder| {
let size = Size::Word;
let size = Size::Word;
let target = decoder.get_mode_as_target(0b000, 0b001, Some(size)).unwrap();
assert_eq!(target, Target::DirectDReg(1));
let target = decoder.get_mode_as_target(0b000, 0b001, Some(size)).unwrap();
assert_eq!(target, Target::DirectDReg(1));
});
}
#[test]
fn target_direct_a() {
let mut decoder = init_decode_test(M68kType::MC68010);
run_decode_test(M68kType::MC68010, |decoder| {
let size = Size::Word;
let size = Size::Word;
let target = decoder.get_mode_as_target(0b001, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::DirectAReg(2));
let target = decoder.get_mode_as_target(0b001, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::DirectAReg(2));
});
}
#[test]
fn target_indirect_a() {
let mut decoder = init_decode_test(M68kType::MC68010);
run_decode_test(M68kType::MC68010, |decoder| {
let size = Size::Long;
let expected = 0x12345678;
let size = Size::Long;
let expected = 0x12345678;
decoder.bus.write_beu32(Instant::START, INIT_ADDR, expected).unwrap();
decoder.bus.write_beu32(Instant::START, INIT_ADDR, expected).unwrap();
let target = decoder.get_mode_as_target(0b010, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectAReg(2));
let target = decoder.get_mode_as_target(0b010, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectAReg(2));
});
}
#[test]
fn target_indirect_a_inc() {
let mut decoder = init_decode_test(M68kType::MC68010);
run_decode_test(M68kType::MC68010, |decoder| {
let size = Size::Long;
let expected = 0x12345678;
let size = Size::Long;
let expected = 0x12345678;
decoder.bus.write_beu32(Instant::START, INIT_ADDR, expected).unwrap();
decoder.bus.write_beu32(Instant::START, INIT_ADDR, expected).unwrap();
let target = decoder.get_mode_as_target(0b011, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectARegInc(2));
let target = decoder.get_mode_as_target(0b011, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectARegInc(2));
});
}
#[test]
fn target_indirect_a_dec() {
let mut decoder = init_decode_test(M68kType::MC68010);
run_decode_test(M68kType::MC68010, |decoder| {
let size = Size::Long;
let expected = 0x12345678;
let size = Size::Long;
let expected = 0x12345678;
decoder.bus.write_beu32(Instant::START, INIT_ADDR, expected).unwrap();
decoder.bus.write_beu32(Instant::START, INIT_ADDR, expected).unwrap();
let target = decoder.get_mode_as_target(0b100, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectARegDec(2));
let target = decoder.get_mode_as_target(0b100, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectARegDec(2));
});
}
#[test]
fn target_indirect_a_reg_offset() {
let mut decoder = init_decode_test(M68kType::MC68010);
run_decode_test(M68kType::MC68010, |decoder| {
let size = Size::Long;
let offset = -8;
let size = Size::Long;
let offset = -8;
decoder.bus.write_beu16(Instant::START, INIT_ADDR, (offset as i16) as u16).unwrap();
decoder.bus.write_beu16(Instant::START, INIT_ADDR, (offset as i16) as u16).unwrap();
let target = decoder.get_mode_as_target(0b101, 0b100, Some(size)).unwrap();
assert_eq!(target, Target::IndirectRegOffset(BaseRegister::AReg(4), None, offset));
let target = decoder.get_mode_as_target(0b101, 0b100, Some(size)).unwrap();
assert_eq!(target, Target::IndirectRegOffset(BaseRegister::AReg(4), None, offset));
});
}
#[test]
fn target_indirect_a_reg_brief_extension_word() {
let mut decoder = init_decode_test(M68kType::MC68010);
run_decode_test(M68kType::MC68010, |decoder| {
let size = Size::Long;
let offset = -8;
let brief_extension = 0x3800 | (((offset as i8) as u8) as u16);
let size = Size::Long;
let offset = -8;
let brief_extension = 0x3800 | (((offset as i8) as u8) as u16);
decoder.bus.write_beu16(Instant::START, INIT_ADDR, brief_extension).unwrap();
decoder.bus.write_beu16(Instant::START, INIT_ADDR + 2, (offset as i16) as u16).unwrap();
decoder.bus.write_beu16(Instant::START, INIT_ADDR, brief_extension).unwrap();
decoder.bus.write_beu16(Instant::START, INIT_ADDR + 2, (offset as i16) as u16).unwrap();
let target = decoder.get_mode_as_target(0b110, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectRegOffset(BaseRegister::AReg(2), Some(IndexRegister { xreg: XRegister::DReg(3), scale: 0, size: size }), offset));
let target = decoder.get_mode_as_target(0b110, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectRegOffset(BaseRegister::AReg(2), Some(IndexRegister { xreg: XRegister::DReg(3), scale: 0, size: size }), offset));
});
}
#[test]
fn target_indirect_a_reg_full_extension_word() {
let mut decoder = init_decode_test(M68kType::MC68020);
run_decode_test(M68kType::MC68020, |decoder| {
let size = Size::Word;
let offset = -1843235 as i32;
let brief_extension = 0xF330;
let size = Size::Word;
let offset = -1843235 as i32;
let brief_extension = 0xF330;
decoder.bus.write_beu16(Instant::START, INIT_ADDR, brief_extension).unwrap();
decoder.bus.write_beu32(Instant::START, INIT_ADDR + 2, offset as u32).unwrap();
decoder.bus.write_beu16(Instant::START, INIT_ADDR, brief_extension).unwrap();
decoder.bus.write_beu32(Instant::START, INIT_ADDR + 2, offset as u32).unwrap();
let target = decoder.get_mode_as_target(0b110, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectRegOffset(BaseRegister::AReg(2), Some(IndexRegister { xreg: XRegister::AReg(7), scale: 1, size: size }), offset));
let target = decoder.get_mode_as_target(0b110, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectRegOffset(BaseRegister::AReg(2), Some(IndexRegister { xreg: XRegister::AReg(7), scale: 1, size: size }), offset));
});
}
#[test]
fn target_indirect_a_reg_full_extension_word_no_base() {
let mut decoder = init_decode_test(M68kType::MC68020);
run_decode_test(M68kType::MC68020, |decoder| {
let size = Size::Word;
let offset = -1843235 as i32;
let brief_extension = 0xF3B0;
let size = Size::Word;
let offset = -1843235 as i32;
let brief_extension = 0xF3B0;
decoder.bus.write_beu16(Instant::START, INIT_ADDR, brief_extension).unwrap();
decoder.bus.write_beu32(Instant::START, INIT_ADDR + 2, offset as u32).unwrap();
decoder.bus.write_beu16(Instant::START, INIT_ADDR, brief_extension).unwrap();
decoder.bus.write_beu32(Instant::START, INIT_ADDR + 2, offset as u32).unwrap();
let target = decoder.get_mode_as_target(0b110, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectRegOffset(BaseRegister::None, Some(IndexRegister { xreg: XRegister::AReg(7), scale: 1, size: size }), offset));
let target = decoder.get_mode_as_target(0b110, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectRegOffset(BaseRegister::None, Some(IndexRegister { xreg: XRegister::AReg(7), scale: 1, size: size }), offset));
});
}
#[test]
fn target_indirect_a_reg_full_extension_word_no_index() {
let mut decoder = init_decode_test(M68kType::MC68020);
run_decode_test(M68kType::MC68020, |decoder| {
let size = Size::Word;
let offset = -1843235 as i32;
let brief_extension = 0xF370;
let size = Size::Word;
let offset = -1843235 as i32;
let brief_extension = 0xF370;
decoder.bus.write_beu16(Instant::START, INIT_ADDR, brief_extension).unwrap();
decoder.bus.write_beu32(Instant::START, INIT_ADDR + 2, offset as u32).unwrap();
decoder.bus.write_beu16(Instant::START, INIT_ADDR, brief_extension).unwrap();
decoder.bus.write_beu32(Instant::START, INIT_ADDR + 2, offset as u32).unwrap();
let target = decoder.get_mode_as_target(0b110, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectRegOffset(BaseRegister::AReg(2), None, offset));
let target = decoder.get_mode_as_target(0b110, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectRegOffset(BaseRegister::AReg(2), None, offset));
});
}
#[test]
fn target_indirect_pc_offset() {
let mut decoder = init_decode_test(M68kType::MC68010);
run_decode_test(M68kType::MC68010, |decoder| {
let size = Size::Long;
let offset = -8;
let size = Size::Long;
let offset = -8;
decoder.bus.write_beu16(Instant::START, INIT_ADDR, (offset as i16) as u16).unwrap();
decoder.bus.write_beu16(Instant::START, INIT_ADDR, (offset as i16) as u16).unwrap();
let target = decoder.get_mode_as_target(0b111, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectRegOffset(BaseRegister::PC, None, offset));
let target = decoder.get_mode_as_target(0b111, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectRegOffset(BaseRegister::PC, None, offset));
});
}
#[test]
fn target_indirect_pc_brief_extension_word() {
let mut decoder = init_decode_test(M68kType::MC68010);
run_decode_test(M68kType::MC68010, |decoder| {
let size = Size::Word;
let offset = -8;
let brief_extension = 0x3000 | (((offset as i8) as u8) as u16);
let size = Size::Word;
let offset = -8;
let brief_extension = 0x3000 | (((offset as i8) as u8) as u16);
decoder.bus.write_beu16(Instant::START, INIT_ADDR, brief_extension).unwrap();
decoder.bus.write_beu16(Instant::START, INIT_ADDR + 2, (offset as i16) as u16).unwrap();
decoder.bus.write_beu16(Instant::START, INIT_ADDR, brief_extension).unwrap();
decoder.bus.write_beu16(Instant::START, INIT_ADDR + 2, (offset as i16) as u16).unwrap();
let target = decoder.get_mode_as_target(0b111, 0b011, Some(size)).unwrap();
assert_eq!(target, Target::IndirectRegOffset(BaseRegister::PC, Some(IndexRegister { xreg: XRegister::DReg(3), scale: 0, size: size }), offset));
let target = decoder.get_mode_as_target(0b111, 0b011, Some(size)).unwrap();
assert_eq!(target, Target::IndirectRegOffset(BaseRegister::PC, Some(IndexRegister { xreg: XRegister::DReg(3), scale: 0, size: size }), offset));
});
}
#[test]
fn target_indirect_pc_full_extension_word() {
let mut decoder = init_decode_test(M68kType::MC68020);
run_decode_test(M68kType::MC68020, |decoder| {
let size = Size::Word;
let offset = -1843235 as i32;
let brief_extension = 0xF330;
let size = Size::Word;
let offset = -1843235 as i32;
let brief_extension = 0xF330;
decoder.bus.write_beu16(Instant::START, INIT_ADDR, brief_extension).unwrap();
decoder.bus.write_beu32(Instant::START, INIT_ADDR + 2, offset as u32).unwrap();
decoder.bus.write_beu16(Instant::START, INIT_ADDR, brief_extension).unwrap();
decoder.bus.write_beu32(Instant::START, INIT_ADDR + 2, offset as u32).unwrap();
let target = decoder.get_mode_as_target(0b111, 0b011, Some(size)).unwrap();
assert_eq!(target, Target::IndirectRegOffset(BaseRegister::PC, Some(IndexRegister { xreg: XRegister::AReg(7), scale: 1, size: size }), offset));
let target = decoder.get_mode_as_target(0b111, 0b011, Some(size)).unwrap();
assert_eq!(target, Target::IndirectRegOffset(BaseRegister::PC, Some(IndexRegister { xreg: XRegister::AReg(7), scale: 1, size: size }), offset));
});
}
#[test]
fn target_indirect_immediate_word() {
let mut decoder = init_decode_test(M68kType::MC68010);
run_decode_test(M68kType::MC68010, |decoder| {
let size = Size::Word;
let expected = 0x1234;
let size = Size::Word;
let expected = 0x1234;
decoder.bus.write_beu16(Instant::START, INIT_ADDR, expected as u16).unwrap();
decoder.bus.write_beu16(Instant::START, INIT_ADDR, expected as u16).unwrap();
let target = decoder.get_mode_as_target(0b111, 0b000, Some(size)).unwrap();
assert_eq!(target, Target::IndirectMemory(expected, Size::Word));
let target = decoder.get_mode_as_target(0b111, 0b000, Some(size)).unwrap();
assert_eq!(target, Target::IndirectMemory(expected, Size::Word));
});
}
#[test]
fn target_indirect_immediate_long() {
let mut decoder = init_decode_test(M68kType::MC68010);
run_decode_test(M68kType::MC68010, |decoder| {
let size = Size::Word;
let expected = 0x12345678;
let size = Size::Word;
let expected = 0x12345678;
decoder.bus.write_beu32(Instant::START, INIT_ADDR, expected).unwrap();
decoder.bus.write_beu32(Instant::START, INIT_ADDR, expected).unwrap();
let target = decoder.get_mode_as_target(0b111, 0b001, Some(size)).unwrap();
assert_eq!(target, Target::IndirectMemory(expected, Size::Long));
let target = decoder.get_mode_as_target(0b111, 0b001, Some(size)).unwrap();
assert_eq!(target, Target::IndirectMemory(expected, Size::Long));
});
}
#[test]
fn target_immediate() {
let mut decoder = init_decode_test(M68kType::MC68010);
run_decode_test(M68kType::MC68010, |decoder| {
let size = Size::Word;
let expected = 0x1234;
let size = Size::Word;
let expected = 0x1234;
decoder.bus.write_beu16(Instant::START, INIT_ADDR, expected as u16).unwrap();
decoder.bus.write_beu16(Instant::START, INIT_ADDR, expected as u16).unwrap();
let target = decoder.get_mode_as_target(0b111, 0b100, Some(size)).unwrap();
assert_eq!(target, Target::Immediate(expected));
let target = decoder.get_mode_as_target(0b111, 0b100, Some(size)).unwrap();
assert_eq!(target, Target::Immediate(expected));
});
}
}
#[cfg(test)]
mod execute_unit_tests {
use femtos::{Instant, Frequency};
use emulator_hal::bus::{BusAdapter, BusAccess};
use emulator_hal::bus::BusAccess;
use emulator_hal::step::Step;
use emulator_hal_memory::MemoryBlock;
@ -265,13 +269,14 @@ mod execute_unit_tests {
// Insert basic initialization
let len = 0x10_0000;
let mut data = Vec::with_capacity(len);
unsafe { data.set_len(len); }
let mut memory = MemoryBlock::from(data);
memory.write_beu32(Instant::START, 0, INIT_STACK as u32).unwrap();
memory.write_beu32(Instant::START, 4, INIT_ADDR as u32).unwrap();
let mut cpu = M68k::from_type(cputype, Frequency::from_mhz(10));
cpu.step(Instant::START, &mut memory).unwrap();
let mut cycle = M68kCycle::new(&mut cpu, Instant::START);
let cycle = M68kCycle::new(&mut cpu, Instant::START);
let mut executor = cycle.begin(&mut cpu, &mut memory);
executor.cycle.decoder.init(true, executor.state.pc);

View File

@ -17,6 +17,7 @@ struct TestCase {
ins: Option<Instruction>,
}
#[rustfmt::skip]
const DECODE_TESTS: &'static [TestCase] = &[
// MC68000
TestCase { cpu: M68kType::MC68000, data: &[0x4e71], ins: Some(Instruction::NOP) },
@ -66,21 +67,16 @@ const DECODE_TESTS: &'static [TestCase] = &[
fn init_decode_test(cputype: M68kType) -> (M68k, M68kCycle, MemoryBlock<u32, Instant>) {
// Insert basic initialization
let len = 0x10_0000;
let len = 0x2000;
let mut data = Vec::with_capacity(len);
unsafe { data.set_len(len); }
let mut memory = MemoryBlock::from(data);
memory.write_beu32(Instant::START, 0, INIT_STACK).unwrap();
memory.write_beu32(Instant::START, 4, INIT_ADDR).unwrap();
// Initialize the CPU and make sure it's in the expected state
let mut cpu = M68k::from_type(cputype, Frequency::from_mhz(10));
//cpu.reset_cpu().unwrap();
//assert_eq!(cpu.state.pc, INIT_ADDR);
//assert_eq!(cpu.state.ssp, INIT_STACK);
let cpu = M68k::from_type(cputype, Frequency::from_mhz(10));
let cycle = M68kCycle::new(&cpu, Instant::START);
//assert_eq!(cycle.decoder.start, INIT_ADDR);
//assert_eq!(cycle.decoder.instruction, Instruction::NOP);
(cpu, cycle, memory)
}
@ -100,12 +96,16 @@ fn run_decode_test(case: &TestCase) {
Some(ins) => {
let mut executor = cycle.begin(&mut cpu, &mut memory);
executor.reset_cpu().unwrap();
assert_eq!(executor.state.pc, INIT_ADDR);
assert_eq!(executor.state.ssp, INIT_STACK);
executor.decode_next().unwrap();
assert_eq!(executor.cycle.decoder.instruction, ins.clone());
},
None => {
let mut executor = cycle.begin(&mut cpu, &mut memory);
executor.reset_cpu().unwrap();
assert_eq!(executor.state.pc, INIT_ADDR);
assert_eq!(executor.state.ssp, INIT_STACK);
let next = executor.decode_next();
println!("{:?}", executor.cycle.decoder.instruction);
assert!(next.is_err());
@ -122,6 +122,7 @@ pub fn run_decode_tests() {
}
#[test]
#[ignore]
pub fn run_assembler_tests() {
let mut tests = 0;
let mut errors = 0;

View File

@ -44,6 +44,7 @@ where
// Insert basic initialization
let len = 0x10_0000;
let mut data = Vec::with_capacity(len);
unsafe { data.set_len(len); }
let mut memory = MemoryBlock::from(data);
memory.write_beu32(Instant::START, 0, INIT_STACK).unwrap();
memory.write_beu32(Instant::START, 4, INIT_ADDR).unwrap();
@ -75,11 +76,9 @@ fn build_state(state: &TestState) -> M68kState {
}
fn load_memory<Bus: BusAccess<u32, Instant>>(bus: &mut Bus, data: &[u16]) {
let mut addr = INIT_ADDR;
for word in data {
bus.write_beu16(Instant::START, addr, *word).unwrap();
addr += 2;
}
for i in 0..data.len() {
bus.write_beu16(Instant::START, (i << 1) as u32, data[i]).unwrap();
}
}
fn run_test(case: &TestCase) {
@ -111,6 +110,7 @@ pub fn run_execute_tests() {
}
#[test]
#[ignore]
pub fn run_assembler_tests() {
use moa_m68k::assembler::M68kAssembler;
@ -152,6 +152,7 @@ fn format_hex(data: &[u16]) -> String {
.join(", ")
}
#[rustfmt::skip]
const TEST_CASES: &'static [TestCase] = &[
TestCase {
name: "nop",
@ -218,7 +219,7 @@ const TEST_CASES: &'static [TestCase] = &[
fini: TestState { pc: 0x00000002, ssp: 0x00000000, usp: 0x00000000, d0: 0x000000FE, d1: 0x0000007F, a0: 0x00000000, a1: 0x00000000, sr: 0x270A, mem: 0x00000000 },
},
TestCase {
name: "addx with extend",
name: "addx with extend; zero flag not set",
ins: Instruction::ADDX(Target::DirectDReg(1), Target::DirectDReg(0), Size::Byte),
data: &[ 0xD101 ],
cputype: M68kType::MC68010,
@ -226,11 +227,27 @@ const TEST_CASES: &'static [TestCase] = &[
fini: TestState { pc: 0x00000002, ssp: 0x00000000, usp: 0x00000000, d0: 0x000000FF, d1: 0x0000007F, a0: 0x00000000, a1: 0x00000000, sr: 0x270A, mem: 0x00000000 },
},
TestCase {
name: "addx with extend and carry",
name: "addx with extend; zero flag set",
ins: Instruction::ADDX(Target::DirectDReg(1), Target::DirectDReg(0), Size::Byte),
data: &[ 0xD101 ],
cputype: M68kType::MC68010,
init: TestState { pc: 0x00000000, ssp: 0x00000000, usp: 0x00000000, d0: 0x0000007F, d1: 0x0000007F, a0: 0x00000000, a1: 0x00000000, sr: 0x2714, mem: 0x00000000 },
fini: TestState { pc: 0x00000002, ssp: 0x00000000, usp: 0x00000000, d0: 0x000000FF, d1: 0x0000007F, a0: 0x00000000, a1: 0x00000000, sr: 0x270A, mem: 0x00000000 },
},
TestCase {
name: "addx with extend and carry; zero flag not set",
ins: Instruction::ADDX(Target::DirectDReg(1), Target::DirectDReg(0), Size::Byte),
data: &[ 0xD101 ],
cputype: M68kType::MC68010,
init: TestState { pc: 0x00000000, ssp: 0x00000000, usp: 0x00000000, d0: 0x00000080, d1: 0x0000007F, a0: 0x00000000, a1: 0x00000000, sr: 0x2710, mem: 0x00000000 },
fini: TestState { pc: 0x00000002, ssp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x0000007F, a0: 0x00000000, a1: 0x00000000, sr: 0x2711, mem: 0x00000000 },
},
TestCase {
name: "addx with extend and carry; zero flag set",
ins: Instruction::ADDX(Target::DirectDReg(1), Target::DirectDReg(0), Size::Byte),
data: &[ 0xD101 ],
cputype: M68kType::MC68010,
init: TestState { pc: 0x00000000, ssp: 0x00000000, usp: 0x00000000, d0: 0x00000080, d1: 0x0000007F, a0: 0x00000000, a1: 0x00000000, sr: 0x2714, mem: 0x00000000 },
fini: TestState { pc: 0x00000002, ssp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x0000007F, a0: 0x00000000, a1: 0x00000000, sr: 0x2715, mem: 0x00000000 },
},
TestCase {
@ -239,7 +256,15 @@ const TEST_CASES: &'static [TestCase] = &[
data: &[ 0x027C, 0xF8FF ],
cputype: M68kType::MC68010,
init: TestState { pc: 0x00000000, ssp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0xA7AA, mem: 0x00000000 },
fini: TestState { pc: 0x00000004, ssp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0xA0AA, mem: 0x00000000 },
fini: TestState { pc: 0x00000004, ssp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0xA00A, mem: 0x00000000 },
},
TestCase {
name: "andi with sr 2",
ins: Instruction::ANDtoSR(0xF8FF),
data: &[ 0x027C, 0xF8FF ],
cputype: M68kType::MC68010,
init: TestState { pc: 0x00000000, ssp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0xA7FA, mem: 0x00000000 },
fini: TestState { pc: 0x00000004, ssp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0xA01A, mem: 0x00000000 },
},
TestCase {
name: "asl",
@ -560,13 +585,14 @@ const TEST_CASES: &'static [TestCase] = &[
init: TestState { pc: 0x00000000, ssp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x00000000, a0: MEM_ADDR, a1: 0x00000000, sr: 0x27FF, mem: 0xFF55FFAA },
fini: TestState { pc: 0x00000004, ssp: 0x00000000, usp: 0x00000000, d0: 0x000055AA, d1: 0x00000000, a0: MEM_ADDR, a1: 0x00000000, sr: 0x27FF, mem: 0xFF55FFAA },
},
// TODO not sure if these cases are correct
TestCase {
name: "movep long from even memory upper",
ins: Instruction::MOVEP(0, 0, 0, Size::Long, Direction::FromTarget),
data: &[ 0x0148, 0x0000 ],
cputype: M68kType::MC68010,
init: TestState { pc: 0x00000000, ssp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x00000000, a0: MEM_ADDR, a1: 0x00000000, sr: 0x27FF, mem: 0xAAFFBBFF },
fini: TestState { pc: 0x00000004, ssp: 0x00000000, usp: 0x00000000, d0: 0xAABB0000, d1: 0x00000000, a0: MEM_ADDR, a1: 0x00000000, sr: 0x27FF, mem: 0xAAFFBBFF },
fini: TestState { pc: 0x00000004, ssp: 0x00000000, usp: 0x00000000, d0: 0xAABBCCDD, d1: 0x00000000, a0: MEM_ADDR, a1: 0x00000000, sr: 0x27FF, mem: 0xAAFFBBFF },
},
TestCase {
name: "movep long from even memory lower",
@ -603,7 +629,7 @@ const TEST_CASES: &'static [TestCase] = &[
data: &[ 0x007C, 0x00AA ],
cputype: M68kType::MC68010,
init: TestState { pc: 0x00000000, ssp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0xA755, mem: 0x00000000 },
fini: TestState { pc: 0x00000004, ssp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0xA7FF, mem: 0x00000000 },
fini: TestState { pc: 0x00000004, ssp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0xA71F, mem: 0x00000000 },
},

View File

@ -17,6 +17,7 @@ fn init_decode_test(cputype: M68kType) -> (M68k, M68kCycle, MemoryBlock<u32, Ins
// Insert basic initialization
let len = 0x10_0000;
let mut data = Vec::with_capacity(len);
unsafe { data.set_len(len); }
let mut memory = MemoryBlock::from(data);
memory.write_beu32(Instant::START, 0, INIT_STACK).unwrap();
memory.write_beu32(Instant::START, 4, INIT_ADDR).unwrap();
@ -24,10 +25,6 @@ fn init_decode_test(cputype: M68kType) -> (M68k, M68kCycle, MemoryBlock<u32, Ins
// Initialize the CPU and make sure it's in the expected state
let cpu = M68k::from_type(cputype, Frequency::from_mhz(10));
let cycle = M68kCycle::new(&cpu, Instant::START);
assert_eq!(cpu.state.pc, INIT_ADDR);
assert_eq!(cpu.state.ssp, INIT_STACK);
assert_eq!(cycle.decoder.start, INIT_ADDR);
assert_eq!(cycle.decoder.instruction, Instruction::NOP);
(cpu, cycle, memory)
}
@ -46,6 +43,10 @@ fn run_timing_test(case: &TimingCase) -> Result<(), String> {
let mut executor = cycle.begin(&mut cpu, &mut memory);
let mut timing = M68kInstructionTiming::new(case.cpu, 16);
executor.reset_cpu().unwrap();
assert_eq!(executor.state.pc, INIT_ADDR);
assert_eq!(executor.state.ssp, INIT_STACK);
executor.decode_next().unwrap();
assert_eq!(executor.cycle.decoder.instruction, case.ins.clone());
@ -67,15 +68,15 @@ fn run_timing_test(case: &TimingCase) -> Result<(), String> {
}
#[test]
#[ignore]
pub fn run_timing_tests() {
let mut errors = 0;
for case in TIMING_TESTS {
// NOTE switched to only show the failures rather than all tests
//print!("Testing for {:?}...", case.ins);
//match run_timing_test(case) {
// Ok(()) => println!("ok"),
// Err(err) => { println!("{}", err.msg); errors += 1 },
//}
print!("Testing for {:?}...", case.ins);
match run_timing_test(case) {
Ok(()) => println!("ok"),
Err(err) => { println!("{:?}", err); errors += 1 },
}
if let Err(_) = run_timing_test(case) {
errors += 1;
@ -94,6 +95,7 @@ pub struct TimingCase {
pub ins: Instruction,
}
#[rustfmt::skip]
pub const TIMING_TESTS: &'static [TimingCase] = &[
TimingCase { cpu: M68kType::MC68000, data: &[0xA000], timing: ( 4, 4, 4), ins: Instruction::UnimplementedA(0xA000) },
TimingCase { cpu: M68kType::MC68000, data: &[0xF000], timing: ( 4, 4, 4), ins: Instruction::UnimplementedF(0xF000) },

View File

@ -28,19 +28,14 @@ fn init_decode_test(cputype: M68kType) -> (M68k, M68kCycle, MemoryBlock<u32, Ins
// Insert basic initialization
let len = 0x10_0000;
let mut data = Vec::with_capacity(len);
unsafe { data.set_len(len); }
let mut memory = MemoryBlock::from(data);
memory.write_beu32(Instant::START, 0, INIT_STACK).unwrap();
memory.write_beu32(Instant::START, 4, INIT_ADDR).unwrap();
// Initialize the CPU and make sure it's in the expected state
let cpu = M68k::from_type(cputype, Frequency::from_mhz(10));
//cpu.reset_cpu().unwrap();
assert_eq!(cpu.state.pc, INIT_ADDR);
assert_eq!(cpu.state.ssp, INIT_STACK);
let cycle = M68kCycle::new(&cpu, Instant::START);
assert_eq!(cycle.decoder.start, INIT_ADDR);
assert_eq!(cycle.decoder.instruction, Instruction::NOP);
(cpu, cycle, memory)
}
@ -59,6 +54,10 @@ fn run_timing_test(case: &TimingCase) -> Result<(), String> {
let mut executor = cycle.begin(&mut cpu, &mut memory);
let mut timing = M68kInstructionTiming::new(case.cpu, 16);
executor.reset_cpu().unwrap();
assert_eq!(executor.state.pc, INIT_ADDR);
assert_eq!(executor.state.ssp, INIT_STACK);
executor.decode_next().unwrap();
assert_eq!(executor.cycle.decoder.instruction, case.ins.clone());
@ -83,12 +82,11 @@ fn run_timing_test(case: &TimingCase) -> Result<(), String> {
pub fn run_timing_tests() {
let mut errors = 0;
for case in TIMING_TESTS {
// NOTE switched to only show the failures rather than all tests
//print!("Testing for {:?}...", case.ins);
//match run_timing_test(case) {
// Ok(()) => println!("ok"),
// Err(err) => { println!("{}", err.msg); errors += 1 },
//}
print!("Testing for {:?}...", case.ins);
match run_timing_test(case) {
Ok(()) => println!("ok"),
Err(err) => { println!("{:?}", err); errors += 1 },
}
if let Err(_) = run_timing_test(case) {
errors += 1;

View File

@ -30,7 +30,7 @@ impl Debuggable for Z80 {
Ok(())
}
fn print_disassembly(&mut self, addr: Address, count: usize) {
fn print_disassembly(&mut self, _system: &System, addr: Address, count: usize) {
let mut decoder = Z80Decoder::default();
decoder.dump_disassembly(&mut self.port, addr as u16, count as u16);
}

View File

@ -1,4 +1,5 @@
use core::fmt::Write;
use femtos::Instant;
use moa_core::{Address, Addressable};
@ -6,11 +7,9 @@ use moa_core::{Address, Addressable};
use crate::state::Z80Error;
use crate::instructions::{Direction, Condition, Register, RegisterPair, IndexRegister, IndexRegisterHalf, SpecialRegister, InterruptMode, Target, LoadTarget, UndocumentedCopy, Instruction};
use emulator_hal::bus::{BusAccess};
struct Z80Bus;
type Z80Address = (bool, u16);
//use emulator_hal::bus::BusAccess;
//
//type Z80Address = (bool, u16);
#[derive(Clone)]
pub struct Z80Decoder {
@ -554,10 +553,10 @@ impl Z80Decoder {
}
pub fn format_instruction_bytes(&mut self, memory: &mut dyn Addressable) -> String {
let ins_data: String =
(0..self.end.saturating_sub(self.start)).map(|offset|
format!("{:02x} ", memory.read_u8(self.clock, (self.start + offset) as Address).unwrap())
).collect();
let mut ins_data = String::new();
for offset in 0..self.end.saturating_sub(self.start) {
write!(ins_data, "{:02x} ", memory.read_u8(self.clock, (self.start + offset) as Address).unwrap()).unwrap()
}
ins_data
}

View File

@ -8,8 +8,6 @@ use crate::state::{Z80, Z80Error, Status, Flags};
use crate::timing::Z80InstructionCycles;
const DEV_NAME: &str = "z80-cpu";
const FLAGS_NUMERIC: u8 = 0xC0;
const FLAGS_ARITHMETIC: u8 = 0x17;
const FLAGS_CARRY_HALF_CARRY: u8 = 0x11;
@ -70,8 +68,8 @@ impl From<Error> for Z80Error {
fn from(err: Error) -> Self {
match err {
Error::Processor(ex) => Z80Error::BusError(format!("processor error {}", ex)),
Error::Breakpoint(msg) => Z80Error::Breakpoint,
Error::Other(msg) | Error::Assertion(msg) | Error::Emulator(_, msg) => Z80Error::BusError(format!("{}", msg)),
Error::Breakpoint(_) => Z80Error::Breakpoint,
Error::Other(msg) | Error::Assertion(msg) | Error::Emulator(_, msg) => Z80Error::BusError(msg.to_string()),
}
}

View File

@ -1,5 +1,4 @@
use std::fmt;
use std::rc::Rc;
use std::cell::RefCell;
use femtos::{Instant, Frequency};

View File

@ -1,5 +1,5 @@
use cpal::{Stream, SampleRate, SampleFormat, StreamConfig, StreamInstant, OutputCallbackInfo, traits::{DeviceTrait, HostTrait, StreamTrait}};
use cpal::{Stream, SampleRate, SampleFormat, StreamConfig, OutputCallbackInfo, traits::{DeviceTrait, HostTrait, StreamTrait}};
use crate::audio::{AudioOutput, SAMPLE_RATE};
@ -22,7 +22,7 @@ impl CpalAudioOutput {
.with_sample_rate(SampleRate(SAMPLE_RATE as u32))
.into();
let data_callback = move |data: &mut [f32], info: &OutputCallbackInfo| {
let data_callback = move |data: &mut [f32], _info: &OutputCallbackInfo| {
let mut index = 0;
while index < data.len() {
if let Some((clock, mut frame)) = output.receive() {

View File

@ -3,7 +3,7 @@ use std::thread;
use std::time::Duration;
use femtos::Frequency;
use moa_core::{System, MemoryBlock, BusPort, Device};
use moa_core::{System, MemoryBlock, Device};
use moa_m68k::{M68k, M68kType};
use moa_peripherals_generic::AtaDevice;

View File

@ -1,5 +1,5 @@
use clap::{Arg, ArgAction};
use clap::Arg;
use moa_console::ConsoleFrontend;
use moa_systems_computie::{build_computie, ComputieOptions};
@ -18,9 +18,9 @@ fn main() {
options.rom = filename.to_string();
}
let mut frontend = ConsoleFrontend::default();
let frontend = ConsoleFrontend;
let system = build_computie(&mut frontend, options).unwrap();
let system = build_computie(&frontend, options).unwrap();
frontend.start(matches, system);
}

View File

@ -10,7 +10,7 @@ fn main() {
.help("ROM file to load (must be flat binary)"))
.get_matches();
let mut frontend = ConsoleFrontend::default();
let mut frontend = ConsoleFrontend;
let mut options = SegaGenesisOptions::default();
if let Some(filename) = matches.get_one::<String>("ROM") {

View File

@ -14,7 +14,7 @@ impl Host for ConsoleFrontend {
fn add_pty(&self) -> Result<Box<dyn Tty>, HostError<Self::Error>> {
use moa_common::tty::SimplePty;
Ok(Box::new(SimplePty::open().map_err(|err| HostError::TTYNotSupported)?)) //.map_err(|err| Error::new(format!("console: error opening pty: {:?}", err)))?))
Ok(Box::new(SimplePty::open().map_err(|_| HostError::TTYNotSupported)?)) //.map_err(|err| Error::new(format!("console: error opening pty: {:?}", err)))?))
}
fn add_video_source(&mut self, _receiver: FrameReceiver) -> Result<(), HostError<Self::Error>> {

View File

@ -154,7 +154,7 @@ impl Debugger {
};
if let Some(device) = system.get_next_debuggable_device() {
device.borrow_mut().as_debuggable().unwrap().print_disassembly(addr, count);
device.borrow_mut().as_debuggable().unwrap().print_disassembly(system, addr, count);
}
},
"c" | "continue" => {

View File

@ -725,13 +725,18 @@ pub struct Ym2612 {
channels: Vec<Channel>,
dac: Dac,
// TODO the timer hasn't been implemented yet
#[allow(dead_code)]
timer_a_enable: bool,
timer_a: u16,
#[allow(dead_code)]
timer_a_current: u16,
timer_a_overflow: bool,
#[allow(dead_code)]
timer_b_enable: bool,
timer_b: u8,
#[allow(dead_code)]
timer_b_current: u8,
timer_b_overflow: bool,
@ -856,8 +861,8 @@ impl Ym2612 {
0x28 => {
let num = (data as usize) & 0x07;
let ch = match num {
0 | 1 | 2 => num,
4 | 5 | 6 => num - 1,
0..=2 => num,
4..=6 => num - 1,
_ => {
log::warn!("{}: attempted key on/off to invalid channel {}", DEV_NAME, num);
return;
@ -1025,7 +1030,7 @@ impl Addressable for Ym2612 {
fn read(&mut self, _clock: Instant, addr: Address, data: &mut [u8]) -> Result<(), Error> {
match addr {
0 | 1 | 2 | 3 => {
0..=3 => {
// Read the status byte (busy/overflow)
data[0] = ((self.timer_a_overflow as u8) << 1) | (self.timer_b_overflow as u8);
}

View File

@ -818,7 +818,7 @@ impl Addressable for Ym7101 {
0x00 | 0x02 => self.state.memory.read_data_port(addr, data)?,
// Read from Control Port
0x04 | 0x05 | 0x06 | 0x07 => {
0x04..=0x07 => {
log::debug!("{}: read status byte {:x}", DEV_NAME, self.state.status);
for item in data {
*item = if (addr % 2) == 0 {

View File

@ -7,11 +7,8 @@ edition = "2021"
femtos = "0.1"
emulator-hal = { path = "../../emulator/libraries/emulator-hal/emulator-hal" }
emulator-hal-memory = { path = "../../emulator/libraries/emulator-hal/emulator-hal-memory" }
moa-m68k = { path = "../../emulator/cpus/m68k" }
moa-core = { path = "../../emulator/core" }
moa-m68k = { path = "../../emulator/cpus/m68k", features = ["moa"] }
#thiserror = "1.0"
serde = "1.0"
serde_json = "1.0"
serde_derive = "1.0"

View File

@ -1,4 +1,4 @@
Last run on 2024-03-15 at commit 59306bceff1a5964902118f33034086a349e2fd3
Last run on 2024-03-16 at commit c20d7afe6e8005ab272602953154280f0e1aa944
ABCD.json.gz completed: 7993 passed, 72 FAILED
ADD.b.json.gz completed, all passed!
@ -11,3 +11,119 @@ ADDX.l.json.gz completed: 5472 passed, 2593 FAILED
ADDX.w.json.gz completed, all passed!
AND.b.json.gz completed, all passed!
AND.l.json.gz completed: 7779 passed, 286 FAILED
AND.w.json.gz completed: 7764 passed, 301 FAILED
ANDItoCCR.json.gz completed, all passed!
ANDItoSR.json.gz completed, all passed!
ASL.b.json.gz completed: 8063 passed, 2 FAILED
ASL.l.json.gz completed, all passed!
ASL.w.json.gz completed: 7896 passed, 169 FAILED
ASR.b.json.gz completed: 7783 passed, 282 FAILED
ASR.l.json.gz completed: 8029 passed, 36 FAILED
ASR.w.json.gz completed: 7891 passed, 174 FAILED
BCHG.json.gz completed, all passed!
BCLR.json.gz completed, all passed!
BSET.json.gz completed, all passed!
BSR.json.gz completed, all passed!
BTST.json.gz completed: 8051 passed, 14 FAILED
Bcc.json.gz completed, all passed!
CHK.json.gz completed: 7744 passed, 321 FAILED
CLR.b.json.gz completed, all passed!
CLR.l.json.gz completed: 7472 passed, 593 FAILED
CLR.w.json.gz completed: 7465 passed, 600 FAILED
CMP.b.json.gz completed, all passed!
CMP.l.json.gz completed, all passed!
CMP.w.json.gz completed, all passed!
CMPA.l.json.gz completed, all passed!
CMPA.w.json.gz completed, all passed!
DBcc.json.gz completed, all passed!
DIVS.json.gz completed, all passed!
DIVU.json.gz completed: 8064 passed, 1 FAILED
EOR.b.json.gz completed, all passed!
EOR.l.json.gz completed: 7519 passed, 546 FAILED
EOR.w.json.gz completed: 7525 passed, 540 FAILED
EORItoCCR.json.gz completed, all passed!
EORItoSR.json.gz completed, all passed!
EXG.json.gz completed, all passed!
EXT.l.json.gz completed, all passed!
EXT.w.json.gz completed, all passed!
JMP.json.gz completed, all passed!
JSR.json.gz completed, all passed!
LEA.json.gz completed, all passed!
LINK.json.gz completed, all passed!
LSL.b.json.gz completed, all passed!
LSL.l.json.gz completed, all passed!
LSL.w.json.gz completed: 7910 passed, 155 FAILED
LSR.b.json.gz completed, all passed!
LSR.l.json.gz completed, all passed!
LSR.w.json.gz completed: 7909 passed, 156 FAILED
MOVE.b.json.gz completed, all passed!
MOVE.l.json.gz completed: 5827 passed, 2238 FAILED
MOVE.q.json.gz completed, all passed!
MOVE.w.json.gz completed: 5855 passed, 2210 FAILED
MOVEA.l.json.gz completed, all passed!
MOVEA.w.json.gz completed, all passed!
MOVEM.l.json.gz completed: 6035 passed, 2030 FAILED
MOVEM.w.json.gz completed: 6431 passed, 1634 FAILED
MOVEP.l.json.gz completed: 4036 passed, 4029 FAILED
MOVEP.w.json.gz completed: 4046 passed, 4019 FAILED
MOVEfromSR.json.gz completed: 6896 passed, 1169 FAILED
MOVEfromUSP.json.gz completed, all passed!
MOVEtoCCR.json.gz completed, all passed!
MOVEtoSR.json.gz completed, all passed!
MOVEtoUSP.json.gz completed, all passed!
MULS.json.gz completed, all passed!
MULU.json.gz completed, all passed!
NBCD.json.gz completed: 8037 passed, 28 FAILED
NEG.b.json.gz completed, all passed!
NEG.l.json.gz completed: 7552 passed, 513 FAILED
NEG.w.json.gz completed: 7531 passed, 534 FAILED
NEGX.b.json.gz completed, all passed!
NEGX.l.json.gz completed: 7520 passed, 545 FAILED
NEGX.w.json.gz completed: 7510 passed, 555 FAILED
NOP.json.gz completed, all passed!
NOT.b.json.gz completed, all passed!
NOT.l.json.gz completed: 7512 passed, 553 FAILED
NOT.w.json.gz completed: 7530 passed, 535 FAILED
OR.b.json.gz completed, all passed!
OR.l.json.gz completed: 7756 passed, 309 FAILED
OR.w.json.gz completed: 7765 passed, 300 FAILED
ORItoCCR.json.gz completed, all passed!
ORItoSR.json.gz completed, all passed!
PEA.json.gz completed, all passed!
RESET.json.gz completed, all passed!
ROL.b.json.gz completed, all passed!
ROL.l.json.gz completed, all passed!
ROL.w.json.gz completed: 7898 passed, 167 FAILED
ROR.b.json.gz completed, all passed!
ROR.l.json.gz completed, all passed!
ROR.w.json.gz completed: 7932 passed, 133 FAILED
ROXL.b.json.gz completed: 8032 passed, 33 FAILED
ROXL.l.json.gz completed: 8029 passed, 36 FAILED
ROXL.w.json.gz completed: 7890 passed, 175 FAILED
ROXR.b.json.gz completed: 8027 passed, 38 FAILED
ROXR.l.json.gz completed: 8039 passed, 26 FAILED
ROXR.w.json.gz completed: 7880 passed, 185 FAILED
RTE.json.gz completed, all passed!
RTR.json.gz completed, all passed!
RTS.json.gz completed, all passed!
SBCD.json.gz completed: 6809 passed, 1256 FAILED
SUB.b.json.gz completed, all passed!
SUB.l.json.gz completed: 7747 passed, 318 FAILED
SUB.w.json.gz completed: 7716 passed, 349 FAILED
SUBA.l.json.gz completed, all passed!
SUBA.w.json.gz completed, all passed!
SUBX.b.json.gz completed, all passed!
SUBX.l.json.gz completed: 5481 passed, 2584 FAILED
SUBX.w.json.gz completed, all passed!
SWAP.json.gz completed, all passed!
Scc.json.gz completed, all passed!
TAS.json.gz completed, all passed!
TRAP.json.gz completed, all passed!
TRAPV.json.gz completed, all passed!
TST.b.json.gz completed, all passed!
TST.l.json.gz completed, all passed!
TST.w.json.gz completed, all passed!
UNLINK.json.gz completed, all passed!
passed: 966036, failed: 34024, total 97%
completed in 0m 7s

View File

@ -449,10 +449,8 @@ fn is_undocumented_instruction(name: &str) -> bool {
(0xFD, op) => {
let upper = op & 0xF0;
let lower = op & 0x0F;
!(lower == 0x06 && (0x30..=0xB0).contains(&upper) && upper != 0x70) &&
!(lower == 0x0E && (0x40..=0xB0).contains(&upper)) &&
!((0x70..=0x77).contains(&op) && op != 0x76) &&
!(op >= 0x21 && op <= 0x23 && op >= 0x34 && op <= 0x36 && op >= 0x29 && op <= 0x2B) &&
!(lower == 0x0E && (0x40..=0xB0).contains(&upper) || (0x70..=0x77).contains(&op) && op != 0x76 || op != 0x76 && (0x70..=0x77).contains(&op) || lower == 0x06 && (0x30..=0xB0).contains(&upper) && upper != 0x70) &&
!((0x21..=0x23).contains(&op) || (0x34..=0x36).contains(&op) || (0x29..=0x2B).contains(&op)) &&
!(lower == 0x09 && upper <= 0x30) &&
!(op == 0xE1 || op == 0xE3 || op == 0xE5 || op == 0xE9 || op == 0xF9)
},

View File

@ -1,5 +1,5 @@
* fix dump_state everywhere, which now requires a writer. Is there an easier way? Maybe serde? Is there a way that doesn't require std
* fix dump_state everywhere, which now requires a writer. Is there an easier way? Is there a way that doesn't require std
* can you clean it up more?
* implement the inspect and debug traits
* move the interrupt controller logic to the step() function only, and have a customish interrupt interface into the sim