2 * Fast486 386/486 CPU Emulation Library
5 * Copyright (C) 2015 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 **********************************************************/
38 Fast486ArithmeticOperation(PFAST486_STATE State
,
45 ULONG SignFlag
= 1 << (Bits
- 1);
46 ULONG MaxValue
= (SignFlag
- 1) | SignFlag
;
48 /* Make sure the values don't exceed the maximum for their size */
49 FirstValue
&= MaxValue
;
50 SecondValue
&= MaxValue
;
52 /* Check which operation is this */
58 Result
= (FirstValue
+ SecondValue
) & MaxValue
;
60 /* Update CF, OF and AF */
61 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
62 State
->Flags
.Of
= ((FirstValue
& SignFlag
) == (SecondValue
& SignFlag
))
63 && ((FirstValue
& SignFlag
) != (Result
& SignFlag
));
64 State
->Flags
.Af
= ((((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) != 0);
72 Result
= FirstValue
| SecondValue
;
73 State
->Flags
.Cf
= State
->Flags
.Of
= FALSE
;
80 INT Carry
= State
->Flags
.Cf
? 1 : 0;
82 Result
= (FirstValue
+ SecondValue
+ Carry
) & MaxValue
;
84 /* Update CF, OF and AF */
85 State
->Flags
.Cf
= ((SecondValue
== MaxValue
) && (Carry
== 1))
86 || ((Result
< FirstValue
) && (Result
< (SecondValue
+ Carry
)));
87 State
->Flags
.Of
= ((FirstValue
& SignFlag
) == (SecondValue
& SignFlag
))
88 && ((FirstValue
& SignFlag
) != (Result
& SignFlag
));
89 State
->Flags
.Af
= ((FirstValue
^ SecondValue
^ Result
) & 0x10) != 0;
97 INT Carry
= State
->Flags
.Cf
? 1 : 0;
99 Result
= (FirstValue
- SecondValue
- Carry
) & MaxValue
;
101 /* Update CF, OF and AF */
102 State
->Flags
.Cf
= Carry
103 ? (FirstValue
<= SecondValue
)
104 : (FirstValue
< SecondValue
);
105 State
->Flags
.Of
= ((FirstValue
& SignFlag
) != (SecondValue
& SignFlag
))
106 && ((FirstValue
& SignFlag
) != (Result
& SignFlag
));
107 State
->Flags
.Af
= ((FirstValue
^ SecondValue
^ Result
) & 0x10) != 0;
115 Result
= FirstValue
& SecondValue
;
116 State
->Flags
.Cf
= State
->Flags
.Of
= FALSE
;
124 Result
= (FirstValue
- SecondValue
) & MaxValue
;
126 /* Update CF, OF and AF */
127 State
->Flags
.Cf
= (FirstValue
< SecondValue
);
128 State
->Flags
.Of
= ((FirstValue
& SignFlag
) != (SecondValue
& SignFlag
))
129 && ((FirstValue
& SignFlag
) != (Result
& SignFlag
));
130 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
138 Result
= FirstValue
^ SecondValue
;
139 State
->Flags
.Cf
= State
->Flags
.Of
= FALSE
;
145 /* Shouldn't happen */
150 /* Update ZF, SF and PF */
151 State
->Flags
.Zf
= (Result
== 0);
152 State
->Flags
.Sf
= ((Result
& SignFlag
) != 0);
153 State
->Flags
.Pf
= Fast486CalculateParity(LOBYTE(Result
));
155 /* Return the result */
162 Fast486RotateOperation(PFAST486_STATE State
,
168 ULONG HighestBit
= 1 << (Bits
- 1);
169 ULONG MaxValue
= HighestBit
| (HighestBit
- 1);
172 /* Normalize the count */
175 if ((Operation
== 2) || (Operation
== 3)) Count
%= Bits
+ 1;
177 /* If the count is zero, do nothing */
178 if (Count
== 0) return Value
;
180 /* Check which operation is this */
187 Result
= (Value
<< Count
) | (Value
>> (Bits
- Count
));
189 /* Update CF and OF */
190 State
->Flags
.Cf
= Result
& 1;
191 if (Count
== 1) State
->Flags
.Of
= State
->Flags
.Cf
192 ^ ((Result
& HighestBit
) != 0);
201 Result
= (Value
>> Count
) | (Value
<< (Bits
- Count
));
203 /* Update CF and OF */
204 State
->Flags
.Cf
= ((Result
& HighestBit
) != 0);
205 if (Count
== 1) State
->Flags
.Of
= State
->Flags
.Cf
206 ^ ((Result
& (HighestBit
>> 1)) != 0);
214 Result
= (Value
<< Count
) | (State
->Flags
.Cf
<< (Count
- 1));
216 /* Complete the calculation, but make sure we don't shift by too much */
217 if ((Bits
- Count
) < 31) Result
|= Value
>> (Bits
- Count
+ 1);
219 /* Update CF and OF */
220 State
->Flags
.Cf
= ((Value
& (1 << (Bits
- Count
))) != 0);
221 if (Count
== 1) State
->Flags
.Of
= State
->Flags
.Cf
^ ((Result
& HighestBit
) != 0);
230 if (Count
== 1) State
->Flags
.Of
= State
->Flags
.Cf
^ ((Value
& HighestBit
) != 0);
232 Result
= (Value
>> Count
) | (State
->Flags
.Cf
<< (Bits
- Count
));
234 /* Complete the calculation, but make sure we don't shift by too much */
235 if ((Bits
- Count
) < 31) Result
|= Value
<< (Bits
- Count
+ 1);
238 State
->Flags
.Cf
= ((Value
& (1 << (Count
- 1))) != 0);
247 Result
= Value
<< Count
;
249 /* Update CF and OF */
250 State
->Flags
.Cf
= ((Value
& (1 << (Bits
- Count
))) != 0);
251 if (Count
== 1) State
->Flags
.Of
= State
->Flags
.Cf
252 ^ ((Result
& HighestBit
) != 0);
260 Result
= Value
>> Count
;
262 /* Update CF and OF */
263 State
->Flags
.Cf
= ((Value
& (1 << (Count
- 1))) != 0);
264 if (Count
== 1) State
->Flags
.Of
= ((Value
& HighestBit
) != 0);
272 Result
= Value
>> Count
;
274 /* Fill the top Count bits with the sign bit */
275 if (Value
& HighestBit
) Result
|= ((1 << Count
) - 1) << (Bits
- Count
);
277 /* Update CF and OF */
278 State
->Flags
.Cf
= ((Value
& (1 << (Count
- 1))) != 0);
279 if (Count
== 1) State
->Flags
.Of
= FALSE
;
287 /* Update ZF, SF and PF */
288 State
->Flags
.Zf
= ((Result
& MaxValue
) == 0);
289 State
->Flags
.Sf
= ((Result
& HighestBit
) != 0);
290 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
293 /* Return the result */
297 /* PUBLIC FUNCTIONS ***********************************************************/
299 FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8082
)
301 UCHAR Immediate
, Value
;
302 FAST486_MOD_REG_RM ModRegRm
;
303 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
305 TOGGLE_ADSIZE(AddressSize
);
307 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
309 /* Exception occurred */
313 /* Fetch the immediate operand */
314 if (!Fast486FetchByte(State
, &Immediate
))
316 /* Exception occurred */
320 /* Read the operands */
321 if (!Fast486ReadModrmByteOperands(State
, &ModRegRm
, NULL
, &Value
))
323 /* Exception occurred */
327 /* Calculate the result */
328 Value
= Fast486ArithmeticOperation(State
, ModRegRm
.Register
, Value
, Immediate
, 8);
330 /* Unless this is CMP, write back the result */
331 if (ModRegRm
.Register
!= 7)
333 Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Value
);
337 FAST486_OPCODE_HANDLER(Fast486OpcodeGroup81
)
339 FAST486_MOD_REG_RM ModRegRm
;
340 BOOLEAN OperandSize
, AddressSize
;
342 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
344 TOGGLE_OPSIZE(OperandSize
);
345 TOGGLE_ADSIZE(AddressSize
);
347 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
349 /* Exception occurred */
355 ULONG Immediate
, Value
;
357 /* Fetch the immediate operand */
358 if (!Fast486FetchDword(State
, &Immediate
))
360 /* Exception occurred */
364 /* Read the operands */
365 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
367 /* Exception occurred */
371 /* Calculate the result */
372 Value
= Fast486ArithmeticOperation(State
, ModRegRm
.Register
, Value
, Immediate
, 32);
374 /* Unless this is CMP, write back the result */
375 if (ModRegRm
.Register
!= 7)
377 Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
382 USHORT Immediate
, Value
;
384 /* Fetch the immediate operand */
385 if (!Fast486FetchWord(State
, &Immediate
))
387 /* Exception occurred */
391 /* Read the operands */
392 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, &Value
))
394 /* Exception occurred */
398 /* Calculate the result */
399 Value
= Fast486ArithmeticOperation(State
, ModRegRm
.Register
, Value
, Immediate
, 16);
401 /* Unless this is CMP, write back the result */
402 if (ModRegRm
.Register
!= 7)
404 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
);
409 FAST486_OPCODE_HANDLER(Fast486OpcodeGroup83
)
412 FAST486_MOD_REG_RM ModRegRm
;
413 BOOLEAN OperandSize
, AddressSize
;
415 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
417 TOGGLE_OPSIZE(OperandSize
);
418 TOGGLE_ADSIZE(AddressSize
);
420 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
422 /* Exception occurred */
426 /* Fetch the immediate operand */
427 if (!Fast486FetchByte(State
, (PUCHAR
)&ImmByte
))
429 /* Exception occurred */
435 ULONG Immediate
= (ULONG
)((LONG
)ImmByte
); // Sign extend
438 /* Read the operands */
439 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
441 /* Exception occurred */
445 /* Calculate the result */
446 Value
= Fast486ArithmeticOperation(State
, ModRegRm
.Register
, Value
, Immediate
, 32);
448 /* Unless this is CMP, write back the result */
449 if (ModRegRm
.Register
!= 7)
451 Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
456 USHORT Immediate
= (USHORT
)((SHORT
)ImmByte
); // Sign extend
459 /* Read the operands */
460 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, &Value
))
462 /* Exception occurred */
466 /* Calculate the result */
467 Value
= Fast486ArithmeticOperation(State
, ModRegRm
.Register
, Value
, Immediate
, 16);
469 /* Unless this is CMP, write back the result */
470 if (ModRegRm
.Register
!= 7)
472 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
);
477 FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8F
)
480 FAST486_MOD_REG_RM ModRegRm
;
481 BOOLEAN OperandSize
, AddressSize
;
483 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
485 TOGGLE_OPSIZE(OperandSize
);
486 TOGGLE_ADSIZE(AddressSize
);
488 /* Pop a value from the stack - this must be done first */
489 if (!Fast486StackPop(State
, &Value
))
491 /* Exception occurred */
495 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
497 /* Exception occurred */
501 if (ModRegRm
.Register
!= 0)
504 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
508 if (OperandSize
) Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
509 else Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, LOWORD(Value
));
512 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC0
)
515 FAST486_MOD_REG_RM ModRegRm
;
516 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
518 TOGGLE_ADSIZE(AddressSize
);
520 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
522 /* Exception occurred */
526 /* Fetch the count */
527 if (!Fast486FetchByte(State
, &Count
))
529 /* Exception occurred */
533 /* Read the operands */
534 if (!Fast486ReadModrmByteOperands(State
, &ModRegRm
, NULL
, &Value
))
536 /* Exception occurred */
540 /* Calculate the result */
541 Value
= LOBYTE(Fast486RotateOperation(State
,
547 /* Write back the result */
548 Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Value
);
551 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC1
)
554 FAST486_MOD_REG_RM ModRegRm
;
555 BOOLEAN OperandSize
, AddressSize
;
557 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
559 TOGGLE_OPSIZE(OperandSize
);
560 TOGGLE_ADSIZE(AddressSize
);
562 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
564 /* Exception occurred */
568 /* Fetch the count */
569 if (!Fast486FetchByte(State
, &Count
))
571 /* Exception occurred */
579 /* Read the operands */
580 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
582 /* Exception occurred */
586 /* Calculate the result */
587 Value
= Fast486RotateOperation(State
,
593 /* Write back the result */
594 Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
600 /* Read the operands */
601 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, &Value
))
603 /* Exception occurred */
607 /* Calculate the result */
608 Value
= LOWORD(Fast486RotateOperation(State
,
614 /* Write back the result */
615 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
);
619 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC6
)
622 FAST486_MOD_REG_RM ModRegRm
;
623 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
625 TOGGLE_ADSIZE(AddressSize
);
627 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
629 /* Exception occurred */
633 if (ModRegRm
.Register
!= 0)
636 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
640 /* Get the immediate operand */
641 if (!Fast486FetchByte(State
, &Immediate
))
643 /* Exception occurred */
647 Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Immediate
);
650 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC7
)
652 FAST486_MOD_REG_RM ModRegRm
;
653 BOOLEAN OperandSize
, AddressSize
;
655 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
657 TOGGLE_OPSIZE(OperandSize
);
658 TOGGLE_ADSIZE(AddressSize
);
660 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
662 /* Exception occurred */
666 if (ModRegRm
.Register
!= 0)
669 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
677 /* Get the immediate operand */
678 if (!Fast486FetchDword(State
, &Immediate
))
680 /* Exception occurred */
684 Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Immediate
);
690 /* Get the immediate operand */
691 if (!Fast486FetchWord(State
, &Immediate
))
693 /* Exception occurred */
697 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Immediate
);
701 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD0
)
704 FAST486_MOD_REG_RM ModRegRm
;
705 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
707 TOGGLE_ADSIZE(AddressSize
);
709 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
711 /* Exception occurred */
715 /* Read the operands */
716 if (!Fast486ReadModrmByteOperands(State
, &ModRegRm
, NULL
, &Value
))
718 /* Exception occurred */
722 /* Calculate the result */
723 Value
= LOBYTE(Fast486RotateOperation(State
, ModRegRm
.Register
, Value
, 8, 1));
725 /* Write back the result */
726 Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Value
);
730 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD1
)
732 FAST486_MOD_REG_RM ModRegRm
;
733 BOOLEAN OperandSize
, AddressSize
;
735 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
737 TOGGLE_OPSIZE(OperandSize
);
738 TOGGLE_ADSIZE(AddressSize
);
740 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
742 /* Exception occurred */
750 /* Read the operands */
751 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
753 /* Exception occurred */
757 /* Calculate the result */
758 Value
= Fast486RotateOperation(State
, ModRegRm
.Register
, Value
, 32, 1);
760 /* Write back the result */
761 Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
767 /* Read the operands */
768 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, &Value
))
770 /* Exception occurred */
774 /* Calculate the result */
775 Value
= LOWORD(Fast486RotateOperation(State
, ModRegRm
.Register
, Value
, 16, 1));
777 /* Write back the result */
778 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
);
782 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD2
)
785 FAST486_MOD_REG_RM ModRegRm
;
786 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
788 TOGGLE_ADSIZE(AddressSize
);
790 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
792 /* Exception occurred */
796 /* Read the operands */
797 if (!Fast486ReadModrmByteOperands(State
, &ModRegRm
, NULL
, &Value
))
799 /* Exception occurred */
803 /* Calculate the result */
804 Value
= LOBYTE(Fast486RotateOperation(State
,
808 State
->GeneralRegs
[FAST486_REG_ECX
].LowByte
));
810 /* Write back the result */
811 Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Value
);
814 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD3
)
816 FAST486_MOD_REG_RM ModRegRm
;
817 BOOLEAN OperandSize
, AddressSize
;
819 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
821 TOGGLE_OPSIZE(OperandSize
);
822 TOGGLE_ADSIZE(AddressSize
);
824 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
826 /* Exception occurred */
834 /* Read the operands */
835 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
837 /* Exception occurred */
841 /* Calculate the result */
842 Value
= Fast486RotateOperation(State
,
846 State
->GeneralRegs
[FAST486_REG_ECX
].LowByte
);
848 /* Write back the result */
849 Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
855 /* Read the operands */
856 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, &Value
))
858 /* Exception occurred */
862 /* Calculate the result */
863 Value
= LOWORD(Fast486RotateOperation(State
,
867 State
->GeneralRegs
[FAST486_REG_ECX
].LowByte
));
869 /* Write back the result */
870 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
);
874 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6
)
877 FAST486_MOD_REG_RM ModRegRm
;
878 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
880 TOGGLE_ADSIZE(AddressSize
);
882 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
884 /* Exception occurred */
888 /* Read the operands */
889 if (!Fast486ReadModrmByteOperands(State
, &ModRegRm
, NULL
, &Value
))
891 /* Exception occurred */
895 switch (ModRegRm
.Register
)
901 UCHAR Immediate
, Result
;
903 /* Fetch the immediate byte */
904 if (!Fast486FetchByte(State
, &Immediate
))
906 /* Exception occurred */
910 /* Calculate the result */
911 Result
= Value
& Immediate
;
913 /* Update the flags */
914 State
->Flags
.Cf
= FALSE
;
915 State
->Flags
.Of
= FALSE
;
916 State
->Flags
.Zf
= (Result
== 0);
917 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
918 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
926 /* Write back the result */
927 Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, ~Value
);
935 /* Calculate the result */
936 UCHAR Result
= -Value
;
938 /* Update the flags */
939 State
->Flags
.Cf
= (Value
!= 0);
940 State
->Flags
.Of
= (Value
& SIGN_FLAG_BYTE
) && (Result
& SIGN_FLAG_BYTE
);
941 State
->Flags
.Af
= ((Value
& 0x0F) != 0);
942 State
->Flags
.Zf
= (Result
== 0);
943 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
944 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
946 /* Write back the result */
947 Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Result
);
955 USHORT Result
= (USHORT
)Value
* (USHORT
)State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
957 /* Update the flags */
958 State
->Flags
.Cf
= State
->Flags
.Of
= (HIBYTE(Result
) != 0);
960 /* Write back the result */
961 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Result
;
969 SHORT Result
= (SHORT
)((CHAR
)Value
) * (SHORT
)((CHAR
)State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
);
971 /* Update the flags */
972 State
->Flags
.Cf
= State
->Flags
.Of
= ((Result
< FAST486_CHAR_MIN
) || (Result
> FAST486_CHAR_MAX
));
974 /* Write back the result */
975 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= (USHORT
)Result
;
989 Fast486Exception(State
, FAST486_EXCEPTION_DE
);
993 Quotient
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
/ Value
;
994 Remainder
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
% Value
;
999 Fast486Exception(State
, FAST486_EXCEPTION_DE
);
1003 /* Write back the results */
1004 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= (UCHAR
)Quotient
;
1005 State
->GeneralRegs
[FAST486_REG_EAX
].HighByte
= Remainder
;
1019 Fast486Exception(State
, FAST486_EXCEPTION_DE
);
1023 Quotient
= (SHORT
)State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
/ (CHAR
)Value
;
1024 Remainder
= (SHORT
)State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
% (CHAR
)Value
;
1026 if (Quotient
> FAST486_CHAR_MAX
|| Quotient
< FAST486_CHAR_MIN
)
1029 Fast486Exception(State
, FAST486_EXCEPTION_DE
);
1033 /* Write back the results */
1034 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= (UCHAR
)((CHAR
)Quotient
);
1035 State
->GeneralRegs
[FAST486_REG_EAX
].HighByte
= (UCHAR
)Remainder
;
1042 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7
)
1044 ULONG Value
= 0, SignFlag
;
1045 FAST486_MOD_REG_RM ModRegRm
;
1046 BOOLEAN OperandSize
, AddressSize
;
1048 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1050 TOGGLE_OPSIZE(OperandSize
);
1051 TOGGLE_ADSIZE(AddressSize
);
1053 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1055 /* Exception occurred */
1059 /* Set the sign flag */
1060 if (OperandSize
) SignFlag
= SIGN_FLAG_LONG
;
1061 else SignFlag
= SIGN_FLAG_WORD
;
1063 /* Read the operand */
1067 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
1069 /* Exception occurred */
1076 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, (PUSHORT
)&Value
))
1078 /* Exception occurred */
1083 switch (ModRegRm
.Register
)
1089 ULONG Immediate
= 0, Result
= 0;
1093 /* Fetch the immediate dword */
1094 if (!Fast486FetchDword(State
, &Immediate
))
1096 /* Exception occurred */
1102 /* Fetch the immediate word */
1103 if (!Fast486FetchWord(State
, (PUSHORT
)&Immediate
))
1105 /* Exception occurred */
1110 /* Calculate the result */
1111 Result
= Value
& Immediate
;
1113 /* Update the flags */
1114 State
->Flags
.Cf
= FALSE
;
1115 State
->Flags
.Of
= FALSE
;
1116 State
->Flags
.Zf
= (Result
== 0);
1117 State
->Flags
.Sf
= ((Result
& SignFlag
) != 0);
1118 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1126 /* Write back the result */
1130 Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, ~Value
);
1135 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, LOWORD(~Value
));
1144 /* Calculate the result */
1145 ULONG Result
= -(LONG
)Value
;
1146 if (!OperandSize
) Result
&= 0xFFFF;
1148 /* Update the flags */
1149 State
->Flags
.Cf
= (Value
!= 0);
1150 State
->Flags
.Of
= (Value
& SignFlag
) && (Result
& SignFlag
);
1151 State
->Flags
.Af
= ((Value
& 0x0F) != 0);
1152 State
->Flags
.Zf
= (Result
== 0);
1153 State
->Flags
.Sf
= ((Result
& SignFlag
) != 0);
1154 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1156 /* Write back the result */
1160 Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Result
);
1165 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, LOWORD(Result
));
1176 ULONGLONG Result
= (ULONGLONG
)Value
* (ULONGLONG
)State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
1178 /* Update the flags */
1179 State
->Flags
.Cf
= State
->Flags
.Of
= ((Result
& 0xFFFFFFFF00000000ULL
) != 0);
1181 /* Write back the result */
1182 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Result
& 0xFFFFFFFFULL
;
1183 State
->GeneralRegs
[FAST486_REG_EDX
].Long
= Result
>> 32;
1187 ULONG Result
= (ULONG
)Value
* (ULONG
)State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
1189 /* Update the flags */
1190 State
->Flags
.Cf
= State
->Flags
.Of
= (HIWORD(Result
) != 0);
1192 /* Write back the result */
1193 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= LOWORD(Result
);
1194 State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
= HIWORD(Result
);
1205 LONGLONG Result
= (LONGLONG
)((LONG
)Value
) * (LONGLONG
)((LONG
)State
->GeneralRegs
[FAST486_REG_EAX
].Long
);
1207 /* Update the flags */
1208 State
->Flags
.Cf
= State
->Flags
.Of
= ((Result
< FAST486_LONG_MIN
) || (Result
> FAST486_LONG_MAX
));
1210 /* Write back the result */
1211 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Result
& 0xFFFFFFFFULL
;
1212 State
->GeneralRegs
[FAST486_REG_EDX
].Long
= Result
>> 32;
1216 LONG Result
= (LONG
)((SHORT
)Value
) * (LONG
)((SHORT
)State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
);
1218 /* Update the flags */
1219 State
->Flags
.Cf
= State
->Flags
.Of
= ((Result
< FAST486_SHORT_MIN
) || (Result
> FAST486_SHORT_MAX
));
1221 /* Write back the result */
1222 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= LOWORD(Result
);
1223 State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
= HIWORD(Result
);
1235 Fast486Exception(State
, FAST486_EXCEPTION_DE
);
1241 ULONGLONG Dividend
= (ULONGLONG
)State
->GeneralRegs
[FAST486_REG_EAX
].Long
1242 | ((ULONGLONG
)State
->GeneralRegs
[FAST486_REG_EDX
].Long
<< 32);
1243 ULONGLONG Quotient
= Dividend
/ Value
;
1244 ULONG Remainder
= Dividend
% Value
;
1246 if (Quotient
> 0xFFFFFFFFULL
)
1249 Fast486Exception(State
, FAST486_EXCEPTION_DE
);
1253 /* Write back the results */
1254 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= (ULONG
)Quotient
;
1255 State
->GeneralRegs
[FAST486_REG_EDX
].Long
= Remainder
;
1259 ULONG Dividend
= (ULONG
)State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
1260 | ((ULONG
)State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
<< 16);
1261 ULONG Quotient
= Dividend
/ Value
;
1262 USHORT Remainder
= Dividend
% Value
;
1264 if (Quotient
> 0xFFFF)
1267 Fast486Exception(State
, FAST486_EXCEPTION_DE
);
1271 /* Write back the results */
1272 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= (USHORT
)Quotient
;
1273 State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
= Remainder
;
1285 Fast486Exception(State
, FAST486_EXCEPTION_DE
);
1291 LONGLONG Dividend
= (LONGLONG
)State
->GeneralRegs
[FAST486_REG_EAX
].Long
1292 | ((LONGLONG
)State
->GeneralRegs
[FAST486_REG_EDX
].Long
<< 32);
1293 LONGLONG Quotient
= Dividend
/ (LONG
)Value
;
1294 LONG Remainder
= Dividend
% (LONG
)Value
;
1296 if (Quotient
> FAST486_LONG_MAX
|| Quotient
< FAST486_LONG_MIN
)
1299 Fast486Exception(State
, FAST486_EXCEPTION_DE
);
1303 /* Write back the results */
1304 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= (ULONG
)((LONG
)Quotient
);
1305 State
->GeneralRegs
[FAST486_REG_EDX
].Long
= (ULONG
)Remainder
;
1309 LONG Dividend
= (LONG
)State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
1310 | ((LONG
)State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
<< 16);
1311 LONG Quotient
= Dividend
/ (SHORT
)LOWORD(Value
);
1312 SHORT Remainder
= Dividend
% (SHORT
)LOWORD(Value
);
1314 if (Quotient
> FAST486_SHORT_MAX
|| Quotient
< FAST486_SHORT_MIN
)
1317 Fast486Exception(State
, FAST486_EXCEPTION_DE
);
1321 /* Write back the results */
1322 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= (USHORT
)((SHORT
)Quotient
);
1323 State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
= (USHORT
)Remainder
;
1331 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFE
)
1334 FAST486_MOD_REG_RM ModRegRm
;
1335 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1337 TOGGLE_ADSIZE(AddressSize
);
1339 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1341 /* Exception occurred */
1345 if (ModRegRm
.Register
> 1)
1348 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1352 /* Read the operands */
1353 if (!Fast486ReadModrmByteOperands(State
, &ModRegRm
, NULL
, &Value
))
1355 /* Exception occurred */
1359 if (ModRegRm
.Register
== 0)
1361 /* Increment and update OF and AF */
1363 State
->Flags
.Of
= (Value
== SIGN_FLAG_BYTE
);
1364 State
->Flags
.Af
= ((Value
& 0x0F) == 0);
1368 /* Decrement and update OF and AF */
1369 State
->Flags
.Of
= (Value
== SIGN_FLAG_BYTE
);
1371 State
->Flags
.Af
= ((Value
& 0x0F) == 0x0F);
1375 State
->Flags
.Zf
= (Value
== 0);
1376 State
->Flags
.Sf
= ((Value
& SIGN_FLAG_BYTE
) != 0);
1377 State
->Flags
.Pf
= Fast486CalculateParity(Value
);
1379 /* Write back the result */
1380 Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Value
);
1383 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF
)
1385 FAST486_MOD_REG_RM ModRegRm
;
1386 BOOLEAN OperandSize
, AddressSize
;
1388 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1390 TOGGLE_OPSIZE(OperandSize
);
1391 TOGGLE_ADSIZE(AddressSize
);
1393 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1395 /* Exception occurred */
1399 if (ModRegRm
.Register
== 7)
1402 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1406 /* Read the operands */
1411 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
1413 /* Exception occurred */
1417 if (ModRegRm
.Register
== 0)
1419 /* Increment and update OF and AF */
1421 State
->Flags
.Of
= (Value
== SIGN_FLAG_LONG
);
1422 State
->Flags
.Af
= ((Value
& 0x0F) == 0);
1424 else if (ModRegRm
.Register
== 1)
1426 /* Decrement and update OF and AF */
1427 State
->Flags
.Of
= (Value
== SIGN_FLAG_LONG
);
1429 State
->Flags
.Af
= ((Value
& 0x0F) == 0x0F);
1431 else if (ModRegRm
.Register
== 2)
1433 /* Push the current value of EIP */
1434 if (!Fast486StackPush(State
, State
->InstPtr
.Long
))
1436 /* Exception occurred */
1440 /* Set the EIP to the address */
1441 State
->InstPtr
.Long
= Value
;
1443 else if (ModRegRm
.Register
== 3)
1446 FAST486_SEG_REGS Segment
= FAST486_REG_DS
;
1448 /* Check for the segment override */
1449 if (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
1451 /* Use the override segment instead */
1452 Segment
= State
->SegmentOverride
;
1455 /* Read the selector */
1456 if (!Fast486ReadMemory(State
,
1458 ModRegRm
.MemoryAddress
+ sizeof(ULONG
),
1463 /* Exception occurred */
1467 if ((State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
1468 && !State
->Flags
.Vm
)
1470 if (!Fast486ProcessGate(State
, Selector
, Value
, TRUE
))
1472 /* Gate processed or exception occurred */
1477 /* Push the current value of CS */
1478 if (!Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_CS
].Selector
))
1480 /* Exception occurred */
1484 /* Push the current value of EIP */
1485 if (!Fast486StackPush(State
, State
->InstPtr
.Long
))
1487 /* Exception occurred */
1491 /* Load the new code segment */
1492 if (!Fast486LoadSegment(State
, FAST486_REG_CS
, Selector
))
1494 /* Exception occurred */
1498 /* Set the EIP to the address */
1499 State
->InstPtr
.Long
= Value
;
1501 else if (ModRegRm
.Register
== 4)
1503 /* Set the EIP to the address */
1504 State
->InstPtr
.Long
= Value
;
1506 else if (ModRegRm
.Register
== 5)
1509 FAST486_SEG_REGS Segment
= FAST486_REG_DS
;
1511 /* Check for the segment override */
1512 if (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
1514 /* Use the override segment instead */
1515 Segment
= State
->SegmentOverride
;
1518 /* Read the selector */
1519 if (!Fast486ReadMemory(State
,
1521 ModRegRm
.MemoryAddress
+ sizeof(ULONG
),
1526 /* Exception occurred */
1530 if ((State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
1531 && !State
->Flags
.Vm
)
1533 if (!Fast486ProcessGate(State
, Selector
, Value
, FALSE
))
1535 /* Gate processed or exception occurred */
1540 /* Load the new code segment */
1541 if (!Fast486LoadSegment(State
, FAST486_REG_CS
, Selector
))
1543 /* Exception occurred */
1547 /* Set the EIP to the address */
1548 State
->InstPtr
.Long
= Value
;
1550 else if (ModRegRm
.Register
== 6)
1552 /* Push the value on to the stack */
1553 Fast486StackPush(State
, Value
);
1557 if (ModRegRm
.Register
<= 1)
1560 State
->Flags
.Sf
= ((Value
& SIGN_FLAG_LONG
) != 0);
1561 State
->Flags
.Zf
= (Value
== 0);
1562 State
->Flags
.Pf
= Fast486CalculateParity(Value
);
1564 /* Write back the result */
1565 Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
1572 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, &Value
))
1574 /* Exception occurred */
1578 if (ModRegRm
.Register
== 0)
1580 /* Increment and update OF */
1582 State
->Flags
.Of
= (Value
== SIGN_FLAG_WORD
);
1583 State
->Flags
.Af
= ((Value
& 0x0F) == 0);
1585 else if (ModRegRm
.Register
== 1)
1587 /* Decrement and update OF */
1588 State
->Flags
.Of
= (Value
== SIGN_FLAG_WORD
);
1590 State
->Flags
.Af
= ((Value
& 0x0F) == 0x0F);
1592 else if (ModRegRm
.Register
== 2)
1594 /* Push the current value of IP */
1595 if (!Fast486StackPush(State
, State
->InstPtr
.LowWord
))
1597 /* Exception occurred */
1601 /* Set the IP to the address */
1602 State
->InstPtr
.LowWord
= Value
;
1604 /* Clear the top half of EIP */
1605 State
->InstPtr
.Long
&= 0xFFFF;
1607 else if (ModRegRm
.Register
== 3)
1610 FAST486_SEG_REGS Segment
= FAST486_REG_DS
;
1612 /* Check for the segment override */
1613 if (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
1615 /* Use the override segment instead */
1616 Segment
= State
->SegmentOverride
;
1619 /* Read the selector */
1620 if (!Fast486ReadMemory(State
,
1622 ModRegRm
.MemoryAddress
+ sizeof(USHORT
),
1627 /* Exception occurred */
1631 if ((State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
1632 && !State
->Flags
.Vm
)
1634 if (!Fast486ProcessGate(State
, Selector
, Value
, TRUE
))
1636 /* Gate processed or exception occurred */
1641 /* Push the current value of CS */
1642 if (!Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_CS
].Selector
))
1644 /* Exception occurred */
1648 /* Push the current value of IP */
1649 if (!Fast486StackPush(State
, State
->InstPtr
.LowWord
))
1651 /* Exception occurred */
1655 /* Load the new code segment */
1656 if (!Fast486LoadSegment(State
, FAST486_REG_CS
, Selector
))
1658 /* Exception occurred */
1662 /* Set the IP to the address */
1663 State
->InstPtr
.LowWord
= Value
;
1665 /* Clear the top half of EIP */
1666 State
->InstPtr
.Long
&= 0xFFFF;
1668 else if (ModRegRm
.Register
== 4)
1670 /* Set the IP to the address */
1671 State
->InstPtr
.LowWord
= Value
;
1673 /* Clear the top half of EIP */
1674 State
->InstPtr
.Long
&= 0xFFFF;
1676 else if (ModRegRm
.Register
== 5)
1679 FAST486_SEG_REGS Segment
= FAST486_REG_DS
;
1681 /* Check for the segment override */
1682 if (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
1684 /* Use the override segment instead */
1685 Segment
= State
->SegmentOverride
;
1688 /* Read the selector */
1689 if (!Fast486ReadMemory(State
,
1691 ModRegRm
.MemoryAddress
+ sizeof(USHORT
),
1696 /* Exception occurred */
1700 if ((State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
1701 && !State
->Flags
.Vm
)
1703 if (!Fast486ProcessGate(State
, Selector
, Value
, FALSE
))
1705 /* Gate processed or exception occurred */
1710 /* Load the new code segment */
1711 if (!Fast486LoadSegment(State
, FAST486_REG_CS
, Selector
))
1713 /* Exception occurred */
1717 /* Set the IP to the address */
1718 State
->InstPtr
.LowWord
= Value
;
1720 /* Clear the top half of EIP */
1721 State
->InstPtr
.Long
&= 0xFFFF;
1723 else if (ModRegRm
.Register
== 6)
1725 /* Push the value on to the stack */
1726 Fast486StackPush(State
, Value
);
1732 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1736 if (ModRegRm
.Register
<= 1)
1739 State
->Flags
.Sf
= ((Value
& SIGN_FLAG_WORD
) != 0);
1740 State
->Flags
.Zf
= (Value
== 0);
1741 State
->Flags
.Pf
= Fast486CalculateParity(Value
);
1743 /* Write back the result */
1744 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
);
1749 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0F00
)
1751 FAST486_MOD_REG_RM ModRegRm
;
1752 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1755 TOGGLE_ADSIZE(AddressSize
);
1757 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1759 /* Exception occurred */
1763 /* Check which operation this is */
1764 switch (ModRegRm
.Register
)
1769 /* Not recognized in real mode or virtual 8086 mode */
1770 if (!(State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
1773 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1777 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, State
->Ldtr
.Selector
);
1784 /* Not recognized in real mode or virtual 8086 mode */
1785 if (!(State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
1788 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1792 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, State
->TaskReg
.Selector
);
1801 FAST486_SYSTEM_DESCRIPTOR GdtEntry
;
1803 /* Not recognized in real mode or virtual 8086 mode */
1804 if (!(State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
1807 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1811 /* This is a privileged instruction */
1812 if (Fast486GetCurrentPrivLevel(State
) != 0)
1814 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
1818 if (!Fast486ReadModrmWordOperands(State
,
1823 /* Exception occurred */
1827 if (Selector
& SEGMENT_TABLE_INDICATOR
)
1829 /* This selector doesn't point to the GDT */
1830 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_GP
, Selector
);
1834 if (!Fast486ReadDescriptorEntry(State
,
1837 (PFAST486_GDT_ENTRY
)&GdtEntry
))
1839 /* Exception occurred */
1845 /* Invalid selector */
1846 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_GP
, Selector
);
1850 if (GET_SEGMENT_INDEX(Selector
) == 0)
1852 RtlZeroMemory(&State
->Ldtr
, sizeof(State
->Ldtr
));
1856 if (!GdtEntry
.Present
)
1858 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_NP
, Selector
);
1862 if (GdtEntry
.Signature
!= FAST486_LDT_SIGNATURE
)
1864 /* This is not a LDT descriptor */
1865 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_GP
, Selector
);
1869 /* Update the LDTR */
1870 State
->Ldtr
.Selector
= Selector
;
1871 State
->Ldtr
.Base
= GdtEntry
.Base
| (GdtEntry
.BaseMid
<< 16) | (GdtEntry
.BaseHigh
<< 24);
1872 State
->Ldtr
.Limit
= GdtEntry
.Limit
| (GdtEntry
.LimitHigh
<< 16);
1874 if (GdtEntry
.Granularity
)
1876 State
->Ldtr
.Limit
<<= 12;
1877 State
->Ldtr
.Limit
|= 0x00000FFF;
1888 FAST486_SYSTEM_DESCRIPTOR GdtEntry
;
1890 /* Not recognized in real mode or virtual 8086 mode */
1891 if (!(State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
1894 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1898 /* This is a privileged instruction */
1899 if (Fast486GetCurrentPrivLevel(State
) != 0)
1901 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
1905 if (!Fast486ReadModrmWordOperands(State
,
1910 /* Exception occurred */
1914 if (Selector
& SEGMENT_TABLE_INDICATOR
)
1916 /* This selector doesn't point to the GDT */
1917 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_GP
, Selector
);
1921 if (!Fast486ReadDescriptorEntry(State
,
1924 (PFAST486_GDT_ENTRY
)&GdtEntry
))
1926 /* Exception occurred */
1932 /* Invalid selector */
1933 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_GP
, Selector
);
1937 if (GET_SEGMENT_INDEX(Selector
) == 0)
1939 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
1943 if (!GdtEntry
.Present
)
1945 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_NP
, Selector
);
1949 if (GdtEntry
.Signature
!= FAST486_TSS_SIGNATURE
1950 && GdtEntry
.Signature
!= FAST486_BUSY_TSS_SIGNATURE
1951 && GdtEntry
.Signature
!= FAST486_TSS_16_SIGNATURE
1952 && GdtEntry
.Signature
!= FAST486_BUSY_TSS_16_SIGNATURE
)
1954 /* This is not a TSS descriptor */
1955 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_GP
, Selector
);
1960 State
->TaskReg
.Selector
= Selector
;
1961 State
->TaskReg
.Base
= GdtEntry
.Base
| (GdtEntry
.BaseMid
<< 16) | (GdtEntry
.BaseHigh
<< 24);
1962 State
->TaskReg
.Limit
= GdtEntry
.Limit
| (GdtEntry
.LimitHigh
<< 16);
1963 State
->TaskReg
.Modern
= GdtEntry
.Signature
== FAST486_TSS_SIGNATURE
1964 || GdtEntry
.Signature
== FAST486_BUSY_TSS_SIGNATURE
;
1966 if (GdtEntry
.Granularity
)
1968 State
->TaskReg
.Limit
<<= 12;
1969 State
->TaskReg
.Limit
|= 0x00000FFF;
1972 if (GdtEntry
.Signature
!= FAST486_BUSY_TSS_SIGNATURE
1973 && GdtEntry
.Signature
!= FAST486_BUSY_TSS_16_SIGNATURE
)
1975 /* Set the busy bit of this TSS descriptor and write it back */
1976 GdtEntry
.Signature
|= 2;
1978 Fast486WriteLinearMemory(State
,
1979 State
->Gdtr
.Address
+ GET_SEGMENT_INDEX(Selector
),
1982 FALSE
/* We already made sure CPL is 0 */);
1994 FAST486_GDT_ENTRY GdtEntry
;
1996 /* Not recognized in real mode or virtual 8086 mode */
1997 if (!(State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
2000 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2004 if (!Fast486ReadModrmWordOperands(State
,
2009 /* Exception occurred */
2013 if (!Fast486ReadDescriptorEntry(State
, Selector
, &Valid
, &GdtEntry
))
2015 /* Exception occurred */
2022 State
->Flags
.Zf
= FALSE
;
2026 /* Set ZF if it is valid and accessible */
2027 State
->Flags
.Zf
= GdtEntry
.Present
// must be present
2028 && GdtEntry
.SystemType
// must be a segment
2029 && (((ModRegRm
.Register
== 4)
2030 /* code segments are only readable if the RW bit is set */
2031 && (!GdtEntry
.Executable
|| GdtEntry
.ReadWrite
))
2032 || ((ModRegRm
.Register
== 5)
2033 /* code segments are never writable, data segments are writable when RW is set */
2034 && (!GdtEntry
.Executable
&& GdtEntry
.ReadWrite
)))
2036 * for segments other than conforming code segments,
2037 * both RPL and CPL must be less than or equal to DPL
2039 && (((!GdtEntry
.Executable
|| !GdtEntry
.DirConf
)
2040 && (GET_SEGMENT_RPL(Selector
) <= GdtEntry
.Dpl
)
2041 && (Fast486GetCurrentPrivLevel(State
) <= GdtEntry
.Dpl
))
2042 /* for conforming code segments, DPL must be less than or equal to CPL */
2043 || ((GdtEntry
.Executable
&& GdtEntry
.DirConf
)
2044 && (GdtEntry
.Dpl
<= Fast486GetCurrentPrivLevel(State
))));
2053 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2058 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0F01
)
2060 // FAST486_TABLE_REG TableReg;
2062 FAST486_MOD_REG_RM ModRegRm
;
2063 BOOLEAN OperandSize
, AddressSize
;
2064 FAST486_SEG_REGS Segment
= FAST486_REG_DS
;
2066 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2069 TOGGLE_OPSIZE(OperandSize
);
2070 TOGGLE_ADSIZE(AddressSize
);
2072 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2074 /* Exception occurred */
2078 /* Check for the segment override */
2079 if (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
2081 /* Use the override segment instead */
2082 Segment
= State
->SegmentOverride
;
2085 /* Check which operation this is */
2086 switch (ModRegRm
.Register
)
2091 if (!ModRegRm
.Memory
)
2093 /* The second operand must be a memory location */
2094 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2098 /* Fill the 6-byte table register */
2099 // TableReg = State->Gdtr;
2100 *((PUSHORT
)&TableReg
) = State
->Gdtr
.Size
;
2101 *((PULONG
)&TableReg
[sizeof(USHORT
)]) = State
->Gdtr
.Address
;
2103 /* Store the GDTR */
2104 Fast486WriteMemory(State
,
2106 ModRegRm
.MemoryAddress
,
2116 if (!ModRegRm
.Memory
)
2118 /* The second operand must be a memory location */
2119 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2123 /* Fill the 6-byte table register */
2124 // TableReg = State->Idtr;
2125 *((PUSHORT
)&TableReg
) = State
->Idtr
.Size
;
2126 *((PULONG
)&TableReg
[sizeof(USHORT
)]) = State
->Idtr
.Address
;
2128 /* Store the IDTR */
2129 Fast486WriteMemory(State
,
2131 ModRegRm
.MemoryAddress
,
2141 /* This is a privileged instruction */
2142 if (Fast486GetCurrentPrivLevel(State
) != 0)
2144 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
2148 if (!ModRegRm
.Memory
)
2150 /* The second operand must be a memory location */
2151 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2155 /* Read the new GDTR */
2156 if (!Fast486ReadMemory(State
,
2158 ModRegRm
.MemoryAddress
,
2163 /* Exception occurred */
2167 /* Load the new GDT */
2168 // State->Gdtr = TableReg;
2169 State
->Gdtr
.Size
= *((PUSHORT
)&TableReg
);
2170 State
->Gdtr
.Address
= *((PULONG
)&TableReg
[sizeof(USHORT
)]);
2172 /* In 16-bit mode the highest byte is masked out */
2173 if (!OperandSize
) State
->Gdtr
.Address
&= 0x00FFFFFF;
2181 /* This is a privileged instruction */
2182 if (Fast486GetCurrentPrivLevel(State
) != 0)
2184 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
2188 if (!ModRegRm
.Memory
)
2190 /* The second operand must be a memory location */
2191 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2195 /* Read the new IDTR */
2196 if (!Fast486ReadMemory(State
,
2198 ModRegRm
.MemoryAddress
,
2203 /* Exception occurred */
2207 /* Load the new IDT */
2208 // State->Idtr = TableReg;
2209 State
->Idtr
.Size
= *((PUSHORT
)&TableReg
);
2210 State
->Idtr
.Address
= *((PULONG
)&TableReg
[sizeof(USHORT
)]);
2212 /* In 16-bit mode the highest byte is masked out */
2213 if (!OperandSize
) State
->Idtr
.Address
&= 0x00FFFFFF;
2221 /* Store the lower 16 bits (Machine Status Word) of CR0 */
2222 Fast486WriteModrmWordOperands(State
,
2225 LOWORD(State
->ControlRegisters
[FAST486_REG_CR0
]));
2233 USHORT MachineStatusWord
;
2235 if (State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
2237 /* This is a privileged instruction */
2238 if (Fast486GetCurrentPrivLevel(State
) != 0)
2240 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
2245 /* Read the new Machine Status Word */
2246 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, &MachineStatusWord
))
2248 /* Exception occurred */
2252 /* Set the lowest 4 bits, but never clear bit 0 */
2253 State
->ControlRegisters
[FAST486_REG_CR0
] &= 0xFFFFFFF1;
2254 State
->ControlRegisters
[FAST486_REG_CR0
] |= MachineStatusWord
& 0x0F;
2262 #ifndef FAST486_NO_PREFETCH
2263 /* Invalidate the prefetch */
2264 State
->PrefetchValid
= FALSE
;
2267 /* This is a privileged instruction */
2268 if (Fast486GetCurrentPrivLevel(State
) != 0)
2270 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
2274 if (!ModRegRm
.Memory
)
2276 /* The second operand must be a memory location */
2277 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2281 if (State
->Tlb
!= NULL
)
2283 /* Clear the TLB entry */
2284 State
->Tlb
[ModRegRm
.MemoryAddress
>> 12] = INVALID_TLB_FIELD
;
2293 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2298 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0FB9
)
2300 FAST486_MOD_REG_RM ModRegRm
;
2301 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2303 TOGGLE_ADSIZE(AddressSize
);
2305 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2307 /* Exception occurred */
2311 /* All of them are reserved (UD2) */
2312 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2316 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0FBA
)
2318 FAST486_MOD_REG_RM ModRegRm
;
2319 BOOLEAN OperandSize
, AddressSize
;
2323 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2325 TOGGLE_OPSIZE(OperandSize
);
2326 TOGGLE_ADSIZE(AddressSize
);
2328 /* Get the number of bits */
2329 if (OperandSize
) DataSize
= 32;
2332 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2334 /* Exception occurred */
2338 if (ModRegRm
.Register
< 4)
2341 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2345 /* Get the bit number */
2346 if (!Fast486FetchByte(State
, &BitNumber
))
2348 /* Exception occurred */
2352 if (ModRegRm
.Memory
)
2355 * For memory operands, add the bit offset divided by
2356 * the data size to the address
2358 ModRegRm
.MemoryAddress
+= BitNumber
/ DataSize
;
2361 /* Normalize the bit number */
2362 BitNumber
%= DataSize
;
2368 /* Read the value */
2369 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
2371 /* Exception occurred */
2375 /* Set CF to the bit value */
2376 State
->Flags
.Cf
= (Value
>> BitNumber
) & 1;
2378 if (ModRegRm
.Register
== 5)
2381 Value
|= 1 << BitNumber
;
2383 else if (ModRegRm
.Register
== 6)
2386 Value
&= ~(1 << BitNumber
);
2388 else if (ModRegRm
.Register
== 7)
2391 Value
^= 1 << BitNumber
;
2394 if (ModRegRm
.Register
>= 5)
2396 /* Write back the result */
2397 if (!Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
))
2399 /* Exception occurred */
2408 /* Read the value */
2409 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, &Value
))
2411 /* Exception occurred */
2415 /* Set CF to the bit value */
2416 State
->Flags
.Cf
= (Value
>> BitNumber
) & 1;
2418 if (ModRegRm
.Register
== 5)
2421 Value
|= 1 << BitNumber
;
2423 else if (ModRegRm
.Register
== 6)
2426 Value
&= ~(1 << BitNumber
);
2428 else if (ModRegRm
.Register
== 7)
2431 Value
^= 1 << BitNumber
;
2434 if (ModRegRm
.Register
>= 5)
2436 /* Write back the result */
2437 if (!Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
))
2439 /* Exception occurred */