diff --git a/src/cpus/m68k/decode.rs b/src/cpus/m68k/decode.rs index a941445..767ecdf 100644 --- a/src/cpus/m68k/decode.rs +++ b/src/cpus/m68k/decode.rs @@ -5,6 +5,24 @@ use crate::memory::{Address, AddressSpace}; use super::execute::MC68010; use super::execute::ERR_ILLEGAL_INSTRUCTION; +const OPCG_BIT_OPS: u8 = 0x0; +const OPCG_MOVE_BYTE: u8 = 0x1; +const OPCG_MOVE_LONG: u8 = 0x2; +const OPCG_MOVE_WORD: u8 = 0x3; +const OPCG_MISC: u8 = 0x04; +const OPCG_ADDQ_SUBQ: u8 = 0x5; +const OPCG_BRANCH: u8 = 0x6; +const OPCG_MOVEQ: u8 = 0x7; +const OPCG_DIV_OR: u8 = 0x8; +const OPCG_SUB: u8 = 0x9; +const OPCG_RESERVED1: u8 = 0xA; +const OPCG_CMP_EOR: u8 = 0xB; +const OPCG_MUL_AND: u8 = 0xC; +const OPCG_ADD: u8 = 0xD; +const OPCG_SHIFT: u8 = 0xE; +const OPCG_RESERVED2: u8 = 0xF; + + #[derive(Copy, Clone, Debug, PartialEq)] pub enum Sign { Signed, @@ -95,6 +113,7 @@ pub enum Instruction { CLR(Target, Size), CMP(Target, Target, Size), + CMPA(Target, u8, Size), DBcc(Condition, u16), DIV(Target, Target, Size, Sign), @@ -160,24 +179,6 @@ pub enum Instruction { } -const OPCG_BIT_OPS: u8 = 0x0; -const OPCG_MOVE_BYTE: u8 = 0x1; -const OPCG_MOVE_LONG: u8 = 0x2; -const OPCG_MOVE_WORD: u8 = 0x3; -const OPCG_MISC: u8 = 0x04; -const OPCG_ADDQ_SUBQ: u8 = 0x5; -const OPCG_BRANCH: u8 = 0x6; -const OPCG_MOVEQ: u8 = 0x7; -const OPCG_DIV_OR: u8 = 0x8; -const OPCG_SUB: u8 = 0x9; -const OPCG_RESERVED1: u8 = 0xA; -const OPCG_CMP_EOR: u8 = 0xB; -const OPCG_MUL_AND: u8 = 0xC; -const OPCG_ADD: u8 = 0xD; -const OPCG_SHIFT: u8 = 0xE; -const OPCG_RESERVED2: u8 = 0xF; - - impl MC68010 { fn read_instruction_word(&mut self, space: &mut AddressSpace) -> Result { let word = space.read_beu16(self.pc as Address)?; @@ -332,7 +333,7 @@ impl MC68010 { } else { let target = self.decode_lower_effective_address(space, ins, None)?; let data = self.read_instruction_word(space)?; - let dir = if (ins & 0x0200) == 0 { Direction::ToTarget } else { Direction::FromTarget }; + let dir = if (ins & 0x0400) == 0 { Direction::ToTarget } else { Direction::FromTarget }; Ok(Instruction::MOVEM(target, size, dir, data)) } } else if (ins & 0b111100000000) == 0b100000000000 { @@ -496,12 +497,12 @@ impl MC68010 { }, (0b0, Some(size)) => { let target = self.decode_lower_effective_address(space, ins, Some(size))?; - Ok(Instruction::CMP(Target::DirectDReg(reg), target, size)) + Ok(Instruction::CMP(target, Target::DirectDReg(reg), size)) }, (_, None) => { let size = if optype == 0 { Size::Word } else { Size::Long }; let target = self.decode_lower_effective_address(space, ins, Some(size))?; - Ok(Instruction::CMP(target, Target::DirectAReg(reg), size)) + Ok(Instruction::CMPA(target, reg, size)) }, _ => return Err(Error::processor(ERR_ILLEGAL_INSTRUCTION)), } @@ -624,7 +625,7 @@ impl MC68010 { 0b111 => { match reg { 0b000 => { - let value = self.read_instruction_word(space)? as u32; + let value = sign_extend_to_long(self.read_instruction_word(space)? as u32, Size::Word) as u32; Target::IndirectMemory(value) }, 0b001 => { diff --git a/src/cpus/m68k/execute.rs b/src/cpus/m68k/execute.rs index 7d70afc..f34afdc 100644 --- a/src/cpus/m68k/execute.rs +++ b/src/cpus/m68k/execute.rs @@ -47,7 +47,7 @@ pub struct MC68010 { pub current_instruction_addr: u32, pub current_instruction: Instruction, - pub breakpoint: u32, + pub breakpoints: Vec, pub use_tracing: bool, pub use_debugger: bool, } @@ -68,7 +68,7 @@ impl MC68010 { current_instruction_addr: 0, current_instruction: Instruction::NOP, - breakpoint: 0, + breakpoints: vec![], use_tracing: false, use_debugger: false, } @@ -87,7 +87,7 @@ impl MC68010 { self.current_instruction_addr = 0; self.current_instruction = Instruction::NOP; - self.breakpoint = 0; + self.breakpoints = vec![]; self.use_tracing = false; self.use_debugger = false; } @@ -106,8 +106,8 @@ impl MC68010 { Ok(()) } - pub fn set_breakpoint(&mut self, addr: Address) { - self.breakpoint = addr as u32; + pub fn add_breakpoint(&mut self, addr: Address) { + self.breakpoints.push(addr as u32); } pub fn step(&mut self, space: &mut AddressSpace) -> Result<(), Error> { @@ -162,9 +162,12 @@ impl MC68010 { self.current_instruction_addr = self.pc; self.current_instruction = self.decode_one(space)?; - if self.breakpoint == self.current_instruction_addr { - self.use_tracing = true; - self.use_debugger = true; + for breakpoint in &self.breakpoints { + if *breakpoint == self.current_instruction_addr { + self.use_tracing = true; + self.use_debugger = true; + break; + } } if self.use_tracing { @@ -190,6 +193,10 @@ impl MC68010 { std::io::stdin().read_line(&mut buffer).unwrap(); match buffer.as_ref() { "dump\n" => space.dump_memory(self.msp as Address, (0x200000 - self.msp) as Address), + "continue\n" => { + self.use_debugger = false; + return; + }, _ => { return; }, } } @@ -277,6 +284,11 @@ impl MC68010 { let existing = self.get_target_value(space, dest, size)?; let result = self.subtract_sized_with_flags(existing, value, size); }, + Instruction::CMPA(src, reg, size) => { + let value = self.get_target_value(space, src, size)?; + let existing = sign_extend_to_long(*self.get_a_reg_mut(reg), size) as u32; + let result = self.subtract_sized_with_flags(existing, value, Size::Long); + }, //Instruction::DBcc(Condition, u16) => { //}, //Instruction::DIV(Target, Target, Size, Sign) => { @@ -374,31 +386,32 @@ impl MC68010 { if dir == Direction::ToTarget { let mut mask = mask; - for i in 0..8 { - if (mask & 0x01) != 0 { - self.set_target_value(space, target, self.d_reg[i], size)?; - } - mask >>= 1; - } - for i in 0..8 { + for i in (0..8).rev() { if (mask & 0x01) != 0 { let value = *self.get_a_reg_mut(i); self.set_target_value(space, target, value, size)?; } mask >>= 1; } + for i in (0..8).rev() { + if (mask & 0x01) != 0 { + self.set_target_value(space, target, self.d_reg[i], size)?; + } + mask >>= 1; + } } else { let mut mask = mask; - for i in (0..8).rev() { + for i in 0..8 { if (mask & 0x01) != 0 { - let value = *self.get_a_reg_mut(i); - self.set_target_value(space, target, value, size)?; + self.d_reg[i] = self.get_target_value(space, target, size)?; } mask >>= 1; } - for i in (0..8).rev() { + for i in 0..8 { if (mask & 0x01) != 0 { - self.set_target_value(space, target, self.d_reg[i], size)?; + let value = self.get_target_value(space, target, size)?; + let addr = self.get_a_reg_mut(i); + *addr = value; } mask >>= 1; } diff --git a/src/main.rs b/src/main.rs index 1c627f4..0708578 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,7 +25,10 @@ fn main() { space.insert(0x00700000, Box::new(serial)); let mut cpu = MC68010::new(); - cpu.set_breakpoint(0x0ea0); + //cpu.add_breakpoint(0x07f8); + //cpu.add_breakpoint(0x0836); + //cpu.add_breakpoint(0x0838); + cpu.use_tracing = true; while cpu.is_running() { match cpu.step(&mut space) { @@ -38,5 +41,13 @@ fn main() { //serial.step(); } + + // TODO I need to add a way to decode and dump the assembly for a section of code, in debugger + /* + cpu.pc = 0x07f8; + while cpu.is_running() { + cpu.decode_next(&mut space).unwrap(); + } + */ } diff --git a/src/memory.rs b/src/memory.rs index bac10c4..109d2e8 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -39,7 +39,8 @@ impl Addressable for MemoryBlock { } fn read(&mut self, addr: Address, count: usize) -> Vec { - self.contents[(addr as usize) .. (addr as usize + count)].to_vec() + let size = if addr as usize + count < self.contents.len() { addr as usize + count } else { self.contents.len() }; + self.contents[(addr as usize) .. size].to_vec() } fn write(&mut self, mut addr: Address, data: &[u8]) { @@ -112,7 +113,12 @@ impl AddressSpace { let mut line = format!("{:#010x}: ", addr); let to = if count < 16 { count / 2 } else { 8 }; for i in 0..to { - line += &format!("{:#06x} ", self.read_beu16(addr).unwrap()); + let word = self.read_beu16(addr); + if word.is_err() { + println!("{}", line); + return; + } + line += &format!("{:#06x} ", word.unwrap()); addr += 2; count -= 2; }