Author: aandrejevic Date: Fri Jan 2 18:29:30 2015 New Revision: 65940
URL: http://svn.reactos.org/svn/reactos?rev=65940&view=rev Log: [FAST486] Split the D8/DC opcode handler into two handlers to eliminate the extra branch. Implement opcode DF (New instructions: FBLD and FBSTP).
Modified: trunk/reactos/lib/fast486/fpu.c trunk/reactos/lib/fast486/fpu.h trunk/reactos/lib/fast486/opcodes.c
Modified: trunk/reactos/lib/fast486/fpu.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/fpu.c?rev=65940... ============================================================================== --- trunk/reactos/lib/fast486/fpu.c [iso-8859-1] (original) +++ trunk/reactos/lib/fast486/fpu.c [iso-8859-1] Fri Jan 2 18:29:30 2015 @@ -291,6 +291,61 @@ return TRUE; }
+static inline BOOLEAN FASTCALL +Fast486FpuFromPackedBcd(PFAST486_STATE State, + PUCHAR Value, + PFAST486_FPU_DATA_REG Result) +{ + INT i; + LONGLONG IntVal = 0LL; + + for (i = 8; i >= 0; i--) + { + if (((Value[i] & 0x0F) > 9) || ((Value[i] >> 4) > 9)) + { + /* Invalid BCD */ + State->FpuStatus.Ie = TRUE; + return FALSE; + } + + IntVal *= 100LL; + IntVal += (Value[i] >> 4) * 10 + (Value[i] & 0x0F); + } + + /* Apply the sign */ + if (Value[9] & 0x80) IntVal = -IntVal; + + /* Now convert the integer to FP80 */ + Fast486FpuFromInteger(State, IntVal, Result); + return TRUE; +} + +static inline BOOLEAN FASTCALL +Fast486FpuToPackedBcd(PFAST486_STATE State, + PFAST486_FPU_DATA_REG Value, + PUCHAR Result) +{ + INT i; + LONGLONG IntVal; + + /* Convert it to an integer first */ + if (!Fast486FpuToInteger(State, Value, &IntVal)) return FALSE; + + if (IntVal < 0LL) + { + IntVal = -IntVal; + Result[9] = 0x80; + } + + for (i = 0; i < 9; i++) + { + Result[i] = (UCHAR)((IntVal % 10) + (((IntVal / 10) % 10) << 4)); + IntVal /= 100LL; + } + + return TRUE; +} + static inline VOID FASTCALL Fast486FpuAdd(PFAST486_STATE State, PFAST486_FPU_DATA_REG FirstOperand, @@ -558,7 +613,7 @@
/* PUBLIC FUNCTIONS ***********************************************************/
-FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8DC) +FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8) { FAST486_MOD_REG_RM ModRegRm; BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; @@ -586,38 +641,15 @@ 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; - } - - Fast486FpuFromDoubleReal(State, Value, &MemoryData); - } - else - { - ULONG Value; - - if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) - { - /* Exception occurred */ - return; - } - - Fast486FpuFromSingleReal(State, Value, &MemoryData); - } - + ULONG Value; + + if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) + { + /* Exception occurred */ + return; + } + + Fast486FpuFromSingleReal(State, Value, &MemoryData); SourceOperand = &MemoryData;
/* The destination operand is ST0 */ @@ -632,22 +664,11 @@ 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); - } + /* Load the source operand from an FPU register */ + SourceOperand = &FPU_ST(ModRegRm.SecondRegister); + + /* The destination operand is ST0 */ + DestOperand = &FPU_ST(0); }
/* Perform the requested operation */ @@ -655,6 +676,77 @@
#endif } + +FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDC) +{ + 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; + } + + FPU_CHECK(); + +#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 */ + ULONGLONG Value; + + if (!Fast486ReadMemory(State, + (State->PrefixFlags & FAST486_PREFIX_SEG) + ? State->SegmentOverride : FAST486_REG_DS, + ModRegRm.MemoryAddress, + FALSE, + &Value, + sizeof(ULONGLONG))) + { + /* Exception occurred */ + return; + } + + Fast486FpuFromDoubleReal(State, Value, &MemoryData); + SourceOperand = &MemoryData; + + /* The destination operand is ST0 */ + DestOperand = &FPU_ST(0); + } + else + { + if (FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY) + { + /* Invalid operation */ + State->FpuStatus.Ie = TRUE; + return; + } + + /* The source operand is ST0 */ + SourceOperand = &FPU_ST(0); + + /* Load the destination operand from an FPU register */ + DestOperand = &FPU_ST(ModRegRm.SecondRegister); + } + + /* Perform the requested operation */ + Fast486FpuArithmeticOperation(State, ModRegRm.Register, SourceOperand, DestOperand); + +#endif +} +
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD9) { @@ -1222,10 +1314,270 @@ FPU_CHECK();
#ifndef FAST486_NO_FPU - // TODO: NOT IMPLEMENTED - UNIMPLEMENTED; -#else - /* Do nothing */ + + if (ModRegRm.Memory) + { + switch (ModRegRm.Register) + { + /* FILD */ + case 0: + { + SHORT Value; + FAST486_FPU_DATA_REG Temp; + + if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, (PUSHORT)&Value)) + { + /* Exception occurred */ + return; + } + + Fast486FpuFromInteger(State, (LONGLONG)Value, &Temp); + Fast486FpuPush(State, &Temp); + + break; + } + + /* FIST */ + case 2: + /* FISTP */ + case 3: + { + LONGLONG Temp; + + if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(0) == FPU_TAG_SPECIAL)) + { + /* Fail */ + State->FpuStatus.Ie = TRUE; + return; + } + + if (!Fast486FpuToInteger(State, &FPU_ST(0), &Temp)) + { + /* Exception occurred */ + return; + } + + /* Check if it can fit in a signed 16-bit integer */ + if ((((ULONGLONG)Temp >> 15) + 1ULL) > 1ULL) + { + State->FpuStatus.Ie = TRUE; + return; + } + + if (!Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, (USHORT)((SHORT)Temp))) + { + /* Exception occurred */ + return; + } + + if (ModRegRm.Register == 3) + { + /* Pop the FPU stack too */ + Fast486FpuPop(State); + } + + break; + } + + /* FBLD */ + case 4: + { + FAST486_FPU_DATA_REG Value; + UCHAR Buffer[10]; + + if (!Fast486ReadMemory(State, + (State->PrefixFlags & FAST486_PREFIX_SEG) + ? State->SegmentOverride : FAST486_REG_DS, + ModRegRm.MemoryAddress, + FALSE, + Buffer, + sizeof(Buffer))) + { + /* Exception occurred */ + return; + } + + if (!Fast486FpuFromPackedBcd(State, Buffer, &Value)) + { + /* Exception occurred */ + return; + } + + Fast486FpuPush(State, &Value); + break; + } + + /* FILD (64-bit int) */ + case 5: + { + LONGLONG Value; + FAST486_FPU_DATA_REG Temp; + + if (!Fast486ReadMemory(State, + (State->PrefixFlags & FAST486_PREFIX_SEG) + ? State->SegmentOverride : FAST486_REG_DS, + ModRegRm.MemoryAddress, + FALSE, + &Value, + sizeof(LONGLONG))) + { + /* Exception occurred */ + return; + } + + Fast486FpuFromInteger(State, (LONGLONG)Value, &Temp); + Fast486FpuPush(State, &Temp); + + break; + } + + /* FBSTP */ + case 6: + { + UCHAR Buffer[10]; + + if (FPU_GET_TAG(0) == FPU_TAG_EMPTY) + { + /* Fail */ + State->FpuStatus.Ie = TRUE; + return; + } + + if (!Fast486FpuToPackedBcd(State, &FPU_ST(0), Buffer)) + { + /* Exception occurred */ + return; + } + + if (!Fast486WriteMemory(State, + (State->PrefixFlags & FAST486_PREFIX_SEG) + ? State->SegmentOverride : FAST486_REG_DS, + ModRegRm.MemoryAddress, + Buffer, + sizeof(Buffer))) + { + /* Exception occurred */ + return; + } + + Fast486FpuPop(State); + break; + } + + /* FISTP (64-bit int) */ + case 7: + { + LONGLONG Temp; + + if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(0) == FPU_TAG_SPECIAL)) + { + /* Fail */ + State->FpuStatus.Ie = TRUE; + return; + } + + if (!Fast486FpuToInteger(State, &FPU_ST(0), &Temp)) + { + /* Exception occurred */ + return; + } + + if (!Fast486WriteMemory(State, + (State->PrefixFlags & FAST486_PREFIX_SEG) + ? State->SegmentOverride : FAST486_REG_DS, + ModRegRm.MemoryAddress, + &Temp, + sizeof(LONGLONG))) + { + /* Exception occurred */ + return; + } + + /* Pop the FPU stack too */ + Fast486FpuPop(State); + + break; + } + + /* Invalid */ + default: + { + Fast486Exception(State, FAST486_EXCEPTION_UD); + } + } + } + else + { + switch (ModRegRm.Register) + { + /* FFREEP */ + case 0: + { + FPU_SET_TAG(ModRegRm.SecondRegister, FPU_TAG_EMPTY); + Fast486FpuPop(State); + + break; + } + + /* FXCH */ + case 1: + { + FAST486_FPU_DATA_REG Temp; + + if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) + || FPU_GET_TAG(ModRegRm.SecondRegister) == FPU_TAG_EMPTY) + { + State->FpuStatus.Ie = TRUE; + break; + } + + /* Exchange */ + Temp = FPU_ST(0); + FPU_ST(0) = FPU_ST(ModRegRm.SecondRegister); + FPU_ST(ModRegRm.SecondRegister) = Temp; + + FPU_UPDATE_TAG(0); + FPU_UPDATE_TAG(ModRegRm.SecondRegister); + + break; + } + + /* FSTP */ + case 2: + case 3: + { + FPU_ST(ModRegRm.SecondRegister) = FPU_ST(0); + FPU_UPDATE_TAG(ModRegRm.SecondRegister); + Fast486FpuPop(State); + + break; + } + + /* FSTSW */ + case 4: + { + if (ModRegRm.SecondRegister != 0) + { + /* Invalid */ + Fast486Exception(State, FAST486_EXCEPTION_UD); + return; + } + + /* Store the status word in AX */ + State->GeneralRegs[FAST486_REG_EAX].LowWord = State->FpuStatus.Value; + + break; + } + + /* Invalid */ + default: + { + Fast486Exception(State, FAST486_EXCEPTION_UD); + return; + } + } + } + #endif }
Modified: trunk/reactos/lib/fast486/fpu.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/fast486/fpu.h?rev=65940... ============================================================================== --- trunk/reactos/lib/fast486/fpu.h [iso-8859-1] (original) +++ trunk/reactos/lib/fast486/fpu.h [iso-8859-1] Fri Jan 2 18:29:30 2015 @@ -78,10 +78,11 @@ FPU_ROUND_TRUNCATE = 3 };
-FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8DC); +FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8); 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=6... ============================================================================== --- trunk/reactos/lib/fast486/opcodes.c [iso-8859-1] (original) +++ trunk/reactos/lib/fast486/opcodes.c [iso-8859-1] Fri Jan 2 18:29:30 2015 @@ -254,11 +254,11 @@ Fast486OpcodeAad, /* 0xD5 */ Fast486OpcodeSalc, /* 0xD6 */ Fast486OpcodeXlat, /* 0xD7 */ - Fast486FpuOpcodeD8DC, /* 0xD8 - 0xDF */ + Fast486FpuOpcodeD8, /* 0xD8 - 0xDF */ Fast486FpuOpcodeD9, Fast486FpuOpcodeDA, Fast486FpuOpcodeDB, - Fast486FpuOpcodeD8DC, + Fast486FpuOpcodeDC, Fast486FpuOpcodeDD, Fast486FpuOpcodeDE, Fast486FpuOpcodeDF,