Author: aandrejevic
Date: Thu Jan 1 19:20:44 2015
New Revision: 65934
URL:
http://svn.reactos.org/svn/reactos?rev=65934&view=rev
Log:
[FAST486]
Implement opcode 0xDE (New instructions: FADDP, FMULP, FCOMPP, FSUBRP, FSUBP, FDIVRP and
FDIVP).
Fix a bug in the 0xD8/0xDC opcode handler.
Modified:
trunk/reactos/lib/fast486/fpu.c
Modified: trunk/reactos/lib/fast486/fpu.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/fpu.c?rev=6593…
==============================================================================
--- trunk/reactos/lib/fast486/fpu.c [iso-8859-1] (original)
+++ trunk/reactos/lib/fast486/fpu.c [iso-8859-1] Thu Jan 1 19:20:44 2015
@@ -423,6 +423,13 @@
#ifndef FAST486_NO_FPU
+ if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
+ {
+ /* Invalid operation */
+ State->FpuStatus.Ie = TRUE;
+ return;
+ }
+
if (ModRegRm.Memory)
{
/* Load the source operand from memory */
@@ -459,28 +466,35 @@
}
SourceOperand = &MemoryData;
+
+ /* The destination operand is ST0 */
+ DestOperand = &FPU_ST(0);
}
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;
}
- }
-
- /* 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;
+
+ if (Opcode == 0xDC)
+ {
+ /* The source operand is ST0 */
+ SourceOperand = &FPU_ST(0);
+
+ /* Load the destination operand from an FPU register */
+ DestOperand = &FPU_ST(ModRegRm.SecondRegister);
+ }
+ else
+ {
+ /* Load the source operand from an FPU register */
+ SourceOperand = &FPU_ST(ModRegRm.SecondRegister);
+
+ /* The destination operand is ST0 */
+ DestOperand = &FPU_ST(0);
+ }
}
/* Check the operation */
@@ -912,6 +926,137 @@
{
FAST486_MOD_REG_RM ModRegRm;
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
+ PFAST486_FPU_DATA_REG SourceOperand, DestOperand;
+ BOOLEAN PopStack = FALSE;
+
+ /* Get the operands */
+ if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
+ {
+ /* Exception occurred */
+ return;
+ }
+
+ FPU_CHECK();
+
+#ifndef FAST486_NO_FPU
+
+ if (FPU_GET_TAG(0) == FPU_TAG_EMPTY)
+ {
+ /* Invalid operation */
+ State->FpuStatus.Ie = TRUE;
+ return;
+ }
+
+ if (ModRegRm.Memory)
+ {
+ SHORT Value;
+ FAST486_FPU_DATA_REG MemoryData;
+
+ /* Load the source operand from memory */
+ if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL,
(PUSHORT)&Value))
+ {
+ /* Exception occurred */
+ return;
+ }
+
+ Fast486FpuFromInteger(State, (LONGLONG)Value, &MemoryData);
+ SourceOperand = &MemoryData;
+
+ /* The destination operand is ST0 */
+ DestOperand = &FPU_ST(0);
+ }
+ else
+ {
+ /* FCOMPP check */
+ if ((ModRegRm.Register == 3) && (ModRegRm.SecondRegister != 1))
+ {
+ /* Invalid */
+ Fast486Exception(State, FAST486_EXCEPTION_UD);
+ return;
+ }
+
+ /* The source operand is ST0 */
+ SourceOperand = &FPU_ST(0);
+
+ /* Load the destination operand from a register */
+ DestOperand = &FPU_ST(ModRegRm.SecondRegister);
+
+ if (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY)
+ {
+ /* Invalid operation */
+ State->FpuStatus.Ie = TRUE;
+ return;
+ }
+
+ PopStack = TRUE;
+ }
+
+ /* Check the operation */
+ switch (ModRegRm.Register)
+ {
+ /* FIADD / FADDP */
+ case 0:
+ {
+ Fast486FpuAdd(State, DestOperand, SourceOperand, DestOperand);
+ break;
+ }
+
+ /* FIMUL / FMULP */
+ case 1:
+ {
+ Fast486FpuMultiply(State, DestOperand, SourceOperand, DestOperand);
+ break;
+ }
+
+ /* FICOM / FCOMP */
+ case 2:
+ /* FICOMP / FCOMPP */
+ case 3:
+ {
+ Fast486FpuCompare(State, DestOperand, SourceOperand);
+ if (ModRegRm.Register == 3) Fast486FpuPop(State);
+
+ break;
+ }
+
+ /* FISUB / FSUBRP */
+ case 4:
+ {
+ Fast486FpuSubtract(State, DestOperand, SourceOperand, DestOperand);
+ break;
+ }
+
+ /* FISUBR / FSUBP */
+ case 5:
+ {
+ Fast486FpuSubtract(State, SourceOperand, DestOperand, DestOperand);
+ break;
+ }
+
+ /* FIDIV / FDIVRP */
+ case 6:
+ {
+ Fast486FpuDivide(State, DestOperand, SourceOperand, DestOperand);
+ break;
+ }
+
+ /* FIDIVR / FDIVP */
+ case 7:
+ {
+ Fast486FpuDivide(State, SourceOperand, DestOperand, DestOperand);
+ break;
+ }
+ }
+
+ if (PopStack) Fast486FpuPop(State);
+
+#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))
@@ -930,26 +1075,4 @@
#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;
- }
-
- FPU_CHECK();
-
-#ifndef FAST486_NO_FPU
- // TODO: NOT IMPLEMENTED
- UNIMPLEMENTED;
-#else
- /* Do nothing */
-#endif
-}
-
/* EOF */