Author: aandrejevic
Date: Fri Oct 10 23:07:14 2014
New Revision: 64656
URL:
http://svn.reactos.org/svn/reactos?rev=64656&view=rev
Log:
[FAST486]
Update the copyright year.
Implement the first batch of FPU instructions. These are still experimental.
Modified:
trunk/reactos/include/reactos/libs/fast486/fast486.h
trunk/reactos/lib/fast486/common.c
trunk/reactos/lib/fast486/common.h
trunk/reactos/lib/fast486/common.inl
trunk/reactos/lib/fast486/extraops.c
trunk/reactos/lib/fast486/extraops.h
trunk/reactos/lib/fast486/fast486.c
trunk/reactos/lib/fast486/fpu.c
trunk/reactos/lib/fast486/fpu.h
trunk/reactos/lib/fast486/opcodes.c
trunk/reactos/lib/fast486/opcodes.h
trunk/reactos/lib/fast486/opgroups.c
trunk/reactos/lib/fast486/opgroups.h
Modified: trunk/reactos/include/reactos/libs/fast486/fast486.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/libs/fast4…
==============================================================================
--- trunk/reactos/include/reactos/libs/fast486/fast486.h [iso-8859-1] (original)
+++ trunk/reactos/include/reactos/libs/fast486/fast486.h [iso-8859-1] Fri Oct 10 23:07:14
2014
@@ -2,7 +2,7 @@
* Fast486 386/486 CPU Emulation Library
* fast486.h
*
- * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ * Copyright (C) 2014 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -90,6 +90,8 @@
#define FAST486_PREFIX_LOCK (1 << 3)
#define FAST486_PREFIX_REPNZ (1 << 4)
#define FAST486_PREFIX_REP (1 << 5)
+
+#define FAST486_FPU_DEFAULT_CONTROL 0x037F
struct _FAST486_STATE;
typedef struct _FAST486_STATE FAST486_STATE, *PFAST486_STATE;
@@ -420,6 +422,7 @@
{
ULONGLONG Mantissa;
USHORT Exponent;
+ UCHAR Sign;
} FAST486_FPU_DATA_REG, *PFAST486_FPU_DATA_REG;
typedef union _FAST486_FPU_STATUS_REG
@@ -490,10 +493,12 @@
FAST486_INT_STATUS IntStatus;
UCHAR PendingIntNum;
PULONG Tlb;
+#ifndef FAST486_NO_FPU
FAST486_FPU_DATA_REG FpuRegisters[FAST486_NUM_FPU_REGS];
FAST486_FPU_STATUS_REG FpuStatus;
FAST486_FPU_CONTROL_REG FpuControl;
USHORT FpuTag;
+#endif
};
/* FUNCTIONS ******************************************************************/
Modified: trunk/reactos/lib/fast486/common.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/common.c?rev=6…
==============================================================================
--- trunk/reactos/lib/fast486/common.c [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/common.c [iso-8859-1] Fri Oct 10 23:07:14 2014
@@ -2,7 +2,7 @@
* Fast486 386/486 CPU Emulation Library
* common.c
*
- * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ * Copyright (C) 2014 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
Modified: trunk/reactos/lib/fast486/common.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/common.h?rev=6…
==============================================================================
--- trunk/reactos/lib/fast486/common.h [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/common.h [iso-8859-1] Fri Oct 10 23:07:14 2014
@@ -2,7 +2,7 @@
* Fast486 386/486 CPU Emulation Library
* common.h
*
- * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ * Copyright (C) 2014 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
Modified: trunk/reactos/lib/fast486/common.inl
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/common.inl?rev…
==============================================================================
--- trunk/reactos/lib/fast486/common.inl [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/common.inl [iso-8859-1] Fri Oct 10 23:07:14 2014
@@ -2,7 +2,7 @@
* Fast486 386/486 CPU Emulation Library
* common.inl
*
- * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ * Copyright (C) 2014 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -20,6 +20,7 @@
*/
#include "common.h"
+#include "fpu.h"
/* PUBLIC FUNCTIONS ***********************************************************/
@@ -1330,4 +1331,76 @@
return TRUE;
}
+#ifndef FAST486_NO_FPU
+
+FORCEINLINE
+VOID
+Fast486FpuNormalize(PFAST486_STATE State, PFAST486_FPU_DATA_REG Data)
+{
+ UINT LeadingZeros = 0;
+
+ if (FPU_IS_NORMALIZED(Data)) return;
+ if (FPU_IS_ZERO(Data))
+ {
+ Data->Exponent = 0;
+ return;
+ }
+
+ /* Count the leading zeros */
+ while (!(Data->Mantissa & (1 << (63 - LeadingZeros)))) LeadingZeros++;
+
+ if (LeadingZeros < Data->Exponent)
+ {
+ Data->Mantissa <<= LeadingZeros;
+ Data->Exponent -= LeadingZeros;
+ }
+ else
+ {
+ /* Make it denormalized */
+ Data->Mantissa <<= Data->Exponent - 1;
+ Data->Exponent = 1;
+
+ /* Underflow */
+ State->FpuStatus.Ue = TRUE;
+ }
+}
+
+FORCEINLINE
+USHORT
+Fast486GetValueTag(PFAST486_FPU_DATA_REG Data)
+{
+ if (FPU_IS_ZERO(Data)) return FPU_TAG_ZERO;
+ else if (FPU_IS_NAN(Data)) return FPU_TAG_SPECIAL;
+ else return FPU_TAG_VALID;
+}
+
+FORCEINLINE
+VOID
+Fast486FpuPush(PFAST486_STATE State,
+ PFAST486_FPU_DATA_REG Data)
+{
+ State->FpuStatus.Top--;
+
+ if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
+ {
+ FPU_ST(0) = *Data;
+ FPU_SET_TAG(0, Fast486GetValueTag(Data));
+ }
+ else State->FpuStatus.Ie = TRUE;
+}
+
+FORCEINLINE
+VOID
+Fast486FpuPop(PFAST486_STATE State)
+{
+ if (FPU_GET_TAG(0) != FPU_TAG_EMPTY)
+ {
+ FPU_SET_TAG(0, FPU_TAG_EMPTY);
+ State->FpuStatus.Top++;
+ }
+ else State->FpuStatus.Ie = TRUE;
+}
+
+#endif
+
/* EOF */
Modified: trunk/reactos/lib/fast486/extraops.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/extraops.c?rev…
==============================================================================
--- trunk/reactos/lib/fast486/extraops.c [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/extraops.c [iso-8859-1] Fri Oct 10 23:07:14 2014
@@ -2,7 +2,7 @@
* Fast486 386/486 CPU Emulation Library
* extraops.c
*
- * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ * Copyright (C) 2014 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
Modified: trunk/reactos/lib/fast486/extraops.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/extraops.h?rev…
==============================================================================
--- trunk/reactos/lib/fast486/extraops.h [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/extraops.h [iso-8859-1] Fri Oct 10 23:07:14 2014
@@ -2,7 +2,7 @@
* Fast486 386/486 CPU Emulation Library
* extraops.h
*
- * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ * Copyright (C) 2014 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
Modified: trunk/reactos/lib/fast486/fast486.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/fast486.c?rev=…
==============================================================================
--- trunk/reactos/lib/fast486/fast486.c [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/fast486.c [iso-8859-1] Fri Oct 10 23:07:14 2014
@@ -2,7 +2,7 @@
* Fast486 386/486 CPU Emulation Library
* fast486.c
*
- * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ * Copyright (C) 2014 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -282,6 +282,11 @@
#ifndef FAST486_NO_FPU
/* Initialize CR0 */
State->ControlRegisters[FAST486_REG_CR0] |= FAST486_CR0_ET;
+
+ /* Initialize the FPU control and tag registers */
+ State->FpuControl.Value = FAST486_FPU_DEFAULT_CONTROL;
+ State->FpuStatus.Value = 0;
+ State->FpuTag = 0xFFFF;
#endif
/* Restore the callbacks and TLB */
Modified: trunk/reactos/lib/fast486/fpu.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/fpu.c?rev=6465…
==============================================================================
--- trunk/reactos/lib/fast486/fpu.c [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/fpu.c [iso-8859-1] Fri Oct 10 23:07:14 2014
@@ -2,7 +2,7 @@
* Fast486 386/486 CPU Emulation Library
* fpu.c
*
- * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ * Copyright (C) 2014 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -28,12 +28,416 @@
#include <fast486.h>
#include "common.h"
-#include "opcodes.h"
#include "fpu.h"
+/* PRIVATE FUNCTIONS **********************************************************/
+
+static ULONGLONG UnsignedMult128(ULONGLONG Multiplicand,
+ ULONGLONG Multiplier,
+ ULONGLONG *HighProduct)
+{
+ ULONG MultiplicandLow, MultiplicandHigh, MultiplierLow, MultiplierHigh;
+ ULONG IntermediateLow, IntermediateHigh;
+ ULONGLONG LowProduct, Intermediate, Intermediate1, Intermediate2;
+
+ MultiplicandLow = (ULONG)(Multiplicand & 0xFFFFFFFFULL);
+ MultiplicandHigh = (ULONG)(Multiplicand >> 32);
+ MultiplierLow = (ULONG)(Multiplier & 0xFFFFFFFFULL);
+ MultiplierHigh = (ULONG)(Multiplier >> 32);
+
+ LowProduct = (ULONGLONG)MultiplicandLow * (ULONGLONG)MultiplierLow;
+ Intermediate1 = (ULONGLONG)MultiplicandLow * (ULONGLONG)MultiplierHigh;
+ Intermediate2 = (ULONGLONG)MultiplicandHigh * (ULONGLONG)MultiplierLow;
+ *HighProduct = (ULONGLONG)MultiplicandHigh * (ULONGLONG)MultiplierHigh;
+
+ Intermediate = Intermediate1 + Intermediate2;
+ if (Intermediate < Intermediate1) *HighProduct += 1ULL << 32;
+
+ IntermediateLow = (ULONG)(Intermediate & 0xFFFFFFFFULL);
+ IntermediateHigh = (ULONG)(Intermediate >> 32);
+
+ LowProduct += (ULONGLONG)IntermediateLow << 32;
+ if ((ULONG)(LowProduct >> 32) < IntermediateLow) (*HighProduct)++;
+
+ *HighProduct += IntermediateHigh;
+ return LowProduct;
+}
+
+static VOID Fast486FpuGetSingleReal(PFAST486_STATE State,
+ ULONG Value,
+ PFAST486_FPU_DATA_REG Result)
+{
+ /* Extract the sign, exponent and mantissa */
+ Result->Sign = (UCHAR)(Value >> 31);
+ Result->Exponent = (USHORT)((Value >> 23) & 0xFF);
+ Result->Mantissa = (((ULONGLONG)Value & 0x7FFFFFULL) | 0x800000ULL) <<
40;
+
+ /* If this is a zero, we're done */
+ if (Value == 0) return;
+
+ if (Result->Exponent == 0xFF) Result->Exponent = FPU_MAX_EXPONENT + 1;
+ else
+ {
+ /* Adjust the exponent bias */
+ Result->Exponent += (FPU_REAL10_BIAS - FPU_REAL4_BIAS);
+ }
+}
+
+static VOID Fast486FpuGetDoubleReal(PFAST486_STATE State,
+ ULONGLONG Value,
+ PFAST486_FPU_DATA_REG Result)
+{
+ /* Extract the sign, exponent and mantissa */
+ Result->Sign = (UCHAR)(Value >> 63);
+ Result->Exponent = (USHORT)((Value >> 52) & 0x7FF);
+ Result->Mantissa = (((ULONGLONG)Value & 0xFFFFFFFFFFFFFULL) |
0x10000000000000ULL) << 11;
+
+ /* If this is a zero, we're done */
+ if (Value == 0) return;
+
+ if (Result->Exponent == 0x3FF) Result->Exponent = FPU_MAX_EXPONENT + 1;
+ else
+ {
+ /* Adjust the exponent bias */
+ Result->Exponent += (FPU_REAL10_BIAS - FPU_REAL8_BIAS);
+ }
+}
+
+static VOID Fast486FpuAdd(PFAST486_STATE State,
+ PFAST486_FPU_DATA_REG FirstOperand,
+ PFAST486_FPU_DATA_REG SecondOperand,
+ PFAST486_FPU_DATA_REG Result)
+{
+ FAST486_FPU_DATA_REG FirstAdjusted = *FirstOperand;
+ FAST486_FPU_DATA_REG SecondAdjusted = *SecondOperand;
+ FAST486_FPU_DATA_REG TempResult;
+
+ if (!FPU_IS_NORMALIZED(FirstOperand) || !FPU_IS_NORMALIZED(SecondOperand))
+ {
+ /* Denormalized */
+ State->FpuStatus.De = TRUE;
+ }
+
+ /* Find the largest exponent */
+ TempResult.Exponent = max(FirstOperand->Exponent, SecondOperand->Exponent);
+
+ /* Adjust the first operand to it */
+ if (FirstAdjusted.Exponent < TempResult.Exponent)
+ {
+ FirstAdjusted.Mantissa >>= (TempResult.Exponent - FirstAdjusted.Exponent);
+ FirstAdjusted.Exponent = TempResult.Exponent;
+ }
+
+ /* ... and the second one too */
+ if (SecondAdjusted.Exponent < TempResult.Exponent)
+ {
+ SecondAdjusted.Mantissa >>= (TempResult.Exponent -
SecondAdjusted.Exponent);
+ SecondAdjusted.Exponent = TempResult.Exponent;
+ }
+
+ if (FirstAdjusted.Sign == SecondAdjusted.Sign)
+ {
+ /* Calculate the mantissa and sign of the result */
+ TempResult.Mantissa = FirstAdjusted.Mantissa + SecondAdjusted.Mantissa;
+ TempResult.Sign = FirstAdjusted.Sign;
+ }
+ else
+ {
+ /* Calculate the sign of the result */
+ if (FirstAdjusted.Mantissa > SecondAdjusted.Mantissa) TempResult.Sign =
FirstAdjusted.Sign;
+ else if (FirstAdjusted.Mantissa < SecondAdjusted.Mantissa) TempResult.Sign =
SecondAdjusted.Sign;
+ else TempResult.Sign = FALSE;
+
+ /* Invert the negative mantissa */
+ if (FirstAdjusted.Sign) FirstAdjusted.Mantissa = -FirstAdjusted.Mantissa;
+ if (SecondAdjusted.Sign) SecondAdjusted.Mantissa = -SecondAdjusted.Mantissa;
+
+ /* Calculate the mantissa of the result */
+ TempResult.Mantissa = FirstAdjusted.Mantissa + SecondAdjusted.Mantissa;
+ }
+
+ /* Did it overflow? */
+ if (FPU_IS_NORMALIZED(&FirstAdjusted) &&
FPU_IS_NORMALIZED(&SecondAdjusted))
+ {
+ if (TempResult.Exponent == FPU_MAX_EXPONENT)
+ {
+ /* Total overflow, return infinity */
+ TempResult.Mantissa = FPU_MANTISSA_HIGH_BIT;
+ TempResult.Exponent = FPU_MAX_EXPONENT + 1;
+
+ /* Update flags */
+ State->FpuStatus.Oe = TRUE;
+ }
+ else
+ {
+ /* Lose the LSB in favor of the carry */
+ TempResult.Mantissa >>= 1;
+ TempResult.Mantissa |= FPU_MANTISSA_HIGH_BIT;
+ TempResult.Exponent++;
+ }
+ }
+
+ /* Normalize the result and return it */
+ Fast486FpuNormalize(State, &TempResult);
+ *Result = TempResult;
+}
+
+static VOID Fast486FpuSubtract(PFAST486_STATE State,
+ PFAST486_FPU_DATA_REG FirstOperand,
+ PFAST486_FPU_DATA_REG SecondOperand,
+ PFAST486_FPU_DATA_REG Result)
+{
+ FAST486_FPU_DATA_REG NegativeSecondOperand = *SecondOperand;
+
+ /* Invert the sign */
+ NegativeSecondOperand.Sign = !NegativeSecondOperand.Sign;
+
+ /* And perform an addition instead */
+ Fast486FpuAdd(State, Result, FirstOperand, &NegativeSecondOperand);
+}
+
+static VOID Fast486FpuCompare(PFAST486_STATE State,
+ PFAST486_FPU_DATA_REG FirstOperand,
+ PFAST486_FPU_DATA_REG SecondOperand)
+{
+ if (FPU_IS_NAN(FirstOperand) || FPU_IS_NAN(SecondOperand))
+ {
+ if (FPU_IS_POS_INF(FirstOperand) && FPU_IS_NEG_INF(SecondOperand))
+ {
+ State->FpuStatus.Code0 = FALSE;
+ State->FpuStatus.Code2 = FALSE;
+ State->FpuStatus.Code3 = FALSE;
+ }
+ else if (FPU_IS_NEG_INF(FirstOperand) && FPU_IS_POS_INF(SecondOperand))
+ {
+ State->FpuStatus.Code0 = TRUE;
+ State->FpuStatus.Code2 = FALSE;
+ State->FpuStatus.Code3 = FALSE;
+ }
+ else
+ {
+ State->FpuStatus.Code0 = TRUE;
+ State->FpuStatus.Code2 = TRUE;
+ State->FpuStatus.Code3 = TRUE;
+ }
+ }
+ else
+ {
+ FAST486_FPU_DATA_REG TempResult;
+
+ Fast486FpuSubtract(State, FirstOperand, SecondOperand, &TempResult);
+
+ if (FPU_IS_ZERO(&TempResult))
+ {
+ State->FpuStatus.Code0 = FALSE;
+ State->FpuStatus.Code2 = FALSE;
+ State->FpuStatus.Code3 = TRUE;
+ }
+ else if (TempResult.Sign)
+ {
+ State->FpuStatus.Code0 = TRUE;
+ State->FpuStatus.Code2 = FALSE;
+ State->FpuStatus.Code3 = FALSE;
+ }
+ else
+ {
+ State->FpuStatus.Code0 = FALSE;
+ State->FpuStatus.Code2 = FALSE;
+ State->FpuStatus.Code3 = FALSE;
+ }
+ }
+}
+
+static VOID Fast486FpuMultiply(PFAST486_STATE State,
+ PFAST486_FPU_DATA_REG FirstOperand,
+ PFAST486_FPU_DATA_REG SecondOperand,
+ PFAST486_FPU_DATA_REG Result)
+{
+ FAST486_FPU_DATA_REG TempResult;
+
+ if (!FPU_IS_NORMALIZED(FirstOperand) || !FPU_IS_NORMALIZED(SecondOperand))
+ {
+ /* Denormalized */
+ State->FpuStatus.De = TRUE;
+ }
+
+ UnsignedMult128(FirstOperand->Mantissa,
+ SecondOperand->Mantissa,
+ &TempResult.Mantissa);
+
+ TempResult.Exponent = FirstOperand->Exponent + SecondOperand->Exponent;
+ TempResult.Sign = FirstOperand->Sign ^ SecondOperand->Sign;
+
+ /* Normalize the result */
+ Fast486FpuNormalize(State, &TempResult);
+ *Result = TempResult;
+}
+
+static VOID Fast486FpuDivide(PFAST486_STATE State,
+ PFAST486_FPU_DATA_REG FirstOperand,
+ PFAST486_FPU_DATA_REG SecondOperand,
+ PFAST486_FPU_DATA_REG Result)
+{
+ FAST486_FPU_DATA_REG TempResult;
+
+ if (FPU_IS_ZERO(SecondOperand))
+ {
+ /* Division by zero */
+ State->FpuStatus.Ze = TRUE;
+ return;
+ }
+
+ TempResult.Exponent = FirstOperand->Exponent - SecondOperand->Exponent;
+ TempResult.Sign = FirstOperand->Sign ^ SecondOperand->Sign;
+
+ // TODO: NOT IMPLEMENTED
+ UNREFERENCED_PARAMETER(TempResult);
+ UNIMPLEMENTED;
+}
+
/* PUBLIC FUNCTIONS ***********************************************************/
-FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8)
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8DC)
+{
+ FAST486_MOD_REG_RM ModRegRm;
+ BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+ PFAST486_FPU_DATA_REG SourceOperand, DestOperand;
+ FAST486_FPU_DATA_REG MemoryData;
+
+ /* Get the operands */
+ if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ FPU_CHECK();
+
+#ifndef FAST486_NO_FPU
+
+ if (ModRegRm.Memory)
+ {
+ /* Load the source operand from memory */
+
+ if (Opcode == 0xDC)
+ {
+ ULONGLONG Value;
+
+ if (!Fast486ReadMemory(State,
+ (State->PrefixFlags & FAST486_PREFIX_SEG)
+ ? State->SegmentOverride : FAST486_REG_DS,
+ ModRegRm.MemoryAddress,
+ FALSE,
+ &Value,
+ sizeof(ULONGLONG)))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ Fast486FpuGetDoubleReal(State, Value, &MemoryData);
+ }
+ else
+ {
+ ULONG Value;
+
+ if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ Fast486FpuGetSingleReal(State, Value, &MemoryData);
+ }
+
+ SourceOperand = &MemoryData;
+ }
+ else
+ {
+ /* Load the source operand from an FPU register */
+ SourceOperand = &FPU_ST(ModRegRm.SecondRegister);
+
+ if (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY)
+ {
+ /* Invalid operation */
+ State->FpuStatus.Ie = TRUE;
+ return FALSE;
+ }
+ }
+
+ /* The destination operand is always ST0 */
+ DestOperand = &FPU_ST(0);
+
+ if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
+ {
+ /* Invalid operation */
+ State->FpuStatus.Ie = TRUE;
+ return FALSE;
+ }
+
+ /* Check the operation */
+ switch (ModRegRm.Register)
+ {
+ /* FADD */
+ case 0:
+ {
+ Fast486FpuAdd(State, DestOperand, SourceOperand, DestOperand);
+ break;
+ }
+
+ /* FMUL */
+ case 1:
+ {
+ Fast486FpuMultiply(State, DestOperand, SourceOperand, DestOperand);
+ break;
+ }
+
+ /* FCOM */
+ case 2:
+ /* FCOMP */
+ case 3:
+ {
+ Fast486FpuCompare(State, DestOperand, SourceOperand);
+ if (ModRegRm.Register == 3) Fast486FpuPop(State);
+
+ break;
+ }
+
+ /* FSUB */
+ case 4:
+ {
+ Fast486FpuSubtract(State, DestOperand, SourceOperand, DestOperand);
+ break;
+ }
+
+ /* FSUBR */
+ case 5:
+ {
+ Fast486FpuSubtract(State, SourceOperand, DestOperand, DestOperand);
+ break;
+ }
+
+ /* FDIV */
+ case 6:
+ {
+ Fast486FpuDivide(State, DestOperand, SourceOperand, DestOperand);
+ break;
+ }
+
+ /* FDIVR */
+ case 7:
+ {
+ Fast486FpuDivide(State, SourceOperand, DestOperand, DestOperand);
+ break;
+ }
+ }
+
+#endif
+
+ return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD9)
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
@@ -58,7 +462,7 @@
#endif
}
-FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD9)
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDA)
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
@@ -83,7 +487,84 @@
#endif
}
-FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDA)
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDB)
+{
+ FAST486_MOD_REG_RM ModRegRm;
+ BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+
+ /* Get the operands */
+ if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ FPU_CHECK();
+
+#ifndef FAST486_NO_FPU
+
+ if (ModRegRm.Memory)
+ {
+ // TODO: NOT IMPLEMENTED
+ UNIMPLEMENTED;
+ }
+ else
+ {
+ /* Only a few of these instructions have any meaning on a 487 */
+ switch ((ModRegRm.SecondRegister << 3) | ModRegRm.Register)
+ {
+ /* FCLEX */
+ case 0x22:
+ {
+ /* Clear exception data */
+ State->FpuStatus.Ie =
+ State->FpuStatus.De =
+ State->FpuStatus.Ze =
+ State->FpuStatus.Oe =
+ State->FpuStatus.Ue =
+ State->FpuStatus.Pe =
+ State->FpuStatus.Sf =
+ State->FpuStatus.Es =
+ State->FpuStatus.Busy = FALSE;
+
+ break;
+ }
+
+ /* FINIT */
+ case 0x23:
+ {
+ /* Restore the state */
+ State->FpuControl.Value = FAST486_FPU_DEFAULT_CONTROL;
+ State->FpuStatus.Value = 0;
+ State->FpuTag = 0xFFFF;
+
+ break;
+ }
+
+ /* FENI */
+ case 0x20:
+ /* FDISI */
+ case 0x21:
+ {
+ /* These do nothing */
+ break;
+ }
+
+ /* Invalid */
+ default:
+ {
+ Fast486Exception(State, FAST486_EXCEPTION_UD);
+ return FALSE;
+ }
+ }
+ }
+
+#endif
+
+ return TRUE;
+}
+
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDD)
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
@@ -108,7 +589,7 @@
#endif
}
-FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDB)
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDE)
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
@@ -133,7 +614,7 @@
#endif
}
-FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDC)
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDF)
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
@@ -158,79 +639,4 @@
#endif
}
-FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDD)
-{
- FAST486_MOD_REG_RM ModRegRm;
- BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
-
- /* Get the operands */
- if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
- {
- /* Exception occurred */
- return FALSE;
- }
-
- FPU_CHECK();
-
-#ifndef FAST486_NO_FPU
- // TODO: NOT IMPLEMENTED
- UNIMPLEMENTED;
-
- return FALSE;
-#else
- /* Do nothing */
- return TRUE;
-#endif
-}
-
-FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDE)
-{
- FAST486_MOD_REG_RM ModRegRm;
- BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
-
- /* Get the operands */
- if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
- {
- /* Exception occurred */
- return FALSE;
- }
-
- FPU_CHECK();
-
-#ifndef FAST486_NO_FPU
- // TODO: NOT IMPLEMENTED
- UNIMPLEMENTED;
-
- return FALSE;
-#else
- /* Do nothing */
- return TRUE;
-#endif
-}
-
-FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDF)
-{
- FAST486_MOD_REG_RM ModRegRm;
- BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
-
- /* Get the operands */
- if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
- {
- /* Exception occurred */
- return FALSE;
- }
-
- FPU_CHECK();
-
-#ifndef FAST486_NO_FPU
- // TODO: NOT IMPLEMENTED
- UNIMPLEMENTED;
-
- return FALSE;
-#else
- /* Do nothing */
- return TRUE;
-#endif
-}
-
/* EOF */
Modified: trunk/reactos/lib/fast486/fpu.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/fpu.h?rev=6465…
==============================================================================
--- trunk/reactos/lib/fast486/fpu.h [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/fpu.h [iso-8859-1] Fri Oct 10 23:07:14 2014
@@ -2,7 +2,7 @@
* Fast486 386/486 CPU Emulation Library
* fpu.h
*
- * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ * Copyright (C) 2014 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -24,6 +24,8 @@
#pragma once
+#include "opcodes.h"
+
/* DEFINES ********************************************************************/
#define FPU_CHECK() if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_EM)
\
@@ -32,6 +34,24 @@
return FALSE; \
}
#define FPU_ST(i) State->FpuRegisters[(State->FpuStatus.Top + (i)) %
FAST486_NUM_FPU_REGS]
+#define FPU_GET_TAG(i) ((State->FpuTag >> ((i) * 2)) & 3)
+#define FPU_SET_TAG(i, t) { \
+ State->FpuTag &= ~((1 << ((i) * 2)) | (1
<< (((i) * 2) + 1))); \
+ State->FpuTag |= ((t) & 3) << ((i) * 2); \
+ }
+
+#define FPU_REAL4_BIAS 0x7F
+#define FPU_REAL8_BIAS 0x3FF
+#define FPU_REAL10_BIAS 0x3FFF
+#define FPU_MAX_EXPONENT 0x7FFE
+#define FPU_MANTISSA_HIGH_BIT 0x8000000000000000ULL
+
+#define FPU_IS_NORMALIZED(x) (!FPU_IS_ZERO(x) && (((x)->Mantissa &
FPU_MANTISSA_HIGH_BIT) != 0ULL))
+#define FPU_IS_ZERO(x) ((x)->Mantissa == 0ULL)
+#define FPU_IS_NAN(x) ((x)->Exponent == (FPU_MAX_EXPONENT + 1))
+#define FPU_IS_INFINITY(x) (FPU_IS_NAN(x) && (x)->Mantissa &
FPU_MANTISSA_HIGH_BIT)
+#define FPU_IS_POS_INF(x) (FPU_IS_INFINITY(x) && !(x)->Sign)
+#define FPU_IS_NEG_INF(x) (FPU_IS_INFINITY(x) && (x)->Sign)
enum
{
@@ -48,11 +68,10 @@
FPU_TAG_EMPTY = 3
};
-FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8);
+FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8DC);
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD9);
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDA);
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDB);
-FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDC);
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDD);
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDE);
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDF);
Modified: trunk/reactos/lib/fast486/opcodes.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/opcodes.c?rev=…
==============================================================================
--- trunk/reactos/lib/fast486/opcodes.c [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/opcodes.c [iso-8859-1] Fri Oct 10 23:07:14 2014
@@ -2,7 +2,7 @@
* Fast486 386/486 CPU Emulation Library
* opcodes.c
*
- * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ * Copyright (C) 2014 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -254,11 +254,11 @@
Fast486OpcodeAad,
Fast486OpcodeSalc,
Fast486OpcodeXlat,
- Fast486FpuOpcodeD8,
+ Fast486FpuOpcodeD8DC,
Fast486FpuOpcodeD9,
Fast486FpuOpcodeDA,
Fast486FpuOpcodeDB,
- Fast486FpuOpcodeDC,
+ Fast486FpuOpcodeD8DC,
Fast486FpuOpcodeDD,
Fast486FpuOpcodeDE,
Fast486FpuOpcodeDF,
Modified: trunk/reactos/lib/fast486/opcodes.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/opcodes.h?rev=…
==============================================================================
--- trunk/reactos/lib/fast486/opcodes.h [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/opcodes.h [iso-8859-1] Fri Oct 10 23:07:14 2014
@@ -2,7 +2,7 @@
* Fast486 386/486 CPU Emulation Library
* opcodes.h
*
- * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ * Copyright (C) 2014 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
Modified: trunk/reactos/lib/fast486/opgroups.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/opgroups.c?rev…
==============================================================================
--- trunk/reactos/lib/fast486/opgroups.c [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/opgroups.c [iso-8859-1] Fri Oct 10 23:07:14 2014
@@ -2,7 +2,7 @@
* Fast486 386/486 CPU Emulation Library
* opgroups.c
*
- * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ * Copyright (C) 2014 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
Modified: trunk/reactos/lib/fast486/opgroups.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/opgroups.h?rev…
==============================================================================
--- trunk/reactos/lib/fast486/opgroups.h [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/opgroups.h [iso-8859-1] Fri Oct 10 23:07:14 2014
@@ -2,7 +2,7 @@
* Fast486 386/486 CPU Emulation Library
* opgroups.h
*
- * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ * Copyright (C) 2014 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License