Added a bunch of unit tests

This commit is contained in:
transistor 2021-10-11 15:04:39 -07:00
parent 39ecd1b0d9
commit 91825e1cb9
6 changed files with 440 additions and 128 deletions

View File

@ -4,6 +4,7 @@ use crate::system::System;
use crate::memory::{Address, Addressable};
use super::state::M68k;
use super::decode::M68kDecoder;
pub struct StackTracer {
pub calls: Vec<u32>,
@ -47,10 +48,12 @@ impl M68kDebugger {
}
impl M68k {
#[allow(dead_code)]
pub fn enable_tracing(&mut self) {
self.debugger.use_tracing = true;
}
#[allow(dead_code)]
pub fn add_breakpoint(&mut self, addr: Address) {
self.debugger.breakpoints.push(addr as u32);
}
@ -119,6 +122,10 @@ impl M68k {
println!(" {:08x}", system.get_bus().read_beu32(*addr as Address)?);
}
},
"dis" | "disassemble" => {
let mut decoder = M68kDecoder::new(self.cputype, 0, 0);
decoder.dump_disassembly(system, self.state.pc, 0x1000);
},
"so" | "stepout" => {
self.debugger.step_until_return = Some(self.debugger.stack_tracer.calls.len() - 1);
return Ok(true);

View File

@ -1,67 +1,242 @@
use crate::system::System;
use crate::devices::{Steppable, wrap_addressable};
use crate::memory::{Address, Addressable, MemoryBlock};
use super::decode::Instruction;
use super::state::{M68k, M68kType};
const INIT_STACK: Address = 0x00002000;
const INIT_ADDR: Address = 0x00000010;
fn init_test() -> (M68k, System) {
let mut system = System::new();
// Insert basic initialization
let data = vec![0; 0x00100000];
let mem = MemoryBlock::new(data);
system.add_addressable_device(0x00000000, wrap_addressable(mem)).unwrap();
system.get_bus().write_beu32(0, INIT_STACK as u32).unwrap();
system.get_bus().write_beu32(4, INIT_ADDR as u32).unwrap();
let mut cpu = M68k::new(M68kType::MC68010);
cpu.step(&system).unwrap();
assert_eq!(cpu.state.pc, INIT_ADDR as u32);
assert_eq!(cpu.state.msp, INIT_STACK as u32);
assert_eq!(cpu.decoder.instruction, Instruction::NOP);
(cpu, system)
}
#[cfg(test)]
mod tests {
use crate::devices::Steppable;
use crate::memory::{Address, Addressable};
mod decode_tests {
use crate::system::System;
use crate::devices::{Steppable, AddressableDeviceBox, wrap_addressable};
use crate::memory::{Address, Addressable, MemoryBlock};
use super::{init_test, INIT_ADDR};
use super::super::decode::{Instruction, Target, Size, Sign, ShiftDirection};
use crate::cpus::m68k::{M68k, M68kType};
use crate::cpus::m68k::decode::{Instruction, Target, Size, Sign, RegisterType, ShiftDirection};
const INIT_STACK: Address = 0x00002000;
const INIT_ADDR: Address = 0x00000010;
fn init_decode_test() -> (M68k, System) {
let mut system = System::new();
// Insert basic initialization
let data = vec![0; 0x00100000];
let mem = MemoryBlock::new(data);
system.add_addressable_device(0x00000000, wrap_addressable(mem)).unwrap();
system.get_bus().write_beu32(0, INIT_STACK as u32).unwrap();
system.get_bus().write_beu32(4, INIT_ADDR as u32).unwrap();
// Initialize the CPU and make sure it's in the expected state
let mut cpu = M68k::new(M68kType::MC68010);
cpu.init(&system).unwrap();
assert_eq!(cpu.state.pc, INIT_ADDR as u32);
assert_eq!(cpu.state.msp, INIT_STACK as u32);
assert_eq!(cpu.decoder.instruction, Instruction::NOP);
(cpu, system)
}
fn get_decode_memory(cpu: &mut M68k, system: &System) -> AddressableDeviceBox {
let (memory, relative_addr) = system.get_bus().get_device_at(INIT_ADDR, 12).unwrap();
cpu.decoder.init((INIT_ADDR - relative_addr) as u32, INIT_ADDR as u32);
memory
}
//
// Addressing Mode Target Tests
//
#[test]
fn target_direct_d() {
let (mut cpu, system) = init_decode_test();
let size = Size::Word;
let expected = 0x1234;
let memory = get_decode_memory(&mut cpu, &system);
let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b000, 0b001, Some(size)).unwrap();
assert_eq!(target, Target::DirectDReg(1));
}
#[test]
fn target_direct_a() {
let (mut cpu, system) = init_decode_test();
let size = Size::Word;
let expected = 0x1234;
let memory = get_decode_memory(&mut cpu, &system);
let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b001, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::DirectAReg(2));
}
#[test]
fn target_indirect_a() {
let (mut cpu, system) = init_decode_test();
let size = Size::Long;
let expected_addr = INIT_ADDR;
let expected = 0x12345678;
system.get_bus().write_beu32(INIT_ADDR, expected).unwrap();
let memory = get_decode_memory(&mut cpu, &system);
let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b010, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectAReg(2));
}
#[test]
fn target_indirect_a_inc() {
let (mut cpu, system) = init_decode_test();
let size = Size::Long;
let expected_addr = INIT_ADDR;
let expected = 0x12345678;
system.get_bus().write_beu32(INIT_ADDR, expected).unwrap();
let memory = get_decode_memory(&mut cpu, &system);
let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b011, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectARegInc(2));
}
#[test]
fn target_indirect_a_dec() {
let (mut cpu, system) = init_decode_test();
let size = Size::Long;
let expected_addr = INIT_ADDR + 4;
let expected = 0x12345678;
system.get_bus().write_beu32(INIT_ADDR, expected).unwrap();
let memory = get_decode_memory(&mut cpu, &system);
let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b100, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectARegDec(2));
}
#[test]
fn target_indirect_a_reg_offset() {
let (mut cpu, system) = init_decode_test();
let size = Size::Long;
let offset = -8;
system.get_bus().write_beu16(INIT_ADDR, (offset as i16) as u16).unwrap();
let memory = get_decode_memory(&mut cpu, &system);
let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b101, 0b100, Some(size)).unwrap();
assert_eq!(target, Target::IndirectARegOffset(4, offset));
}
#[test]
fn target_indirect_a_reg_extension_word() {
let (mut cpu, system) = init_decode_test();
let size = Size::Long;
let offset = -8;
let brief_extension = 0x3800 | (((offset as i8) as u8) as u16);
system.get_bus().write_beu16(INIT_ADDR, brief_extension).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, (offset as i16) as u16).unwrap();
let memory = get_decode_memory(&mut cpu, &system);
let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b110, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectARegXRegOffset(2, RegisterType::Data, 3, offset, size));
}
#[test]
fn target_indirect_immediate_word() {
let (mut cpu, system) = init_decode_test();
let size = Size::Word;
let expected = 0x1234;
system.get_bus().write_beu16(INIT_ADDR, expected as u16).unwrap();
let memory = get_decode_memory(&mut cpu, &system);
let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b111, 0b000, Some(size)).unwrap();
assert_eq!(target, Target::IndirectMemory(expected));
}
#[test]
fn target_indirect_immediate_long() {
let (mut cpu, system) = init_decode_test();
let size = Size::Word;
let expected = 0x12345678;
system.get_bus().write_beu32(INIT_ADDR, expected).unwrap();
let memory = get_decode_memory(&mut cpu, &system);
let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b111, 0b001, Some(size)).unwrap();
assert_eq!(target, Target::IndirectMemory(expected));
}
#[test]
fn target_indirect_pc_offset() {
let (mut cpu, system) = init_decode_test();
let size = Size::Long;
let offset = -8;
system.get_bus().write_beu16(INIT_ADDR, (offset as i16) as u16).unwrap();
let memory = get_decode_memory(&mut cpu, &system);
let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b111, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectPCOffset(offset));
}
#[test]
fn target_indirect_pc_extension_word() {
let (mut cpu, system) = init_decode_test();
let size = Size::Word;
let offset = -8;
let brief_extension = 0x3000 | (((offset as i8) as u8) as u16);
system.get_bus().write_beu16(INIT_ADDR, brief_extension).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, (offset as i16) as u16).unwrap();
let memory = get_decode_memory(&mut cpu, &system);
let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b111, 0b011, Some(size)).unwrap();
assert_eq!(target, Target::IndirectPCXRegOffset(RegisterType::Data, 3, offset, size));
}
#[test]
fn target_immediate() {
let (mut cpu, system) = init_decode_test();
let size = Size::Word;
let expected = 0x1234;
system.get_bus().write_beu16(INIT_ADDR, expected as u16).unwrap();
let memory = get_decode_memory(&mut cpu, &system);
let target = cpu.decoder.get_mode_as_target(&mut memory.borrow_mut(), 0b111, 0b100, Some(size)).unwrap();
assert_eq!(target, Target::Immediate(expected));
}
//
// Instruction Decode Tests
//
#[test]
fn instruction_nop() {
let (mut cpu, mut system) = init_test();
let (mut cpu, system) = init_decode_test();
system.get_bus().write_beu16(INIT_ADDR, 0x4e71).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::NOP);
cpu.execute_current(&system).unwrap();
// TODO you need a way to easily check the entire state (you maybe need to make a special struct for the state)
}
#[test]
fn instruction_ori() {
let (mut cpu, mut system) = init_test();
let (mut cpu, system) = init_decode_test();
system.get_bus().write_beu16(INIT_ADDR, 0x0008).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, 0x00FF).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::OR(Target::Immediate(0xFF), Target::DirectAReg(0), Size::Byte));
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.a_reg[0], 0x000000FF);
}
#[test]
fn instruction_cmpi_equal() {
let (mut cpu, mut system) = init_test();
let (mut cpu, system) = init_decode_test();
system.get_bus().write_beu16(INIT_ADDR, 0x7020).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
@ -69,13 +244,11 @@ mod tests {
cpu.step(&system).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::CMP(Target::Immediate(0x20), Target::DirectDReg(0), Size::Byte));
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.sr & 0x0F, 0x04);
}
#[test]
fn instruction_cmpi_greater() {
let (mut cpu, mut system) = init_test();
let (mut cpu, system) = init_decode_test();
system.get_bus().write_beu16(INIT_ADDR, 0x7020).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
@ -83,13 +256,11 @@ mod tests {
cpu.step(&system).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::CMP(Target::Immediate(0x30), Target::DirectDReg(0), Size::Byte));
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.sr & 0x0F, 0x009);
}
#[test]
fn instruction_cmpi_less() {
let (mut cpu, mut system) = init_test();
let (mut cpu, system) = init_decode_test();
system.get_bus().write_beu16(INIT_ADDR, 0x7020).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
@ -97,43 +268,206 @@ mod tests {
cpu.step(&system).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::CMP(Target::Immediate(0x10), Target::DirectDReg(0), Size::Byte));
}
#[test]
fn instruction_andi_sr() {
let (mut cpu, system) = init_decode_test();
system.get_bus().write_beu16(INIT_ADDR, 0x027C).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, 0xF8FF).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ANDtoSR(0xF8FF));
}
#[test]
fn instruction_muls() {
let (mut cpu, system) = init_decode_test();
system.get_bus().write_beu16(INIT_ADDR, 0xC1FC).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, 0x0276).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::MUL(Target::Immediate(0x276), Target::DirectDReg(0), Size::Word, Sign::Signed));
}
#[test]
fn instruction_asli() {
let (mut cpu, system) = init_decode_test();
system.get_bus().write_beu16(INIT_ADDR, 0xE300).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ASd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Left));
}
#[test]
fn instruction_asri() {
let (mut cpu, system) = init_decode_test();
system.get_bus().write_beu16(INIT_ADDR, 0xE200).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ASd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right));
}
#[test]
fn instruction_roli() {
let (mut cpu, system) = init_decode_test();
system.get_bus().write_beu16(INIT_ADDR, 0xE318).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ROd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Left));
}
#[test]
fn instruction_rori() {
let (mut cpu, system) = init_decode_test();
system.get_bus().write_beu16(INIT_ADDR, 0xE218).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ROd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right));
}
}
#[cfg(test)]
mod execute_tests {
use crate::system::System;
use crate::devices::{Steppable, wrap_addressable};
use crate::memory::{Address, Addressable, MemoryBlock};
use crate::cpus::m68k::{M68k, M68kType};
use crate::cpus::m68k::decode::{Instruction, Target, Size, Sign, ShiftDirection};
const INIT_STACK: Address = 0x00002000;
const INIT_ADDR: Address = 0x00000010;
fn init_test() -> (M68k, System) {
let mut system = System::new();
// Insert basic initialization
let data = vec![0; 0x00100000];
let mem = MemoryBlock::new(data);
system.add_addressable_device(0x00000000, wrap_addressable(mem)).unwrap();
system.get_bus().write_beu32(0, INIT_STACK as u32).unwrap();
system.get_bus().write_beu32(4, INIT_ADDR as u32).unwrap();
let mut cpu = M68k::new(M68kType::MC68010);
cpu.step(&system).unwrap();
assert_eq!(cpu.state.pc, INIT_ADDR as u32);
assert_eq!(cpu.state.msp, INIT_STACK as u32);
assert_eq!(cpu.decoder.instruction, Instruction::NOP);
(cpu, system)
}
#[test]
fn instruction_nop() {
let (mut cpu, system) = init_test();
cpu.decoder.instruction = Instruction::NOP;
let previous = cpu.state.clone();
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state, previous);
}
#[test]
fn instruction_ori() {
let (mut cpu, system) = init_test();
cpu.decoder.instruction = Instruction::OR(Target::Immediate(0xFF), Target::DirectAReg(0), Size::Byte);
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.a_reg[0], 0x000000FF);
}
#[test]
fn instruction_cmpi_equal() {
let (mut cpu, system) = init_test();
let value = 0x20;
cpu.state.d_reg[0] = value;
cpu.decoder.instruction = Instruction::CMP(Target::Immediate(value), Target::DirectDReg(0), Size::Byte);
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.sr & 0x0F, 0x04);
}
#[test]
fn instruction_cmpi_greater() {
let (mut cpu, system) = init_test();
cpu.state.d_reg[0] = 0x20;
cpu.decoder.instruction = Instruction::CMP(Target::Immediate(0x30), Target::DirectDReg(0), Size::Byte);
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.sr & 0x0F, 0x09);
}
#[test]
fn instruction_cmpi_less() {
let (mut cpu, system) = init_test();
cpu.state.d_reg[0] = 0x20;
cpu.decoder.instruction = Instruction::CMP(Target::Immediate(0x10), Target::DirectDReg(0), Size::Byte);
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.sr & 0x0F, 0x00);
}
#[test]
fn instruction_andi_sr() {
let (mut cpu, mut system) = init_test();
let (mut cpu, system) = init_test();
system.get_bus().write_beu16(INIT_ADDR, 0x027C).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, 0xF8FF).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ANDtoSR(0xF8FF));
//cpu.execute_current(&system).unwrap();
//assert_eq!(cpu.state.sr & 0x0F, 0x00);
cpu.state.sr = 0x87AA;
cpu.decoder.instruction = Instruction::ANDtoSR(0xF8FF);
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.sr, 0x80AA);
}
#[test]
fn instruction_ori_sr() {
let (mut cpu, system) = init_test();
cpu.state.sr = 0x8755;
cpu.decoder.instruction = Instruction::ORtoSR(0x00AA);
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.sr, 0x87FF);
}
#[test]
fn instruction_muls() {
let (mut cpu, mut system) = init_test();
let (mut cpu, system) = init_test();
system.get_bus().write_beu16(INIT_ADDR, 0xC1FC).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, 0x0276).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::MUL(Target::Immediate(0x276), Target::DirectDReg(0), Size::Word, Sign::Signed));
//cpu.execute_current(&system).unwrap();
//assert_eq!(cpu.state.sr & 0x0F, 0x00);
let value = 0x0276;
cpu.state.d_reg[0] = 0x0200;
cpu.decoder.instruction = Instruction::MUL(Target::Immediate(value), Target::DirectDReg(0), Size::Word, Sign::Signed);
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x4ec00);
}
#[test]
fn instruction_divu() {
let (mut cpu, system) = init_test();
let value = 0x0245;
cpu.state.d_reg[0] = 0x40000;
cpu.decoder.instruction = Instruction::DIV(Target::Immediate(value), Target::DirectDReg(0), Size::Word, Sign::Unsigned);
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x007101C3);
}
#[test]
fn instruction_asli() {
let (mut cpu, mut system) = init_test();
system.get_bus().write_beu16(INIT_ADDR, 0xE300).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ASd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Left));
let (mut cpu, system) = init_test();
cpu.state.d_reg[0] = 0x01;
cpu.decoder.instruction = Instruction::ASd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Left);
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x00000002);
assert_eq!(cpu.state.sr & 0x1F, 0x00);
@ -141,13 +475,11 @@ mod tests {
#[test]
fn instruction_asri() {
let (mut cpu, mut system) = init_test();
system.get_bus().write_beu16(INIT_ADDR, 0xE200).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ASd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right));
let (mut cpu, system) = init_test();
cpu.state.d_reg[0] = 0x81;
cpu.decoder.instruction = Instruction::ASd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right);
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x000000C0);
assert_eq!(cpu.state.sr & 0x1F, 0x19);
@ -155,13 +487,11 @@ mod tests {
#[test]
fn instruction_roli() {
let (mut cpu, mut system) = init_test();
system.get_bus().write_beu16(INIT_ADDR, 0xE318).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ROd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Left));
let (mut cpu, system) = init_test();
cpu.state.d_reg[0] = 0x80;
cpu.decoder.instruction = Instruction::ROd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Left);
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x00000001);
assert_eq!(cpu.state.sr & 0x1F, 0x01);
@ -169,13 +499,11 @@ mod tests {
#[test]
fn instruction_rori() {
let (mut cpu, mut system) = init_test();
system.get_bus().write_beu16(INIT_ADDR, 0xE218).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ROd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right));
let (mut cpu, system) = init_test();
cpu.state.d_reg[0] = 0x01;
cpu.decoder.instruction = Instruction::ROd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right);
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x00000080);
assert_eq!(cpu.state.sr & 0x1F, 0x09);
@ -183,17 +511,13 @@ mod tests {
#[test]
fn target_value_direct_d() {
let (mut cpu, mut system) = init_test();
let (mut cpu, system) = init_test();
let size = Size::Word;
let expected = 0x1234;
let target = cpu.decoder.get_mode_as_target(&system, 0b000, 0b001, Some(size)).unwrap();
assert_eq!(target, Target::DirectDReg(1));
let target = Target::DirectDReg(1);
cpu.state.d_reg[1] = expected;
let result = cpu.get_target_value(&system, target, size).unwrap();
@ -202,13 +526,11 @@ mod tests {
#[test]
fn target_value_direct_a() {
let (mut cpu, mut system) = init_test();
let (mut cpu, system) = init_test();
let size = Size::Word;
let expected = 0x1234;
let target = cpu.decoder.get_mode_as_target(&system, 0b001, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::DirectAReg(2));
let target = Target::DirectAReg(2);
cpu.state.a_reg[2] = expected;
let result = cpu.get_target_value(&system, target, size).unwrap();
@ -217,15 +539,13 @@ mod tests {
#[test]
fn target_value_indirect_a() {
let (mut cpu, mut system) = init_test();
let (mut cpu, system) = init_test();
let size = Size::Long;
let expected_addr = INIT_ADDR;
let expected = 0x12345678;
let target = Target::IndirectAReg(2);
system.get_bus().write_beu32(INIT_ADDR, expected).unwrap();
let target = cpu.decoder.get_mode_as_target(&system, 0b010, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectAReg(2));
cpu.state.a_reg[2] = INIT_ADDR as u32;
let result = cpu.get_target_value(&system, target, size).unwrap();
@ -234,15 +554,13 @@ mod tests {
#[test]
fn target_value_indirect_a_inc() {
let (mut cpu, mut system) = init_test();
let (mut cpu, system) = init_test();
let size = Size::Long;
let expected_addr = INIT_ADDR;
let expected = 0x12345678;
let target = Target::IndirectARegInc(2);
system.get_bus().write_beu32(INIT_ADDR, expected).unwrap();
let target = cpu.decoder.get_mode_as_target(&system, 0b011, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectARegInc(2));
cpu.state.a_reg[2] = INIT_ADDR as u32;
let result = cpu.get_target_value(&system, target, size).unwrap();
@ -252,15 +570,13 @@ mod tests {
#[test]
fn target_value_indirect_a_dec() {
let (mut cpu, mut system) = init_test();
let (mut cpu, system) = init_test();
let size = Size::Long;
let expected_addr = INIT_ADDR + 4;
let expected = 0x12345678;
let target = Target::IndirectARegDec(2);
system.get_bus().write_beu32(INIT_ADDR, expected).unwrap();
let target = cpu.decoder.get_mode_as_target(&system, 0b100, 0b010, Some(size)).unwrap();
assert_eq!(target, Target::IndirectARegDec(2));
cpu.state.a_reg[2] = (INIT_ADDR as u32) + 4;
let result = cpu.get_target_value(&system, target, size).unwrap();
@ -271,17 +587,16 @@ mod tests {
#[test]
fn target_value_immediate() {
let (mut cpu, mut system) = init_test();
let (mut cpu, system) = init_test();
let size = Size::Word;
let expected = 0x1234;
system.get_bus().write_beu16(cpu.decoder.end as Address, expected as u16).unwrap();
let target = cpu.decoder.get_mode_as_target(&system, 0b111, 0b100, Some(size)).unwrap();
assert_eq!(target, Target::Immediate(expected));
let target = Target::Immediate(expected);
let result = cpu.get_target_value(&system, target, size).unwrap();
assert_eq!(result, expected);
}
}

View File

@ -9,27 +9,33 @@ use crate::memory::{Addressable};
pub type Clock = u64;
/// A device that can change state over time. The `step()` method will be called
/// by the containing `System` when the system clock advances. If an error occurs
/// with any device, the `on_error()` method will be called to display any state
/// information that might be helpful for debugging.
pub trait Steppable {
fn step(&mut self, system: &System) -> Result<Clock, Error>;
fn on_error(&mut self, _system: &System) { }
}
/// A device that can receive an interrupt. The `interrupt_state_change()` method
/// will be called whenever an interrupt signal changes goes high or low.
pub trait Interruptable {
fn interrupt_state_change(&mut self, state: bool, priority: u8, number: u8) -> Result<(), Error>;
}
pub trait AddressableDevice: Addressable + Steppable { }
pub trait InterruptableDevice: Interruptable + Steppable { }
impl<T: Addressable + Steppable> AddressableDevice for T { }
impl<T: Interruptable + Steppable> InterruptableDevice for T { }
pub type AddressableDeviceBox = Rc<RefCell<Box<dyn AddressableDevice>>>;
pub type InterruptableDeviceBox = Rc<RefCell<Box<dyn InterruptableDevice>>>;
pub type AddressableDeviceRefMut<'a> = RefMut<'a, Box<dyn AddressableDevice>>;
impl<T: Addressable + Steppable> AddressableDevice for T { }
impl<T: Interruptable + Steppable> InterruptableDevice for T { }
pub fn wrap_addressable<T: AddressableDevice + 'static>(value: T) -> AddressableDeviceBox {
Rc::new(RefCell::new(Box::new(value)))
}

View File

@ -3,7 +3,6 @@
pub enum ErrorType {
Emulator,
Processor,
Internal,
}
#[derive(Debug)]

View File

@ -58,21 +58,6 @@ fn main() {
},
}
}
/*
// TODO I need to add a way to decode and dump the assembly for a section of code, in debugger
cpu.enable_tracing();
cpu.state.pc = 0x0010781a;
while cpu.is_running() {
match cpu.decode_next(&system) {
Ok(()) => { },
Err(err) => {
cpu.dump_state(&system);
panic!("{:?}", err);
},
}
}
*/
}
pub fn launch_terminal_emulator(name: String) {
@ -84,7 +69,6 @@ pub fn launch_terminal_emulator(name: String) {
}
pub fn launch_slip_connection(name: String) {
use nix::unistd::sleep;
use std::process::Command;
Command::new("sudo").args(["slattach", "-s", "38400", "-p", "slip", &name]).spawn().unwrap();

View File

@ -8,6 +8,7 @@ use crate::devices::{Clock, Steppable, AddressableDeviceBox};
pub type Address = u64;
/// A device that can be addressed to read data from or write data to the device.
pub trait Addressable {
fn len(&self) -> usize;
fn read(&mut self, addr: Address, count: usize) -> Result<Vec<u8>, Error>;