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=65934... ============================================================================== --- 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 */