Added Debuggable trait and added tests

This commit is contained in:
transistor 2021-10-26 12:17:59 -07:00
parent c980c2f56d
commit 1ad7ad1807
8 changed files with 291 additions and 117 deletions

View File

@ -32,7 +32,7 @@ fn main() {
system.add_addressable_device(0x00700000, wrap_transmutable(serial)).unwrap();
let mut cpu = M68k::new(M68kType::MC68030);
let mut cpu = M68k::new(M68kType::MC68030, 8_000_000);
//cpu.enable_tracing();
//cpu.add_breakpoint(0x10781a);

View File

@ -1,7 +1,7 @@
use crate::error::Error;
use crate::system::System;
use crate::devices::{Address, Addressable};
use crate::devices::{Address, Addressable, Debuggable};
use super::state::M68k;
use super::decode::M68kDecoder;
@ -47,22 +47,22 @@ impl M68kDebugger {
}
}
impl M68k {
#[allow(dead_code)]
pub fn enable_tracing(&mut self) {
self.debugger.use_tracing = true;
}
#[allow(dead_code)]
pub fn enable_debugging(&mut self) {
impl Debuggable for M68k {
fn enable_debugging(&mut self) {
self.debugger.use_tracing = true;
self.debugger.use_debugger = true;
}
#[allow(dead_code)]
pub fn add_breakpoint(&mut self, addr: Address) {
fn add_breakpoint(&mut self, addr: Address) {
self.debugger.breakpoints.push(addr as u32);
}
}
impl M68k {
#[allow(dead_code)]
pub fn enable_tracing(&mut self) {
self.debugger.use_tracing = true;
}
pub fn check_breakpoints(&mut self) {
for breakpoint in &self.debugger.breakpoints {

View File

@ -88,7 +88,7 @@ impl M68kDecoder {
let data = self.read_instruction_word(memory)?;
match optype {
0b0000 => Ok(Instruction::ORtoCCR(data as u8)),
0b0001 => Ok(Instruction::ANDtoCCR(data as u8)),
0b0010 => Ok(Instruction::ANDtoCCR(data as u8)),
0b1010 => Ok(Instruction::EORtoCCR(data as u8)),
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
@ -423,10 +423,12 @@ impl M68kDecoder {
match size {
Some(size) => {
if (ins & 0b100110000) == 0b100000000 {
let mode = (ins & 0x08) == 0;
// TODO implement SUBX
panic!("Not Implemented");
let src = get_low_reg(ins);
let dest = get_high_reg(ins);
match (ins & 0x08) == 0 {
true => Ok(Instruction::SUBX(Target::DirectDReg(src), Target::DirectDReg(dest), size)),
false => Ok(Instruction::SUBX(Target::IndirectARegDec(src), Target::DirectDReg(dest), size)),
}
} else {
let target = self.decode_lower_effective_address(memory, ins, Some(size))?;
if dir == 0 {
@ -506,10 +508,12 @@ impl M68kDecoder {
match size {
Some(size) => {
if (ins & 0b100110000) == 0b100000000 {
let mode = (ins & 0x08) == 0;
// TODO implement ADDX
panic!("Not Implemented");
let src = get_low_reg(ins);
let dest = get_high_reg(ins);
match (ins & 0x08) == 0 {
true => Ok(Instruction::ADDX(Target::DirectDReg(src), Target::DirectDReg(dest), size)),
false => Ok(Instruction::ADDX(Target::IndirectARegDec(src), Target::DirectDReg(dest), size)),
}
} else {
let target = self.decode_lower_effective_address(memory, ins, Some(size))?;
if dir == 0 {

View File

@ -1,7 +1,7 @@
use crate::system::System;
use crate::error::{ErrorType, Error};
use crate::devices::{ClockElapsed, Address, Steppable, Interruptable, Addressable, Transmutable};
use crate::devices::{ClockElapsed, Address, Steppable, Interruptable, Addressable, Debuggable, Transmutable};
use super::instructions::{
Register,
@ -67,6 +67,10 @@ impl Transmutable for M68k {
fn as_interruptable(&mut self) -> Option<&mut dyn Interruptable> {
Some(self)
}
fn as_debuggable(&mut self) -> Option<&mut dyn Debuggable> {
Some(self)
}
}

View File

@ -98,6 +98,7 @@ pub enum Target {
pub enum Instruction {
ABCD(Target, Target),
ADD(Target, Target, Size),
ADDX(Target, Target, Size),
AND(Target, Target, Size),
ANDtoCCR(u8),
ANDtoSR(u16),
@ -183,6 +184,7 @@ pub enum Instruction {
Scc(Condition, Target),
STOP(u16),
SUB(Target, Target, Size),
SUBX(Target, Target, Size),
SWAP(Register),
TAS(Target),

View File

@ -32,6 +32,14 @@ mod decode_tests {
(cpu, system)
}
fn load_memory(system: &System, data: &[u16]) {
let mut addr = INIT_ADDR;
for word in data {
system.get_bus().write_beu16(addr, *word).unwrap();
addr += 2;
}
}
fn get_decode_memory(cpu: &mut M68k, system: &System) -> TransmutableBox {
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);
@ -302,30 +310,130 @@ mod decode_tests {
fn instruction_nop() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
system.get_bus().write_beu16(INIT_ADDR, 0x4e71).unwrap();
load_memory(&system, &[0x4e71]);
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::NOP);
}
#[test]
fn instruction_ori() {
fn instruction_ori_byte() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
system.get_bus().write_beu16(INIT_ADDR, 0x0008).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, 0x00FF).unwrap();
load_memory(&system, &[0x0008, 0x00FF]);
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::OR(Target::Immediate(0xFF), Target::DirectAReg(0), Size::Byte));
}
#[test]
fn instruction_ori_to_ccr() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
load_memory(&system, &[0x003C, 0x00FF]);
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ORtoCCR(0xFF));
}
#[test]
fn instruction_ori_to_sr() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
load_memory(&system, &[0x007C, 0x1234]);
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ORtoSR(0x1234));
}
#[test]
fn instruction_andi_word() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
load_memory(&system, &[0x0263, 0x1234]);
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::AND(Target::Immediate(0x1234), Target::IndirectARegDec(3), Size::Word));
}
#[test]
fn instruction_andi_to_ccr() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
load_memory(&system, &[0x023C, 0x1234]);
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ANDtoCCR(0x34));
}
#[test]
fn instruction_andi_to_sr() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
load_memory(&system, &[0x027C, 0xF8FF]);
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ANDtoSR(0xF8FF));
}
#[test]
fn instruction_subi() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
load_memory(&system, &[0x0487, 0x1234, 0x5678]);
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::SUB(Target::Immediate(0x12345678), Target::DirectDReg(7), Size::Long));
}
#[test]
fn instruction_addi() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
load_memory(&system, &[0x063A, 0x1234, 0x0055]);
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ADD(Target::Immediate(0x34), Target::IndirectRegOffset(BaseRegister::PC, None, 0x55), Size::Byte));
}
#[test]
fn instruction_eori_byte() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
load_memory(&system, &[0x0A23, 0x1234]);
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::EOR(Target::Immediate(0x34), Target::IndirectARegDec(3), Size::Byte));
}
#[test]
fn instruction_eori_to_ccr() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
load_memory(&system, &[0x0A3C, 0x1234]);
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::EORtoCCR(0x34));
}
#[test]
fn instruction_eori_to_sr() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
load_memory(&system, &[0x0A7C, 0xF8FF]);
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::EORtoSR(0xF8FF));
}
#[test]
fn instruction_cmpi_equal() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
system.get_bus().write_beu16(INIT_ADDR, 0x7020).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 4, 0x0020).unwrap();
cpu.step(&system).unwrap();
load_memory(&system, &[0x0C00, 0x0020]);
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::CMP(Target::Immediate(0x20), Target::DirectDReg(0), Size::Byte));
}
@ -333,11 +441,9 @@ mod decode_tests {
fn instruction_cmpi_greater() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
system.get_bus().write_beu16(INIT_ADDR, 0x7020).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 4, 0x0030).unwrap();
cpu.step(&system).unwrap();
load_memory(&system, &[0x0C00, 0x0030]);
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::CMP(Target::Immediate(0x30), Target::DirectDReg(0), Size::Byte));
}
@ -345,62 +451,59 @@ mod decode_tests {
fn instruction_cmpi_less() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
system.get_bus().write_beu16(INIT_ADDR, 0x7020).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 4, 0x0010).unwrap();
cpu.step(&system).unwrap();
load_memory(&system, &[0x0C00, 0x0010]);
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(M68kType::MC68010);
fn instruction_movel_full_extension() {
let (mut cpu, system) = init_decode_test(M68kType::MC68030);
system.get_bus().write_beu16(INIT_ADDR, 0x027C).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, 0xF8FF).unwrap();
load_memory(&system, &[0x21bc, 0x0010, 0x14c4, 0x09b0, 0x0010, 0xdf40]);
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ANDtoSR(0xF8FF));
}
#[test]
fn instruction_muls() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
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::MULW(Target::Immediate(0x276), 0, Sign::Signed));
}
#[test]
fn instruction_divs() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
system.get_bus().write_beu16(INIT_ADDR, 0x81FC).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, 0x0003).unwrap();
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::DIVW(Target::Immediate(3), 0, Sign::Signed));
assert_eq!(cpu.decoder.instruction, Instruction::MOVE(Target::Immediate(1053892), Target::IndirectRegOffset(BaseRegister::None, Some(IndexRegister { xreg: XRegister::DReg(0), scale: 0, size: Size::Long }), 0x10df40), Size::Long));
}
#[test]
fn instruction_mulsl() {
let (mut cpu, system) = init_decode_test(M68kType::MC68030);
system.get_bus().write_beu16(INIT_ADDR, 0x4c3c).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 2, 0x0800).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 4, 0x0000).unwrap();
system.get_bus().write_beu16(INIT_ADDR + 6, 0x0097).unwrap();
load_memory(&system, &[0x4c3c, 0x0800, 0x0000, 0x0097]);
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::MULL(Target::Immediate(0x97), None, 0, Sign::Signed));
}
#[test]
fn instruction_divs() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
load_memory(&system, &[0x81FC, 0x0003]);
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::DIVW(Target::Immediate(3), 0, Sign::Signed));
}
#[test]
fn instruction_muls() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
load_memory(&system, &[0xC1FC, 0x0276]);
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::MULW(Target::Immediate(0x276), 0, Sign::Signed));
}
#[test]
fn instruction_asli() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
system.get_bus().write_beu16(INIT_ADDR, 0xE300).unwrap();
load_memory(&system, &[0xE300]);
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ASd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Left));
}
@ -408,8 +511,9 @@ mod decode_tests {
fn instruction_asri() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
system.get_bus().write_beu16(INIT_ADDR, 0xE200).unwrap();
load_memory(&system, &[0xE200]);
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ASd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right));
}
@ -417,8 +521,9 @@ mod decode_tests {
fn instruction_roli() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
system.get_bus().write_beu16(INIT_ADDR, 0xE318).unwrap();
load_memory(&system, &[0xE318]);
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ROd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Left));
}
@ -426,25 +531,11 @@ mod decode_tests {
fn instruction_rori() {
let (mut cpu, system) = init_decode_test(M68kType::MC68010);
system.get_bus().write_beu16(INIT_ADDR, 0xE218).unwrap();
load_memory(&system, &[0xE218]);
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::ROd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right));
}
#[test]
fn instruction_movel_full_extension() {
let (mut cpu, system) = init_decode_test(M68kType::MC68030);
let mut addr = INIT_ADDR;
let data = [0x21bc, 0x0010, 0x14c4, 0x09b0, 0x0010, 0xdf40];
for word in data {
system.get_bus().write_beu16(addr, word).unwrap();
addr += 2;
}
cpu.decode_next(&system).unwrap();
assert_eq!(cpu.decoder.instruction, Instruction::MOVE(Target::Immediate(1053892), Target::IndirectRegOffset(BaseRegister::None, Some(IndexRegister { xreg: XRegister::DReg(0), scale: 0, size: Size::Long }), 0x10df40), Size::Long));
}
}
@ -485,9 +576,10 @@ mod execute_tests {
cpu.decoder.instruction = Instruction::NOP;
let previous = cpu.state.clone();
let expected_state = cpu.state.clone();
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state, previous);
assert_eq!(cpu.state, expected_state);
}
@ -497,8 +589,12 @@ mod execute_tests {
cpu.decoder.instruction = Instruction::OR(Target::Immediate(0xFF), Target::DirectAReg(0), Size::Byte);
let mut expected_state = cpu.state.clone();
expected_state.sr = 0x2708;
expected_state.a_reg[0] = 0x000000FF;
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.a_reg[0], 0x000000FF);
assert_eq!(cpu.state, expected_state);
}
#[test]
@ -509,8 +605,11 @@ mod execute_tests {
cpu.state.d_reg[0] = value;
cpu.decoder.instruction = Instruction::CMP(Target::Immediate(value), Target::DirectDReg(0), Size::Byte);
let mut expected_state = cpu.state.clone();
expected_state.sr = 0x2704;
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.sr & 0x0F, 0x04);
assert_eq!(cpu.state, expected_state);
}
#[test]
@ -520,8 +619,11 @@ mod execute_tests {
cpu.state.d_reg[0] = 0x20;
cpu.decoder.instruction = Instruction::CMP(Target::Immediate(0x30), Target::DirectDReg(0), Size::Byte);
let mut expected_state = cpu.state.clone();
expected_state.sr = 0x2709;
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.sr & 0x0F, 0x09);
assert_eq!(cpu.state, expected_state);
}
#[test]
@ -531,8 +633,11 @@ mod execute_tests {
cpu.state.d_reg[0] = 0x20;
cpu.decoder.instruction = Instruction::CMP(Target::Immediate(0x10), Target::DirectDReg(0), Size::Byte);
let mut expected_state = cpu.state.clone();
expected_state.sr = 0x2700;
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.sr & 0x0F, 0x00);
assert_eq!(cpu.state, expected_state);
}
#[test]
@ -542,8 +647,11 @@ mod execute_tests {
cpu.state.sr = 0xA7AA;
cpu.decoder.instruction = Instruction::ANDtoSR(0xF8FF);
let mut expected_state = cpu.state.clone();
expected_state.sr = 0xA0AA;
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.sr, 0xA0AA);
assert_eq!(cpu.state, expected_state);
}
#[test]
@ -553,8 +661,11 @@ mod execute_tests {
cpu.state.sr = 0xA755;
cpu.decoder.instruction = Instruction::ORtoSR(0x00AA);
let mut expected_state = cpu.state.clone();
expected_state.sr = 0xA7FF;
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.sr, 0xA7FF);
assert_eq!(cpu.state, expected_state);
}
#[test]
@ -565,8 +676,11 @@ mod execute_tests {
cpu.state.d_reg[0] = 0x0200;
cpu.decoder.instruction = Instruction::MULW(Target::Immediate(value), 0, Sign::Signed);
let mut expected_state = cpu.state.clone();
expected_state.d_reg[0] = 0x4ec00;
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x4ec00);
assert_eq!(cpu.state, expected_state);
}
#[test]
@ -577,8 +691,11 @@ mod execute_tests {
cpu.state.d_reg[0] = 0x40000;
cpu.decoder.instruction = Instruction::DIVW(Target::Immediate(value), 0, Sign::Unsigned);
let mut expected_state = cpu.state.clone();
expected_state.d_reg[0] = 0x007101C3;
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x007101C3);
assert_eq!(cpu.state, expected_state);
}
#[test]
@ -588,9 +705,12 @@ mod execute_tests {
cpu.state.d_reg[0] = 0x01;
cpu.decoder.instruction = Instruction::ASd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Left);
let mut expected_state = cpu.state.clone();
expected_state.sr = 0x2700;
expected_state.d_reg[0] = 0x00000002;
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x00000002);
assert_eq!(cpu.state.sr & 0x1F, 0x00);
assert_eq!(cpu.state, expected_state);
}
#[test]
@ -600,9 +720,12 @@ mod execute_tests {
cpu.state.d_reg[0] = 0x81;
cpu.decoder.instruction = Instruction::ASd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right);
let mut expected_state = cpu.state.clone();
expected_state.sr = 0x2719;
expected_state.d_reg[0] = 0x000000C0;
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x000000C0);
assert_eq!(cpu.state.sr & 0x1F, 0x19);
assert_eq!(cpu.state, expected_state);
}
#[test]
@ -612,9 +735,12 @@ mod execute_tests {
cpu.state.d_reg[0] = 0x80;
cpu.decoder.instruction = Instruction::ROd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Left);
let mut expected_state = cpu.state.clone();
expected_state.sr = 0x2701;
expected_state.d_reg[0] = 0x00000001;
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x00000001);
assert_eq!(cpu.state.sr & 0x1F, 0x01);
assert_eq!(cpu.state, expected_state);
}
#[test]
@ -624,9 +750,12 @@ mod execute_tests {
cpu.state.d_reg[0] = 0x01;
cpu.decoder.instruction = Instruction::ROd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right);
let mut expected_state = cpu.state.clone();
expected_state.sr = 0x2709;
expected_state.d_reg[0] = 0x00000080;
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x00000080);
assert_eq!(cpu.state.sr & 0x1F, 0x09);
assert_eq!(cpu.state, expected_state);
}
#[test]
@ -637,9 +766,12 @@ mod execute_tests {
cpu.state.sr = 0x2700;
cpu.decoder.instruction = Instruction::ROXd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Left);
let mut expected_state = cpu.state.clone();
expected_state.sr = 0x2715;
expected_state.d_reg[0] = 0x00000000;
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x00000000);
assert_eq!(cpu.state.sr & 0x1F, 0x15);
assert_eq!(cpu.state, expected_state);
}
#[test]
@ -650,9 +782,12 @@ mod execute_tests {
cpu.state.sr = 0x2700;
cpu.decoder.instruction = Instruction::ROXd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right);
let mut expected_state = cpu.state.clone();
expected_state.sr = 0x2715;
expected_state.d_reg[0] = 0x00000000;
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x00000000);
assert_eq!(cpu.state.sr & 0x1F, 0x15);
assert_eq!(cpu.state, expected_state);
}
#[test]
@ -663,9 +798,12 @@ mod execute_tests {
cpu.state.sr = 0x2700;
cpu.decoder.instruction = Instruction::ROXd(Target::Immediate(2), Target::DirectDReg(0), Size::Byte, ShiftDirection::Left);
let mut expected_state = cpu.state.clone();
expected_state.sr = 0x2700;
expected_state.d_reg[0] = 0x00000001;
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x00000001);
assert_eq!(cpu.state.sr & 0x1F, 0x00);
assert_eq!(cpu.state, expected_state);
}
#[test]
@ -676,9 +814,28 @@ mod execute_tests {
cpu.state.sr = 0x2700;
cpu.decoder.instruction = Instruction::ROXd(Target::Immediate(2), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right);
let mut expected_state = cpu.state.clone();
expected_state.sr = 0x2708;
expected_state.d_reg[0] = 0x00000080;
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state.d_reg[0], 0x00000080);
assert_eq!(cpu.state.sr & 0x1F, 0x08);
assert_eq!(cpu.state, expected_state);
}
#[test]
fn instruction_neg_word() {
let (mut cpu, system) = init_test();
cpu.state.d_reg[0] = 0x80;
cpu.state.sr = 0x2700;
cpu.decoder.instruction = Instruction::NEG(Target::DirectDReg(0), Size::Word);
let mut expected_state = cpu.state.clone();
expected_state.sr = 0x2709;
expected_state.d_reg[0] = 0x0000FF80;
cpu.execute_current(&system).unwrap();
assert_eq!(cpu.state, expected_state);
}

