From ffd4faa9a3438a10b0f44cb67beafd8b395964e8 Mon Sep 17 00:00:00 2001 From: transistor Date: Fri, 15 Oct 2021 14:37:31 -0700 Subject: [PATCH] Fixed decode of EXT, and fixed some bugs with 020+ code --- src/cpus/m68k/decode.rs | 63 +++++++++++++++++++++++++------------- src/cpus/m68k/execute.rs | 59 ++++++++++++++++++----------------- src/interrupts.rs | 2 +- src/main.rs | 2 ++ src/peripherals/mc68681.rs | 8 ++--- 5 files changed, 79 insertions(+), 55 deletions(-) diff --git a/src/cpus/m68k/decode.rs b/src/cpus/m68k/decode.rs index c140970..0bf5912 100644 --- a/src/cpus/m68k/decode.rs +++ b/src/cpus/m68k/decode.rs @@ -49,9 +49,9 @@ pub enum ShiftDirection { } #[derive(Copy, Clone, Debug, PartialEq)] -pub enum RegisterType { - Data, - Address, +pub enum XRegister { + Data(u8), + Address(u8), } #[derive(Copy, Clone, Debug, PartialEq)] @@ -95,10 +95,10 @@ pub enum Target { IndirectARegInc(u8), IndirectARegDec(u8), IndirectARegOffset(u8, i32), - IndirectARegXRegOffset(u8, RegisterType, u8, i32, Size), + IndirectARegXRegOffset(u8, XRegister, i32, u8, Size), IndirectMemory(u32), IndirectPCOffset(i32), - IndirectPCXRegOffset(RegisterType, u8, i32, Size), + IndirectPCXRegOffset(XRegister, i32, u8, Size), } #[derive(Clone, Debug, PartialEq)] @@ -131,7 +131,7 @@ pub enum Instruction { EORtoCCR(u8), EORtoSR(u16), EXG(Target, Target), - EXT(u8, Size), + EXT(u8, Size, Size), ILLEGAL, @@ -328,7 +328,7 @@ impl M68kDecoder { let ins_0f00 = ins & 0xF00; let ins_00f0 = ins & 0x0F0; - if (ins & 0x180) == 0x180 { + if (ins & 0x180) == 0x180 && (ins & 0x038) != 0 { if (ins & 0x040) == 0 { let size = match get_size(ins) { Some(Size::Word) => Size::Word, @@ -382,7 +382,7 @@ impl M68kDecoder { }, _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), } - } else if ins_0f00 == 0x800 { + } else if ins_0f00 == 0x800 || ins_0f00 == 0x900 { let subselect = (ins & 0x01C0) >> 6; let mode = get_low_mode(ins); match (subselect, mode) { @@ -400,10 +400,14 @@ impl M68kDecoder { let target = self.decode_lower_effective_address(system, ins, None)?; Ok(Instruction::PEA(target)) }, - (0b010, 0b000) | + (0b010, 0b000) => { + Ok(Instruction::EXT(get_low_reg(ins), Size::Byte, Size::Word)) + }, (0b011, 0b000) => { - let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long }; - Ok(Instruction::EXT(get_low_reg(ins), size)) + Ok(Instruction::EXT(get_low_reg(ins), Size::Word, Size::Long)) + }, + (0b111, 0b000) => { + Ok(Instruction::EXT(get_low_reg(ins), Size::Byte, Size::Long)) }, _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), } @@ -509,7 +513,7 @@ impl M68kDecoder { let mut disp = ((ins & 0xFF) as i8) as i32; if disp == 0 { disp = (self.read_instruction_word(system)? as i16) as i32; - } else if disp == 0xff && self.cputype >= M68kType::MC68020 { + } else if disp == -1 && self.cputype >= M68kType::MC68020 { disp = self.read_instruction_long(system)? as i32; } let condition = get_condition(ins); @@ -725,17 +729,17 @@ impl M68kDecoder { fn decode_extension_word(&mut self, system: &mut AddressableDeviceRefMut<'_>, areg: Option) -> Result { let brief_extension = self.read_instruction_word(system)?; - let rtype = if (brief_extension & 0x8000) == 0 { RegisterType::Data } else { RegisterType::Address }; - let xreg = ((brief_extension & 0x7000) >> 12) as u8; + let xreg_num = ((brief_extension & 0x7000) >> 12) as u8; + let xreg = if (brief_extension & 0x8000) == 0 { XRegister::Data(xreg_num) } else { XRegister::Address(xreg_num) }; let size = if (brief_extension & 0x0800) == 0 { Size::Word } else { Size::Long }; + let scale = ((brief_extension & 0x0600) >> 9) as u8; let use_full = (brief_extension & 0x0100) == 1; - let scale = (brief_extension & 0x0600) >> 9 as u8; if !use_full { let displacement = sign_extend_to_long((brief_extension & 0x00FF) as u32, Size::Byte); match areg { - Some(areg) => Ok(Target::IndirectARegXRegOffset(areg, rtype, xreg, displacement, size)), - None => Ok(Target::IndirectPCXRegOffset(rtype, xreg, displacement, size)), + Some(areg) => Ok(Target::IndirectARegXRegOffset(areg, xreg, displacement, scale, size)), + None => Ok(Target::IndirectPCXRegOffset(xreg, displacement, scale, size)), } } else if self.cputype >= M68kType::MC68020 { let use_base = (brief_extension & 0x0080) == 0; @@ -821,7 +825,7 @@ impl M68kDecoder { (0..((self.end - self.start) / 2)).map(|offset| Ok(format!("{:04x} ", system.get_bus().read_beu16((self.start + (offset * 2)) as Address).unwrap())) ).collect(); - println!("{:#010x}: {}\n\t{}\n", self.start, ins_data.unwrap(), self.instruction); + println!("{:#010x}: {}\n\t{:?}\n", self.start, ins_data.unwrap(), self.instruction); } } @@ -940,7 +944,7 @@ impl fmt::Display for Condition { match self { Condition::True => write!(f, "t"), Condition::False => write!(f, "f"), - Condition::High => write!(f, "h"), + Condition::High => write!(f, "hi"), Condition::LowOrSame => write!(f, "ls"), Condition::CarryClear => write!(f, "cc"), Condition::CarrySet => write!(f, "cs"), @@ -966,6 +970,15 @@ impl fmt::Display for ControlRegister { } } +impl fmt::Display for XRegister { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + XRegister::Data(reg) => write!(f, "d{}", reg), + XRegister::Address(reg) => write!(f, "a{}", reg), + } + } +} + impl fmt::Display for Target { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -976,10 +989,16 @@ impl fmt::Display for Target { Target::IndirectARegInc(reg) => write!(f, "(%a{})+", reg), Target::IndirectARegDec(reg) => write!(f, "-(%a{})", reg), Target::IndirectARegOffset(reg, offset) => write!(f, "(%a{} + #{:04x})", reg, offset), - Target::IndirectARegXRegOffset(reg, rtype, xreg, offset, _) => write!(f, "(%a{} + %{}{} + #{:04x})", reg, if *rtype == RegisterType::Data { 'd' } else { 'a' }, xreg, offset), + Target::IndirectARegXRegOffset(reg, xreg, offset, scale, _) => { + let scale_str = if *scale != 0 { format!("<< {}", scale) } else { "".to_string() }; + write!(f, "(%a{} + %{} + #{:04x}{})", reg, xreg, offset, scale_str) + }, Target::IndirectMemory(value) => write!(f, "(#{:08x})", value), Target::IndirectPCOffset(offset) => write!(f, "(%pc + #{:04x})", offset), - Target::IndirectPCXRegOffset(rtype, xreg, offset, _) => write!(f, "(%pc + %{}{} + #{:04x})", if *rtype == RegisterType::Data { 'd' } else { 'a' }, xreg, offset), + Target::IndirectPCXRegOffset(xreg, offset, scale, _) => { + let scale_str = if *scale != 0 { format!("<< {}", scale) } else { "".to_string() }; + write!(f, "(%pc + %{} + #{:04x}{})", xreg, offset, scale_str) + }, } } } @@ -1019,7 +1038,7 @@ impl fmt::Display for Instruction { Instruction::EORtoCCR(value) => write!(f, "eorb\t{:02x}, %ccr", value), Instruction::EORtoSR(value) => write!(f, "eorw\t{:04x}, %sr", value), Instruction::EXG(src, dest) => write!(f, "exg\t{}, {}", src, dest), - Instruction::EXT(reg, size) => write!(f, "ext{}\t%d{}", size, reg), + Instruction::EXT(reg, from_size, to_size) => write!(f, "ext{}{}\t%d{}", from_size, to_size, reg), Instruction::ILLEGAL => write!(f, "illegal"), diff --git a/src/cpus/m68k/execute.rs b/src/cpus/m68k/execute.rs index 6e5f9dc..c448fcc 100644 --- a/src/cpus/m68k/execute.rs +++ b/src/cpus/m68k/execute.rs @@ -13,7 +13,7 @@ use super::decode::{ Condition, ShiftDirection, ControlRegister, - RegisterType, + XRegister, sign_extend_to_long }; @@ -131,6 +131,8 @@ impl M68k { if self.debugger.use_tracing { self.decoder.dump_decoded(system); + // TODO for debugging temporarily + self.dump_state(system); } if self.debugger.use_debugger { @@ -288,15 +290,16 @@ impl M68k { }, //Instruction::EXG(Target, Target) => { //}, - Instruction::EXT(reg, size) => { - let byte = (self.state.d_reg[reg as usize] as u8) as i8; - let result = match size { - Size::Byte => (byte as u8) as u32, - Size::Word => ((byte as i16) as u16) as u32, - Size::Long => (byte as i32) as u32, + Instruction::EXT(reg, from_size, to_size) => { + let input = self.state.d_reg[reg as usize]; + let result = match (from_size, to_size) { + (Size::Byte, Size::Word) => ((((input as u8) as i8) as i16) as u16) as u32, + (Size::Word, Size::Long) => (((input as u16) as i16) as i32) as u32, + (Size::Byte, Size::Long) => (((input as u8) as i8) as i32) as u32, + _ => panic!("Unsupported size for EXT instruction"), }; - set_value_sized(&mut self.state.d_reg[reg as usize], result, size); - self.set_logic_flags(result, size); + set_value_sized(&mut self.state.d_reg[reg as usize], result, to_size); + self.set_logic_flags(result, to_size); }, //Instruction::ILLEGAL => { //}, @@ -605,10 +608,10 @@ impl M68k { let addr = self.get_a_reg_mut(reg); get_address_sized(system, (*addr).wrapping_add(offset as u32) as Address, size) }, - Target::IndirectARegXRegOffset(reg, rtype, xreg, offset, target_size) => { - let reg_offset = sign_extend_to_long(self.get_x_reg_value(rtype, xreg), target_size); + Target::IndirectARegXRegOffset(reg, xreg, offset, scale, target_size) => { + let reg_offset = sign_extend_to_long(self.get_x_reg_value(xreg), target_size); let addr = self.get_a_reg_mut(reg); - get_address_sized(system, (*addr).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) as Address, size) + get_address_sized(system, ((*addr).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) << scale) as Address, size) }, Target::IndirectMemory(addr) => { get_address_sized(system, addr as Address, size) @@ -616,9 +619,9 @@ impl M68k { Target::IndirectPCOffset(offset) => { get_address_sized(system, (self.decoder.start + 2).wrapping_add(offset as u32) as Address, size) }, - Target::IndirectPCXRegOffset(rtype, xreg, offset, target_size) => { - let reg_offset = sign_extend_to_long(self.get_x_reg_value(rtype, xreg), target_size); - get_address_sized(system, (self.decoder.start + 2).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) as Address, size) + Target::IndirectPCXRegOffset(xreg, offset, scale, target_size) => { + let reg_offset = sign_extend_to_long(self.get_x_reg_value(xreg), target_size); + get_address_sized(system, ((self.decoder.start + 2).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) << scale) as Address, size) }, } } @@ -648,10 +651,10 @@ impl M68k { let addr = self.get_a_reg_mut(reg); set_address_sized(system, (*addr).wrapping_add(offset as u32) as Address, value, size)?; }, - Target::IndirectARegXRegOffset(reg, rtype, xreg, offset, target_size) => { - let reg_offset = sign_extend_to_long(self.get_x_reg_value(rtype, xreg), target_size); + Target::IndirectARegXRegOffset(reg, xreg, offset, scale, target_size) => { + let reg_offset = sign_extend_to_long(self.get_x_reg_value(xreg), target_size); let addr = self.get_a_reg_mut(reg); - set_address_sized(system, (*addr).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) as Address, value, size)?; + set_address_sized(system, ((*addr).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) << scale) as Address, value, size)?; }, Target::IndirectMemory(addr) => { set_address_sized(system, addr as Address, value, size)?; @@ -668,10 +671,10 @@ impl M68k { let addr = self.get_a_reg_mut(reg); (*addr).wrapping_add(offset as u32) }, - Target::IndirectARegXRegOffset(reg, rtype, xreg, offset, target_size) => { - let reg_offset = sign_extend_to_long(self.get_x_reg_value(rtype, xreg), target_size); + Target::IndirectARegXRegOffset(reg, xreg, offset, scale, target_size) => { + let reg_offset = sign_extend_to_long(self.get_x_reg_value(xreg), target_size); let addr = self.get_a_reg_mut(reg); - (*addr).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) + (*addr).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) << scale }, Target::IndirectMemory(addr) => { addr @@ -679,9 +682,9 @@ impl M68k { Target::IndirectPCOffset(offset) => { (self.decoder.start + 2).wrapping_add(offset as u32) }, - Target::IndirectPCXRegOffset(rtype, xreg, offset, target_size) => { - let reg_offset = sign_extend_to_long(self.get_x_reg_value(rtype, xreg), target_size); - (self.decoder.start + 2).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) + Target::IndirectPCXRegOffset(xreg, offset, scale, target_size) => { + let reg_offset = sign_extend_to_long(self.get_x_reg_value(xreg), target_size); + (self.decoder.start + 2).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) << scale }, _ => return Err(Error::new(&format!("Invalid addressing target: {:?}", target))), }; @@ -708,10 +711,10 @@ impl M68k { } } - fn get_x_reg_value(&self, rtype: RegisterType, reg: u8) -> u32 { - match rtype { - RegisterType::Data => self.state.d_reg[reg as usize], - RegisterType::Address => self.state.a_reg[reg as usize], + fn get_x_reg_value(&self, xreg: XRegister) -> u32 { + match xreg { + XRegister::Data(reg) => self.state.d_reg[reg as usize], + XRegister::Address(reg) => self.state.a_reg[reg as usize], } } diff --git a/src/interrupts.rs b/src/interrupts.rs index db5c41e..cc5f04f 100644 --- a/src/interrupts.rs +++ b/src/interrupts.rs @@ -70,7 +70,7 @@ impl InterruptController { // TODO how does this find the specific device it's connected to? // TODO for the time being, this will find the first device to handle it or fail - println!("interrupts: priority {} state changed to {}", priority, state); + debug!("interrupts: priority {} state changed to {}", priority, state); match &self.target { Some(dev) => { Ok(dev.borrow_mut().interrupt_state_change(state, priority, number)?) diff --git a/src/main.rs b/src/main.rs index dd281c3..ae25777 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,6 +40,7 @@ fn main() { let mut cpu = M68k::new(M68kType::MC68010); + //let mut cpu = M68k::new(M68kType::MC68030); //cpu.enable_tracing(); //cpu.add_breakpoint(0x10781a); @@ -47,6 +48,7 @@ fn main() { //cpu.add_breakpoint(0x106a94); //cpu.add_breakpoint(0x10b79c); //cpu.decoder.dump_disassembly(&mut system, 0x100000, 0x2000); + //cpu.decoder.dump_disassembly(&mut system, 0x2ac, 0x200); system.add_interruptable_device(wrap_interruptable(cpu)).unwrap(); loop { diff --git a/src/peripherals/mc68681.rs b/src/peripherals/mc68681.rs index e8beeed..106ebc6 100644 --- a/src/peripherals/mc68681.rs +++ b/src/peripherals/mc68681.rs @@ -278,10 +278,6 @@ impl Addressable for MC68681 { fn read(&mut self, addr: Address, count: usize) -> Result, Error> { let mut data = vec![0; count]; - if addr != REG_SRA_RD && addr != REG_SRB_RD { - debug!("{}: reading from {:0x}", DEV_NAME, addr); - } - match addr { REG_SRA_RD => { data[0] = self.port_a.status @@ -326,6 +322,10 @@ impl Addressable for MC68681 { _ => { }, } + if addr != REG_SRA_RD && addr != REG_SRB_RD { + debug!("{}: read from {:0x} of {:0x}", DEV_NAME, addr, data[0]); + } + Ok(data) }