From bf1af5db2d2f5ddc65597d53f492410389418d2d Mon Sep 17 00:00:00 2001 From: "Eric P. Nusbaum" Date: Sun, 14 Jul 2024 10:24:09 -0400 Subject: [PATCH] 3OP IMUL Fixes - Fixes 3 Operand IMUL Operations - Unit Tests for IMUL --- MBBSEmu.Tests/CPU/IMUL_Tests.cs | 113 ++++++++++++++++++++++++++++++++ MBBSEmu.Tests/CPU/MUL_Tests.cs | 2 - MBBSEmu/CPU/CPUCore.cs | 6 +- 3 files changed, 116 insertions(+), 5 deletions(-) create mode 100644 MBBSEmu.Tests/CPU/IMUL_Tests.cs diff --git a/MBBSEmu.Tests/CPU/IMUL_Tests.cs b/MBBSEmu.Tests/CPU/IMUL_Tests.cs new file mode 100644 index 00000000..53634c31 --- /dev/null +++ b/MBBSEmu.Tests/CPU/IMUL_Tests.cs @@ -0,0 +1,113 @@ +using Iced.Intel; +using Xunit; +using static Iced.Intel.AssemblerRegisters; + +namespace MBBSEmu.Tests.CPU +{ + public class IMUL_Tests : CpuTestBase + { + [Theory] + [InlineData(1, -1, -1, false, false)] + [InlineData(-1, -1, 1, false, false)] + [InlineData(-127, -1, 127, false, false)] + [InlineData(127, -1, -127, false, false)] + public void IMUL_8_R8_Test(sbyte alValue, sbyte valueToMultiply, short expectedValue, bool carryFlag, + bool overflowFlag) + { + Reset(); + mbbsEmuCpuRegisters.AL = (byte)alValue; + mbbsEmuCpuRegisters.BL = (byte)valueToMultiply; + + var instructions = new Assembler(16); + instructions.imul(bl); + CreateCodeSegment(instructions); + + mbbsEmuCpuCore.Tick(); + + //Verify Results + Assert.Equal(expectedValue, (sbyte)mbbsEmuCpuRegisters.AL); + Assert.Equal(carryFlag, mbbsEmuCpuRegisters.CarryFlag); + Assert.Equal(overflowFlag, mbbsEmuCpuRegisters.OverflowFlag); + } + + [Theory] + [InlineData(1, -1, -1, false, false)] + [InlineData(-1, -1, 1, false, false)] + [InlineData(-127, -1, 127, false, false)] + [InlineData(127, -1, -127, false, false)] + [InlineData(short.MaxValue, -1, short.MinValue + 1, false, false)] + public void IMUL_16_R16_Test(short axValue, short valueToMultiply, short expectedValue, bool carryFlag, + bool overflowFlag) + { + Reset(); + mbbsEmuCpuRegisters.AX = (ushort)axValue; + mbbsEmuCpuRegisters.BX = (ushort)valueToMultiply; + + var instructions = new Assembler(16); + instructions.imul(bx); + CreateCodeSegment(instructions); + + mbbsEmuCpuCore.Tick(); + + //Verify Results + Assert.Equal(expectedValue, (short)mbbsEmuCpuRegisters.AX); + Assert.Equal(carryFlag, mbbsEmuCpuRegisters.CarryFlag); + Assert.Equal(overflowFlag, mbbsEmuCpuRegisters.OverflowFlag); + } + + + [Theory] + [InlineData(1, -1, -1, false, false)] + [InlineData(-1, -1, 1, false, false)] + [InlineData(-127, -1, 127, false, false)] + [InlineData(127, -1, -127, false, false)] + [InlineData(short.MaxValue, -1, short.MinValue + 1, false, false)] + public void IMUL_16_R16_3OP_Test(short bxValue, short valueToMultiply, short expectedValue, bool carryFlag, + bool overflowFlag) + { + Reset(); + mbbsEmuCpuRegisters.BX = (ushort)bxValue; + + var instructions = new Assembler(16); + //AX = BX * ValueToMultiply + instructions.imul(ax, bx, valueToMultiply); + CreateCodeSegment(instructions); + + mbbsEmuCpuCore.Tick(); + + //Verify Results + Assert.Equal(expectedValue, (short)mbbsEmuCpuRegisters.AX); + Assert.Equal(carryFlag, mbbsEmuCpuRegisters.CarryFlag); + Assert.Equal(overflowFlag, mbbsEmuCpuRegisters.OverflowFlag); + } + + [Theory] + [InlineData(1, -1, -1, false, false)] + [InlineData(-1, -1, 1, false, false)] + [InlineData(-127, -1, 127, false, false)] + [InlineData(127, -1, -127, false, false)] + [InlineData(short.MaxValue, -1, short.MinValue + 1, false, false)] + public void IMUL_16_M16_3OP_Test(short memoryValue, short valueToMultiply, short expectedValue, bool carryFlag, + bool overflowFlag) + { + Reset(); + + //Setup Memory + CreateDataSegment(new byte[ushort.MaxValue]); + mbbsEmuMemoryCore.SetWord(2,0, (ushort)memoryValue); + mbbsEmuCpuRegisters.DS = 2; + + var instructions = new Assembler(16); + //AX == DS:[0] * ValueToMultiply + instructions.imul(ax, __word_ptr[0], valueToMultiply); + CreateCodeSegment(instructions); + + mbbsEmuCpuCore.Tick(); + + //Verify Results + Assert.Equal(expectedValue, (short)mbbsEmuCpuRegisters.AX); + Assert.Equal(carryFlag, mbbsEmuCpuRegisters.CarryFlag); + Assert.Equal(overflowFlag, mbbsEmuCpuRegisters.OverflowFlag); + } + } +} diff --git a/MBBSEmu.Tests/CPU/MUL_Tests.cs b/MBBSEmu.Tests/CPU/MUL_Tests.cs index 0df1be4a..4b99c96a 100644 --- a/MBBSEmu.Tests/CPU/MUL_Tests.cs +++ b/MBBSEmu.Tests/CPU/MUL_Tests.cs @@ -1,6 +1,4 @@ using Iced.Intel; -using MBBSEmu.CPU; -using MBBSEmu.Extensions; using Xunit; using static Iced.Intel.AssemblerRegisters; diff --git a/MBBSEmu/CPU/CPUCore.cs b/MBBSEmu/CPU/CPUCore.cs index 29ff9c12..820fc732 100644 --- a/MBBSEmu/CPU/CPUCore.cs +++ b/MBBSEmu/CPU/CPUCore.cs @@ -2737,9 +2737,9 @@ private void Op_Imul_3operand() { var operand2 = _currentOperationSize switch { - 1 => GetOperandValueUInt8(_currentInstruction.Op1Kind, EnumOperandType.Destination), - 2 => GetOperandValueUInt16(_currentInstruction.Op1Kind, EnumOperandType.Destination), - 4 => GetOperandValueUInt32(_currentInstruction.Op1Kind, EnumOperandType.Destination), + 1 => GetOperandValueUInt8(_currentInstruction.Op1Kind, EnumOperandType.Source), + 2 => GetOperandValueUInt16(_currentInstruction.Op1Kind, EnumOperandType.Source), + 4 => GetOperandValueUInt32(_currentInstruction.Op1Kind, EnumOperandType.Source), _ => throw new Exception("Unsupported Operation Size") };