View File

@ -102,6 +102,13 @@ pub fn write_beu32(value: u32) -> [u8; 4] {
]
}
/// A device that can debugged by putting it into debug mode, or setting breakpoints
pub trait Debuggable {
fn enable_debugging(&mut self);
fn add_breakpoint(&mut self, addr: Address);
}
pub trait Transmutable {
fn as_steppable(&mut self) -> Option<&mut dyn Steppable> {
None
@ -114,6 +121,10 @@ pub trait Transmutable {
fn as_interruptable(&mut self) -> Option<&mut dyn Interruptable> {
None
}
fn as_debuggable(&mut self) -> Option<&mut dyn Debuggable> {
None
}
}
pub type TransmutableBox = Rc<RefCell<Box<dyn Transmutable>>>;

View File

@ -1,15 +1,11 @@
* should you simulate clock ticks, and only step devices when they next request it
* make devices nameable, using a hashmap to store them
* can you eventually make the system connections all configurable via a config file?
* make it possible to break out of the current execution, into the debugger, by using a certain keystroke
* make tests for each instruction
* unimplemented: ABCD, ADDX, BFFFO, BFINS, BKPT, CHK, EXG, ILLEGAL, MOVEfromCCR, MOVEP, RTR, RTD, SBCD, SUBX
* undecoded: ADDX, SUBX
* modify execution for >=MC68020: MOVEM
* >=MC68020 undecoded & unimplemented: CALLM, CAS, CAS2, CHK2, CMP2, RTM, PACK, TRAPcc, UNPK
* add support for MMU