From e81a5d430a183949c34c10b19911caf68663893a Mon Sep 17 00:00:00 2001 From: transistor Date: Tue, 19 Oct 2021 19:50:42 -0700 Subject: [PATCH] Fixed some bugs and added the ROXd instruction --- src/cpus/m68k/execute.rs | 29 ++++++++++++------ src/cpus/m68k/tests.rs | 63 ++++++++++++++++++++++++++++++++++++---- src/memory.rs | 10 +++++++ 3 files changed, 88 insertions(+), 14 deletions(-) diff --git a/src/cpus/m68k/execute.rs b/src/cpus/m68k/execute.rs index 4d269cb..15babf7 100644 --- a/src/cpus/m68k/execute.rs +++ b/src/cpus/m68k/execute.rs @@ -347,7 +347,7 @@ impl M68k { return Ok(()); } - let existing = get_value_sized(self.state.d_reg[dest as usize], Size::Word); + let existing = get_value_sized(self.state.d_reg[dest as usize], Size::Long); let (remainder, quotient) = match sign { Sign::Signed => { let value = sign_extend_to_long(value, Size::Word) as u32; @@ -574,7 +574,20 @@ impl M68k { let count = self.get_target_value(system, count, size)? % 64; let mut pair = (self.get_target_value(system, target, size)?, false); for _ in 0..count { - pair = rotate_operation(pair.0, size, shift_dir); + pair = rotate_operation(pair.0, size, shift_dir, None); + } + self.set_logic_flags(pair.0, size); + if pair.1 { + self.set_flag(Flags::Carry, true); + } + self.set_target_value(system, target, pair.0, size)?; + }, + Instruction::ROXd(count, target, size, shift_dir) => { + let count = self.get_target_value(system, count, size)? % 64; + let mut pair = (self.get_target_value(system, target, size)?, false); + for _ in 0..count { + pair = rotate_operation(pair.0, size, shift_dir, Some(self.get_flag(Flags::Extend))); + self.set_flag(Flags::Extend, pair.1); } self.set_logic_flags(pair.0, size); if pair.1 { @@ -582,8 +595,6 @@ impl M68k { } self.set_target_value(system, target, pair.0, size)?; }, - //Instruction::ROXd(Target, Target, Size, ShiftDirection) => { - //}, Instruction::RTE => { self.require_supervisor()?; self.state.sr = self.pop_word(system)?; @@ -791,11 +802,11 @@ impl M68k { Target::IndirectARegInc(reg) => { let addr = self.get_a_reg_mut(reg); set_address_sized(system, *addr as Address, value, size)?; - *addr += size.in_bytes(); + *addr = (*addr).wrapping_add(size.in_bytes()); }, Target::IndirectARegDec(reg) => { let addr = self.get_a_reg_mut(reg); - *addr -= size.in_bytes(); + *addr = (*addr).wrapping_sub(size.in_bytes()); set_address_sized(system, *addr as Address, value, size)?; }, Target::IndirectRegOffset(base_reg, index_reg, displacement) => { @@ -1056,11 +1067,11 @@ fn shift_operation(value: u32, size: Size, dir: ShiftDirection, arithmetic: bool } } -fn rotate_operation(value: u32, size: Size, dir: ShiftDirection) -> (u32, bool) { +fn rotate_operation(value: u32, size: Size, dir: ShiftDirection, use_extend: Option) -> (u32, bool) { match dir { ShiftDirection::Left => { let bit = get_msb(value, size); - let mask = if bit { 0x01 } else { 0x00 }; + let mask = if use_extend.unwrap_or(bit) { 0x01 } else { 0x00 }; match size { Size::Byte => (mask | ((value as u8) << 1) as u32, bit), Size::Word => (mask | ((value as u16) << 1) as u32, bit), @@ -1069,7 +1080,7 @@ fn rotate_operation(value: u32, size: Size, dir: ShiftDirection) -> (u32, bool) }, ShiftDirection::Right => { let bit = if (value & 0x01) != 0 { true } else { false }; - let mask = if bit { get_msb_mask(0xffffffff, size) } else { 0x0 }; + let mask = if use_extend.unwrap_or(bit) { get_msb_mask(0xffffffff, size) } else { 0x0 }; ((value >> 1) | mask, bit) }, } diff --git a/src/cpus/m68k/tests.rs b/src/cpus/m68k/tests.rs index 049c6b0..9e14707 100644 --- a/src/cpus/m68k/tests.rs +++ b/src/cpus/m68k/tests.rs @@ -370,18 +370,19 @@ mod decode_tests { 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)); + assert_eq!(cpu.decoder.instruction, Instruction::MULW(Target::Immediate(0x276), 0, Sign::Signed)); } #[test] fn instruction_mulsl() { - let (mut cpu, system) = init_decode_test(M68kType::MC68010); + 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(); cpu.decode_next(&system).unwrap(); - assert_eq!(cpu.decoder.instruction, Instruction::MUL(Target::Immediate(0x276), Target::DirectDReg(0), Size::Word, Sign::Signed)); + assert_eq!(cpu.decoder.instruction, Instruction::MULL(Target::Immediate(0x97), None, 0, Sign::Signed)); } #[test] @@ -552,7 +553,7 @@ mod execute_tests { 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.decoder.instruction = Instruction::MULW(Target::Immediate(value), 0, Sign::Signed); cpu.execute_current(&system).unwrap(); assert_eq!(cpu.state.d_reg[0], 0x4ec00); @@ -564,7 +565,7 @@ mod execute_tests { 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.decoder.instruction = Instruction::DIVW(Target::Immediate(value), 0, Sign::Unsigned); cpu.execute_current(&system).unwrap(); assert_eq!(cpu.state.d_reg[0], 0x007101C3); @@ -618,6 +619,58 @@ mod execute_tests { assert_eq!(cpu.state.sr & 0x1F, 0x09); } + #[test] + fn instruction_roxl() { + let (mut cpu, system) = init_test(); + + cpu.state.d_reg[0] = 0x80; + cpu.state.sr = 0x2700; + cpu.decoder.instruction = Instruction::ROXd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Left); + + cpu.execute_current(&system).unwrap(); + assert_eq!(cpu.state.d_reg[0], 0x00000000); + assert_eq!(cpu.state.sr & 0x1F, 0x15); + } + + #[test] + fn instruction_roxr() { + let (mut cpu, system) = init_test(); + + cpu.state.d_reg[0] = 0x01; + cpu.state.sr = 0x2700; + cpu.decoder.instruction = Instruction::ROXd(Target::Immediate(1), Target::DirectDReg(0), Size::Byte, ShiftDirection::Right); + + cpu.execute_current(&system).unwrap(); + assert_eq!(cpu.state.d_reg[0], 0x00000000); + assert_eq!(cpu.state.sr & 0x1F, 0x15); + } + + #[test] + fn instruction_roxl_2() { + let (mut cpu, system) = init_test(); + + cpu.state.d_reg[0] = 0x80; + cpu.state.sr = 0x2700; + cpu.decoder.instruction = Instruction::ROXd(Target::Immediate(2), 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, 0x00); + } + + #[test] + fn instruction_roxr_2() { + let (mut cpu, system) = init_test(); + + cpu.state.d_reg[0] = 0x01; + cpu.state.sr = 0x2700; + cpu.decoder.instruction = Instruction::ROXd(Target::Immediate(2), 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, 0x08); + } + #[test] diff --git a/src/memory.rs b/src/memory.rs index dca0e32..ebadd03 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -76,12 +76,21 @@ pub struct Block { pub struct Bus { pub blocks: Vec, + pub mask: Address, } impl Bus { pub fn new() -> Bus { Bus { blocks: vec!(), + mask: !0, + } + } + + pub fn address_limit(&mut self, bits: u8) { + self.mask = 0; + for _ in 0..bits { + self.mask = (self.mask << 1) | 0x01; } } @@ -97,6 +106,7 @@ impl Bus { } pub fn get_device_at(&self, addr: Address, count: usize) -> Result<(TransmutableBox, Address), Error> { + let addr = addr & self.mask; for block in &self.blocks { if addr >= block.base && addr <= (block.base + block.length as Address) { let relative_addr = addr - block.base;