From b165e18fac21175d80fc487c66c3a7a5f13b41d8 Mon Sep 17 00:00:00 2001 From: transistor Date: Wed, 1 Dec 2021 15:40:41 -0800 Subject: [PATCH] Added ADDX/SUBX instructions to m68k --- src/cpus/m68k/execute.rs | 26 +++++++++++++++++---- src/cpus/m68k/tests.rs | 49 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/src/cpus/m68k/execute.rs b/src/cpus/m68k/execute.rs index 93aca9d..0d0def9 100644 --- a/src/cpus/m68k/execute.rs +++ b/src/cpus/m68k/execute.rs @@ -184,8 +184,17 @@ impl M68k { let (result, _) = overflowing_add_sized(existing, value, Size::Long); *self.get_a_reg_mut(dest) = result; }, - //Instruction::ADDX(Target) => { - //}, + Instruction::ADDX(src, dest, size) => { + let value = self.get_target_value(src, size)?; + let existing = self.get_target_value(dest, size)?; + let extend = self.get_flag(Flags::Extend) as u32; + let (result1, carry1) = overflowing_add_sized(existing, value, size); + let (result2, carry2) = overflowing_add_sized(result1, extend, size); + let overflow = get_add_overflow(existing, value, result2, size); + self.set_compare_flags(result2, size, carry1 || carry2, overflow); + self.set_flag(Flags::Extend, carry1 || carry2); + self.set_target_value(dest, result2, size)?; + }, Instruction::AND(src, dest, size) => { let value = self.get_target_value(src, size)?; let existing = self.get_target_value(dest, size)?; @@ -689,8 +698,17 @@ impl M68k { let (result, _) = overflowing_sub_sized(existing, value, Size::Long); *self.get_a_reg_mut(dest) = result; }, - //Instruction::SUBX(Target) => { - //}, + Instruction::SUBX(src, dest, size) => { + let value = self.get_target_value(src, size)?; + let existing = self.get_target_value(dest, size)?; + let extend = self.get_flag(Flags::Extend) as u32; + let (result1, carry1) = overflowing_sub_sized(existing, value, size); + let (result2, carry2) = overflowing_sub_sized(result1, extend, size); + let overflow = get_sub_overflow(existing, value, result2, size); + self.set_compare_flags(result2, size, carry1 || carry2, overflow); + self.set_flag(Flags::Extend, carry1 || carry2); + self.set_target_value(dest, result2, size)?; + }, Instruction::SWAP(reg) => { let value = self.state.d_reg[reg as usize]; self.state.d_reg[reg as usize] = ((value & 0x0000FFFF) << 16) | ((value & 0xFFFF0000) >> 16); diff --git a/src/cpus/m68k/tests.rs b/src/cpus/m68k/tests.rs index 5dafb25..8420c17 100644 --- a/src/cpus/m68k/tests.rs +++ b/src/cpus/m68k/tests.rs @@ -518,6 +518,30 @@ mod execute_tests { init: TestState { pc: 0x00000000, ssp: 0x00000000, usp: 0x00000000, d0: 0x0000F800, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0x27FF, mem: 0x00000000 }, fini: TestState { pc: 0x00000002, ssp: 0x00000000, usp: 0x00000000, d0: 0x0000F800, d1: 0x00000000, a0: 0xFFFFF800, a1: 0x00000000, sr: 0x27FF, mem: 0x00000000 }, }, + TestCase { + name: "addx", + ins: Instruction::ADDX(Target::DirectDReg(1), Target::DirectDReg(0), Size::Byte), + data: &[ 0xD101 ], + cputype: M68kType::MC68010, + init: TestState { pc: 0x00000000, ssp: 0x00000000, usp: 0x00000000, d0: 0x0000007F, d1: 0x0000007F, a0: 0x00000000, a1: 0x00000000, sr: 0x2700, mem: 0x00000000 }, + fini: TestState { pc: 0x00000002, ssp: 0x00000000, usp: 0x00000000, d0: 0x000000FE, d1: 0x0000007F, a0: 0x00000000, a1: 0x00000000, sr: 0x270A, mem: 0x00000000 }, + }, + TestCase { + name: "addx with extend", + ins: Instruction::ADDX(Target::DirectDReg(1), Target::DirectDReg(0), Size::Byte), + data: &[ 0xD101 ], + cputype: M68kType::MC68010, + init: TestState { pc: 0x00000000, ssp: 0x00000000, usp: 0x00000000, d0: 0x0000007F, d1: 0x0000007F, a0: 0x00000000, a1: 0x00000000, sr: 0x2710, mem: 0x00000000 }, + fini: TestState { pc: 0x00000002, ssp: 0x00000000, usp: 0x00000000, d0: 0x000000FF, d1: 0x0000007F, a0: 0x00000000, a1: 0x00000000, sr: 0x270A, mem: 0x00000000 }, + }, + TestCase { + name: "addx with extend and carry", + ins: Instruction::ADDX(Target::DirectDReg(1), Target::DirectDReg(0), Size::Byte), + data: &[ 0xD101 ], + cputype: M68kType::MC68010, + init: TestState { pc: 0x00000000, ssp: 0x00000000, usp: 0x00000000, d0: 0x00000080, d1: 0x0000007F, a0: 0x00000000, a1: 0x00000000, sr: 0x2710, mem: 0x00000000 }, + fini: TestState { pc: 0x00000002, ssp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x0000007F, a0: 0x00000000, a1: 0x00000000, sr: 0x2715, mem: 0x00000000 }, + }, TestCase { name: "andi with sr", ins: Instruction::ANDtoSR(0xF8FF), @@ -933,6 +957,31 @@ mod execute_tests { init: TestState { pc: 0x00000000, ssp: 0x00000000, usp: 0x00000000, d0: 0x00000001, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0x2700, mem: 0x00000000 }, fini: TestState { pc: 0x00000002, ssp: 0x00000000, usp: 0x00000000, d0: 0x00000080, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0x2708, mem: 0x00000000 }, }, + + TestCase { + name: "subx", + ins: Instruction::SUBX(Target::DirectDReg(1), Target::DirectDReg(0), Size::Byte), + data: &[ 0x9101 ], + cputype: M68kType::MC68010, + init: TestState { pc: 0x00000000, ssp: 0x00000000, usp: 0x00000000, d0: 0x000000FF, d1: 0x0000007F, a0: 0x00000000, a1: 0x00000000, sr: 0x2700, mem: 0x00000000 }, + fini: TestState { pc: 0x00000002, ssp: 0x00000000, usp: 0x00000000, d0: 0x00000080, d1: 0x0000007F, a0: 0x00000000, a1: 0x00000000, sr: 0x2708, mem: 0x00000000 }, + }, + TestCase { + name: "subx with extend", + ins: Instruction::SUBX(Target::DirectDReg(1), Target::DirectDReg(0), Size::Byte), + data: &[ 0x9101 ], + cputype: M68kType::MC68010, + init: TestState { pc: 0x00000000, ssp: 0x00000000, usp: 0x00000000, d0: 0x000000FF, d1: 0x0000007F, a0: 0x00000000, a1: 0x00000000, sr: 0x2710, mem: 0x00000000 }, + fini: TestState { pc: 0x00000002, ssp: 0x00000000, usp: 0x00000000, d0: 0x0000007F, d1: 0x0000007F, a0: 0x00000000, a1: 0x00000000, sr: 0x2702, mem: 0x00000000 }, + }, + TestCase { + name: "subx with extend and carry", + ins: Instruction::SUBX(Target::DirectDReg(1), Target::DirectDReg(0), Size::Byte), + data: &[ 0x9101 ], + cputype: M68kType::MC68010, + init: TestState { pc: 0x00000000, ssp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x0000007F, a0: 0x00000000, a1: 0x00000000, sr: 0x2710, mem: 0x00000000 }, + fini: TestState { pc: 0x00000002, ssp: 0x00000000, usp: 0x00000000, d0: 0x00000080, d1: 0x0000007F, a0: 0x00000000, a1: 0x00000000, sr: 0x2719, mem: 0x00000000 }, + }, ];