mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 22:46:17 +00:00
[FAST486]
Finish implementing FPU opcode 0xDB (FILD, FIST, FISTP, FLD, FSTP). svn path=/trunk/; revision=65927
This commit is contained in:
parent
e274681598
commit
d89cf74100
2 changed files with 236 additions and 10 deletions
|
@ -67,9 +67,105 @@ UnsignedMult128(ULONGLONG Multiplicand,
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID
|
static VOID
|
||||||
Fast486FpuGetSingleReal(PFAST486_STATE State,
|
Fast486FpuFromInteger(PFAST486_STATE State,
|
||||||
ULONG Value,
|
LONGLONG Value,
|
||||||
PFAST486_FPU_DATA_REG Result)
|
PFAST486_FPU_DATA_REG Result)
|
||||||
|
{
|
||||||
|
ULONG ZeroCount;
|
||||||
|
|
||||||
|
Result->Sign = Result->Exponent = Result->Mantissa = 0;
|
||||||
|
if (Value == 0LL) return;
|
||||||
|
|
||||||
|
if (Value < 0LL)
|
||||||
|
{
|
||||||
|
Result->Sign = 1;
|
||||||
|
Value = -Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result->Mantissa = (ULONGLONG)Value;
|
||||||
|
ZeroCount = CountLeadingZeros64(Result->Mantissa);
|
||||||
|
|
||||||
|
Result->Mantissa <<= ZeroCount;
|
||||||
|
Result->Exponent = FPU_REAL10_BIAS + 63 - ZeroCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOLEAN
|
||||||
|
Fast486FpuToInteger(PFAST486_STATE State,
|
||||||
|
PFAST486_FPU_DATA_REG Value,
|
||||||
|
PLONGLONG Result)
|
||||||
|
{
|
||||||
|
ULONG Bits;
|
||||||
|
ULONGLONG Remainder;
|
||||||
|
SHORT UnbiasedExp = (SHORT)Value->Exponent - FPU_REAL10_BIAS;
|
||||||
|
|
||||||
|
if (FPU_IS_ZERO(Value))
|
||||||
|
{
|
||||||
|
Result = 0LL;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FPU_IS_NAN(Value) || !FPU_IS_NORMALIZED(Value)
|
||||||
|
|| (UnbiasedExp < 0) || (UnbiasedExp > 63))
|
||||||
|
{
|
||||||
|
State->FpuStatus.Ie = TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bits = 63 - UnbiasedExp;
|
||||||
|
|
||||||
|
/* Calculate the result and the remainder */
|
||||||
|
*Result = (LONGLONG)(Value->Mantissa >> Bits);
|
||||||
|
Remainder = Value->Mantissa & ((1 << Bits) - 1);
|
||||||
|
|
||||||
|
/* The result must be positive here */
|
||||||
|
ASSERT(*Result >= 0LL);
|
||||||
|
|
||||||
|
switch (State->FpuControl.Rc)
|
||||||
|
{
|
||||||
|
case FPU_ROUND_NEAREST:
|
||||||
|
{
|
||||||
|
/* Check if the highest bit of the remainder is set */
|
||||||
|
if (Remainder & (1 << (Bits - 1)))
|
||||||
|
{
|
||||||
|
*Result++;
|
||||||
|
|
||||||
|
/* Check if all the other bits are clear */
|
||||||
|
if (!(Remainder & ((1 << (Bits - 1)) - 1)))
|
||||||
|
{
|
||||||
|
/* Round to even */
|
||||||
|
*Result &= ~1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case FPU_ROUND_DOWN:
|
||||||
|
{
|
||||||
|
if ((Remainder != 0ULL) && Value->Sign) *Result++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case FPU_ROUND_UP:
|
||||||
|
{
|
||||||
|
if ((Remainder != 0ULL) && !Value->Sign) *Result++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
/* Leave it truncated */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Value->Sign) *Result = -*Result;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID
|
||||||
|
Fast486FpuFromSingleReal(PFAST486_STATE State,
|
||||||
|
ULONG Value,
|
||||||
|
PFAST486_FPU_DATA_REG Result)
|
||||||
{
|
{
|
||||||
/* Extract the sign, exponent and mantissa */
|
/* Extract the sign, exponent and mantissa */
|
||||||
Result->Sign = (UCHAR)(Value >> 31);
|
Result->Sign = (UCHAR)(Value >> 31);
|
||||||
|
@ -88,9 +184,9 @@ Fast486FpuGetSingleReal(PFAST486_STATE State,
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID
|
static VOID
|
||||||
Fast486FpuGetDoubleReal(PFAST486_STATE State,
|
Fast486FpuFromDoubleReal(PFAST486_STATE State,
|
||||||
ULONGLONG Value,
|
ULONGLONG Value,
|
||||||
PFAST486_FPU_DATA_REG Result)
|
PFAST486_FPU_DATA_REG Result)
|
||||||
{
|
{
|
||||||
/* Extract the sign, exponent and mantissa */
|
/* Extract the sign, exponent and mantissa */
|
||||||
Result->Sign = (UCHAR)(Value >> 63);
|
Result->Sign = (UCHAR)(Value >> 63);
|
||||||
|
@ -347,7 +443,7 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8DC)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Fast486FpuGetDoubleReal(State, Value, &MemoryData);
|
Fast486FpuFromDoubleReal(State, Value, &MemoryData);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -359,7 +455,7 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8DC)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Fast486FpuGetSingleReal(State, Value, &MemoryData);
|
Fast486FpuFromSingleReal(State, Value, &MemoryData);
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceOperand = &MemoryData;
|
SourceOperand = &MemoryData;
|
||||||
|
@ -509,8 +605,130 @@ FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDB)
|
||||||
|
|
||||||
if (ModRegRm.Memory)
|
if (ModRegRm.Memory)
|
||||||
{
|
{
|
||||||
// TODO: NOT IMPLEMENTED
|
switch (ModRegRm.Register)
|
||||||
UNIMPLEMENTED;
|
{
|
||||||
|
/* FILD */
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
LONG Value;
|
||||||
|
FAST486_FPU_DATA_REG Temp;
|
||||||
|
|
||||||
|
if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, (PULONG)&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 32-bit integer */
|
||||||
|
if ((((ULONGLONG)Temp >> 31) + 1ULL) > 1ULL)
|
||||||
|
{
|
||||||
|
State->FpuStatus.Ie = TRUE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, (ULONG)((LONG)Temp)))
|
||||||
|
{
|
||||||
|
/* Exception occurred */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ModRegRm.Register == 3)
|
||||||
|
{
|
||||||
|
/* Pop the FPU stack too */
|
||||||
|
Fast486FpuPop(State);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FLD */
|
||||||
|
case 5:
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value.Mantissa = *((PULONGLONG)Buffer);
|
||||||
|
Value.Exponent = *((PUSHORT)&Buffer[8]) & (FPU_MAX_EXPONENT + 1);
|
||||||
|
Value.Sign = *((PUCHAR)&Buffer[9]) >> 7;
|
||||||
|
|
||||||
|
Fast486FpuPush(State, &Value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FSTP */
|
||||||
|
case 7:
|
||||||
|
{
|
||||||
|
UCHAR Buffer[10];
|
||||||
|
|
||||||
|
if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY) || (FPU_GET_TAG(0) == FPU_TAG_SPECIAL))
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
State->FpuStatus.Ie = TRUE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*((PULONGLONG)Buffer) = FPU_ST(0).Mantissa;
|
||||||
|
*((PUSHORT)&Buffer[sizeof(ULONGLONG)]) = FPU_ST(0).Exponent | (FPU_ST(0).Sign ? 0x8000 : 0);
|
||||||
|
|
||||||
|
if (!Fast486WriteMemory(State,
|
||||||
|
(State->PrefixFlags & FAST486_PREFIX_SEG)
|
||||||
|
? State->SegmentOverride : FAST486_REG_DS,
|
||||||
|
ModRegRm.MemoryAddress,
|
||||||
|
Buffer,
|
||||||
|
sizeof(Buffer)))
|
||||||
|
{
|
||||||
|
/* Exception occurred */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Fast486FpuPop(State);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Invalid */
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
Fast486Exception(State, FAST486_EXCEPTION_UD);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -68,6 +68,14 @@ enum
|
||||||
FPU_TAG_EMPTY = 3
|
FPU_TAG_EMPTY = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
FPU_ROUND_NEAREST = 0,
|
||||||
|
FPU_ROUND_DOWN = 1,
|
||||||
|
FPU_ROUND_UP = 2,
|
||||||
|
FPU_ROUND_TRUNCATE = 3
|
||||||
|
};
|
||||||
|
|
||||||
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8DC);
|
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8DC);
|
||||||
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD9);
|
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD9);
|
||||||
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDA);
|
FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDA);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue