2 * Fast486 386/486 CPU Emulation Library
5 * Copyright (C) 2014 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 /* INCLUDES *******************************************************************/
33 /* PRIVATE FUNCTIONS **********************************************************/
35 #ifndef FAST486_NO_FPU
38 UnsignedMult128(ULONGLONG Multiplicand
,
40 ULONGLONG
*HighProduct
)
42 ULONG MultiplicandLow
, MultiplicandHigh
, MultiplierLow
, MultiplierHigh
;
43 ULONG IntermediateLow
, IntermediateHigh
;
44 ULONGLONG LowProduct
, Intermediate
, Intermediate1
, Intermediate2
;
46 MultiplicandLow
= (ULONG
)(Multiplicand
& 0xFFFFFFFFULL
);
47 MultiplicandHigh
= (ULONG
)(Multiplicand
>> 32);
48 MultiplierLow
= (ULONG
)(Multiplier
& 0xFFFFFFFFULL
);
49 MultiplierHigh
= (ULONG
)(Multiplier
>> 32);
51 LowProduct
= (ULONGLONG
)MultiplicandLow
* (ULONGLONG
)MultiplierLow
;
52 Intermediate1
= (ULONGLONG
)MultiplicandLow
* (ULONGLONG
)MultiplierHigh
;
53 Intermediate2
= (ULONGLONG
)MultiplicandHigh
* (ULONGLONG
)MultiplierLow
;
54 *HighProduct
= (ULONGLONG
)MultiplicandHigh
* (ULONGLONG
)MultiplierHigh
;
56 Intermediate
= Intermediate1
+ Intermediate2
;
57 if (Intermediate
< Intermediate1
) *HighProduct
+= 1ULL << 32;
59 IntermediateLow
= (ULONG
)(Intermediate
& 0xFFFFFFFFULL
);
60 IntermediateHigh
= (ULONG
)(Intermediate
>> 32);
62 LowProduct
+= (ULONGLONG
)IntermediateLow
<< 32;
63 if ((ULONG
)(LowProduct
>> 32) < IntermediateLow
) (*HighProduct
)++;
65 *HighProduct
+= IntermediateHigh
;
70 UnsignedDivMod128(ULONGLONG DividendLow
,
71 ULONGLONG DividendHigh
,
73 PULONGLONG QuotientLow
,
74 PULONGLONG QuotientHigh
)
76 ULONGLONG ValueLow
= DividendLow
;
77 ULONGLONG ValueHigh
= DividendHigh
;
78 ULONGLONG CurrentLow
= 0ULL;
79 ULONGLONG CurrentHigh
= Divisor
;
82 ASSERT(Divisor
!= 0ULL);
84 /* Initialize the quotient */
85 *QuotientLow
= *QuotientHigh
= 0ULL;
87 /* Exit early if the dividend is lower than the divisor */
88 if ((DividendHigh
== 0ULL) && (DividendLow
< Divisor
)) return ValueLow
;
90 /* Normalize the current divisor */
91 Bits
= CountLeadingZeros64(CurrentHigh
);
96 /* Shift the quotient left by one bit */
98 *QuotientHigh
|= *QuotientLow
>> 63;
101 /* Check if the value is higher than or equal to the current divisor */
102 if ((ValueHigh
> CurrentHigh
)
103 || ((ValueHigh
== CurrentHigh
) && (ValueLow
>= CurrentLow
)))
105 BOOLEAN Carry
= ValueLow
< CurrentLow
;
107 /* Subtract the current divisor from the value */
108 ValueHigh
-= CurrentHigh
;
109 ValueLow
-= CurrentLow
;
110 if (Carry
) ValueHigh
--;
112 /* Set the lowest bit of the quotient */
115 /* Stop if the value is lower than the original divisor */
116 if ((ValueHigh
== 0ULL) && (ValueLow
< Divisor
)) break;
119 /* Shift the current divisor right by one bit */
121 CurrentLow
|= (CurrentHigh
& 1) << 63;
126 * Calculate the number of significant bits the current
127 * divisor has more than the original divisor
129 Bits
= CountLeadingZeros64(Divisor
) + 64;
130 Bits
-= (CurrentHigh
> 0ULL) ? CountLeadingZeros64(CurrentHigh
) : 64;
131 Bits
-= (CurrentLow
> 0ULL) ? CountLeadingZeros64(CurrentLow
) : 64;
135 /* Shift the quotient left by that amount */
136 *QuotientHigh
<<= Bits
;
137 *QuotientHigh
|= *QuotientLow
>> (64 - Bits
);
138 *QuotientLow
<<= Bits
;
141 /* Return the remainder */
145 static inline VOID FASTCALL
146 Fast486FpuFromInteger(PFAST486_STATE State
,
148 PFAST486_FPU_DATA_REG Result
)
152 Result
->Sign
= Result
->Exponent
= Result
->Mantissa
= 0;
153 if (Value
== 0LL) return;
161 Result
->Mantissa
= (ULONGLONG
)Value
;
162 ZeroCount
= CountLeadingZeros64(Result
->Mantissa
);
164 Result
->Mantissa
<<= ZeroCount
;
165 Result
->Exponent
= FPU_REAL10_BIAS
+ 63 - ZeroCount
;
168 static inline BOOLEAN FASTCALL
169 Fast486FpuToInteger(PFAST486_STATE State
,
170 PFAST486_FPU_DATA_REG Value
,
175 SHORT UnbiasedExp
= (SHORT
)Value
->Exponent
- FPU_REAL10_BIAS
;
177 if (FPU_IS_ZERO(Value
))
183 if (FPU_IS_NAN(Value
) || !FPU_IS_NORMALIZED(Value
)
184 || (UnbiasedExp
< 0) || (UnbiasedExp
> 63))
186 /* Raise an invalid operation exception */
187 State
->FpuStatus
.Ie
= TRUE
;
189 if (State
->FpuControl
.Im
)
196 Fast486FpuException(State
);
201 Bits
= 63 - UnbiasedExp
;
203 /* Calculate the result and the remainder */
204 *Result
= (LONGLONG
)(Value
->Mantissa
>> Bits
);
205 Remainder
= Value
->Mantissa
& ((1 << Bits
) - 1);
207 /* The result must be positive here */
208 ASSERT(*Result
>= 0LL);
210 switch (State
->FpuControl
.Rc
)
212 case FPU_ROUND_NEAREST
:
214 /* Check if the highest bit of the remainder is set */
215 if (Remainder
& (1 << (Bits
- 1)))
219 /* Check if all the other bits are clear */
220 if (!(Remainder
& ((1 << (Bits
- 1)) - 1)))
232 if ((Remainder
!= 0ULL) && Value
->Sign
) (*Result
)++;
238 if ((Remainder
!= 0ULL) && !Value
->Sign
) (*Result
)++;
244 /* Leave it truncated */
248 if (Value
->Sign
) *Result
= -*Result
;
252 static inline VOID FASTCALL
253 Fast486FpuFromSingleReal(PFAST486_STATE State
,
255 PFAST486_FPU_DATA_REG Result
)
257 /* Extract the sign, exponent and mantissa */
258 Result
->Sign
= (UCHAR
)(Value
>> 31);
259 Result
->Exponent
= (USHORT
)((Value
>> 23) & 0xFF);
260 Result
->Mantissa
= (((ULONGLONG
)Value
& 0x7FFFFFULL
) | 0x800000ULL
) << 40;
262 /* If this is a zero, we're done */
263 if (Value
== 0) return;
265 if (Result
->Exponent
== 0xFF) Result
->Exponent
= FPU_MAX_EXPONENT
+ 1;
268 /* Adjust the exponent bias */
269 Result
->Exponent
+= (FPU_REAL10_BIAS
- FPU_REAL4_BIAS
);
273 static inline VOID FASTCALL
274 Fast486FpuFromDoubleReal(PFAST486_STATE State
,
276 PFAST486_FPU_DATA_REG Result
)
278 /* Extract the sign, exponent and mantissa */
279 Result
->Sign
= (UCHAR
)(Value
>> 63);
280 Result
->Exponent
= (USHORT
)((Value
>> 52) & 0x7FF);
281 Result
->Mantissa
= (((ULONGLONG
)Value
& 0xFFFFFFFFFFFFFULL
) | 0x10000000000000ULL
) << 11;
283 /* If this is a zero, we're done */
284 if (Value
== 0) return;
286 if (Result
->Exponent
== 0x3FF) Result
->Exponent
= FPU_MAX_EXPONENT
+ 1;
289 /* Adjust the exponent bias */
290 Result
->Exponent
+= (FPU_REAL10_BIAS
- FPU_REAL8_BIAS
);
294 static inline BOOLEAN FASTCALL
295 Fast486FpuToDoubleReal(PFAST486_STATE State
,
296 PFAST486_FPU_DATA_REG Value
,
300 SHORT UnbiasedExp
= (SHORT
)Value
->Exponent
- FPU_REAL10_BIAS
;
302 if (FPU_IS_ZERO(Value
))
308 /* Calculate the mantissa */
309 *Result
= (Value
->Mantissa
>> 11) & ((1ULL << 52) - 1);
311 if (FPU_IS_NAN(Value
))
313 *Result
|= 0x7FFULL
<< 52;
317 /* Check for underflow */
318 if (!FPU_IS_NORMALIZED(Value
) || (UnbiasedExp
< -1023))
320 /* Raise the underflow exception */
321 State
->FpuStatus
.Ue
= TRUE
;
323 if (State
->FpuControl
.Um
)
325 /* The result is zero due to underflow */
331 Fast486FpuException(State
);
336 /* Check for overflow */
337 if (UnbiasedExp
> 1023)
339 /* Raise the overflow exception */
340 State
->FpuStatus
.Oe
= TRUE
;
342 if (State
->FpuControl
.Om
)
344 /* The result is infinity due to overflow */
345 *Result
= FPU_REAL8_INFINITY
;
350 Fast486FpuException(State
);
355 /* Calculate the remainder */
356 Remainder
= Value
->Mantissa
& ((1 << 11) - 1);
358 switch (State
->FpuControl
.Rc
)
360 case FPU_ROUND_NEAREST
:
362 /* Check if the highest bit of the remainder is set */
363 if (Remainder
& (1 << 10))
367 /* Check if all the other bits are clear */
368 if (!(Remainder
& ((1 << 10) - 1)))
380 if ((Remainder
!= 0ULL) && Value
->Sign
) (*Result
)++;
386 if ((Remainder
!= 0ULL) && !Value
->Sign
) (*Result
)++;
392 /* Leave it truncated */
396 /* Store the biased exponent */
397 *Result
|= (ULONGLONG
)(UnbiasedExp
+ FPU_REAL8_BIAS
) << 52;
401 if (Value
->Sign
) *Result
|= 1ULL << 63;
405 static inline VOID FASTCALL
406 Fast486FpuFromPackedBcd(PFAST486_STATE State
,
408 PFAST486_FPU_DATA_REG Result
)
411 LONGLONG IntVal
= 0LL;
413 for (i
= 8; i
>= 0; i
--)
416 IntVal
+= (Value
[i
] >> 4) * 10 + (Value
[i
] & 0x0F);
420 if (Value
[9] & 0x80) IntVal
= -IntVal
;
422 /* Now convert the integer to FP80 */
423 Fast486FpuFromInteger(State
, IntVal
, Result
);
426 static inline BOOLEAN FASTCALL
427 Fast486FpuToPackedBcd(PFAST486_STATE State
,
428 PFAST486_FPU_DATA_REG Value
,
434 /* Convert it to an integer first */
435 if (!Fast486FpuToInteger(State
, Value
, &IntVal
)) return FALSE
;
443 for (i
= 0; i
< 9; i
++)
445 Result
[i
] = (UCHAR
)((IntVal
% 10) + (((IntVal
/ 10) % 10) << 4));
452 static inline VOID FASTCALL
453 Fast486FpuAdd(PFAST486_STATE State
,
454 PFAST486_FPU_DATA_REG FirstOperand
,
455 PFAST486_FPU_DATA_REG SecondOperand
,
456 PFAST486_FPU_DATA_REG Result
)
458 FAST486_FPU_DATA_REG FirstAdjusted
= *FirstOperand
;
459 FAST486_FPU_DATA_REG SecondAdjusted
= *SecondOperand
;
460 FAST486_FPU_DATA_REG TempResult
;
462 if ((!FPU_IS_NORMALIZED(FirstOperand
) || !FPU_IS_NORMALIZED(SecondOperand
)))
464 /* Raise the denormalized exception */
465 State
->FpuStatus
.De
= TRUE
;
467 if (!State
->FpuControl
.Dm
)
469 Fast486FpuException(State
);
474 /* Find the largest exponent */
475 TempResult
.Exponent
= max(FirstOperand
->Exponent
, SecondOperand
->Exponent
);
477 /* Adjust the first operand to it... */
478 if (FirstAdjusted
.Exponent
< TempResult
.Exponent
)
480 FirstAdjusted
.Mantissa
>>= (TempResult
.Exponent
- FirstAdjusted
.Exponent
);
481 FirstAdjusted
.Exponent
= TempResult
.Exponent
;
484 /* ... and the second one too */
485 if (SecondAdjusted
.Exponent
< TempResult
.Exponent
)
487 SecondAdjusted
.Mantissa
>>= (TempResult
.Exponent
- SecondAdjusted
.Exponent
);
488 SecondAdjusted
.Exponent
= TempResult
.Exponent
;
491 if (FirstAdjusted
.Sign
== SecondAdjusted
.Sign
)
493 /* Calculate the mantissa and sign of the result */
494 TempResult
.Mantissa
= FirstAdjusted
.Mantissa
+ SecondAdjusted
.Mantissa
;
495 TempResult
.Sign
= FirstAdjusted
.Sign
;
499 /* Calculate the sign of the result */
500 if (FirstAdjusted
.Mantissa
> SecondAdjusted
.Mantissa
) TempResult
.Sign
= FirstAdjusted
.Sign
;
501 else if (FirstAdjusted
.Mantissa
< SecondAdjusted
.Mantissa
) TempResult
.Sign
= SecondAdjusted
.Sign
;
502 else TempResult
.Sign
= FALSE
;
504 /* Invert the negative mantissa */
505 if (FirstAdjusted
.Sign
) FirstAdjusted
.Mantissa
= -FirstAdjusted
.Mantissa
;
506 if (SecondAdjusted
.Sign
) SecondAdjusted
.Mantissa
= -SecondAdjusted
.Mantissa
;
508 /* Calculate the mantissa of the result */
509 TempResult
.Mantissa
= FirstAdjusted
.Mantissa
+ SecondAdjusted
.Mantissa
;
512 /* Did it overflow? */
513 if (FPU_IS_NORMALIZED(&FirstAdjusted
) && FPU_IS_NORMALIZED(&SecondAdjusted
))
515 if (TempResult
.Exponent
== FPU_MAX_EXPONENT
)
517 /* Raise the overflow exception */
518 State
->FpuStatus
.Oe
= TRUE
;
520 if (State
->FpuControl
.Om
)
522 /* Total overflow, return infinity */
523 TempResult
.Mantissa
= FPU_MANTISSA_HIGH_BIT
;
524 TempResult
.Exponent
= FPU_MAX_EXPONENT
+ 1;
528 Fast486FpuException(State
);
534 /* Lose the LSB in favor of the carry */
535 TempResult
.Mantissa
>>= 1;
536 TempResult
.Mantissa
|= FPU_MANTISSA_HIGH_BIT
;
537 TempResult
.Exponent
++;
541 /* Normalize the result and return it */
542 Fast486FpuNormalize(State
, &TempResult
);
543 *Result
= TempResult
;
546 static inline VOID FASTCALL
547 Fast486FpuSubtract(PFAST486_STATE State
,
548 PFAST486_FPU_DATA_REG FirstOperand
,
549 PFAST486_FPU_DATA_REG SecondOperand
,
550 PFAST486_FPU_DATA_REG Result
)
552 FAST486_FPU_DATA_REG NegativeSecondOperand
= *SecondOperand
;
554 /* Invert the sign */
555 NegativeSecondOperand
.Sign
= !NegativeSecondOperand
.Sign
;
557 /* And perform an addition instead */
558 Fast486FpuAdd(State
, FirstOperand
, &NegativeSecondOperand
, Result
);
561 static inline VOID FASTCALL
562 Fast486FpuCompare(PFAST486_STATE State
,
563 PFAST486_FPU_DATA_REG FirstOperand
,
564 PFAST486_FPU_DATA_REG SecondOperand
)
566 if (FPU_IS_NAN(FirstOperand
) || FPU_IS_NAN(SecondOperand
))
568 if (FPU_IS_POS_INF(FirstOperand
) && FPU_IS_NEG_INF(SecondOperand
))
570 State
->FpuStatus
.Code0
= FALSE
;
571 State
->FpuStatus
.Code2
= FALSE
;
572 State
->FpuStatus
.Code3
= FALSE
;
574 else if (FPU_IS_NEG_INF(FirstOperand
) && FPU_IS_POS_INF(SecondOperand
))
576 State
->FpuStatus
.Code0
= TRUE
;
577 State
->FpuStatus
.Code2
= FALSE
;
578 State
->FpuStatus
.Code3
= FALSE
;
582 State
->FpuStatus
.Code0
= TRUE
;
583 State
->FpuStatus
.Code2
= TRUE
;
584 State
->FpuStatus
.Code3
= TRUE
;
589 FAST486_FPU_DATA_REG TempResult
;
591 Fast486FpuSubtract(State
, FirstOperand
, SecondOperand
, &TempResult
);
593 if (FPU_IS_ZERO(&TempResult
))
595 State
->FpuStatus
.Code0
= FALSE
;
596 State
->FpuStatus
.Code2
= FALSE
;
597 State
->FpuStatus
.Code3
= TRUE
;
599 else if (TempResult
.Sign
)
601 State
->FpuStatus
.Code0
= TRUE
;
602 State
->FpuStatus
.Code2
= FALSE
;
603 State
->FpuStatus
.Code3
= FALSE
;
607 State
->FpuStatus
.Code0
= FALSE
;
608 State
->FpuStatus
.Code2
= FALSE
;
609 State
->FpuStatus
.Code3
= FALSE
;
614 static inline VOID FASTCALL
615 Fast486FpuMultiply(PFAST486_STATE State
,
616 PFAST486_FPU_DATA_REG FirstOperand
,
617 PFAST486_FPU_DATA_REG SecondOperand
,
618 PFAST486_FPU_DATA_REG Result
)
620 FAST486_FPU_DATA_REG TempResult
;
622 if ((!FPU_IS_NORMALIZED(FirstOperand
) || !FPU_IS_NORMALIZED(SecondOperand
)))
624 /* Raise the denormalized exception */
625 State
->FpuStatus
.De
= TRUE
;
627 if (!State
->FpuControl
.Dm
)
629 Fast486FpuException(State
);
634 UnsignedMult128(FirstOperand
->Mantissa
,
635 SecondOperand
->Mantissa
,
636 &TempResult
.Mantissa
);
638 TempResult
.Exponent
= FirstOperand
->Exponent
+ SecondOperand
->Exponent
;
639 TempResult
.Sign
= FirstOperand
->Sign
^ SecondOperand
->Sign
;
641 /* Normalize the result */
642 Fast486FpuNormalize(State
, &TempResult
);
643 *Result
= TempResult
;
646 static inline VOID FASTCALL
647 Fast486FpuDivide(PFAST486_STATE State
,
648 PFAST486_FPU_DATA_REG FirstOperand
,
649 PFAST486_FPU_DATA_REG SecondOperand
,
650 PFAST486_FPU_DATA_REG Result
)
652 FAST486_FPU_DATA_REG TempResult
;
653 ULONGLONG QuotientLow
, QuotientHigh
, Remainder
;
656 if (FPU_IS_INDEFINITE(FirstOperand
)
657 || FPU_IS_INDEFINITE(SecondOperand
)
658 || (FPU_IS_INFINITY(FirstOperand
) && FPU_IS_INFINITY(SecondOperand
))
659 || (FPU_IS_ZERO(FirstOperand
) && FPU_IS_ZERO(SecondOperand
)))
661 /* Raise the invalid operation exception */
662 State
->FpuStatus
.Ie
= TRUE
;
664 if (State
->FpuControl
.Im
)
666 /* Return the indefinite NaN */
668 Result
->Exponent
= FPU_MAX_EXPONENT
+ 1;
669 Result
->Mantissa
= FPU_INDEFINITE_MANTISSA
;
671 else Fast486FpuException(State
);
676 if (FPU_IS_ZERO(SecondOperand
) || FPU_IS_INFINITY(FirstOperand
))
678 /* Raise the division by zero exception */
679 State
->FpuStatus
.Ze
= TRUE
;
681 if (State
->FpuControl
.Zm
)
683 /* Return infinity */
684 Result
->Sign
= FirstOperand
->Sign
;
685 Result
->Exponent
= FPU_MAX_EXPONENT
+ 1;
686 Result
->Mantissa
= FPU_MANTISSA_HIGH_BIT
;
688 else Fast486FpuException(State
);
693 /* Calculate the sign of the result */
694 TempResult
.Sign
= FirstOperand
->Sign
^ SecondOperand
->Sign
;
696 if (FPU_IS_ZERO(FirstOperand
) || FPU_IS_INFINITY(SecondOperand
))
699 Result
->Sign
= TempResult
.Sign
;
700 Result
->Mantissa
= 0ULL;
701 Result
->Exponent
= 0;
705 /* Calculate the exponent of the result */
706 Exponent
= (LONG
)FirstOperand
->Exponent
- (LONG
)SecondOperand
->Exponent
- 64;
708 /* Divide the two mantissas */
709 Remainder
= UnsignedDivMod128(0ULL,
710 /* Notice the 64 above - this is the high part */
711 FirstOperand
->Mantissa
,
712 SecondOperand
->Mantissa
,
715 UNREFERENCED_PARAMETER(Remainder
); // TODO: Rounding
717 TempResult
.Mantissa
= QuotientLow
;
719 if (QuotientHigh
> 0ULL)
721 ULONG BitsToShift
= 64 - CountLeadingZeros64(QuotientHigh
);
723 TempResult
.Mantissa
>>= BitsToShift
;
724 TempResult
.Mantissa
|= QuotientHigh
<< (64 - BitsToShift
);
725 Exponent
+= BitsToShift
;
730 if (Exponent
< -FPU_REAL10_BIAS
)
732 TempResult
.Mantissa
>>= -(Exponent
+ FPU_REAL10_BIAS
);
733 Exponent
= -FPU_REAL10_BIAS
;
738 TempResult
.Exponent
= (USHORT
)(Exponent
+ FPU_REAL10_BIAS
);
740 /* Normalize the result */
741 Fast486FpuNormalize(State
, &TempResult
);
742 *Result
= TempResult
;
745 static inline VOID FASTCALL
746 Fast486FpuArithmeticOperation(PFAST486_STATE State
,
748 PFAST486_FPU_DATA_REG SourceOperand
,
749 PFAST486_FPU_DATA_REG DestOperand
)
751 ASSERT(!(Operation
& ~7));
753 /* Check the operation */
759 Fast486FpuAdd(State
, DestOperand
, SourceOperand
, DestOperand
);
766 Fast486FpuMultiply(State
, DestOperand
, SourceOperand
, DestOperand
);
775 Fast486FpuCompare(State
, DestOperand
, SourceOperand
);
776 if (Operation
== 3) Fast486FpuPop(State
);
784 Fast486FpuSubtract(State
, DestOperand
, SourceOperand
, DestOperand
);
791 Fast486FpuSubtract(State
, SourceOperand
, DestOperand
, DestOperand
);
798 Fast486FpuDivide(State
, DestOperand
, SourceOperand
, DestOperand
);
805 Fast486FpuDivide(State
, SourceOperand
, DestOperand
, DestOperand
);
813 /* PUBLIC FUNCTIONS ***********************************************************/
815 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD8
)
817 FAST486_MOD_REG_RM ModRegRm
;
818 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
819 PFAST486_FPU_DATA_REG SourceOperand
, DestOperand
;
820 FAST486_FPU_DATA_REG MemoryData
;
822 /* Get the operands */
823 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
825 /* Exception occurred */
831 #ifndef FAST486_NO_FPU
833 /* The destination operand is ST0 */
834 DestOperand
= &FPU_ST(0);
836 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
838 /* Raise the invalid operation exception */
839 State
->FpuStatus
.Ie
= TRUE
;
841 if (State
->FpuControl
.Im
)
843 /* Return the indefinite NaN */
844 DestOperand
->Sign
= TRUE
;
845 DestOperand
->Exponent
= FPU_MAX_EXPONENT
+ 1;
846 DestOperand
->Mantissa
= FPU_INDEFINITE_MANTISSA
;
848 FPU_SET_TAG(0, FPU_TAG_SPECIAL
);
850 else Fast486FpuException(State
);
857 /* Load the source operand from memory */
860 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
862 /* Exception occurred */
866 Fast486FpuFromSingleReal(State
, Value
, &MemoryData
);
867 SourceOperand
= &MemoryData
;
871 if (FPU_GET_TAG(ModRegRm
.SecondRegister
) == FPU_TAG_EMPTY
)
873 /* Raise the invalid operation exception */
874 State
->FpuStatus
.Ie
= TRUE
;
876 if (State
->FpuControl
.Im
)
878 /* Return the indefinite NaN */
879 DestOperand
->Sign
= TRUE
;
880 DestOperand
->Exponent
= FPU_MAX_EXPONENT
+ 1;
881 DestOperand
->Mantissa
= FPU_INDEFINITE_MANTISSA
;
883 FPU_SET_TAG(0, FPU_TAG_SPECIAL
);
885 else Fast486FpuException(State
);
890 /* Load the source operand from an FPU register */
891 SourceOperand
= &FPU_ST(ModRegRm
.SecondRegister
);
894 /* Perform the requested operation */
895 Fast486FpuArithmeticOperation(State
, ModRegRm
.Register
, SourceOperand
, DestOperand
);
900 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDC
)
902 FAST486_MOD_REG_RM ModRegRm
;
903 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
904 PFAST486_FPU_DATA_REG SourceOperand
, DestOperand
;
905 FAST486_FPU_DATA_REG MemoryData
;
907 /* Get the operands */
908 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
910 /* Exception occurred */
916 #ifndef FAST486_NO_FPU
922 /* The destination operand is ST0 */
923 DestOperand
= &FPU_ST(0);
925 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
927 /* Raise the invalid operation exception */
928 State
->FpuStatus
.Ie
= TRUE
;
930 if (State
->FpuControl
.Im
)
932 /* Return the indefinite NaN */
933 DestOperand
->Sign
= TRUE
;
934 DestOperand
->Exponent
= FPU_MAX_EXPONENT
+ 1;
935 DestOperand
->Mantissa
= FPU_INDEFINITE_MANTISSA
;
937 FPU_SET_TAG(0, FPU_TAG_SPECIAL
);
939 else Fast486FpuException(State
);
944 /* Load the source operand from memory */
945 if (!Fast486ReadMemory(State
,
946 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
947 ? State
->SegmentOverride
: FAST486_REG_DS
,
948 ModRegRm
.MemoryAddress
,
953 /* Exception occurred */
957 Fast486FpuFromDoubleReal(State
, Value
, &MemoryData
);
958 SourceOperand
= &MemoryData
;
962 /* The source operand is ST0 */
963 SourceOperand
= &FPU_ST(0);
965 /* Load the destination operand from an FPU register */
966 DestOperand
= &FPU_ST(ModRegRm
.SecondRegister
);
968 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
969 || (FPU_GET_TAG(ModRegRm
.SecondRegister
) == FPU_TAG_EMPTY
))
971 /* Raise the invalid operation exception */
972 State
->FpuStatus
.Ie
= TRUE
;
974 if (State
->FpuControl
.Im
)
976 /* Return the indefinite NaN */
977 DestOperand
->Sign
= TRUE
;
978 DestOperand
->Exponent
= FPU_MAX_EXPONENT
+ 1;
979 DestOperand
->Mantissa
= FPU_INDEFINITE_MANTISSA
;
981 FPU_SET_TAG(ModRegRm
.SecondRegister
, FPU_TAG_SPECIAL
);
983 else Fast486FpuException(State
);
989 /* Perform the requested operation */
990 Fast486FpuArithmeticOperation(State
, ModRegRm
.Register
, SourceOperand
, DestOperand
);
996 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeD9
)
998 FAST486_MOD_REG_RM ModRegRm
;
999 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1001 /* Get the operands */
1002 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1004 /* Exception occurred */
1010 #ifndef FAST486_NO_FPU
1012 if (ModRegRm
.Memory
)
1014 switch (ModRegRm
.Register
)
1020 FAST486_FPU_DATA_REG MemoryData
;
1022 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
1024 /* Exception occurred */
1028 Fast486FpuFromSingleReal(State
, Value
, &MemoryData
);
1029 Fast486FpuPush(State
, &MemoryData
);
1039 // TODO: NOT IMPLEMENTED
1048 // TODO: NOT IMPLEMENTED
1057 Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, &State
->FpuControl
.Value
);
1064 // TODO: NOT IMPLEMENTED
1073 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, State
->FpuControl
.Value
);
1080 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1087 // TODO: NOT IMPLEMENTED
1094 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDA
)
1096 FAST486_MOD_REG_RM ModRegRm
;
1097 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1098 PFAST486_FPU_DATA_REG SourceOperand
, DestOperand
;
1100 FAST486_FPU_DATA_REG MemoryData
;
1102 /* Get the operands */
1103 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1105 /* Exception occurred */
1111 #ifndef FAST486_NO_FPU
1113 if (!ModRegRm
.Memory
)
1115 /* The only valid opcode in this case is FUCOMPP (0xDA 0xE9) */
1116 if ((ModRegRm
.Register
!= 5) && (ModRegRm
.SecondRegister
!= 1))
1118 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1122 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY
) || (FPU_GET_TAG(1) == FPU_TAG_EMPTY
))
1124 /* Raise the invalid operation exception*/
1125 State
->FpuStatus
.Ie
= TRUE
;
1127 if (!State
->FpuControl
.Im
) Fast486FpuException(State
);
1132 Fast486FpuCompare(State
, &FPU_ST(0), &FPU_ST(1));
1135 Fast486FpuPop(State
);
1136 Fast486FpuPop(State
);
1141 /* Load the source operand from memory */
1142 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, (PULONG
)&Value
))
1144 /* Exception occurred */
1148 /* The destination operand is always ST0 */
1149 DestOperand
= &FPU_ST(0);
1151 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
1153 /* Raise the invalid operation exception */
1154 State
->FpuStatus
.Ie
= TRUE
;
1156 if (State
->FpuControl
.Im
)
1158 /* Return the indefinite NaN */
1159 DestOperand
->Sign
= TRUE
;
1160 DestOperand
->Exponent
= FPU_MAX_EXPONENT
+ 1;
1161 DestOperand
->Mantissa
= FPU_INDEFINITE_MANTISSA
;
1163 FPU_SET_TAG(0, FPU_TAG_SPECIAL
);
1165 else Fast486FpuException(State
);
1170 Fast486FpuFromInteger(State
, (LONGLONG
)Value
, &MemoryData
);
1171 SourceOperand
= &MemoryData
;
1173 /* Perform the requested operation */
1174 Fast486FpuArithmeticOperation(State
, ModRegRm
.Register
, SourceOperand
, DestOperand
);
1179 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDB
)
1181 FAST486_MOD_REG_RM ModRegRm
;
1182 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1184 /* Get the operands */
1185 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1187 /* Exception occurred */
1193 #ifndef FAST486_NO_FPU
1195 if (ModRegRm
.Memory
)
1197 switch (ModRegRm
.Register
)
1203 FAST486_FPU_DATA_REG Temp
;
1205 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, (PULONG
)&Value
))
1207 /* Exception occurred */
1211 Fast486FpuFromInteger(State
, (LONGLONG
)Value
, &Temp
);
1212 Fast486FpuPush(State
, &Temp
);
1224 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY
) || (FPU_GET_TAG(0) == FPU_TAG_SPECIAL
))
1226 /* Raise the invalid operation exception */
1227 State
->FpuStatus
.Ie
= TRUE
;
1229 if (!State
->FpuControl
.Im
)
1231 Fast486FpuException(State
);
1235 else if (!Fast486FpuToInteger(State
, &FPU_ST(0), &Temp
))
1237 /* Exception occurred */
1241 /* Check if it can fit in a signed 32-bit integer */
1242 if ((((ULONGLONG
)Temp
>> 31) + 1ULL) > 1ULL)
1244 State
->FpuStatus
.Ie
= TRUE
;
1246 if (State
->FpuControl
.Im
) Temp
= 0LL;
1249 Fast486FpuException(State
);
1254 if (!Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, (ULONG
)((LONG
)Temp
)))
1256 /* Exception occurred */
1260 if (ModRegRm
.Register
== 3)
1262 /* Pop the FPU stack too */
1263 Fast486FpuPop(State
);
1272 FAST486_FPU_DATA_REG Value
;
1275 if (!Fast486ReadMemory(State
,
1276 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
1277 ? State
->SegmentOverride
: FAST486_REG_DS
,
1278 ModRegRm
.MemoryAddress
,
1283 /* Exception occurred */
1287 Value
.Mantissa
= *((PULONGLONG
)Buffer
);
1288 Value
.Exponent
= *((PUSHORT
)&Buffer
[8]) & (FPU_MAX_EXPONENT
+ 1);
1289 Value
.Sign
= *((PUCHAR
)&Buffer
[9]) >> 7;
1291 Fast486FpuPush(State
, &Value
);
1300 if (FPU_GET_TAG(0) != FPU_TAG_EMPTY
)
1302 *((PULONGLONG
)Buffer
) = FPU_ST(0).Mantissa
;
1303 *((PUSHORT
)&Buffer
[sizeof(ULONGLONG
)]) = FPU_ST(0).Exponent
1304 | (FPU_ST(0).Sign
? 0x8000 : 0);
1308 /* Raise the invalid operation exception */
1309 State
->FpuStatus
.Ie
= TRUE
;
1311 if (State
->FpuControl
.Im
)
1313 *((PULONGLONG
)Buffer
) = FPU_INDEFINITE_MANTISSA
;
1314 *((PUSHORT
)&Buffer
[sizeof(ULONGLONG
)]) = 0x8000 | (FPU_MAX_EXPONENT
+ 1);
1318 Fast486FpuException(State
);
1323 if (!Fast486WriteMemory(State
,
1324 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
1325 ? State
->SegmentOverride
: FAST486_REG_DS
,
1326 ModRegRm
.MemoryAddress
,
1330 /* Exception occurred */
1334 Fast486FpuPop(State
);
1341 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1348 /* Only a few of these instructions have any meaning on a 487 */
1349 switch ((ModRegRm
.Register
<< 3) | ModRegRm
.SecondRegister
)
1354 /* Clear exception data */
1355 State
->FpuStatus
.Ie
=
1356 State
->FpuStatus
.De
=
1357 State
->FpuStatus
.Ze
=
1358 State
->FpuStatus
.Oe
=
1359 State
->FpuStatus
.Ue
=
1360 State
->FpuStatus
.Pe
=
1361 State
->FpuStatus
.Sf
=
1362 State
->FpuStatus
.Es
=
1363 State
->FpuStatus
.Busy
= FALSE
;
1371 /* Restore the state */
1372 State
->FpuControl
.Value
= FAST486_FPU_DEFAULT_CONTROL
;
1373 State
->FpuStatus
.Value
= 0;
1374 State
->FpuTag
= 0xFFFF;
1384 /* These do nothing */
1391 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1400 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDD
)
1402 FAST486_MOD_REG_RM ModRegRm
;
1403 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1405 /* Get the operands */
1406 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1408 /* Exception occurred */
1414 #ifndef FAST486_NO_FPU
1416 if (ModRegRm
.Memory
)
1418 switch (ModRegRm
.Register
)
1424 FAST486_FPU_DATA_REG MemoryData
;
1426 if (!Fast486ReadMemory(State
,
1427 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
1428 ? State
->SegmentOverride
: FAST486_REG_DS
,
1429 ModRegRm
.MemoryAddress
,
1434 /* Exception occurred */
1438 Fast486FpuFromDoubleReal(State
, Value
, &MemoryData
);
1439 Fast486FpuPush(State
, &MemoryData
);
1449 ULONGLONG Value
= FPU_REAL8_INDEFINITE
;
1451 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
1453 /* Raise the invalid operation exception */
1454 State
->FpuStatus
.Ie
= TRUE
;
1456 if (!State
->FpuControl
.Im
)
1458 Fast486FpuException(State
);
1462 else if (!Fast486FpuToDoubleReal(State
, &FPU_ST(0), &Value
))
1464 /* Exception occurred */
1468 if (!Fast486WriteMemory(State
,
1469 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
1470 ? State
->SegmentOverride
: FAST486_REG_DS
,
1471 ModRegRm
.MemoryAddress
,
1475 /* Exception occurred */
1479 if (ModRegRm
.Register
== 3) Fast486FpuPop(State
);
1486 // TODO: NOT IMPLEMENTED
1495 // TODO: NOT IMPLEMENTED
1504 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, State
->FpuStatus
.Value
);
1511 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1517 switch (ModRegRm
.Register
)
1522 FPU_SET_TAG(ModRegRm
.SecondRegister
, FPU_TAG_EMPTY
);
1529 FAST486_FPU_DATA_REG Temp
;
1531 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
1532 || FPU_GET_TAG(ModRegRm
.SecondRegister
) == FPU_TAG_EMPTY
)
1534 State
->FpuStatus
.Ie
= TRUE
;
1536 if (!State
->FpuControl
.Im
) Fast486FpuException(State
);
1542 FPU_ST(0) = FPU_ST(ModRegRm
.SecondRegister
);
1543 FPU_ST(ModRegRm
.SecondRegister
) = Temp
;
1546 FPU_UPDATE_TAG(ModRegRm
.SecondRegister
);
1556 FPU_ST(ModRegRm
.SecondRegister
) = FPU_ST(0);
1557 FPU_UPDATE_TAG(ModRegRm
.SecondRegister
);
1559 if (ModRegRm
.Register
== 3) Fast486FpuPop(State
);
1568 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
1569 || (FPU_GET_TAG(ModRegRm
.SecondRegister
) == FPU_TAG_EMPTY
))
1571 State
->FpuStatus
.Ie
= TRUE
;
1573 if (!State
->FpuControl
.Im
) Fast486FpuException(State
);
1577 Fast486FpuCompare(State
, &FPU_ST(0), &FPU_ST(ModRegRm
.SecondRegister
));
1578 if (ModRegRm
.Register
== 5) Fast486FpuPop(State
);
1586 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1594 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDE
)
1596 FAST486_MOD_REG_RM ModRegRm
;
1597 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1598 PFAST486_FPU_DATA_REG SourceOperand
, DestOperand
;
1600 /* Get the operands */
1601 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1603 /* Exception occurred */
1609 #ifndef FAST486_NO_FPU
1611 if (ModRegRm
.Memory
)
1614 FAST486_FPU_DATA_REG MemoryData
;
1616 /* The destination operand is ST0 */
1617 DestOperand
= &FPU_ST(0);
1619 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
1621 /* Raise the invalid operation exception */
1622 State
->FpuStatus
.Ie
= TRUE
;
1624 if (State
->FpuControl
.Im
)
1626 /* Return the indefinite NaN */
1627 DestOperand
->Sign
= TRUE
;
1628 DestOperand
->Exponent
= FPU_MAX_EXPONENT
+ 1;
1629 DestOperand
->Mantissa
= FPU_INDEFINITE_MANTISSA
;
1631 FPU_SET_TAG(0, FPU_TAG_SPECIAL
);
1633 else Fast486FpuException(State
);
1638 /* Load the source operand from memory */
1639 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, (PUSHORT
)&Value
))
1641 /* Exception occurred */
1645 Fast486FpuFromInteger(State
, (LONGLONG
)Value
, &MemoryData
);
1646 SourceOperand
= &MemoryData
;
1651 if ((ModRegRm
.Register
== 3) && (ModRegRm
.SecondRegister
!= 1))
1654 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1658 /* The source operand is ST0 */
1659 SourceOperand
= &FPU_ST(0);
1661 /* Load the destination operand from a register */
1662 DestOperand
= &FPU_ST(ModRegRm
.SecondRegister
);
1664 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
1665 || (FPU_GET_TAG(ModRegRm
.SecondRegister
) == FPU_TAG_EMPTY
))
1667 /* Raise the invalid operation exception, if unmasked */
1668 State
->FpuStatus
.Ie
= TRUE
;
1670 if (!State
->FpuControl
.Im
) Fast486FpuException(State
);
1675 /* Perform the requested operation */
1676 Fast486FpuArithmeticOperation(State
, ModRegRm
.Register
, SourceOperand
, DestOperand
);
1677 if (!ModRegRm
.Memory
) Fast486FpuPop(State
);
1682 FAST486_OPCODE_HANDLER(Fast486FpuOpcodeDF
)
1684 FAST486_MOD_REG_RM ModRegRm
;
1685 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1687 /* Get the operands */
1688 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1690 /* Exception occurred */
1696 #ifndef FAST486_NO_FPU
1698 if (ModRegRm
.Memory
)
1700 switch (ModRegRm
.Register
)
1706 FAST486_FPU_DATA_REG Temp
;
1708 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, (PUSHORT
)&Value
))
1710 /* Exception occurred */
1714 Fast486FpuFromInteger(State
, (LONGLONG
)Value
, &Temp
);
1715 Fast486FpuPush(State
, &Temp
);
1725 LONGLONG Temp
= 0LL;
1727 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY
) || (FPU_GET_TAG(0) == FPU_TAG_SPECIAL
))
1729 /* Raise the invalid operation exception */
1730 State
->FpuStatus
.Ie
= TRUE
;
1732 if (!State
->FpuControl
.Im
)
1734 Fast486FpuException(State
);
1738 else if (!Fast486FpuToInteger(State
, &FPU_ST(0), &Temp
))
1740 /* Exception occurred */
1744 /* Check if it can fit in a signed 16-bit integer */
1745 if ((((ULONGLONG
)Temp
>> 15) + 1ULL) > 1ULL)
1747 /* Raise the invalid operation exception */
1748 State
->FpuStatus
.Ie
= TRUE
;
1750 if (State
->FpuControl
.Im
) Temp
= 0LL;
1753 Fast486FpuException(State
);
1758 if (!Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, (USHORT
)((SHORT
)Temp
)))
1760 /* Exception occurred */
1764 if (ModRegRm
.Register
== 3)
1766 /* Pop the FPU stack too */
1767 Fast486FpuPop(State
);
1776 FAST486_FPU_DATA_REG Value
;
1779 if (!Fast486ReadMemory(State
,
1780 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
1781 ? State
->SegmentOverride
: FAST486_REG_DS
,
1782 ModRegRm
.MemoryAddress
,
1787 /* Exception occurred */
1791 Fast486FpuFromPackedBcd(State
, Buffer
, &Value
);
1792 Fast486FpuPush(State
, &Value
);
1797 /* FILD (64-bit int) */
1801 FAST486_FPU_DATA_REG Temp
;
1803 if (!Fast486ReadMemory(State
,
1804 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
1805 ? State
->SegmentOverride
: FAST486_REG_DS
,
1806 ModRegRm
.MemoryAddress
,
1811 /* Exception occurred */
1815 Fast486FpuFromInteger(State
, (LONGLONG
)Value
, &Temp
);
1816 Fast486FpuPush(State
, &Temp
);
1824 UCHAR Buffer
[10] = {0};
1826 if (FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
1828 /* Raise the invalid operation exception */
1829 State
->FpuStatus
.Ie
= TRUE
;
1831 if (!State
->FpuControl
.Im
)
1833 Fast486FpuException(State
);
1837 else if (!Fast486FpuToPackedBcd(State
, &FPU_ST(0), Buffer
))
1839 /* Exception occurred */
1843 if (!Fast486WriteMemory(State
,
1844 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
1845 ? State
->SegmentOverride
: FAST486_REG_DS
,
1846 ModRegRm
.MemoryAddress
,
1850 /* Exception occurred */
1854 Fast486FpuPop(State
);
1858 /* FISTP (64-bit int) */
1861 LONGLONG Temp
= 0LL;
1863 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY
) || (FPU_GET_TAG(0) == FPU_TAG_SPECIAL
))
1865 /* Raise the invalid operation exception */
1866 State
->FpuStatus
.Ie
= TRUE
;
1868 if (!State
->FpuControl
.Im
)
1870 Fast486FpuException(State
);
1874 else if (!Fast486FpuToInteger(State
, &FPU_ST(0), &Temp
))
1876 /* Exception occurred */
1880 if (!Fast486WriteMemory(State
,
1881 (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
1882 ? State
->SegmentOverride
: FAST486_REG_DS
,
1883 ModRegRm
.MemoryAddress
,
1887 /* Exception occurred */
1891 /* Pop the FPU stack too */
1892 Fast486FpuPop(State
);
1900 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1906 switch (ModRegRm
.Register
)
1911 FPU_SET_TAG(ModRegRm
.SecondRegister
, FPU_TAG_EMPTY
);
1912 Fast486FpuPop(State
);
1920 FAST486_FPU_DATA_REG Temp
;
1922 if ((FPU_GET_TAG(0) == FPU_TAG_EMPTY
)
1923 || FPU_GET_TAG(ModRegRm
.SecondRegister
) == FPU_TAG_EMPTY
)
1925 State
->FpuStatus
.Ie
= TRUE
;
1927 if (!State
->FpuControl
.Im
) Fast486FpuException(State
);
1933 FPU_ST(0) = FPU_ST(ModRegRm
.SecondRegister
);
1934 FPU_ST(ModRegRm
.SecondRegister
) = Temp
;
1937 FPU_UPDATE_TAG(ModRegRm
.SecondRegister
);
1946 FPU_ST(ModRegRm
.SecondRegister
) = FPU_ST(0);
1947 FPU_UPDATE_TAG(ModRegRm
.SecondRegister
);
1948 Fast486FpuPop(State
);
1956 if (ModRegRm
.SecondRegister
!= 0)
1959 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1963 /* Store the status word in AX */
1964 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= State
->FpuStatus
.Value
;
1972 Fast486Exception(State
, FAST486_EXCEPTION_UD
);