Skip to content

Commit

Permalink
Enhance IMUL 3 Operand
Browse files Browse the repository at this point in the history
- Enhanced 3 Operand `IMUL` to use width specific helper functions
- Properly Set OF/CF on Overflow
  • Loading branch information
enusbaum committed Jul 14, 2024
1 parent 777cad9 commit e0981ed
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 7 deletions.
3 changes: 3 additions & 0 deletions MBBSEmu.Tests/CPU/IMUL_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public void IMUL_16_R16_Test(short axValue, short valueToMultiply, short expecte
[InlineData(-127, -1, 127, false, false)]
[InlineData(127, -1, -127, false, false)]
[InlineData(short.MaxValue, -1, short.MinValue + 1, false, false)]
[InlineData(short.MaxValue, -2, 2, true, true)]
public void IMUL_16_R16_3OP_Test(short bxValue, short valueToMultiply, short expectedValue, bool carryFlag,
bool overflowFlag)
{
Expand All @@ -83,10 +84,12 @@ public void IMUL_16_R16_3OP_Test(short bxValue, short valueToMultiply, short exp

[Theory]
[InlineData(1, -1, -1, false, false)]
[InlineData(5, 10, 50, 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)]
[InlineData(short.MaxValue, -2, 2, true, true)]
public void IMUL_16_M16_3OP_Test(short memoryValue, short valueToMultiply, short expectedValue, bool carryFlag,
bool overflowFlag)
{
Expand Down
52 changes: 45 additions & 7 deletions MBBSEmu/CPU/CPUCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -360,9 +360,9 @@ public void Tick()
{
_showDebug = true; //Set to log Register values to console after execution
_logger.Debug($"{Registers.CS:X4}:{_currentInstruction.IP16:X4} {_currentInstruction}");
foreach(var l in Registers.ToString().Split("\n"))
foreach (var l in Registers.ToString().Split("\n"))
_logger.Debug(l);
for(var i = 0; i < 8; i++)
for (var i = 0; i < 8; i++)
_logger.Debug($"FPU[{i}]: {FpuStack[i]} {(i == Registers.Fpu.GetStackTop() ? " <--" : string.Empty)}");
}
else
Expand Down Expand Up @@ -954,6 +954,7 @@ private uint GetOperandValueUInt32(OpKind opKind, EnumOperandType operandType)
}
}

/// <summary>
/// <summary>
/// This is a helper method which takes the resulting value from GetOperandValueUInt64 and signs it depending on the underlying
/// OpKind and MemorySize
Expand Down Expand Up @@ -983,7 +984,6 @@ private long GetOperandValueInt64(OpKind opKind)
MemorySize.Int32 => (int)value,
MemorySize.UInt32 => (uint)value,
MemorySize.Int64 => (long)value,
MemorySize.UInt64 => (long)value,
_ => throw new Exception($"Invalid Operand Size: {_currentInstruction.MemorySize}")
},
_ => throw new Exception($"Unsupported OpKind: {opKind}")
Expand Down Expand Up @@ -1733,7 +1733,7 @@ private byte Op_Rcl_8()
}

//For 1 Bit Rotations, we evaluate Overflow
if(source == 1)
if (source == 1)
Registers.OverflowFlag = result.IsBitSet(7) ^ Registers.CarryFlag;

return result;
Expand Down Expand Up @@ -2749,16 +2749,54 @@ private void Op_Imul_3operand()
2 => GetOperandValueUInt16(_currentInstruction.Op2Kind, EnumOperandType.Source),
4 => GetOperandValueUInt32(_currentInstruction.Op2Kind, EnumOperandType.Source),
_ => throw new Exception("Unsupported Operation Size")

Check failure on line 2751 in MBBSEmu/CPU/CPUCore.cs

View workflow job for this annotation

GitHub Actions / build

Syntax error, ',' expected
};
uint result;

Check failure on line 2752 in MBBSEmu/CPU/CPUCore.cs

View workflow job for this annotation

GitHub Actions / build

Syntax error, '=>' expected

Check failure on line 2752 in MBBSEmu/CPU/CPUCore.cs

View workflow job for this annotation

GitHub Actions / build

Invalid expression term ';'

Check failure on line 2752 in MBBSEmu/CPU/CPUCore.cs

View workflow job for this annotation

GitHub Actions / build

Syntax error, ',' expected
unchecked

Check failure on line 2753 in MBBSEmu/CPU/CPUCore.cs

View workflow job for this annotation

GitHub Actions / build

Syntax error, '(' expected

Check failure on line 2753 in MBBSEmu/CPU/CPUCore.cs

View workflow job for this annotation

GitHub Actions / build

Invalid expression term '{'

Check failure on line 2753 in MBBSEmu/CPU/CPUCore.cs

View workflow job for this annotation

GitHub Actions / build

) expected

Check failure on line 2753 in MBBSEmu/CPU/CPUCore.cs

View workflow job for this annotation

GitHub Actions / build

Syntax error, '=>' expected

Check failure on line 2753 in MBBSEmu/CPU/CPUCore.cs

View workflow job for this annotation

GitHub Actions / build

Syntax error, ',' expected
{

Check failure on line 2754 in MBBSEmu/CPU/CPUCore.cs

View workflow job for this annotation

GitHub Actions / build

} expected
result = operand2 * operand3;
case 1:
Op_Imul_3operand_8();
return;
case 2:
Op_Imul_3operand_16();
return;
case 4:
Op_Imul_3operand_32();
return;
default:
throw new Exception("Unsupported Operation Size");
}
}

WriteToDestination(result);
var operand3 = GetOperandValueInt8(_currentInstruction.Op2Kind, EnumOperandType.Source);
}

[MethodImpl(OpcodeSubroutineCompilerOptimizations)]
private void Op_Imul_3operand_16()
{
var operand2 = GetOperandValueInt16(_currentInstruction.Op1Kind, EnumOperandType.Source);
var operand3 = GetOperandValueInt16(_currentInstruction.Op2Kind, EnumOperandType.Source);
var result = operand2 * operand3;

//Set CarryFlag and OverflowFlag if the result is too large to fit in the destination
Registers.OverflowFlag = Registers.CarryFlag = result is > short.MaxValue or < short.MinValue;

WriteToDestination((ushort)result);
}

[MethodImpl(OpcodeSubroutineCompilerOptimizations)]
private void Op_Imul_3operand_32()
{
var operand2 = GetOperandValueInt32(_currentInstruction.Op1Kind, EnumOperandType.Source);
var operand3 = GetOperandValueInt32(_currentInstruction.Op2Kind, EnumOperandType.Source);
long result = operand2 * operand3;

//Set CarryFlag and OverflowFlag if the result is too large to fit in the destination
Registers.OverflowFlag = Registers.CarryFlag = result is > int.MaxValue or < int.MinValue;

WriteToDestination((uint)result);
}


[MethodImpl(OpcodeCompilerOptimizations)]
private void Op_Mul()
{
Expand Down Expand Up @@ -4041,7 +4079,7 @@ private byte Op_Ror_8()
Registers.CarryFlag = result.IsNegative();

//If Bits 7 & 6 are not the same, then we overflowed for 1 bit rotations
if(source == 1)
if (source == 1)
Registers.OverflowFlag = result.IsBitSet(7) != result.IsBitSet(6);

return result;
Expand Down

0 comments on commit e0981ed

Please sign in to comment.