2 * Fast486 386/486 CPU Emulation Library
5 * Copyright (C) 2013 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 *******************************************************************/
24 // #define WIN32_NO_STATUS
25 // #define _INC_WINDOWS
35 /* PRIVATE FUNCTIONS **********************************************************/
40 Fast486ArithmeticOperation(PFAST486_STATE State
,
47 ULONG SignFlag
= 1 << (Bits
- 1);
48 ULONG MaxValue
= (1 << Bits
) - 1;
50 /* Make sure the values don't exceed the maximum for their size */
51 FirstValue
&= MaxValue
;
52 SecondValue
&= MaxValue
;
54 /* Check which operation is this */
60 Result
= (FirstValue
+ SecondValue
) & MaxValue
;
62 /* Update CF, OF and AF */
63 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
64 State
->Flags
.Of
= ((FirstValue
& SignFlag
) == (SecondValue
& SignFlag
))
65 && ((FirstValue
& SignFlag
) != (Result
& SignFlag
));
66 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
74 Result
= FirstValue
| SecondValue
;
81 INT Carry
= State
->Flags
.Cf
? 1 : 0;
83 Result
= (FirstValue
+ SecondValue
+ Carry
) & MaxValue
;
85 /* Update CF, OF and AF */
86 State
->Flags
.Cf
= ((SecondValue
== MaxValue
) && (Carry
== 1))
87 || ((Result
< FirstValue
) && (Result
< (SecondValue
+ Carry
)));
88 State
->Flags
.Of
= ((FirstValue
& SignFlag
) == (SecondValue
& SignFlag
))
89 && ((FirstValue
& SignFlag
) != (Result
& SignFlag
));
90 State
->Flags
.Af
= (((FirstValue
& 0x0F) + ((SecondValue
+ Carry
) & 0x0F)) & 0x10)
99 INT Carry
= State
->Flags
.Cf
? 1 : 0;
101 Result
= (FirstValue
- SecondValue
- Carry
) & MaxValue
;
103 /* Update CF, OF and AF */
104 State
->Flags
.Cf
= FirstValue
< (SecondValue
+ Carry
);
105 State
->Flags
.Of
= ((FirstValue
& SignFlag
) != (SecondValue
& SignFlag
))
106 && ((FirstValue
& SignFlag
) != (Result
& SignFlag
));
107 State
->Flags
.Af
= (FirstValue
& 0x0F) < ((SecondValue
+ Carry
) & 0x0F);
115 Result
= FirstValue
& SecondValue
;
123 Result
= (FirstValue
- SecondValue
) & MaxValue
;
125 /* Update CF, OF and AF */
126 State
->Flags
.Cf
= FirstValue
< SecondValue
;
127 State
->Flags
.Of
= ((FirstValue
& SignFlag
) != (SecondValue
& SignFlag
))
128 && ((FirstValue
& SignFlag
) != (Result
& SignFlag
));
129 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
137 Result
= FirstValue
^ SecondValue
;
143 /* Shouldn't happen */
148 /* Update ZF, SF and PF */
149 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
150 State
->Flags
.Sf
= (Result
& SignFlag
) ? TRUE
: FALSE
;
151 State
->Flags
.Pf
= Fast486CalculateParity(LOBYTE(Result
));
153 /* Return the result */
160 Fast486RotateOperation(PFAST486_STATE State
,
166 ULONG HighestBit
= 1 << (Bits
- 1);
169 if ((Operation
!= 2) && (Operation
!= 3))
176 /* For RCL and RCR, the CF is included in the value */
180 /* Check which operation is this */
186 Result
= (Value
<< Count
) | (Value
>> (Bits
- Count
));
188 /* Update CF and OF */
189 State
->Flags
.Cf
= Result
& 1;
190 if (Count
== 1) State
->Flags
.Of
= ((Result
& HighestBit
) ? TRUE
: FALSE
)
199 Result
= (Value
>> Count
) | (Value
<< (Bits
- Count
));
201 /* Update CF and OF */
202 State
->Flags
.Cf
= (Result
& HighestBit
) ? TRUE
: FALSE
;
203 if (Count
== 1) State
->Flags
.Of
= State
->Flags
.Cf
204 ^ ((Result
& (HighestBit
>> 1))
213 Result
= (Value
<< Count
)
214 | (State
->Flags
.Cf
<< (Count
- 1))
215 | (Value
>> (Bits
- Count
+ 1));
217 /* Update CF and OF */
218 State
->Flags
.Cf
= (Value
& (1 << (Bits
- Count
))) ? TRUE
: FALSE
;
219 if (Count
== 1) State
->Flags
.Of
= ((Result
& HighestBit
) ? TRUE
: FALSE
)
228 Result
= (Value
>> Count
)
229 | (State
->Flags
.Cf
<< (Bits
- Count
))
230 | (Value
<< (Bits
- Count
+ 1));
232 /* Update CF and OF */
233 State
->Flags
.Cf
= (Value
& (1 << (Bits
- Count
))) ? TRUE
: FALSE
;
234 if (Count
== 1) State
->Flags
.Of
= State
->Flags
.Cf
235 ^ ((Result
& (HighestBit
>> 1))
245 Result
= Value
<< Count
;
247 /* Update CF and OF */
248 State
->Flags
.Cf
= (Value
& (1 << (Bits
- Count
))) ? TRUE
: FALSE
;
249 if (Count
== 1) State
->Flags
.Of
= ((Result
& HighestBit
) ? TRUE
: FALSE
)
250 ^ (State
->Flags
.Cf
? TRUE
: FALSE
);
258 Result
= Value
>> Count
;
260 /* Update CF and OF */
261 State
->Flags
.Cf
= (Value
& (1 << (Count
- 1))) ? TRUE
: FALSE
;
262 if (Count
== 1) State
->Flags
.Of
= (Value
& HighestBit
) ? TRUE
: FALSE
;
270 Result
= Value
>> Count
;
272 /* Fill the top Count bits with the sign bit */
273 if (Value
& HighestBit
) Result
|= ((1 << Count
) - 1) << (Bits
- Count
);
275 /* Update CF and OF */
276 State
->Flags
.Cf
= (Value
& (1 << (Count
- 1))) ? TRUE
: FALSE
;
277 if (Count
== 1) State
->Flags
.Of
= FALSE
;
283 /* Update ZF, SF and PF */
284 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
285 State
->Flags
.Sf
= (Result
& HighestBit
) ? TRUE
: FALSE
;
286 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
288 /* Return the result */
292 /* PUBLIC FUNCTIONS ***********************************************************/
294 FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8082
)
296 UCHAR Immediate
, Dummy
, Value
;
297 FAST486_MOD_REG_RM ModRegRm
;
298 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
300 TOGGLE_ADSIZE(AddressSize
);
302 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
304 /* Exception occurred */
308 /* Fetch the immediate operand */
309 if (!Fast486FetchByte(State
, &Immediate
))
311 /* Exception occurred */
315 /* Read the operands */
316 if (!Fast486ReadModrmByteOperands(State
, &ModRegRm
, &Dummy
, &Value
))
318 /* Exception occurred */
322 /* Calculate the result */
323 Value
= Fast486ArithmeticOperation(State
, ModRegRm
.Register
, Value
, Immediate
, 8);
325 /* Unless this is CMP, write back the result */
326 if (ModRegRm
.Register
!= 7)
328 return Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Value
);
334 FAST486_OPCODE_HANDLER(Fast486OpcodeGroup81
)
336 FAST486_MOD_REG_RM ModRegRm
;
337 BOOLEAN OperandSize
, AddressSize
;
339 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
341 TOGGLE_OPSIZE(OperandSize
);
342 TOGGLE_ADSIZE(AddressSize
);
344 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
346 /* Exception occurred */
352 ULONG Immediate
, Value
, Dummy
;
354 /* Fetch the immediate operand */
355 if (!Fast486FetchDword(State
, &Immediate
))
357 /* Exception occurred */
361 /* Read the operands */
362 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
364 /* Exception occurred */
368 /* Calculate the result */
369 Value
= Fast486ArithmeticOperation(State
, ModRegRm
.Register
, Value
, Immediate
, 32);
371 /* Unless this is CMP, write back the result */
372 if (ModRegRm
.Register
!= 7)
374 return Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
379 USHORT Immediate
, Value
, Dummy
;
381 /* Fetch the immediate operand */
382 if (!Fast486FetchWord(State
, &Immediate
))
384 /* Exception occurred */
388 /* Read the operands */
389 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
391 /* Exception occurred */
395 /* Calculate the result */
396 Value
= Fast486ArithmeticOperation(State
, ModRegRm
.Register
, Value
, Immediate
, 16);
398 /* Unless this is CMP, write back the result */
399 if (ModRegRm
.Register
!= 7)
401 return Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
);
408 FAST486_OPCODE_HANDLER(Fast486OpcodeGroup83
)
411 FAST486_MOD_REG_RM ModRegRm
;
412 BOOLEAN OperandSize
, AddressSize
;
414 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
416 TOGGLE_OPSIZE(OperandSize
);
417 TOGGLE_ADSIZE(AddressSize
);
419 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
421 /* Exception occurred */
425 /* Fetch the immediate operand */
426 if (!Fast486FetchByte(State
, (PUCHAR
)&ImmByte
))
428 /* Exception occurred */
434 ULONG Immediate
= (ULONG
)((LONG
)ImmByte
); // Sign extend
437 /* Read the operands */
438 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
440 /* Exception occurred */
444 /* Calculate the result */
445 Value
= Fast486ArithmeticOperation(State
, ModRegRm
.Register
, Value
, Immediate
, 32);
447 /* Unless this is CMP, write back the result */
448 if (ModRegRm
.Register
!= 7)
450 return Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
455 USHORT Immediate
= (USHORT
)((SHORT
)ImmByte
); // Sign extend
458 /* Read the operands */
459 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
461 /* Exception occurred */
465 /* Calculate the result */
466 Value
= Fast486ArithmeticOperation(State
, ModRegRm
.Register
, Value
, Immediate
, 16);
468 /* Unless this is CMP, write back the result */
469 if (ModRegRm
.Register
!= 7)
471 return Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
);
478 FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8F
)
481 FAST486_MOD_REG_RM ModRegRm
;
482 BOOLEAN OperandSize
, AddressSize
;
484 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
486 TOGGLE_OPSIZE(OperandSize
);
487 TOGGLE_ADSIZE(AddressSize
);
489 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
491 /* Exception occurred */
495 if (ModRegRm
.Register
!= 0)
498 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
502 /* Pop a value from the stack */
503 if (!Fast486StackPop(State
, &Value
))
505 /* Exception occurred */
511 return Fast486WriteModrmDwordOperands(State
,
518 return Fast486WriteModrmWordOperands(State
,
525 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC0
)
527 UCHAR Dummy
, Value
, Count
;
528 FAST486_MOD_REG_RM ModRegRm
;
529 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
531 TOGGLE_ADSIZE(AddressSize
);
533 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
535 /* Exception occurred */
539 /* Fetch the count */
540 if (!Fast486FetchByte(State
, &Count
))
542 /* Exception occurred */
546 /* Read the operands */
547 if (!Fast486ReadModrmByteOperands(State
, &ModRegRm
, &Dummy
, &Value
))
549 /* Exception occurred */
553 /* Calculate the result */
554 Value
= LOBYTE(Fast486RotateOperation(State
,
560 /* Write back the result */
561 return Fast486WriteModrmByteOperands(State
,
567 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC1
)
570 FAST486_MOD_REG_RM ModRegRm
;
571 BOOLEAN OperandSize
, AddressSize
;
573 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
575 TOGGLE_OPSIZE(OperandSize
);
576 TOGGLE_ADSIZE(AddressSize
);
578 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
580 /* Exception occurred */
584 /* Fetch the count */
585 if (!Fast486FetchByte(State
, &Count
))
587 /* Exception occurred */
595 /* Read the operands */
596 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
598 /* Exception occurred */
602 /* Calculate the result */
603 Value
= Fast486RotateOperation(State
,
609 /* Write back the result */
610 return Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
616 /* Read the operands */
617 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
619 /* Exception occurred */
623 /* Calculate the result */
624 Value
= LOWORD(Fast486RotateOperation(State
,
630 /* Write back the result */
631 return Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
);
635 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC6
)
638 FAST486_MOD_REG_RM ModRegRm
;
639 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
641 TOGGLE_ADSIZE(AddressSize
);
643 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
645 /* Exception occurred */
649 if (ModRegRm
.Register
!= 0)
652 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
656 /* Get the immediate operand */
657 if (!Fast486FetchByte(State
, &Immediate
))
659 /* Exception occurred */
663 return Fast486WriteModrmByteOperands(State
,
669 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC7
)
671 FAST486_MOD_REG_RM ModRegRm
;
672 BOOLEAN OperandSize
, AddressSize
;
674 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
676 TOGGLE_OPSIZE(OperandSize
);
677 TOGGLE_ADSIZE(AddressSize
);
679 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
681 /* Exception occurred */
685 if (ModRegRm
.Register
!= 0)
688 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
696 /* Get the immediate operand */
697 if (!Fast486FetchDword(State
, &Immediate
))
699 /* Exception occurred */
703 return Fast486WriteModrmDwordOperands(State
,
712 /* Get the immediate operand */
713 if (!Fast486FetchWord(State
, &Immediate
))
715 /* Exception occurred */
719 return Fast486WriteModrmWordOperands(State
,
726 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD0
)
729 FAST486_MOD_REG_RM ModRegRm
;
730 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
732 TOGGLE_ADSIZE(AddressSize
);
734 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
736 /* Exception occurred */
740 /* Read the operands */
741 if (!Fast486ReadModrmByteOperands(State
, &ModRegRm
, &Dummy
, &Value
))
743 /* Exception occurred */
747 /* Calculate the result */
748 Value
= LOBYTE(Fast486RotateOperation(State
, ModRegRm
.Register
, Value
, 8, 1));
750 /* Write back the result */
751 return Fast486WriteModrmByteOperands(State
,
758 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD1
)
760 FAST486_MOD_REG_RM ModRegRm
;
761 BOOLEAN OperandSize
, AddressSize
;
763 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
765 TOGGLE_OPSIZE(OperandSize
);
766 TOGGLE_ADSIZE(AddressSize
);
768 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
770 /* Exception occurred */
778 /* Read the operands */
779 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
781 /* Exception occurred */
785 /* Calculate the result */
786 Value
= Fast486RotateOperation(State
, ModRegRm
.Register
, Value
, 32, 1);
788 /* Write back the result */
789 return Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
795 /* Read the operands */
796 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
798 /* Exception occurred */
802 /* Calculate the result */
803 Value
= LOWORD(Fast486RotateOperation(State
, ModRegRm
.Register
, Value
, 16, 1));
805 /* Write back the result */
806 return Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
);
810 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD2
)
813 FAST486_MOD_REG_RM ModRegRm
;
814 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
816 TOGGLE_ADSIZE(AddressSize
);
818 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
820 /* Exception occurred */
824 /* Read the operands */
825 if (!Fast486ReadModrmByteOperands(State
, &ModRegRm
, &Dummy
, &Value
))
827 /* Exception occurred */
831 /* Calculate the result */
832 Value
= LOBYTE(Fast486RotateOperation(State
,
836 State
->GeneralRegs
[FAST486_REG_ECX
].LowByte
));
838 /* Write back the result */
839 return Fast486WriteModrmByteOperands(State
,
845 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD3
)
847 FAST486_MOD_REG_RM ModRegRm
;
848 BOOLEAN OperandSize
, AddressSize
;
850 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
852 TOGGLE_OPSIZE(OperandSize
);
853 TOGGLE_ADSIZE(AddressSize
);
855 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
857 /* Exception occurred */
865 /* Read the operands */
866 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
868 /* Exception occurred */
872 /* Calculate the result */
873 Value
= Fast486RotateOperation(State
,
877 State
->GeneralRegs
[FAST486_REG_ECX
].LowByte
);
879 /* Write back the result */
880 return Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Value
);
886 /* Read the operands */
887 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
889 /* Exception occurred */
893 /* Calculate the result */
894 Value
= LOWORD(Fast486RotateOperation(State
,
898 State
->GeneralRegs
[FAST486_REG_ECX
].LowByte
));
900 /* Write back the result */
901 return Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, Value
);
905 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6
)
907 UCHAR Dummy
, Value
= 0;
908 FAST486_MOD_REG_RM ModRegRm
;
909 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
911 TOGGLE_ADSIZE(AddressSize
);
913 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
915 /* Exception occurred */
919 /* Read the operands */
920 if (!Fast486ReadModrmByteOperands(State
, &ModRegRm
, &Dummy
, &Value
))
922 /* Exception occurred */
926 switch (ModRegRm
.Register
)
932 UCHAR Immediate
, Result
;
934 /* Fetch the immediate byte */
935 if (!Fast486FetchByte(State
, &Immediate
))
937 /* Exception occurred */
941 /* Calculate the result */
942 Result
= Value
& Immediate
;
944 /* Update the flags */
945 State
->Flags
.Cf
= FALSE
;
946 State
->Flags
.Of
= FALSE
;
947 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
948 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
949 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
957 /* Write back the result */
958 return Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, ~Value
);
964 /* Calculate the result */
965 UCHAR Result
= -Value
;
967 /* Update the flags */
968 State
->Flags
.Cf
= (Value
!= 0) ? TRUE
: FALSE
;
969 State
->Flags
.Of
= (Value
& SIGN_FLAG_BYTE
) && (Result
& SIGN_FLAG_BYTE
);
970 State
->Flags
.Af
= ((Value
& 0x0F) != 0) ? TRUE
: FALSE
;
971 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
972 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
973 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
975 /* Write back the result */
976 return Fast486WriteModrmByteOperands(State
, &ModRegRm
, FALSE
, Result
);
982 USHORT Result
= (USHORT
)Value
* (USHORT
)State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
984 /* Update the flags */
985 State
->Flags
.Cf
= State
->Flags
.Of
= HIBYTE(Result
) ? TRUE
: FALSE
;
987 /* Write back the result */
988 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Result
;
996 SHORT Result
= (SHORT
)((CHAR
)Value
) * (SHORT
)((CHAR
)State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
);
998 /* Update the flags */
999 State
->Flags
.Cf
= State
->Flags
.Of
=
1000 ((Result
< -128) || (Result
> 127)) ? TRUE
: FALSE
;
1002 /* Write back the result */
1003 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= (USHORT
)Result
;
1011 UCHAR Quotient
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
/ Value
;
1012 UCHAR Remainder
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
% Value
;
1014 /* Write back the results */
1015 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= Quotient
;
1016 State
->GeneralRegs
[FAST486_REG_EAX
].HighByte
= Remainder
;
1024 CHAR Quotient
= (SHORT
)State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
/ (CHAR
)Value
;
1025 CHAR Remainder
= (SHORT
)State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
% (CHAR
)Value
;
1027 /* Write back the results */
1028 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= (UCHAR
)Quotient
;
1029 State
->GeneralRegs
[FAST486_REG_EAX
].HighByte
= (UCHAR
)Remainder
;
1038 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7
)
1040 ULONG Dummy
, Value
= 0, SignFlag
;
1041 FAST486_MOD_REG_RM ModRegRm
;
1042 BOOLEAN OperandSize
, AddressSize
;
1044 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1046 TOGGLE_OPSIZE(OperandSize
);
1047 TOGGLE_ADSIZE(AddressSize
);
1049 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1051 /* Exception occurred */
1055 /* Set the sign flag */
1056 if (OperandSize
) SignFlag
= SIGN_FLAG_LONG
;
1057 else SignFlag
= SIGN_FLAG_WORD
;
1059 /* Read the operand */
1063 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
1065 /* Exception occurred */
1072 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, (PUSHORT
)&Dummy
, (PUSHORT
)&Value
))
1074 /* Exception occurred */
1079 switch (ModRegRm
.Register
)
1085 ULONG Immediate
= 0, Result
= 0;
1089 /* Fetch the immediate dword */
1090 if (!Fast486FetchDword(State
, &Immediate
))
1092 /* Exception occurred */
1098 /* Fetch the immediate word */
1099 if (!Fast486FetchWord(State
, (PUSHORT
)&Immediate
))
1101 /* Exception occurred */
1106 /* Calculate the result */
1107 Result
= Value
& Immediate
;
1109 /* Update the flags */
1110 State
->Flags
.Cf
= FALSE
;
1111 State
->Flags
.Of
= FALSE
;
1112 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1113 State
->Flags
.Sf
= (Result
& SignFlag
) ? TRUE
: FALSE
;
1114 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1122 /* Write back the result */
1126 return Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, ~Value
);
1131 return Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, LOWORD(~Value
));
1138 /* Calculate the result */
1139 ULONG Result
= -Value
;
1140 if (!OperandSize
) Result
&= 0xFFFF;
1142 /* Update the flags */
1143 State
->Flags
.Cf
= (Value
!= 0) ? TRUE
: FALSE
;
1144 State
->Flags
.Of
= (Value
& SignFlag
) && (Result
& SignFlag
);
1145 State
->Flags
.Af
= ((Value
& 0x0F) != 0) ? TRUE
: FALSE
;
1146 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1147 State
->Flags
.Sf
= (Result
& SignFlag
) ? TRUE
: FALSE
;
1148 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1150 /* Write back the result */
1154 return Fast486WriteModrmDwordOperands(State
, &ModRegRm
, FALSE
, Result
);
1159 return Fast486WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, LOWORD(Result
));
1168 ULONGLONG Result
= (ULONGLONG
)Value
* (ULONGLONG
)State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
1170 /* Update the flags */
1171 State
->Flags
.Cf
= State
->Flags
.Of
=
1172 (Result
& 0xFFFFFFFF00000000ULL
) ? TRUE
: FALSE
;
1174 /* Write back the result */
1175 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Result
& 0xFFFFFFFFULL
;
1176 State
->GeneralRegs
[FAST486_REG_EDX
].Long
= Result
>> 32;
1180 ULONG Result
= (ULONG
)Value
* (ULONG
)State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
1182 /* Update the flags */
1183 State
->Flags
.Cf
= State
->Flags
.Of
= HIWORD(Result
) ? TRUE
: FALSE
;
1185 /* Write back the result */
1186 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= LOWORD(Result
);
1187 State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
= HIWORD(Result
);
1198 LONGLONG Result
= (LONGLONG
)((LONG
)Value
) * (LONGLONG
)((LONG
)State
->GeneralRegs
[FAST486_REG_EAX
].Long
);
1200 /* Update the flags */
1201 State
->Flags
.Cf
= State
->Flags
.Of
=
1202 ((Result
< -2147483648LL) || (Result
> 2147483647LL)) ? TRUE
: FALSE
;
1204 /* Write back the result */
1205 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Result
& 0xFFFFFFFFULL
;
1206 State
->GeneralRegs
[FAST486_REG_EDX
].Long
= Result
>> 32;
1210 LONG Result
= (LONG
)((SHORT
)Value
) * (LONG
)((SHORT
)State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
);
1212 /* Update the flags */
1213 State
->Flags
.Cf
= State
->Flags
.Of
=
1214 ((Result
< -32768) || (Result
> 32767)) ? TRUE
: FALSE
;
1216 /* Write back the result */
1217 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= LOWORD(Result
);
1218 State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
= HIWORD(Result
);
1229 ULONGLONG Dividend
= (ULONGLONG
)State
->GeneralRegs
[FAST486_REG_EAX
].Long
1230 | ((ULONGLONG
)State
->GeneralRegs
[FAST486_REG_EDX
].Long
<< 32);
1231 ULONG Quotient
= Dividend
/ Value
;
1232 ULONG Remainder
= Dividend
% Value
;
1234 /* Write back the results */
1235 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Quotient
;
1236 State
->GeneralRegs
[FAST486_REG_EDX
].Long
= Remainder
;
1240 ULONG Dividend
= (ULONG
)State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
1241 | ((ULONG
)State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
<< 16);
1242 USHORT Quotient
= Dividend
/ Value
;
1243 USHORT Remainder
= Dividend
% Value
;
1245 /* Write back the results */
1246 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Quotient
;
1247 State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
= Remainder
;
1258 LONGLONG Dividend
= (LONGLONG
)State
->GeneralRegs
[FAST486_REG_EAX
].Long
1259 | ((LONGLONG
)State
->GeneralRegs
[FAST486_REG_EDX
].Long
<< 32);
1260 LONG Quotient
= Dividend
/ (LONG
)Value
;
1261 LONG Remainder
= Dividend
% (LONG
)Value
;
1263 /* Write back the results */
1264 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= (ULONG
)Quotient
;
1265 State
->GeneralRegs
[FAST486_REG_EDX
].Long
= (ULONG
)Remainder
;
1269 LONG Dividend
= (LONG
)State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
1270 | ((LONG
)State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
<< 16);
1271 SHORT Quotient
= Dividend
/ (SHORT
)LOWORD(Value
);
1272 SHORT Remainder
= Dividend
% (SHORT
)LOWORD(Value
);
1274 /* Write back the results */
1275 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= (USHORT
)Quotient
;
1276 State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
= (USHORT
)Remainder
;
1286 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFE
)
1289 FAST486_MOD_REG_RM ModRegRm
;
1290 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1292 TOGGLE_ADSIZE(AddressSize
);
1294 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1296 /* Exception occurred */
1300 if (ModRegRm
.Register
> 1)
1303 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1307 /* Read the operands */
1308 if (!Fast486ReadModrmByteOperands(State
, &ModRegRm
, &Dummy
, &Value
))
1310 /* Exception occurred */
1314 if (ModRegRm
.Register
== 0)
1316 /* Increment and update OF and AF */
1318 State
->Flags
.Of
= (Value
== SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1319 State
->Flags
.Af
= ((Value
& 0x0F) == 0);
1323 /* Decrement and update OF and AF */
1324 State
->Flags
.Of
= (Value
== SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1326 State
->Flags
.Af
= ((Value
& 0x0F) == 0x0F);
1330 State
->Flags
.Sf
= (Value
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1331 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
1332 State
->Flags
.Pf
= Fast486CalculateParity(Value
);
1334 /* Write back the result */
1335 return Fast486WriteModrmByteOperands(State
,
1341 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF
)
1343 FAST486_MOD_REG_RM ModRegRm
;
1344 BOOLEAN OperandSize
, AddressSize
;
1346 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1348 TOGGLE_OPSIZE(OperandSize
);
1349 TOGGLE_ADSIZE(AddressSize
);
1351 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1353 /* Exception occurred */
1357 if (ModRegRm
.Register
== 7)
1360 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1364 /* Read the operands */
1369 if (!Fast486ReadModrmDwordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
1371 /* Exception occurred */
1375 if (ModRegRm
.Register
== 0)
1377 /* Increment and update OF and AF */
1379 State
->Flags
.Of
= (Value
== SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1380 State
->Flags
.Af
= ((Value
& 0x0F) == 0);
1382 else if (ModRegRm
.Register
== 1)
1384 /* Decrement and update OF and AF */
1385 State
->Flags
.Of
= (Value
== SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1387 State
->Flags
.Af
= ((Value
& 0x0F) == 0x0F);
1389 else if (ModRegRm
.Register
== 2)
1391 /* Push the current value of EIP */
1392 if (!Fast486StackPush(State
, State
->InstPtr
.Long
))
1394 /* Exception occurred */
1398 /* Set the EIP to the address */
1399 State
->InstPtr
.Long
= Value
;
1401 else if (ModRegRm
.Register
== 3)
1404 INT Segment
= FAST486_REG_DS
;
1406 /* Check for the segment override */
1407 if (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
1409 /* Use the override segment instead */
1410 Segment
= State
->SegmentOverride
;
1413 /* Read the selector */
1414 if (!Fast486ReadMemory(State
,
1416 ModRegRm
.MemoryAddress
+ sizeof(ULONG
),
1421 /* Exception occurred */
1425 /* Push the current value of CS */
1426 if (!Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_CS
].Selector
))
1428 /* Exception occurred */
1432 /* Push the current value of EIP */
1433 if (!Fast486StackPush(State
, State
->InstPtr
.Long
))
1435 /* Exception occurred */
1439 /* Load the new code segment */
1440 if (!Fast486LoadSegment(State
, FAST486_REG_CS
, Selector
))
1442 /* Exception occurred */
1446 /* Set the EIP to the address */
1447 State
->InstPtr
.Long
= Value
;
1449 else if (ModRegRm
.Register
== 4)
1451 /* Set the EIP to the address */
1452 State
->InstPtr
.Long
= Value
;
1454 else if (ModRegRm
.Register
== 5)
1457 INT Segment
= FAST486_REG_DS
;
1459 /* Check for the segment override */
1460 if (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
1462 /* Use the override segment instead */
1463 Segment
= State
->SegmentOverride
;
1466 /* Read the selector */
1467 if (!Fast486ReadMemory(State
,
1469 ModRegRm
.MemoryAddress
+ sizeof(ULONG
),
1474 /* Exception occurred */
1478 /* Load the new code segment */
1479 if (!Fast486LoadSegment(State
, FAST486_REG_CS
, Selector
))
1481 /* Exception occurred */
1485 /* Set the EIP to the address */
1486 State
->InstPtr
.Long
= Value
;
1488 else if (ModRegRm
.Register
== 6)
1490 /* Push the value on to the stack */
1491 return Fast486StackPush(State
, Value
);
1494 if (ModRegRm
.Register
<= 1)
1497 State
->Flags
.Sf
= (Value
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1498 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
1499 State
->Flags
.Pf
= Fast486CalculateParity(Value
);
1501 /* Write back the result */
1502 return Fast486WriteModrmDwordOperands(State
,
1510 USHORT Dummy
, Value
;
1512 if (!Fast486ReadModrmWordOperands(State
, &ModRegRm
, &Dummy
, &Value
))
1514 /* Exception occurred */
1518 if (ModRegRm
.Register
== 0)
1520 /* Increment and update OF */
1522 State
->Flags
.Of
= (Value
== SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
1523 State
->Flags
.Af
= ((Value
& 0x0F) == 0);
1525 else if (ModRegRm
.Register
== 1)
1527 /* Decrement and update OF */
1528 State
->Flags
.Of
= (Value
== SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
1530 State
->Flags
.Af
= ((Value
& 0x0F) == 0x0F);
1532 else if (ModRegRm
.Register
== 2)
1534 /* Push the current value of IP */
1535 if (!Fast486StackPush(State
, State
->InstPtr
.LowWord
))
1537 /* Exception occurred */
1541 /* Set the IP to the address */
1542 State
->InstPtr
.LowWord
= Value
;
1544 else if (ModRegRm
.Register
== 3)
1547 INT Segment
= FAST486_REG_DS
;
1549 /* Check for the segment override */
1550 if (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
1552 /* Use the override segment instead */
1553 Segment
= State
->SegmentOverride
;
1556 /* Read the selector */
1557 if (!Fast486ReadMemory(State
,
1559 ModRegRm
.MemoryAddress
+ sizeof(USHORT
),
1564 /* Exception occurred */
1568 /* Push the current value of CS */
1569 if (!Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_CS
].Selector
))
1571 /* Exception occurred */
1575 /* Push the current value of IP */
1576 if (!Fast486StackPush(State
, State
->InstPtr
.LowWord
))
1578 /* Exception occurred */
1582 /* Load the new code segment */
1583 if (!Fast486LoadSegment(State
, FAST486_REG_CS
, Selector
))
1585 /* Exception occurred */
1589 /* Set the IP to the address */
1590 State
->InstPtr
.LowWord
= Value
;
1593 else if (ModRegRm
.Register
== 4)
1595 /* Set the IP to the address */
1596 State
->InstPtr
.LowWord
= Value
;
1598 else if (ModRegRm
.Register
== 5)
1601 INT Segment
= FAST486_REG_DS
;
1603 /* Check for the segment override */
1604 if (State
->PrefixFlags
& FAST486_PREFIX_SEG
)
1606 /* Use the override segment instead */
1607 Segment
= State
->SegmentOverride
;
1610 /* Read the selector */
1611 if (!Fast486ReadMemory(State
,
1613 ModRegRm
.MemoryAddress
+ sizeof(USHORT
),
1618 /* Exception occurred */
1622 /* Load the new code segment */
1623 if (!Fast486LoadSegment(State
, FAST486_REG_CS
, Selector
))
1625 /* Exception occurred */
1629 /* Set the IP to the address */
1630 State
->InstPtr
.LowWord
= Value
;
1632 else if (ModRegRm
.Register
== 6)
1634 /* Push the value on to the stack */
1635 return Fast486StackPush(State
, Value
);
1640 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1644 if (ModRegRm
.Register
<= 1)
1647 State
->Flags
.Sf
= (Value
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
1648 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
1649 State
->Flags
.Pf
= Fast486CalculateParity(Value
);
1651 /* Write back the result */
1652 return Fast486WriteModrmWordOperands(State
,