diff --git a/MBBSEmu.Tests/CPU/FLDCW_Tests.cs b/MBBSEmu.Tests/CPU/FLDCW_Tests.cs
index 4fa7e793..1104b415 100644
--- a/MBBSEmu.Tests/CPU/FLDCW_Tests.cs
+++ b/MBBSEmu.Tests/CPU/FLDCW_Tests.cs
@@ -7,22 +7,41 @@ namespace MBBSEmu.Tests.CPU
{
public class FLDCW_Tests : CpuTestBase
{
- [Fact]
- public void FLDCW_Test()
+ ///
+ /// Loads the FPU Control Word from Memory and sets the FPU Control Word
+ ///
+ /// We'll verify this by not only setting the Control Word, but also verify
+ /// the Round Mode is set correctly
+ ///
+ /// Rounding Flag Conversion:
+ /// Rounding Mode = (ControlWord >> 10) & 0x3;
+ /// 0 => MidpointRounding.ToEven
+ /// 1 => MidpointRounding.ToNegativeInfinity
+ /// 2 => MidpointRounding.ToPositiveInfinity
+ /// 3 => MidpointRounding.ToZero
+ ///
+ [Theory]
+ [InlineData(0x0000, MidpointRounding.ToEven)]
+ [InlineData(0x0400, MidpointRounding.ToNegativeInfinity)]
+ [InlineData(0x0800, MidpointRounding.ToPositiveInfinity)]
+ [InlineData(0x0C00, MidpointRounding.ToZero)]
+ public void FLDCW_Test(ushort controlWord, MidpointRounding roundingMode)
{
Reset();
mbbsEmuCpuRegisters.Fpu.ControlWord = 0;
CreateDataSegment(new ReadOnlySpan(), 2);
- mbbsEmuMemoryCore.SetWord(2,0, 0xFFFF);
+ mbbsEmuMemoryCore.SetArray(2, 0, [0, 0, 0]); //Set some junk data ahead of the actual address
+ mbbsEmuMemoryCore.SetWord(2,3, controlWord);
mbbsEmuCpuRegisters.DS = 2;
var instructions = new Assembler(16);
- instructions.fldcw(__word_ptr[0]);
+ instructions.fldcw(__word_ptr[3]);
CreateCodeSegment(instructions);
mbbsEmuCpuCore.Tick();
- Assert.Equal(0xFFFF, mbbsEmuCpuRegisters.Fpu.ControlWord);
+ Assert.Equal(controlWord, mbbsEmuCpuRegisters.Fpu.ControlWord);
+ Assert.Equal(roundingMode, mbbsEmuCpuRegisters.Fpu.GetRoundingControl());
}
}
}
diff --git a/MBBSEmu.Tests/CPU/FRNDINT_Tests.cs b/MBBSEmu.Tests/CPU/FRNDINT_Tests.cs
index 879e0cb7..b56782d4 100644
--- a/MBBSEmu.Tests/CPU/FRNDINT_Tests.cs
+++ b/MBBSEmu.Tests/CPU/FRNDINT_Tests.cs
@@ -5,20 +5,40 @@ namespace MBBSEmu.Tests.CPU
{
public class FRNDINT_Tests : CpuTestBase
{
+ ///
+ /// Tests the FRNDINT Instruction which rounds the value in ST(0) to the nearest integer
+ ///
+ /// We'll test this by setting the FPU Control Mode to Round to different modes and verify.
+ ///
+ /// Rounding Flag Conversion:
+ /// Rounding Mode = (ControlWord >> 10) & 0x3;
+ /// 0 => MidpointRounding.ToEven
+ /// 1 => MidpointRounding.ToNegativeInfinity
+ /// 2 => MidpointRounding.ToPositiveInfinity
+ /// 3 => MidpointRounding.ToZero
+ ///
+ ///
+ ///
[Theory]
- [InlineData(2.1d, 2d)]
- [InlineData(0.1d, 0d)]
- [InlineData(1.9d, 2d)]
- [InlineData(-1.9d, -2d)]
- [InlineData(0.5d, 0d)]
- [InlineData(0.49999999d, 0d)]
- public void FRNDINT_Test(double ST0Value, double expectedValue)
+ //Round to Even
+ [InlineData(1.5, 2.0, 0x0000)]
+ [InlineData(-1.5, -2.0, 0x0000)]
+ //Round to Negative Infinity
+ [InlineData(1.5, 1.0, 0x0400)]
+ [InlineData(-1.5, -2.0, 0x0400)]
+ //Round to Positive Infinity
+ [InlineData(1.5, 2.0, 0x0800)]
+ [InlineData(-1.5, -1.0, 0x0800)]
+ //Round to Zero
+ [InlineData(1.5, 1.0, 0x0C00)]
+ [InlineData(-1.5, -1.0, 0x0C00)]
+ public void FRNDINT_Test(double ST0Value, double expectedValue, ushort controlWord)
{
Reset();
mbbsEmuCpuCore.FpuStack[mbbsEmuCpuRegisters.Fpu.GetStackTop()] = ST0Value;
//Set FPU Control Word to set rounding to even
- mbbsEmuCpuRegisters.Fpu.ControlWord = 0x0000000C;
+ mbbsEmuCpuRegisters.Fpu.ControlWord = controlWord;
var instructions = new Assembler(16);
instructions.frndint();
diff --git a/MBBSEmu/CPU/CpuRegisters.cs b/MBBSEmu/CPU/CpuRegisters.cs
index 6c25d450..6bb85f73 100644
--- a/MBBSEmu/CPU/CpuRegisters.cs
+++ b/MBBSEmu/CPU/CpuRegisters.cs
@@ -89,6 +89,7 @@ public void SetPointer(FarPtr ptr)
public void PopStackTop() => Registers.Fpu.PopStackTop();
public void PushStackTop() => Registers.Fpu.PushStackTop();
public void ClearExceptions() => Registers.Fpu.ClearExceptions();
+ public MidpointRounding GetRoundingControl() => Registers.Fpu.GetRoundingControl();
///
/// Overridden ToString() to display the current state of the CPU Registers
diff --git a/MBBSEmu/CPU/ICpuRegisters.cs b/MBBSEmu/CPU/ICpuRegisters.cs
index edb6aee4..f244b782 100644
--- a/MBBSEmu/CPU/ICpuRegisters.cs
+++ b/MBBSEmu/CPU/ICpuRegisters.cs
@@ -10,20 +10,16 @@ namespace MBBSEmu.CPU
public interface IFpuRegisters
{
ushort StatusWord { get; set; }
-
ushort ControlWord { get; set; }
-
void SetFlag(EnumFpuStatusFlags statusFlag);
void ClearFlag(EnumFpuStatusFlags statusFlag);
-
byte GetStackTop();
-
void SetStackTop(byte value);
-
int GetStackPointer(Register register);
void PopStackTop();
void PushStackTop();
void ClearExceptions();
+ MidpointRounding GetRoundingControl();
}
///