diff --git a/src/cpus/m68k/decode.rs b/src/cpus/m68k/decode.rs index 7e0ba0a..fa42a24 100644 --- a/src/cpus/m68k/decode.rs +++ b/src/cpus/m68k/decode.rs @@ -30,15 +30,12 @@ const OPCG_BRANCH: u8 = 0x6; const OPCG_MOVEQ: u8 = 0x7; const OPCG_DIV_OR: u8 = 0x8; const OPCG_SUB: u8 = 0x9; +const OPCG_ALINE: u8 = 0xA; const OPCG_CMP_EOR: u8 = 0xB; const OPCG_MUL_AND: u8 = 0xC; const OPCG_ADD: u8 = 0xD; const OPCG_SHIFT: u8 = 0xE; - -#[allow(dead_code)] -const OPCG_RESERVED1: u8 = 0xA; -#[allow(dead_code)] -const OPCG_RESERVED2: u8 = 0xF; +const OPCG_FLINE: u8 = 0xF; pub struct M68kDecoder { @@ -597,6 +594,12 @@ impl M68kDecoder { }, } }, + OPCG_ALINE => { + Ok(Instruction::UnimplementedA(ins)) + }, + OPCG_FLINE => { + Ok(Instruction::UnimplementedF(ins)) + }, _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), } } diff --git a/src/cpus/m68k/execute.rs b/src/cpus/m68k/execute.rs index 78d5977..170e9fc 100644 --- a/src/cpus/m68k/execute.rs +++ b/src/cpus/m68k/execute.rs @@ -706,6 +706,14 @@ impl M68k { let addr = self.get_a_reg_mut(reg); *addr = new_value; }, + Instruction::UnimplementedA(ins) => { + self.state.pc -= 2; + self.exception(Exceptions::LineAEmulator as u8, false)?; + }, + Instruction::UnimplementedF(ins) => { + self.state.pc -= 2; + self.exception(Exceptions::LineFEmulator as u8, false)?; + }, _ => { return Err(Error::new("Unsupported instruction")); }, } @@ -716,7 +724,6 @@ impl M68k { fn execute_movem(&mut self, target: Target, size: Size, dir: Direction, mut mask: u16) -> Result<(), Error> { let mut addr = self.get_target_address(target)?; - // If we're using a MC68020 or higher, and it was Post-Inc/Pre-Dec target, then update the value before it's stored if self.cputype >= M68kType::MC68020 { match target { diff --git a/src/cpus/m68k/instructions.rs b/src/cpus/m68k/instructions.rs index 8018c9c..aea72ec 100644 --- a/src/cpus/m68k/instructions.rs +++ b/src/cpus/m68k/instructions.rs @@ -195,6 +195,8 @@ pub enum Instruction { TRAPV, UNLK(Register), + UnimplementedA(u16), + UnimplementedF(u16), } pub fn sign_extend_to_long(value: u32, from: Size) -> i32 { diff --git a/src/cpus/m68k/state.rs b/src/cpus/m68k/state.rs index 4aa1553..0c64e51 100644 --- a/src/cpus/m68k/state.rs +++ b/src/cpus/m68k/state.rs @@ -45,6 +45,9 @@ pub enum Exceptions { ChkInstruction = 6, TrapvInstruction = 7, PrivilegeViolation = 8, + Trace = 9, + LineAEmulator = 10, + LineFEmulator = 11, } diff --git a/src/cpus/m68k/tests.rs b/src/cpus/m68k/tests.rs index 7785fdd..edf0c52 100644 --- a/src/cpus/m68k/tests.rs +++ b/src/cpus/m68k/tests.rs @@ -46,6 +46,8 @@ mod decode_tests { TestCase { cpu: M68kType::MC68000, data: &[0xE200], ins: Some(Instruction::ASd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right)) }, TestCase { cpu: M68kType::MC68000, data: &[0xE318], ins: Some(Instruction::ROd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Left)) }, TestCase { cpu: M68kType::MC68000, data: &[0xE218], ins: Some(Instruction::ROd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right)) }, + TestCase { cpu: M68kType::MC68000, data: &[0xA000], ins: Some(Instruction::UnimplementedA(0xA000)) }, + TestCase { cpu: M68kType::MC68000, data: &[0xFFFF], ins: Some(Instruction::UnimplementedF(0xFFFF)) }, // MC68030 TestCase { cpu: M68kType::MC68030, data: &[0x4C3C, 0x0800, 0x0000, 0x0097], ins: Some(Instruction::MULL(Target::Immediate(0x97), None, 0, Sign::Signed)) }, @@ -53,7 +55,6 @@ mod decode_tests { // Should Fail TestCase { cpu: M68kType::MC68000, data: &[0x21BC, 0x0010, 0x14C4, 0x09B0, 0x0010, 0xDF40], ins: None }, - TestCase { cpu: M68kType::MC68000, data: &[0xA000], ins: None }, ]; @@ -373,8 +374,8 @@ mod execute_tests { d1: u32, a0: u32, a1: u32, - mem: u32, sr: u16, + mem: u32, } struct TestCase { diff --git a/src/debugger.rs b/src/debugger.rs index 32e17e9..de74da6 100644 --- a/src/debugger.rs +++ b/src/debugger.rs @@ -3,31 +3,9 @@ use std::io::Write; use crate::error::Error; use crate::system::System; -use crate::devices::{Address, Debuggable, TransmutableBox}; +use crate::devices::{Address, Addressable, Debuggable, TransmutableBox}; -/* -pub struct StackTracer { - pub calls: Vec, -} - -impl StackTracer { - pub fn new() -> StackTracer { - StackTracer { - calls: vec![], - } - } - - pub fn push_return(&mut self, addr: u32) { - self.calls.push(addr); - } - - pub fn pop_return(&mut self) { - self.calls.pop(); - } -} -*/ - pub struct Debugger { pub last_command: Option, pub repeat: u32, @@ -98,7 +76,7 @@ impl Debugger { }, "r" | "remove" => { if args.len() != 2 { - println!("Usage: breakpoint "); + println!("Usage: remove "); } else { let addr = u32::from_str_radix(args[1], 16).map_err(|_| Error::new("Unable to parse breakpoint address"))?; debug_obj.remove_breakpoint(addr as Address); @@ -142,6 +120,20 @@ impl Debugger { self.trace_only = true; return Ok(true); } + "setb" | "setw" | "setl" => { + if args.len() != 3 { + println!("Usage: set[b|w|l] "); + } else { + let addr = u64::from_str_radix(args[1], 16).map_err(|_| Error::new("Unable to parse set address"))?; + let data = u32::from_str_radix(args[2], 16).map_err(|_| Error::new("Unable to parse data"))?; + match args[0] { + "setb" => system.get_bus().write_u8(addr, data as u8)?, + "setw" => system.get_bus().write_beu16(addr, data as u16)?, + "setl" => system.get_bus().write_beu32(addr, data)?, + _ => panic!("Unimplemented: {:?}", args[0]), + } + } + }, //"ds" | "stack" | "dumpstack" => { // println!("Stack:"); // for addr in &self.debugger.stack_tracer.calls { diff --git a/src/memory.rs b/src/memory.rs index 6349232..72a1b65 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -130,7 +130,7 @@ impl Bus { pub fn insert(&mut self, base: Address, length: usize, dev: TransmutableBox) { let block = Block { base, length, dev }; - let i = self.blocks.iter().position(|cur| cur.base > block.base).unwrap_or(0); + let i = self.blocks.iter().position(|cur| cur.base > block.base).unwrap_or(self.blocks.len()); self.blocks.insert(i, block); } @@ -145,7 +145,7 @@ impl Bus { } } } - return Err(Error::new(&format!("No segment found at {:#08x}", addr))); + return Err(Error::new(&format!("No segment found at {:#010x}", addr))); } pub fn dump_memory(&mut self, mut addr: Address, mut count: Address) { diff --git a/src/system.rs b/src/system.rs index d7fa399..00bd3ba 100644 --- a/src/system.rs +++ b/src/system.rs @@ -7,13 +7,13 @@ use crate::memory::Bus; use crate::debugger::Debugger; use crate::error::{Error, ErrorType}; use crate::interrupts::InterruptController; -use crate::devices::{Clock, Address, TransmutableBox}; +use crate::devices::{Clock, ClockElapsed, Address, TransmutableBox}; pub struct System { pub clock: Clock, pub devices: HashMap, - pub event_queue: Vec, + pub event_queue: Vec, pub debug_enabled: Cell, pub debugger: RefCell, @@ -89,12 +89,12 @@ impl System { result } - pub fn run_for(&mut self, clocks: Clock) -> Result<(), Error> { - let target = self.clock + clocks; + pub fn run_for(&mut self, elapsed: ClockElapsed) -> Result<(), Error> { + let target = self.clock + elapsed; while self.clock < target { if self.debug_enabled.get() && self.event_queue[self.event_queue.len() - 1].device.borrow_mut().as_debuggable().is_some() { - self.debugger.borrow_mut().run_debugger(&self, self.event_queue[self.event_queue.len() - 1].device.clone()).unwrap(); + self.debugger.borrow_mut().run_debugger(&self, self.event_queue[self.event_queue.len() - 1].device.clone()); } match self.step() { @@ -129,11 +129,11 @@ impl System { fn try_queue_device(&mut self, device: TransmutableBox) { if device.borrow_mut().as_steppable().is_some() { - self.queue_device(DeviceStep::new(device)); + self.queue_device(NextStep::new(device)); } } - fn queue_device(&mut self, device_step: DeviceStep) { + fn queue_device(&mut self, device_step: NextStep) { for i in (0..self.event_queue.len()).rev() { if self.event_queue[i].next_clock > device_step.next_clock { self.event_queue.insert(i + 1, device_step); @@ -145,12 +145,12 @@ impl System { } -pub struct DeviceStep { +pub struct NextStep { pub next_clock: Clock, pub device: TransmutableBox, } -impl DeviceStep { +impl NextStep { pub fn new(device: TransmutableBox) -> Self { Self { next_clock: 0, diff --git a/todo.txt b/todo.txt index c0406be..112d2ba 100644 --- a/todo.txt +++ b/todo.txt @@ -1,4 +1,10 @@ +* movem still isn't working (for genesis) +* fix movem tests + +* modify the frame swapper and frontend to avoid the extra buffer copy +* I had to remove the mask colour from blit because it doesn't work with the mac... need a new solution + * add more m68k tests and try to test against a working impl * maybe see about a Mac 128k or something