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 **********************************************************/
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 - restore SP */
498 if (OperandSize
) State
->GeneralRegs
[FAST486_REG_ESP
].Long
-= sizeof(ULONG
);
499 else State
->GeneralRegs
[FAST486_REG_ESP
].LowWord
-= sizeof(USHORT
);
504 if (ModRegRm
.Register
!= 0)
507 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
511 if (OperandSize
) Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
512 else Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, LOWORD(Value
));
515 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC0
)
518 FAST486_MOD_REG_RM ModRegRm
;
519 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
521 TOGGLE_ADSIZE(AddressSize
);
523 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
525 /* Exception occurred */
529 /* Fetch the count */
530 if (!Fast486FetchByte(State
, &Count
))
532 /* Exception occurred */
536 /* Read the operands */
537 if (!Fast486ReadModrmByteOperands(State
, &ModRegRm
, NULL
, &Value
))
539 /* Exception occurred */
543 /* Calculate the result */
544 Value
= LOBYTE(Fast486RotateOperation(State
,
550 /* Write back the result */
551 Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Value
);
554 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC1
)
557 FAST486_MOD_REG_RM ModRegRm
;
558 BOOLEAN OperandSize
, AddressSize
;
560 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
562 TOGGLE_OPSIZE(OperandSize
);
563 TOGGLE_ADSIZE(AddressSize
);
565 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
567 /* Exception occurred */
571 /* Fetch the count */
572 if (!Fast486FetchByte(State
, &Count
))
574 /* Exception occurred */
582 /* Read the operands */
583 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
585 /* Exception occurred */
589 /* Calculate the result */
590 Value
= Fast486RotateOperation(State
,
596 /* Write back the result */
597 Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
603 /* Read the operands */
604 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, &Value
))
606 /* Exception occurred */
610 /* Calculate the result */
611 Value
= LOWORD(Fast486RotateOperation(State
,
617 /* Write back the result */
618 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
);
622 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC6
)
625 FAST486_MOD_REG_RM ModRegRm
;
626 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
628 TOGGLE_ADSIZE(AddressSize
);
630 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
632 /* Exception occurred */
636 if (ModRegRm
.Register
!= 0)
639 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
643 /* Get the immediate operand */
644 if (!Fast486FetchByte(State
, &Immediate
))
646 /* Exception occurred */
650 Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Immediate
);
653 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC7
)
655 FAST486_MOD_REG_RM ModRegRm
;
656 BOOLEAN OperandSize
, AddressSize
;
658 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
660 TOGGLE_OPSIZE(OperandSize
);
661 TOGGLE_ADSIZE(AddressSize
);
663 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
665 /* Exception occurred */
669 if (ModRegRm
.Register
!= 0)
672 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
680 /* Get the immediate operand */
681 if (!Fast486FetchDword(State
, &Immediate
))
683 /* Exception occurred */
687 Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Immediate
);
693 /* Get the immediate operand */
694 if (!Fast486FetchWord(State
, &Immediate
))
696 /* Exception occurred */
700 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Immediate
);
704 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD0
)
707 FAST486_MOD_REG_RM ModRegRm
;
708 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
710 TOGGLE_ADSIZE(AddressSize
);
712 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
714 /* Exception occurred */
718 /* Read the operands */
719 if (!Fast486ReadModrmByteOperands(State
, &ModRegRm
, NULL
, &Value
))
721 /* Exception occurred */
725 /* Calculate the result */
726 Value
= LOBYTE(Fast486RotateOperation(State
, ModRegRm
.Register
, Value
, 8, 1));
728 /* Write back the result */
729 Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Value
);
733 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD1
)
735 FAST486_MOD_REG_RM ModRegRm
;
736 BOOLEAN OperandSize
, AddressSize
;
738 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
740 TOGGLE_OPSIZE(OperandSize
);
741 TOGGLE_ADSIZE(AddressSize
);
743 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
745 /* Exception occurred */
753 /* Read the operands */
754 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
756 /* Exception occurred */
760 /* Calculate the result */
761 Value
= Fast486RotateOperation(State
, ModRegRm
.Register
, Value
, 32, 1);
763 /* Write back the result */
764 Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
770 /* Read the operands */
771 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, &Value
))
773 /* Exception occurred */
777 /* Calculate the result */
778 Value
= LOWORD(Fast486RotateOperation(State
, ModRegRm
.Register
, Value
, 16, 1));
780 /* Write back the result */
781 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
);
785 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD2
)
788 FAST486_MOD_REG_RM ModRegRm
;
789 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
791 TOGGLE_ADSIZE(AddressSize
);
793 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
795 /* Exception occurred */
799 /* Read the operands */
800 if (!Fast486ReadModrmByteOperands(State
, &ModRegRm
, NULL
, &Value
))
802 /* Exception occurred */
806 /* Calculate the result */
807 Value
= LOBYTE(Fast486RotateOperation(State
,
811 State
->GeneralRegs
[FAST486_REG_ECX
].LowByte
));
813 /* Write back the result */
814 Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Value
);
817 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD3
)
819 FAST486_MOD_REG_RM ModRegRm
;
820 BOOLEAN OperandSize
, AddressSize
;
822 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
824 TOGGLE_OPSIZE(OperandSize
);
825 TOGGLE_ADSIZE(AddressSize
);
827 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
829 /* Exception occurred */
837 /* Read the operands */
838 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
840 /* Exception occurred */
844 /* Calculate the result */
845 Value
= Fast486RotateOperation(State
,
849 State
->GeneralRegs
[FAST486_REG_ECX
].LowByte
);
851 /* Write back the result */
852 Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
858 /* Read the operands */
859 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, &Value
))
861 /* Exception occurred */
865 /* Calculate the result */
866 Value
= LOWORD(Fast486RotateOperation(State
,
870 State
->GeneralRegs
[FAST486_REG_ECX
].LowByte
));
872 /* Write back the result */
873 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
);
877 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6
)
880 FAST486_MOD_REG_RM ModRegRm
;
881 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
883 TOGGLE_ADSIZE(AddressSize
);
885 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
887 /* Exception occurred */
891 /* Read the operands */
892 if (!Fast486ReadModrmByteOperands(State
, &ModRegRm
, NULL
, &Value
))
894 /* Exception occurred */
898 switch (ModRegRm
.Register
)
904 UCHAR Immediate
, Result
;
906 /* Fetch the immediate byte */
907 if (!Fast486FetchByte(State
, &Immediate
))
909 /* Exception occurred */
913 /* Calculate the result */
914 Result
= Value
& Immediate
;
916 /* Update the flags */
917 State
->Flags
.Cf
= FALSE
;
918 State
->Flags
.Of
= FALSE
;
919 State
->Flags
.Zf
= (Result
== 0);
920 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
921 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
929 /* Write back the result */
930 Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, ~Value
);
938 /* Calculate the result */
939 UCHAR Result
= -Value
;
941 /* Update the flags */
942 State
->Flags
.Cf
= (Value
!= 0);
943 State
->Flags
.Of
= (Value
& SIGN_FLAG_BYTE
) && (Result
& SIGN_FLAG_BYTE
);
944 State
->Flags
.Af
= ((Value
& 0x0F) != 0);
945 State
->Flags
.Zf
= (Result
== 0);
946 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
947 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
949 /* Write back the result */
950 Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Result
);
958 USHORT Result
= (USHORT
)Value
* (USHORT
)State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
960 /* Update the flags */
961 State
->Flags
.Cf
= State
->Flags
.Of
= (HIBYTE(Result
) != 0);
963 /* Write back the result */
964 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Result
;
972 SHORT Result
= (SHORT
)((CHAR
)Value
) * (SHORT
)((CHAR
)State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
);
974 /* Update the flags */
975 State
->Flags
.Cf
= State
->Flags
.Of
= ((Result
< -128) || (Result
> 127));
977 /* Write back the result */
978 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= (USHORT
)Result
;
992 Fast486Exception(State
, FAST486_EXCEPTION_DE
);
996 Quotient
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
/ Value
;
997 Remainder
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
% Value
;
1002 Fast486Exception(State
, FAST486_EXCEPTION_DE
);
1006 /* Write back the results */
1007 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= (UCHAR
)Quotient
;
1008 State
->GeneralRegs
[FAST486_REG_EAX
].HighByte
= Remainder
;
1022 Fast486Exception(State
, FAST486_EXCEPTION_DE
);
1026 Quotient
= (SHORT
)State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
/ (CHAR
)Value
;
1027 Remainder
= (SHORT
)State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
% (CHAR
)Value
;
1029 if (Quotient
> 127 || Quotient
< -128)
1032 Fast486Exception(State
, FAST486_EXCEPTION_DE
);
1036 /* Write back the results */
1037 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= (UCHAR
)((CHAR
)Quotient
);
1038 State
->GeneralRegs
[FAST486_REG_EAX
].HighByte
= (UCHAR
)Remainder
;
1045 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7
)
1047 ULONG Value
= 0, SignFlag
;
1048 FAST486_MOD_REG_RM ModRegRm
;
1049 BOOLEAN OperandSize
, AddressSize
;
1051 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1053 TOGGLE_OPSIZE(OperandSize
);
1054 TOGGLE_ADSIZE(AddressSize
);
1056 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1058 /* Exception occurred */
1062 /* Set the sign flag */
1063 if (OperandSize
) SignFlag
= SIGN_FLAG_LONG
;
1064 else SignFlag
= SIGN_FLAG_WORD
;
1066 /* Read the operand */
1070 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
1072 /* Exception occurred */
1079 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, (PUSHORT
)&Value
))
1081 /* Exception occurred */
1086 switch (ModRegRm
.Register
)
1092 ULONG Immediate
= 0, Result
= 0;
1096 /* Fetch the immediate dword */
1097 if (!Fast486FetchDword(State
, &Immediate
))
1099 /* Exception occurred */
1105 /* Fetch the immediate word */
1106 if (!Fast486FetchWord(State
, (PUSHORT
)&Immediate
))
1108 /* Exception occurred */
1113 /* Calculate the result */
1114 Result
= Value
& Immediate
;
1116 /* Update the flags */
1117 State
->Flags
.Cf
= FALSE
;
1118 State
->Flags
.Of
= FALSE
;
1119 State
->Flags
.Zf
= (Result
== 0);
1120 State
->Flags
.Sf
= ((Result
& SignFlag
) != 0);
1121 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1129 /* Write back the result */
1133 Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, ~Value
);
1138 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, LOWORD(~Value
));
1147 /* Calculate the result */
1148 ULONG Result
= -(LONG
)Value
;
1149 if (!OperandSize
) Result
&= 0xFFFF;
1151 /* Update the flags */
1152 State
->Flags
.Cf
= (Value
!= 0);
1153 State
->Flags
.Of
= (Value
& SignFlag
) && (Result
& SignFlag
);
1154 State
->Flags
.Af
= ((Value
& 0x0F) != 0);
1155 State
->Flags
.Zf
= (Result
== 0);
1156 State
->Flags
.Sf
= ((Result
& SignFlag
) != 0);
1157 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1159 /* Write back the result */
1163 Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Result
);
1168 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, LOWORD(Result
));
1179 ULONGLONG Result
= (ULONGLONG
)Value
* (ULONGLONG
)State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
1181 /* Update the flags */
1182 State
->Flags
.Cf
= State
->Flags
.Of
= ((Result
& 0xFFFFFFFF00000000ULL
) != 0);
1184 /* Write back the result */
1185 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Result
& 0xFFFFFFFFULL
;
1186 State
->GeneralRegs
[FAST486_REG_EDX
].Long
= Result
>> 32;
1190 ULONG Result
= (ULONG
)Value
* (ULONG
)State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
1192 /* Update the flags */
1193 State
->Flags
.Cf
= State
->Flags
.Of
= (HIWORD(Result
) != 0);
1195 /* Write back the result */
1196 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= LOWORD(Result
);
1197 State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
= HIWORD(Result
);
1208 LONGLONG Result
= (LONGLONG
)((LONG
)Value
) * (LONGLONG
)((LONG
)State
->GeneralRegs
[FAST486_REG_EAX
].Long
);
1210 /* Update the flags */
1211 State
->Flags
.Cf
= State
->Flags
.Of
= ((Result
< -2147483648LL) || (Result
> 2147483647LL));
1213 /* Write back the result */
1214 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Result
& 0xFFFFFFFFULL
;
1215 State
->GeneralRegs
[FAST486_REG_EDX
].Long
= Result
>> 32;
1219 LONG Result
= (LONG
)((SHORT
)Value
) * (LONG
)((SHORT
)State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
);
1221 /* Update the flags */
1222 State
->Flags
.Cf
= State
->Flags
.Of
= ((Result
< -32768) || (Result
> 32767));
1224 /* Write back the result */
1225 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= LOWORD(Result
);
1226 State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
= HIWORD(Result
);
1238 Fast486Exception(State
, FAST486_EXCEPTION_DE
);
1244 ULONGLONG Dividend
= (ULONGLONG
)State
->GeneralRegs
[FAST486_REG_EAX
].Long
1245 | ((ULONGLONG
)State
->GeneralRegs
[FAST486_REG_EDX
].Long
<< 32);
1246 ULONGLONG Quotient
= Dividend
/ Value
;
1247 ULONG Remainder
= Dividend
% Value
;
1249 if (Quotient
> 0xFFFFFFFFULL
)
1252 Fast486Exception(State
, FAST486_EXCEPTION_DE
);
1256 /* Write back the results */
1257 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= (ULONG
)Quotient
;
1258 State
->GeneralRegs
[FAST486_REG_EDX
].Long
= Remainder
;
1262 ULONG Dividend
= (ULONG
)State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
1263 | ((ULONG
)State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
<< 16);
1264 ULONG Quotient
= Dividend
/ Value
;
1265 USHORT Remainder
= Dividend
% Value
;
1267 if (Quotient
> 0xFFFF)
1270 Fast486Exception(State
, FAST486_EXCEPTION_DE
);
1274 /* Write back the results */
1275 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= (USHORT
)Quotient
;
1276 State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
= Remainder
;
1288 Fast486Exception(State
, FAST486_EXCEPTION_DE
);
1294 LONGLONG Dividend
= (LONGLONG
)State
->GeneralRegs
[FAST486_REG_EAX
].Long
1295 | ((LONGLONG
)State
->GeneralRegs
[FAST486_REG_EDX
].Long
<< 32);
1296 LONGLONG Quotient
= Dividend
/ (LONG
)Value
;
1297 LONG Remainder
= Dividend
% (LONG
)Value
;
1299 if (Quotient
> 2147483647LL || Quotient
< -2147483648LL)
1302 Fast486Exception(State
, FAST486_EXCEPTION_DE
);
1306 /* Write back the results */
1307 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= (ULONG
)((LONG
)Quotient
);
1308 State
->GeneralRegs
[FAST486_REG_EDX
].Long
= (ULONG
)Remainder
;
1312 LONG Dividend
= (LONG
)State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
1313 | ((LONG
)State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
<< 16);
1314 LONG Quotient
= Dividend
/ (SHORT
)LOWORD(Value
);
1315 SHORT Remainder
= Dividend
% (SHORT
)LOWORD(Value
);
1317 if (Quotient
> 32767 || Quotient
< -32768)
1320 Fast486Exception(State
, FAST486_EXCEPTION_DE
);
1324 /* Write back the results */
1325 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= (USHORT
)((SHORT
)Quotient
);
1326 State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
= (USHORT
)Remainder
;
1334 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFE
)
1337 FAST486_MOD_REG_RM ModRegRm
;
1338 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1340 TOGGLE_ADSIZE(AddressSize
);
1342 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1344 /* Exception occurred */
1348 if (ModRegRm
.Register
> 1)
1351 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1355 /* Read the operands */
1356 if (!Fast486ReadModrmByteOperands(State
, &ModRegRm
, NULL
, &Value
))
1358 /* Exception occurred */
1362 if (ModRegRm
.Register
== 0)
1364 /* Increment and update OF and AF */
1366 State
->Flags
.Of
= (Value
== SIGN_FLAG_BYTE
);
1367 State
->Flags
.Af
= ((Value
& 0x0F) == 0);
1371 /* Decrement and update OF and AF */
1372 State
->Flags
.Of
= (Value
== SIGN_FLAG_BYTE
);
1374 State
->Flags
.Af
= ((Value
& 0x0F) == 0x0F);
1378 State
->Flags
.Zf
= (Value
== 0);
1379 State
->Flags
.Sf
= ((Value
& SIGN_FLAG_BYTE
) != 0);
1380 State
->Flags
.Pf
= Fast486CalculateParity(Value
);
1382 /* Write back the result */
1383 Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Value
);
1386 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF
)
1388 FAST486_MOD_REG_RM ModRegRm
;
1389 BOOLEAN OperandSize
, AddressSize
;
1391 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1393 TOGGLE_OPSIZE(OperandSize
);
1394 TOGGLE_ADSIZE(AddressSize
);
1396 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1398 /* Exception occurred */
1402 if (ModRegRm
.Register
== 7)
1405 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1409 /* Read the operands */
1414 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
1416 /* Exception occurred */
1420 if (ModRegRm
.Register
== 0)
1422 /* Increment and update OF and AF */
1424 State
->Flags
.Of
= (Value
== SIGN_FLAG_LONG
);
1425 State
->Flags
.Af
= ((Value
& 0x0F) == 0);
1427 else if (ModRegRm
.Register
== 1)
1429 /* Decrement and update OF and AF */
1430 State
->Flags
.Of
= (Value
== SIGN_FLAG_LONG
);
1432 State
->Flags
.Af
= ((Value
& 0x0F) == 0x0F);
1434 else if (ModRegRm
.Register
== 2)
1436 /* Push the current value of EIP */
1437 if (!Fast486StackPush(State
, State
->InstPtr
.Long
))
1439 /* Exception occurred */
1443 /* Set the EIP to the address */
1444 State
->InstPtr
.Long
= Value
;
1446 else if (ModRegRm
.Register
== 3)
1449 FAST486_SEG_REGS Segment
= FAST486_REG_DS
;
1451 /* Check for the segment override */
1452 if (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
1454 /* Use the override segment instead */
1455 Segment
= State
->SegmentOverride
;
1458 /* Read the selector */
1459 if (!Fast486ReadMemory(State
,
1461 ModRegRm
.MemoryAddress
+ sizeof(ULONG
),
1466 /* Exception occurred */
1470 if (State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
1472 if (!Fast486ProcessGate(State
, Selector
, Value
, TRUE
))
1474 /* Gate processed or exception occurred */
1479 /* Push the current value of CS */
1480 if (!Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_CS
].Selector
))
1482 /* Exception occurred */
1486 /* Push the current value of EIP */
1487 if (!Fast486StackPush(State
, State
->InstPtr
.Long
))
1489 /* Exception occurred */
1493 /* Load the new code segment */
1494 if (!Fast486LoadSegment(State
, FAST486_REG_CS
, Selector
))
1496 /* Exception occurred */
1500 /* Set the EIP to the address */
1501 State
->InstPtr
.Long
= Value
;
1503 else if (ModRegRm
.Register
== 4)
1505 /* Set the EIP to the address */
1506 State
->InstPtr
.Long
= Value
;
1508 else if (ModRegRm
.Register
== 5)
1511 FAST486_SEG_REGS Segment
= FAST486_REG_DS
;
1513 /* Check for the segment override */
1514 if (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
1516 /* Use the override segment instead */
1517 Segment
= State
->SegmentOverride
;
1520 /* Read the selector */
1521 if (!Fast486ReadMemory(State
,
1523 ModRegRm
.MemoryAddress
+ sizeof(ULONG
),
1528 /* Exception occurred */
1532 if (State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
1534 if (!Fast486ProcessGate(State
, Selector
, Value
, FALSE
))
1536 /* Gate processed or exception occurred */
1541 /* Load the new code segment */
1542 if (!Fast486LoadSegment(State
, FAST486_REG_CS
, Selector
))
1544 /* Exception occurred */
1548 /* Set the EIP to the address */
1549 State
->InstPtr
.Long
= Value
;
1551 else if (ModRegRm
.Register
== 6)
1553 /* Push the value on to the stack */
1554 Fast486StackPush(State
, Value
);
1558 if (ModRegRm
.Register
<= 1)
1561 State
->Flags
.Sf
= ((Value
& SIGN_FLAG_LONG
) != 0);
1562 State
->Flags
.Zf
= (Value
== 0);
1563 State
->Flags
.Pf
= Fast486CalculateParity(Value
);
1565 /* Write back the result */
1566 Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
1573 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, &Value
))
1575 /* Exception occurred */
1579 if (ModRegRm
.Register
== 0)
1581 /* Increment and update OF */
1583 State
->Flags
.Of
= (Value
== SIGN_FLAG_WORD
);
1584 State
->Flags
.Af
= ((Value
& 0x0F) == 0);
1586 else if (ModRegRm
.Register
== 1)
1588 /* Decrement and update OF */
1589 State
->Flags
.Of
= (Value
== SIGN_FLAG_WORD
);
1591 State
->Flags
.Af
= ((Value
& 0x0F) == 0x0F);
1593 else if (ModRegRm
.Register
== 2)
1595 /* Push the current value of IP */
1596 if (!Fast486StackPush(State
, State
->InstPtr
.LowWord
))
1598 /* Exception occurred */
1602 /* Set the IP to the address */
1603 State
->InstPtr
.LowWord
= Value
;
1605 /* Clear the top half of EIP */
1606 State
->InstPtr
.Long
&= 0xFFFF;
1608 else if (ModRegRm
.Register
== 3)
1611 FAST486_SEG_REGS Segment
= FAST486_REG_DS
;
1613 /* Check for the segment override */
1614 if (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
1616 /* Use the override segment instead */
1617 Segment
= State
->SegmentOverride
;
1620 /* Read the selector */
1621 if (!Fast486ReadMemory(State
,
1623 ModRegRm
.MemoryAddress
+ sizeof(USHORT
),
1628 /* Exception occurred */
1632 /* Push the current value of CS */
1633 if (!Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_CS
].Selector
))
1635 /* Exception occurred */
1639 /* Push the current value of IP */
1640 if (!Fast486StackPush(State
, State
->InstPtr
.LowWord
))
1642 /* Exception occurred */
1646 /* Load the new code segment */
1647 if (!Fast486LoadSegment(State
, FAST486_REG_CS
, Selector
))
1649 /* Exception occurred */
1653 /* Set the IP to the address */
1654 State
->InstPtr
.LowWord
= Value
;
1656 /* Clear the top half of EIP */
1657 State
->InstPtr
.Long
&= 0xFFFF;
1659 else if (ModRegRm
.Register
== 4)
1661 /* Set the IP to the address */
1662 State
->InstPtr
.LowWord
= Value
;
1664 /* Clear the top half of EIP */
1665 State
->InstPtr
.Long
&= 0xFFFF;
1667 else if (ModRegRm
.Register
== 5)
1670 FAST486_SEG_REGS Segment
= FAST486_REG_DS
;
1672 /* Check for the segment override */
1673 if (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
1675 /* Use the override segment instead */
1676 Segment
= State
->SegmentOverride
;
1679 /* Read the selector */
1680 if (!Fast486ReadMemory(State
,
1682 ModRegRm
.MemoryAddress
+ sizeof(USHORT
),
1687 /* Exception occurred */
1691 /* Load the new code segment */
1692 if (!Fast486LoadSegment(State
, FAST486_REG_CS
, Selector
))
1694 /* Exception occurred */
1698 /* Set the IP to the address */
1699 State
->InstPtr
.LowWord
= Value
;
1701 /* Clear the top half of EIP */
1702 State
->InstPtr
.Long
&= 0xFFFF;
1704 else if (ModRegRm
.Register
== 6)
1706 /* Push the value on to the stack */
1707 Fast486StackPush(State
, Value
);
1713 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1717 if (ModRegRm
.Register
<= 1)
1720 State
->Flags
.Sf
= ((Value
& SIGN_FLAG_WORD
) != 0);
1721 State
->Flags
.Zf
= (Value
== 0);
1722 State
->Flags
.Pf
= Fast486CalculateParity(Value
);
1724 /* Write back the result */
1725 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
);
1730 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0F00
)
1732 FAST486_MOD_REG_RM ModRegRm
;
1733 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1736 TOGGLE_ADSIZE(AddressSize
);
1738 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1740 /* Exception occurred */
1744 /* Check which operation this is */
1745 switch (ModRegRm
.Register
)
1750 /* Not recognized in real mode or virtual 8086 mode */
1751 if (!(State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
1754 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1758 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, State
->Ldtr
.Selector
);
1765 /* Not recognized in real mode or virtual 8086 mode */
1766 if (!(State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
1769 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1773 Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, State
->TaskReg
.Selector
);
1782 FAST486_SYSTEM_DESCRIPTOR GdtEntry
;
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 /* This is a privileged instruction */
1793 if (Fast486GetCurrentPrivLevel(State
) != 0)
1795 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
1799 if (!Fast486ReadModrmWordOperands(State
,
1804 /* Exception occurred */
1808 if (Selector
& SEGMENT_TABLE_INDICATOR
)
1810 /* This selector doesn't point to the GDT */
1811 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_GP
, Selector
);
1815 if (!Fast486ReadDescriptorEntry(State
,
1818 (PFAST486_GDT_ENTRY
)&GdtEntry
))
1820 /* Exception occurred */
1826 /* Invalid selector */
1827 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_GP
, Selector
);
1831 if (GET_SEGMENT_INDEX(Selector
) == 0)
1833 RtlZeroMemory(&State
->Ldtr
, sizeof(State
->Ldtr
));
1837 if (!GdtEntry
.Present
)
1839 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_NP
, Selector
);
1843 if (GdtEntry
.Signature
!= FAST486_LDT_SIGNATURE
)
1845 /* This is not a LDT descriptor */
1846 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_GP
, Selector
);
1850 /* Update the LDTR */
1851 State
->Ldtr
.Selector
= Selector
;
1852 State
->Ldtr
.Base
= GdtEntry
.Base
| (GdtEntry
.BaseMid
<< 16) | (GdtEntry
.BaseHigh
<< 24);
1853 State
->Ldtr
.Limit
= GdtEntry
.Limit
| (GdtEntry
.LimitHigh
<< 16);
1855 if (GdtEntry
.Granularity
)
1857 State
->Ldtr
.Limit
<<= 12;
1858 State
->Ldtr
.Limit
|= 0x00000FFF;
1869 FAST486_SYSTEM_DESCRIPTOR GdtEntry
;
1871 /* Not recognized in real mode or virtual 8086 mode */
1872 if (!(State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
1875 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1879 /* This is a privileged instruction */
1880 if (Fast486GetCurrentPrivLevel(State
) != 0)
1882 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
1886 if (!Fast486ReadModrmWordOperands(State
,
1891 /* Exception occurred */
1895 if (Selector
& SEGMENT_TABLE_INDICATOR
)
1897 /* This selector doesn't point to the GDT */
1898 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_GP
, Selector
);
1902 if (!Fast486ReadDescriptorEntry(State
,
1905 (PFAST486_GDT_ENTRY
)&GdtEntry
))
1907 /* Exception occurred */
1913 /* Invalid selector */
1914 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_GP
, Selector
);
1918 if (GET_SEGMENT_INDEX(Selector
) == 0)
1920 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
1924 if (!GdtEntry
.Present
)
1926 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_NP
, Selector
);
1930 if (GdtEntry
.Signature
!= FAST486_TSS_SIGNATURE
)
1932 /* This is not a TSS descriptor */
1933 Fast486ExceptionWithErrorCode(State
, FAST486_EXCEPTION_GP
, Selector
);
1938 State
->TaskReg
.Selector
= Selector
;
1939 State
->TaskReg
.Base
= GdtEntry
.Base
| (GdtEntry
.BaseMid
<< 16) | (GdtEntry
.BaseHigh
<< 24);
1940 State
->TaskReg
.Limit
= GdtEntry
.Limit
| (GdtEntry
.LimitHigh
<< 16);
1942 if (GdtEntry
.Granularity
)
1944 State
->TaskReg
.Limit
<<= 12;
1945 State
->TaskReg
.Limit
|= 0x00000FFF;
1957 FAST486_GDT_ENTRY GdtEntry
;
1959 /* Not recognized in real mode or virtual 8086 mode */
1960 if (!(State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
1963 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1967 /* This is a privileged instruction */
1968 if (Fast486GetCurrentPrivLevel(State
) != 0)
1970 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
1974 if (!Fast486ReadModrmWordOperands(State
,
1979 /* Exception occurred */
1983 if (!Fast486ReadDescriptorEntry(State
, Selector
, &Valid
, &GdtEntry
))
1985 /* Exception occurred */
1992 State
->Flags
.Zf
= FALSE
;
1996 /* Set ZF if it is valid and accessible */
1997 State
->Flags
.Zf
= GdtEntry
.Present
// must be present
1998 && GdtEntry
.SystemType
// must be a segment
1999 && (((ModRegRm
.Register
== 4)
2000 /* code segments are only readable if the RW bit is set */
2001 && (!GdtEntry
.Executable
|| GdtEntry
.ReadWrite
))
2002 || ((ModRegRm
.Register
== 5)
2003 /* code segments are never writable, data segments are writable when RW is set */
2004 && (!GdtEntry
.Executable
&& GdtEntry
.ReadWrite
)))
2006 * for segments other than conforming code segments,
2007 * both RPL and CPL must be less than or equal to DPL
2009 && ((!GdtEntry
.Executable
|| !GdtEntry
.DirConf
)
2010 && ((GET_SEGMENT_RPL(Selector
) <= GdtEntry
.Dpl
)
2011 && (Fast486GetCurrentPrivLevel(State
) <= GdtEntry
.Dpl
)))
2012 /* for conforming code segments, DPL must be less than or equal to CPL */
2013 && ((GdtEntry
.Executable
&& GdtEntry
.DirConf
)
2014 && (GdtEntry
.Dpl
<= Fast486GetCurrentPrivLevel(State
)));
2023 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2028 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0F01
)
2030 // FAST486_TABLE_REG TableReg;
2032 FAST486_MOD_REG_RM ModRegRm
;
2033 BOOLEAN OperandSize
, AddressSize
;
2034 FAST486_SEG_REGS Segment
= FAST486_REG_DS
;
2036 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2039 TOGGLE_OPSIZE(OperandSize
);
2040 TOGGLE_ADSIZE(AddressSize
);
2042 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2044 /* Exception occurred */
2048 /* Check for the segment override */
2049 if (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
2051 /* Use the override segment instead */
2052 Segment
= State
->SegmentOverride
;
2055 /* Check which operation this is */
2056 switch (ModRegRm
.Register
)
2061 if (!ModRegRm
.Memory
)
2063 /* The second operand must be a memory location */
2064 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2068 /* Fill the 6-byte table register */
2069 // TableReg = State->Gdtr;
2070 *((PUSHORT
)&TableReg
) = State
->Gdtr
.Size
;
2071 *((PULONG
)&TableReg
[sizeof(USHORT
)]) = State
->Gdtr
.Address
;
2073 /* Store the GDTR */
2074 Fast486WriteMemory(State
,
2076 ModRegRm
.MemoryAddress
,
2086 if (!ModRegRm
.Memory
)
2088 /* The second operand must be a memory location */
2089 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2093 /* Fill the 6-byte table register */
2094 // TableReg = State->Idtr;
2095 *((PUSHORT
)&TableReg
) = State
->Idtr
.Size
;
2096 *((PULONG
)&TableReg
[sizeof(USHORT
)]) = State
->Idtr
.Address
;
2098 /* Store the IDTR */
2099 Fast486WriteMemory(State
,
2101 ModRegRm
.MemoryAddress
,
2111 /* This is a privileged instruction */
2112 if (Fast486GetCurrentPrivLevel(State
) != 0)
2114 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
2118 if (!ModRegRm
.Memory
)
2120 /* The second operand must be a memory location */
2121 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2125 /* Read the new GDTR */
2126 if (!Fast486ReadMemory(State
,
2128 ModRegRm
.MemoryAddress
,
2133 /* Exception occurred */
2137 /* Load the new GDT */
2138 // State->Gdtr = TableReg;
2139 State
->Gdtr
.Size
= *((PUSHORT
)&TableReg
);
2140 State
->Gdtr
.Address
= *((PULONG
)&TableReg
[sizeof(USHORT
)]);
2142 /* In 16-bit mode the highest byte is masked out */
2143 if (!OperandSize
) State
->Gdtr
.Address
&= 0x00FFFFFF;
2151 /* This is a privileged instruction */
2152 if (Fast486GetCurrentPrivLevel(State
) != 0)
2154 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
2158 if (!ModRegRm
.Memory
)
2160 /* The second operand must be a memory location */
2161 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2165 /* Read the new IDTR */
2166 if (!Fast486ReadMemory(State
,
2168 ModRegRm
.MemoryAddress
,
2173 /* Exception occurred */
2177 /* Load the new IDT */
2178 // State->Idtr = TableReg;
2179 State
->Idtr
.Size
= *((PUSHORT
)&TableReg
);
2180 State
->Idtr
.Address
= *((PULONG
)&TableReg
[sizeof(USHORT
)]);
2182 /* In 16-bit mode the highest byte is masked out */
2183 if (!OperandSize
) State
->Idtr
.Address
&= 0x00FFFFFF;
2191 /* Store the lower 16 bits (Machine Status Word) of CR0 */
2192 Fast486WriteModrmWordOperands(State
,
2195 LOWORD(State
->ControlRegisters
[FAST486_REG_CR0
]));
2203 USHORT MachineStatusWord
;
2205 /* This is a privileged instruction */
2206 if (Fast486GetCurrentPrivLevel(State
) != 0)
2208 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
2212 /* Read the new Machine Status Word */
2213 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, &MachineStatusWord
))
2215 /* Exception occurred */
2219 /* This instruction cannot be used to return to real mode */
2220 if ((State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
2221 && !(MachineStatusWord
& FAST486_CR0_PE
))
2223 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
2227 /* Set the lowest 4 bits */
2228 State
->ControlRegisters
[FAST486_REG_CR0
] &= 0xFFFFFFF0;
2229 State
->ControlRegisters
[FAST486_REG_CR0
] |= MachineStatusWord
& 0x0F;
2237 #ifndef FAST486_NO_PREFETCH
2238 /* Invalidate the prefetch */
2239 State
->PrefetchValid
= FALSE
;
2242 /* This is a privileged instruction */
2243 if (Fast486GetCurrentPrivLevel(State
) != 0)
2245 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
2249 if (!ModRegRm
.Memory
)
2251 /* The second operand must be a memory location */
2252 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2256 if (State
->Tlb
!= NULL
)
2258 /* Clear the TLB entry */
2259 State
->Tlb
[ModRegRm
.MemoryAddress
>> 12] = INVALID_TLB_FIELD
;
2268 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2273 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0FB9
)
2275 FAST486_MOD_REG_RM ModRegRm
;
2276 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2278 TOGGLE_ADSIZE(AddressSize
);
2280 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2282 /* Exception occurred */
2286 /* All of them are reserved (UD2) */
2287 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2291 FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0FBA
)
2293 FAST486_MOD_REG_RM ModRegRm
;
2294 BOOLEAN OperandSize
, AddressSize
;
2298 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2300 TOGGLE_OPSIZE(OperandSize
);
2301 TOGGLE_ADSIZE(AddressSize
);
2303 /* Get the number of bits */
2304 if (OperandSize
) DataSize
= 32;
2307 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2309 /* Exception occurred */
2313 if (ModRegRm
.Register
< 4)
2316 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2320 /* Get the bit number */
2321 if (!Fast486FetchByte(State
, &BitNumber
))
2323 /* Exception occurred */
2327 if (ModRegRm
.Memory
)
2330 * For memory operands, add the bit offset divided by
2331 * the data size to the address
2333 ModRegRm
.MemoryAddress
+= BitNumber
/ DataSize
;
2336 /* Normalize the bit number */
2337 BitNumber
%= DataSize
;
2343 /* Read the value */
2344 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, NULL
, &Value
))
2346 /* Exception occurred */
2350 /* Set CF to the bit value */
2351 State
->Flags
.Cf
= (Value
>> BitNumber
) & 1;
2353 if (ModRegRm
.Register
== 5)
2356 Value
|= 1 << BitNumber
;
2358 else if (ModRegRm
.Register
== 6)
2361 Value
&= ~(1 << BitNumber
);
2363 else if (ModRegRm
.Register
== 7)
2366 Value
^= 1 << BitNumber
;
2369 if (ModRegRm
.Register
>= 5)
2371 /* Write back the result */
2372 if (!Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
))
2374 /* Exception occurred */
2383 /* Read the value */
2384 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, NULL
, &Value
))
2386 /* Exception occurred */
2390 /* Set CF to the bit value */
2391 State
->Flags
.Cf
= (Value
>> BitNumber
) & 1;
2393 if (ModRegRm
.Register
== 5)
2396 Value
|= 1 << BitNumber
;
2398 else if (ModRegRm
.Register
== 6)
2401 Value
&= ~(1 << BitNumber
);
2403 else if (ModRegRm
.Register
== 7)
2406 Value
^= 1 << BitNumber
;
2409 if (ModRegRm
.Register
>= 5)
2411 /* Write back the result */
2412 if (!Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
))
2414 /* Exception occurred */