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 *******************************************************************/
36 /* PUBLIC VARIABLES ***********************************************************/
38 FAST486_OPCODE_HANDLER_PROC
39 Fast486OpcodeHandlers
[FAST486_NUM_OPCODE_HANDLERS
] =
41 Fast486OpcodeAddByteModrm
,
42 Fast486OpcodeAddModrm
,
43 Fast486OpcodeAddByteModrm
,
44 Fast486OpcodeAddModrm
,
49 Fast486OpcodeOrByteModrm
,
51 Fast486OpcodeOrByteModrm
,
56 Fast486OpcodeExtended
,
57 Fast486OpcodeAdcByteModrm
,
58 Fast486OpcodeAdcModrm
,
59 Fast486OpcodeAdcByteModrm
,
60 Fast486OpcodeAdcModrm
,
65 Fast486OpcodeSbbByteModrm
,
66 Fast486OpcodeSbbModrm
,
67 Fast486OpcodeSbbByteModrm
,
68 Fast486OpcodeSbbModrm
,
73 Fast486OpcodeAndByteModrm
,
74 Fast486OpcodeAndModrm
,
75 Fast486OpcodeAndByteModrm
,
76 Fast486OpcodeAndModrm
,
81 Fast486OpcodeCmpSubByteModrm
,
82 Fast486OpcodeCmpSubModrm
,
83 Fast486OpcodeCmpSubByteModrm
,
84 Fast486OpcodeCmpSubModrm
,
85 Fast486OpcodeCmpSubAl
,
86 Fast486OpcodeCmpSubEax
,
89 Fast486OpcodeXorByteModrm
,
90 Fast486OpcodeXorModrm
,
91 Fast486OpcodeXorByteModrm
,
92 Fast486OpcodeXorModrm
,
97 Fast486OpcodeCmpSubByteModrm
,
98 Fast486OpcodeCmpSubModrm
,
99 Fast486OpcodeCmpSubByteModrm
,
100 Fast486OpcodeCmpSubModrm
,
101 Fast486OpcodeCmpSubAl
,
102 Fast486OpcodeCmpSubEax
,
105 Fast486OpcodeIncrement
,
106 Fast486OpcodeIncrement
,
107 Fast486OpcodeIncrement
,
108 Fast486OpcodeIncrement
,
109 Fast486OpcodeIncrement
,
110 Fast486OpcodeIncrement
,
111 Fast486OpcodeIncrement
,
112 Fast486OpcodeIncrement
,
113 Fast486OpcodeDecrement
,
114 Fast486OpcodeDecrement
,
115 Fast486OpcodeDecrement
,
116 Fast486OpcodeDecrement
,
117 Fast486OpcodeDecrement
,
118 Fast486OpcodeDecrement
,
119 Fast486OpcodeDecrement
,
120 Fast486OpcodeDecrement
,
121 Fast486OpcodePushReg
,
122 Fast486OpcodePushReg
,
123 Fast486OpcodePushReg
,
124 Fast486OpcodePushReg
,
125 Fast486OpcodePushReg
,
126 Fast486OpcodePushReg
,
127 Fast486OpcodePushReg
,
128 Fast486OpcodePushReg
,
137 Fast486OpcodePushAll
,
145 Fast486OpcodePushImm
,
146 Fast486OpcodeImulModrmImm
,
147 Fast486OpcodePushByteImm
,
148 Fast486OpcodeImulModrmImm
,
153 Fast486OpcodeShortConditionalJmp
,
154 Fast486OpcodeShortConditionalJmp
,
155 Fast486OpcodeShortConditionalJmp
,
156 Fast486OpcodeShortConditionalJmp
,
157 Fast486OpcodeShortConditionalJmp
,
158 Fast486OpcodeShortConditionalJmp
,
159 Fast486OpcodeShortConditionalJmp
,
160 Fast486OpcodeShortConditionalJmp
,
161 Fast486OpcodeShortConditionalJmp
,
162 Fast486OpcodeShortConditionalJmp
,
163 Fast486OpcodeShortConditionalJmp
,
164 Fast486OpcodeShortConditionalJmp
,
165 Fast486OpcodeShortConditionalJmp
,
166 Fast486OpcodeShortConditionalJmp
,
167 Fast486OpcodeShortConditionalJmp
,
168 Fast486OpcodeShortConditionalJmp
,
169 Fast486OpcodeGroup8082
,
170 Fast486OpcodeGroup81
,
171 Fast486OpcodeGroup8082
,
172 Fast486OpcodeGroup83
,
173 Fast486OpcodeTestByteModrm
,
174 Fast486OpcodeTestModrm
,
175 Fast486OpcodeXchgByteModrm
,
176 Fast486OpcodeXchgModrm
,
177 Fast486OpcodeMovByteModrm
,
178 Fast486OpcodeMovModrm
,
179 Fast486OpcodeMovByteModrm
,
180 Fast486OpcodeMovModrm
,
181 Fast486OpcodeMovStoreSeg
,
183 Fast486OpcodeMovLoadSeg
,
184 Fast486OpcodeGroup8F
,
186 Fast486OpcodeExchangeEax
,
187 Fast486OpcodeExchangeEax
,
188 Fast486OpcodeExchangeEax
,
189 Fast486OpcodeExchangeEax
,
190 Fast486OpcodeExchangeEax
,
191 Fast486OpcodeExchangeEax
,
192 Fast486OpcodeExchangeEax
,
195 Fast486OpcodeCallAbs
,
197 Fast486OpcodePushFlags
,
198 Fast486OpcodePopFlags
,
201 Fast486OpcodeMovAlOffset
,
202 Fast486OpcodeMovEaxOffset
,
203 Fast486OpcodeMovOffsetAl
,
204 Fast486OpcodeMovOffsetEax
,
210 Fast486OpcodeTestEax
,
217 Fast486OpcodeMovByteRegImm
,
218 Fast486OpcodeMovByteRegImm
,
219 Fast486OpcodeMovByteRegImm
,
220 Fast486OpcodeMovByteRegImm
,
221 Fast486OpcodeMovByteRegImm
,
222 Fast486OpcodeMovByteRegImm
,
223 Fast486OpcodeMovByteRegImm
,
224 Fast486OpcodeMovByteRegImm
,
225 Fast486OpcodeMovRegImm
,
226 Fast486OpcodeMovRegImm
,
227 Fast486OpcodeMovRegImm
,
228 Fast486OpcodeMovRegImm
,
229 Fast486OpcodeMovRegImm
,
230 Fast486OpcodeMovRegImm
,
231 Fast486OpcodeMovRegImm
,
232 Fast486OpcodeMovRegImm
,
233 Fast486OpcodeGroupC0
,
234 Fast486OpcodeGroupC1
,
239 Fast486OpcodeGroupC6
,
240 Fast486OpcodeGroupC7
,
249 Fast486OpcodeGroupD0
,
250 Fast486OpcodeGroupD1
,
251 Fast486OpcodeGroupD2
,
252 Fast486OpcodeGroupD3
,
271 Fast486OpcodeOutByte
,
276 Fast486OpcodeShortJump
,
279 Fast486OpcodeOutByte
,
286 Fast486OpcodeComplCarry
,
287 Fast486OpcodeGroupF6
,
288 Fast486OpcodeGroupF7
,
289 Fast486OpcodeClearCarry
,
290 Fast486OpcodeSetCarry
,
291 Fast486OpcodeClearInt
,
293 Fast486OpcodeClearDir
,
295 Fast486OpcodeGroupFE
,
296 Fast486OpcodeGroupFF
,
299 /* PUBLIC FUNCTIONS ***********************************************************/
301 FAST486_OPCODE_HANDLER(Fast486OpcodePrefix
)
303 BOOLEAN Valid
= FALSE
;
310 if (!(State
->PrefixFlags
& FAST486_PREFIX_SEG
))
312 State
->PrefixFlags
|= FAST486_PREFIX_SEG
;
313 State
->SegmentOverride
= FAST486_REG_ES
;
323 if (!(State
->PrefixFlags
& FAST486_PREFIX_SEG
))
325 State
->PrefixFlags
|= FAST486_PREFIX_SEG
;
326 State
->SegmentOverride
= FAST486_REG_CS
;
336 if (!(State
->PrefixFlags
& FAST486_PREFIX_SEG
))
338 State
->PrefixFlags
|= FAST486_PREFIX_SEG
;
339 State
->SegmentOverride
= FAST486_REG_SS
;
349 if (!(State
->PrefixFlags
& FAST486_PREFIX_SEG
))
351 State
->PrefixFlags
|= FAST486_PREFIX_SEG
;
352 State
->SegmentOverride
= FAST486_REG_DS
;
362 if (!(State
->PrefixFlags
& FAST486_PREFIX_SEG
))
364 State
->PrefixFlags
|= FAST486_PREFIX_SEG
;
365 State
->SegmentOverride
= FAST486_REG_FS
;
375 if (!(State
->PrefixFlags
& FAST486_PREFIX_SEG
))
377 State
->PrefixFlags
|= FAST486_PREFIX_SEG
;
378 State
->SegmentOverride
= FAST486_REG_GS
;
388 if (!(State
->PrefixFlags
& FAST486_PREFIX_OPSIZE
))
390 State
->PrefixFlags
|= FAST486_PREFIX_OPSIZE
;
400 if (!(State
->PrefixFlags
& FAST486_PREFIX_ADSIZE
))
402 State
->PrefixFlags
|= FAST486_PREFIX_ADSIZE
;
411 if (!(State
->PrefixFlags
& FAST486_PREFIX_LOCK
))
413 State
->PrefixFlags
|= FAST486_PREFIX_LOCK
;
423 /* Mutually exclusive with REP */
424 if (!(State
->PrefixFlags
425 & (FAST486_PREFIX_REPNZ
| FAST486_PREFIX_REP
)))
427 State
->PrefixFlags
|= FAST486_PREFIX_REPNZ
;
437 /* Mutually exclusive with REPNZ */
438 if (!(State
->PrefixFlags
439 & (FAST486_PREFIX_REPNZ
| FAST486_PREFIX_REP
)))
441 State
->PrefixFlags
|= FAST486_PREFIX_REP
;
451 /* Clear all prefixes */
452 State
->PrefixFlags
= 0;
454 /* Throw an exception */
455 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
462 FAST486_OPCODE_HANDLER(Fast486OpcodeIncrement
)
465 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
470 /* Make sure this is the right instruction */
471 ASSERT((Opcode
& 0xF8) == 0x40);
475 Value
= ++State
->GeneralRegs
[Opcode
& 0x07].Long
;
477 State
->Flags
.Of
= (Value
== SIGN_FLAG_LONG
);
478 State
->Flags
.Sf
= ((Value
& SIGN_FLAG_LONG
) != 0);
482 Value
= ++State
->GeneralRegs
[Opcode
& 0x07].LowWord
;
484 State
->Flags
.Of
= (Value
== SIGN_FLAG_WORD
);
485 State
->Flags
.Sf
= ((Value
& SIGN_FLAG_WORD
) != 0);
488 State
->Flags
.Zf
= (Value
== 0);
489 State
->Flags
.Af
= ((Value
& 0x0F) == 0);
490 State
->Flags
.Pf
= Fast486CalculateParity(LOBYTE(Value
));
496 FAST486_OPCODE_HANDLER(Fast486OpcodeDecrement
)
499 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
504 /* Make sure this is the right instruction */
505 ASSERT((Opcode
& 0xF8) == 0x48);
509 Value
= --State
->GeneralRegs
[Opcode
& 0x07].Long
;
511 State
->Flags
.Of
= (Value
== (SIGN_FLAG_LONG
- 1));
512 State
->Flags
.Sf
= ((Value
& SIGN_FLAG_LONG
) != 0);
516 Value
= --State
->GeneralRegs
[Opcode
& 0x07].LowWord
;
518 State
->Flags
.Of
= (Value
== (SIGN_FLAG_WORD
- 1));
519 State
->Flags
.Sf
= ((Value
& SIGN_FLAG_WORD
) != 0);
522 State
->Flags
.Zf
= (Value
== 0);
523 State
->Flags
.Af
= ((Value
& 0x0F) == 0x0F);
524 State
->Flags
.Pf
= Fast486CalculateParity(LOBYTE(Value
));
530 FAST486_OPCODE_HANDLER(Fast486OpcodePushReg
)
534 /* Make sure this is the right instruction */
535 ASSERT((Opcode
& 0xF8) == 0x50);
537 /* Call the internal function */
538 return Fast486StackPush(State
, State
->GeneralRegs
[Opcode
& 0x07].Long
);
541 FAST486_OPCODE_HANDLER(Fast486OpcodePopReg
)
544 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
549 /* Make sure this is the right instruction */
550 ASSERT((Opcode
& 0xF8) == 0x58);
552 /* Call the internal function */
553 if (!Fast486StackPop(State
, &Value
)) return FALSE
;
555 /* Store the value */
556 if (Size
) State
->GeneralRegs
[Opcode
& 0x07].Long
= Value
;
557 else State
->GeneralRegs
[Opcode
& 0x07].LowWord
= Value
;
563 FAST486_OPCODE_HANDLER(Fast486OpcodeNop
)
565 if (State
->PrefixFlags
& FAST486_PREFIX_REP
)
568 State
->IdleCallback(State
);
574 FAST486_OPCODE_HANDLER(Fast486OpcodeExchangeEax
)
576 INT Reg
= Opcode
& 0x07;
577 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
582 /* Make sure this is the right instruction */
583 ASSERT((Opcode
& 0xF8) == 0x90);
585 /* Exchange the values */
590 Value
= State
->GeneralRegs
[Reg
].Long
;
591 State
->GeneralRegs
[Reg
].Long
= State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
592 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Value
;
598 Value
= State
->GeneralRegs
[Reg
].LowWord
;
599 State
->GeneralRegs
[Reg
].LowWord
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
600 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Value
;
606 FAST486_OPCODE_HANDLER(Fast486OpcodeShortConditionalJmp
)
608 BOOLEAN Jump
= FALSE
;
610 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
612 /* Make sure this is the right instruction */
613 ASSERT((Opcode
& 0xF0) == 0x70);
617 /* Fetch the offset */
618 if (!Fast486FetchByte(State
, (PUCHAR
)&Offset
))
620 /* An exception occurred */
624 switch ((Opcode
& 0x0F) >> 1)
629 Jump
= State
->Flags
.Of
;
636 Jump
= State
->Flags
.Cf
;
643 Jump
= State
->Flags
.Zf
;
650 Jump
= State
->Flags
.Cf
|| State
->Flags
.Zf
;
657 Jump
= State
->Flags
.Sf
;
664 Jump
= State
->Flags
.Pf
;
671 Jump
= State
->Flags
.Sf
!= State
->Flags
.Of
;
678 Jump
= (State
->Flags
.Sf
!= State
->Flags
.Of
) || State
->Flags
.Zf
;
685 /* Invert the result */
691 /* Move the instruction pointer */
692 State
->InstPtr
.Long
+= Offset
;
696 /* Clear the top half of EIP */
697 State
->InstPtr
.Long
&= 0xFFFF;
705 FAST486_OPCODE_HANDLER(Fast486OpcodeClearCarry
)
707 /* Make sure this is the right instruction */
708 ASSERT(Opcode
== 0xF8);
710 /* No prefixes allowed */
711 if (State
->PrefixFlags
)
713 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
717 /* Clear CF and return success */
718 State
->Flags
.Cf
= FALSE
;
722 FAST486_OPCODE_HANDLER(Fast486OpcodeSetCarry
)
724 /* Make sure this is the right instruction */
725 ASSERT(Opcode
== 0xF9);
727 /* No prefixes allowed */
728 if (State
->PrefixFlags
)
730 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
734 /* Set CF and return success*/
735 State
->Flags
.Cf
= TRUE
;
739 FAST486_OPCODE_HANDLER(Fast486OpcodeComplCarry
)
741 /* Make sure this is the right instruction */
742 ASSERT(Opcode
== 0xF5);
744 /* No prefixes allowed */
745 if (State
->PrefixFlags
)
747 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
751 /* Toggle CF and return success */
752 State
->Flags
.Cf
= !State
->Flags
.Cf
;
756 FAST486_OPCODE_HANDLER(Fast486OpcodeClearInt
)
758 /* Make sure this is the right instruction */
759 ASSERT(Opcode
== 0xFA);
761 /* No prefixes allowed */
762 if (State
->PrefixFlags
)
764 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
768 /* Check for protected mode */
769 if (State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
772 if (State
->Flags
.Iopl
>= State
->SegmentRegs
[FAST486_REG_CS
].Dpl
)
774 /* Clear the interrupt flag */
775 State
->Flags
.If
= FALSE
;
779 /* General Protection Fault */
780 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
786 /* Just clear the interrupt flag */
787 State
->Flags
.If
= FALSE
;
794 FAST486_OPCODE_HANDLER(Fast486OpcodeSetInt
)
796 /* Make sure this is the right instruction */
797 ASSERT(Opcode
== 0xFB);
799 /* No prefixes allowed */
800 if (State
->PrefixFlags
)
802 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
806 /* Check for protected mode */
807 if (State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
810 if (State
->Flags
.Iopl
>= State
->SegmentRegs
[FAST486_REG_CS
].Dpl
)
812 /* Set the interrupt flag */
813 State
->Flags
.If
= TRUE
;
817 /* General Protection Fault */
818 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
824 /* Just set the interrupt flag */
825 State
->Flags
.If
= TRUE
;
832 FAST486_OPCODE_HANDLER(Fast486OpcodeClearDir
)
834 /* Make sure this is the right instruction */
835 ASSERT(Opcode
== 0xFC);
837 /* No prefixes allowed */
838 if (State
->PrefixFlags
)
840 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
844 /* Clear DF and return success */
845 State
->Flags
.Df
= FALSE
;
849 FAST486_OPCODE_HANDLER(Fast486OpcodeSetDir
)
851 /* Make sure this is the right instruction */
852 ASSERT(Opcode
== 0xFD);
854 /* No prefixes allowed */
855 if (State
->PrefixFlags
)
857 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
861 /* Set DF and return success*/
862 State
->Flags
.Df
= TRUE
;
866 FAST486_OPCODE_HANDLER(Fast486OpcodeHalt
)
868 /* Make sure this is the right instruction */
869 ASSERT(Opcode
== 0xF4);
871 /* No prefixes allowed */
872 if (State
->PrefixFlags
)
874 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
878 /* Privileged instructions can only be executed under CPL = 0 */
879 if (State
->SegmentRegs
[FAST486_REG_CS
].Dpl
!= 0)
881 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
886 // TODO: Halt the CPU until an interrupt occurs, using IdleCallback if needed.
892 FAST486_OPCODE_HANDLER(Fast486OpcodeInByte
)
897 /* Make sure this is the right instruction */
898 ASSERT((Opcode
& 0xF7) == 0xE4);
902 /* Fetch the parameter */
903 if (!Fast486FetchByte(State
, &Data
))
905 /* Exception occurred */
909 /* Set the port number to the parameter */
914 /* The port number is in DX */
915 Port
= State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
;
918 /* Read a byte from the I/O port */
919 State
->IoReadCallback(State
, Port
, &Data
, 1, sizeof(UCHAR
));
921 /* Store the result in AL */
922 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= Data
;
927 FAST486_OPCODE_HANDLER(Fast486OpcodeIn
)
930 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
932 /* Make sure this is the right instruction */
933 ASSERT((Opcode
& 0xF7) == 0xE5);
942 /* Fetch the parameter */
943 if (!Fast486FetchByte(State
, &Data
))
945 /* Exception occurred */
949 /* Set the port number to the parameter */
954 /* The port number is in DX */
955 Port
= State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
;
962 /* Read a dword from the I/O port */
963 State
->IoReadCallback(State
, Port
, &Data
, 1, sizeof(ULONG
));
965 /* Store the value in EAX */
966 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Data
;
972 /* Read a word from the I/O port */
973 State
->IoReadCallback(State
, Port
, &Data
, 1, sizeof(USHORT
));
975 /* Store the value in AX */
976 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Data
;
982 FAST486_OPCODE_HANDLER(Fast486OpcodeOutByte
)
987 /* Make sure this is the right instruction */
988 ASSERT((Opcode
& 0xF7) == 0xE6);
992 /* Fetch the parameter */
993 if (!Fast486FetchByte(State
, &Data
))
995 /* Exception occurred */
999 /* Set the port number to the parameter */
1004 /* The port number is in DX */
1005 Port
= State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
;
1008 /* Read the value from AL */
1009 Data
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
1011 /* Write the byte to the I/O port */
1012 State
->IoWriteCallback(State
, Port
, &Data
, 1, sizeof(UCHAR
));
1017 FAST486_OPCODE_HANDLER(Fast486OpcodeOut
)
1020 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1022 /* Make sure this is the right instruction */
1023 ASSERT((Opcode
& 0xF7) == 0xE7);
1025 TOGGLE_OPSIZE(Size
);
1032 /* Fetch the parameter */
1033 if (!Fast486FetchByte(State
, &Data
))
1035 /* Exception occurred */
1039 /* Set the port number to the parameter */
1044 /* The port number is in DX */
1045 Port
= State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
;
1050 /* Get the value from EAX */
1051 ULONG Data
= State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
1053 /* Write a dword to the I/O port */
1054 State
->IoWriteCallback(State
, Port
, &Data
, 1, sizeof(ULONG
));
1058 /* Get the value from AX */
1059 USHORT Data
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
1061 /* Write a word to the I/O port */
1062 State
->IoWriteCallback(State
, Port
, &Data
, 1, sizeof(USHORT
));
1068 FAST486_OPCODE_HANDLER(Fast486OpcodeShortJump
)
1071 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1073 TOGGLE_OPSIZE(Size
);
1075 /* Make sure this is the right instruction */
1076 ASSERT(Opcode
== 0xEB);
1078 /* Fetch the offset */
1079 if (!Fast486FetchByte(State
, (PUCHAR
)&Offset
))
1081 /* An exception occurred */
1085 /* Move the instruction pointer */
1086 State
->InstPtr
.Long
+= Offset
;
1090 /* Clear the top half of EIP */
1091 State
->InstPtr
.Long
&= 0xFFFF;
1097 FAST486_OPCODE_HANDLER(Fast486OpcodeMovRegImm
)
1099 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1101 /* Make sure this is the right instruction */
1102 ASSERT((Opcode
& 0xF8) == 0xB8);
1104 TOGGLE_OPSIZE(Size
);
1111 /* Fetch the dword */
1112 if (!Fast486FetchDword(State
, &Value
))
1114 /* Exception occurred */
1118 /* Store the value in the register */
1119 State
->GeneralRegs
[Opcode
& 0x07].Long
= Value
;
1125 /* Fetch the word */
1126 if (!Fast486FetchWord(State
, &Value
))
1128 /* Exception occurred */
1132 /* Store the value in the register */
1133 State
->GeneralRegs
[Opcode
& 0x07].LowWord
= Value
;
1139 FAST486_OPCODE_HANDLER(Fast486OpcodeMovByteRegImm
)
1143 /* Make sure this is the right instruction */
1144 ASSERT((Opcode
& 0xF8) == 0xB0);
1146 if (State
->PrefixFlags
!= 0)
1148 /* Invalid prefix */
1149 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1153 /* Fetch the byte */
1154 if (!Fast486FetchByte(State
, &Value
))
1156 /* Exception occurred */
1162 /* AH, CH, DH or BH */
1163 State
->GeneralRegs
[Opcode
& 0x03].HighByte
= Value
;
1167 /* AL, CL, DL or BL */
1168 State
->GeneralRegs
[Opcode
& 0x03].LowByte
= Value
;
1174 FAST486_OPCODE_HANDLER(Fast486OpcodeAddByteModrm
)
1176 UCHAR FirstValue
, SecondValue
, Result
;
1177 FAST486_MOD_REG_RM ModRegRm
;
1178 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1180 /* Make sure this is the right instruction */
1181 ASSERT((Opcode
& 0xFD) == 0x00);
1183 TOGGLE_ADSIZE(AddressSize
);
1185 /* Get the operands */
1186 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1188 /* Exception occurred */
1192 if (!Fast486ReadModrmByteOperands(State
,
1197 /* Exception occurred */
1201 /* Calculate the result */
1202 Result
= FirstValue
+ SecondValue
;
1204 /* Update the flags */
1205 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1206 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
1207 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
1208 State
->Flags
.Af
= ((((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) != 0);
1209 State
->Flags
.Zf
= (Result
== 0);
1210 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
1211 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1213 /* Write back the result */
1214 return Fast486WriteModrmByteOperands(State
,
1216 Opcode
& FAST486_OPCODE_WRITE_REG
,
1220 FAST486_OPCODE_HANDLER(Fast486OpcodeAddModrm
)
1222 FAST486_MOD_REG_RM ModRegRm
;
1223 BOOLEAN OperandSize
, AddressSize
;
1225 /* Make sure this is the right instruction */
1226 ASSERT((Opcode
& 0xFD) == 0x01);
1228 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1230 TOGGLE_ADSIZE(AddressSize
);
1231 TOGGLE_OPSIZE(OperandSize
);
1233 /* Get the operands */
1234 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1236 /* Exception occurred */
1240 /* Check the operand size */
1243 ULONG FirstValue
, SecondValue
, Result
;
1245 if (!Fast486ReadModrmDwordOperands(State
,
1250 /* Exception occurred */
1254 /* Calculate the result */
1255 Result
= FirstValue
+ SecondValue
;
1257 /* Update the flags */
1258 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1259 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
1260 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
1261 State
->Flags
.Af
= ((((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) != 0);
1262 State
->Flags
.Zf
= (Result
== 0);
1263 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
1264 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1266 /* Write back the result */
1267 return Fast486WriteModrmDwordOperands(State
,
1269 Opcode
& FAST486_OPCODE_WRITE_REG
,
1274 USHORT FirstValue
, SecondValue
, Result
;
1276 if (!Fast486ReadModrmWordOperands(State
,
1281 /* Exception occurred */
1285 /* Calculate the result */
1286 Result
= FirstValue
+ SecondValue
;
1288 /* Update the flags */
1289 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1290 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
1291 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
1292 State
->Flags
.Af
= ((((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) != 0);
1293 State
->Flags
.Zf
= (Result
== 0);
1294 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
1295 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1297 /* Write back the result */
1298 return Fast486WriteModrmWordOperands(State
,
1300 Opcode
& FAST486_OPCODE_WRITE_REG
,
1305 FAST486_OPCODE_HANDLER(Fast486OpcodeAddAl
)
1307 UCHAR FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
1308 UCHAR SecondValue
, Result
;
1310 /* Make sure this is the right instruction */
1311 ASSERT(Opcode
== 0x04);
1313 if (State
->PrefixFlags
)
1315 /* This opcode doesn't take any prefixes */
1316 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1320 if (!Fast486FetchByte(State
, &SecondValue
))
1322 /* Exception occurred */
1326 /* Calculate the result */
1327 Result
= FirstValue
+ SecondValue
;
1329 /* Update the flags */
1330 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1331 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
1332 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
1333 State
->Flags
.Af
= ((((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) != 0);
1334 State
->Flags
.Zf
= (Result
== 0);
1335 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
1336 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1338 /* Write back the result */
1339 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= Result
;
1344 FAST486_OPCODE_HANDLER(Fast486OpcodeAddEax
)
1346 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1348 /* Make sure this is the right instruction */
1349 ASSERT(Opcode
== 0x05);
1352 TOGGLE_OPSIZE(Size
);
1356 ULONG FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
1357 ULONG SecondValue
, Result
;
1359 if (!Fast486FetchDword(State
, &SecondValue
))
1361 /* Exception occurred */
1365 /* Calculate the result */
1366 Result
= FirstValue
+ SecondValue
;
1368 /* Update the flags */
1369 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1370 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
1371 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
1372 State
->Flags
.Af
= ((((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) != 0);
1373 State
->Flags
.Zf
= (Result
== 0);
1374 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
1375 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1377 /* Write back the result */
1378 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Result
;
1382 USHORT FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
1383 USHORT SecondValue
, Result
;
1385 if (!Fast486FetchWord(State
, &SecondValue
))
1387 /* Exception occurred */
1391 /* Calculate the result */
1392 Result
= FirstValue
+ SecondValue
;
1394 /* Update the flags */
1395 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1396 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
1397 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
1398 State
->Flags
.Af
= ((((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) != 0);
1399 State
->Flags
.Zf
= (Result
== 0);
1400 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
1401 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1403 /* Write back the result */
1404 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Result
;
1410 FAST486_OPCODE_HANDLER(Fast486OpcodeOrByteModrm
)
1412 UCHAR FirstValue
, SecondValue
, Result
;
1413 FAST486_MOD_REG_RM ModRegRm
;
1414 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1416 /* Make sure this is the right instruction */
1417 ASSERT((Opcode
& 0xFD) == 0x08);
1419 TOGGLE_ADSIZE(AddressSize
);
1421 /* Get the operands */
1422 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1424 /* Exception occurred */
1428 if (!Fast486ReadModrmByteOperands(State
,
1433 /* Exception occurred */
1437 /* Calculate the result */
1438 Result
= FirstValue
| SecondValue
;
1440 /* Update the flags */
1441 State
->Flags
.Cf
= FALSE
;
1442 State
->Flags
.Of
= FALSE
;
1443 State
->Flags
.Zf
= (Result
== 0);
1444 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
1445 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1447 /* Write back the result */
1448 return Fast486WriteModrmByteOperands(State
,
1450 Opcode
& FAST486_OPCODE_WRITE_REG
,
1454 FAST486_OPCODE_HANDLER(Fast486OpcodeOrModrm
)
1456 FAST486_MOD_REG_RM ModRegRm
;
1457 BOOLEAN OperandSize
, AddressSize
;
1459 /* Make sure this is the right instruction */
1460 ASSERT((Opcode
& 0xFD) == 0x09);
1462 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1464 TOGGLE_ADSIZE(AddressSize
);
1465 TOGGLE_OPSIZE(OperandSize
);
1467 /* Get the operands */
1468 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1470 /* Exception occurred */
1474 /* Check the operand size */
1477 ULONG FirstValue
, SecondValue
, Result
;
1479 if (!Fast486ReadModrmDwordOperands(State
,
1484 /* Exception occurred */
1488 /* Calculate the result */
1489 Result
= FirstValue
| SecondValue
;
1491 /* Update the flags */
1492 State
->Flags
.Cf
= FALSE
;
1493 State
->Flags
.Of
= FALSE
;
1494 State
->Flags
.Zf
= (Result
== 0);
1495 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
1496 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1498 /* Write back the result */
1499 return Fast486WriteModrmDwordOperands(State
,
1501 Opcode
& FAST486_OPCODE_WRITE_REG
,
1506 USHORT FirstValue
, SecondValue
, Result
;
1508 if (!Fast486ReadModrmWordOperands(State
,
1513 /* Exception occurred */
1517 /* Calculate the result */
1518 Result
= FirstValue
| SecondValue
;
1520 /* Update the flags */
1521 State
->Flags
.Cf
= FALSE
;
1522 State
->Flags
.Of
= FALSE
;
1523 State
->Flags
.Zf
= (Result
== 0);
1524 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
1525 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1527 /* Write back the result */
1528 return Fast486WriteModrmWordOperands(State
,
1530 Opcode
& FAST486_OPCODE_WRITE_REG
,
1535 FAST486_OPCODE_HANDLER(Fast486OpcodeOrAl
)
1537 UCHAR FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
1538 UCHAR SecondValue
, Result
;
1540 /* Make sure this is the right instruction */
1541 ASSERT(Opcode
== 0x0C);
1543 if (State
->PrefixFlags
)
1545 /* This opcode doesn't take any prefixes */
1546 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1550 if (!Fast486FetchByte(State
, &SecondValue
))
1552 /* Exception occurred */
1556 /* Calculate the result */
1557 Result
= FirstValue
| SecondValue
;
1559 /* Update the flags */
1560 State
->Flags
.Cf
= FALSE
;
1561 State
->Flags
.Of
= FALSE
;
1562 State
->Flags
.Zf
= (Result
== 0);
1563 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
1564 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1566 /* Write back the result */
1567 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= Result
;
1572 FAST486_OPCODE_HANDLER(Fast486OpcodeOrEax
)
1574 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1576 /* Make sure this is the right instruction */
1577 ASSERT(Opcode
== 0x0D);
1580 TOGGLE_OPSIZE(Size
);
1584 ULONG FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
1585 ULONG SecondValue
, Result
;
1587 if (!Fast486FetchDword(State
, &SecondValue
))
1589 /* Exception occurred */
1593 /* Calculate the result */
1594 Result
= FirstValue
| SecondValue
;
1596 /* Update the flags */
1597 State
->Flags
.Cf
= FALSE
;
1598 State
->Flags
.Of
= FALSE
;
1599 State
->Flags
.Zf
= (Result
== 0);
1600 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
1601 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1603 /* Write back the result */
1604 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Result
;
1608 USHORT FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
1609 USHORT SecondValue
, Result
;
1611 if (!Fast486FetchWord(State
, &SecondValue
))
1613 /* Exception occurred */
1617 /* Calculate the result */
1618 Result
= FirstValue
| SecondValue
;
1620 /* Update the flags */
1621 State
->Flags
.Cf
= FALSE
;
1622 State
->Flags
.Of
= FALSE
;
1623 State
->Flags
.Zf
= (Result
== 0);
1624 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
1625 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1627 /* Write back the result */
1628 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Result
;
1634 FAST486_OPCODE_HANDLER(Fast486OpcodeAndByteModrm
)
1636 UCHAR FirstValue
, SecondValue
, Result
;
1637 FAST486_MOD_REG_RM ModRegRm
;
1638 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1640 /* Make sure this is the right instruction */
1641 ASSERT((Opcode
& 0xFD) == 0x20);
1643 TOGGLE_ADSIZE(AddressSize
);
1645 /* Get the operands */
1646 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1648 /* Exception occurred */
1652 if (!Fast486ReadModrmByteOperands(State
,
1657 /* Exception occurred */
1661 /* Calculate the result */
1662 Result
= FirstValue
& SecondValue
;
1664 /* Update the flags */
1665 State
->Flags
.Cf
= FALSE
;
1666 State
->Flags
.Of
= FALSE
;
1667 State
->Flags
.Zf
= (Result
== 0);
1668 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
1669 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1671 /* Write back the result */
1672 return Fast486WriteModrmByteOperands(State
,
1674 Opcode
& FAST486_OPCODE_WRITE_REG
,
1678 FAST486_OPCODE_HANDLER(Fast486OpcodeAndModrm
)
1680 FAST486_MOD_REG_RM ModRegRm
;
1681 BOOLEAN OperandSize
, AddressSize
;
1683 /* Make sure this is the right instruction */
1684 ASSERT((Opcode
& 0xFD) == 0x21);
1686 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1688 TOGGLE_ADSIZE(AddressSize
);
1689 TOGGLE_OPSIZE(OperandSize
);
1691 /* Get the operands */
1692 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1694 /* Exception occurred */
1698 /* Check the operand size */
1701 ULONG FirstValue
, SecondValue
, Result
;
1703 if (!Fast486ReadModrmDwordOperands(State
,
1708 /* Exception occurred */
1712 /* Calculate the result */
1713 Result
= FirstValue
& SecondValue
;
1715 /* Update the flags */
1716 State
->Flags
.Cf
= FALSE
;
1717 State
->Flags
.Of
= FALSE
;
1718 State
->Flags
.Zf
= (Result
== 0);
1719 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
1720 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1722 /* Write back the result */
1723 return Fast486WriteModrmDwordOperands(State
,
1725 Opcode
& FAST486_OPCODE_WRITE_REG
,
1730 USHORT FirstValue
, SecondValue
, Result
;
1732 if (!Fast486ReadModrmWordOperands(State
,
1737 /* Exception occurred */
1741 /* Calculate the result */
1742 Result
= FirstValue
& SecondValue
;
1744 /* Update the flags */
1745 State
->Flags
.Cf
= FALSE
;
1746 State
->Flags
.Of
= FALSE
;
1747 State
->Flags
.Zf
= (Result
== 0);
1748 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
1749 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1751 /* Write back the result */
1752 return Fast486WriteModrmWordOperands(State
,
1754 Opcode
& FAST486_OPCODE_WRITE_REG
,
1759 FAST486_OPCODE_HANDLER(Fast486OpcodeAndAl
)
1761 UCHAR FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
1762 UCHAR SecondValue
, Result
;
1764 /* Make sure this is the right instruction */
1765 ASSERT(Opcode
== 0x24);
1769 if (!Fast486FetchByte(State
, &SecondValue
))
1771 /* Exception occurred */
1775 /* Calculate the result */
1776 Result
= FirstValue
& SecondValue
;
1778 /* Update the flags */
1779 State
->Flags
.Cf
= FALSE
;
1780 State
->Flags
.Of
= FALSE
;
1781 State
->Flags
.Zf
= (Result
== 0);
1782 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
1783 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1785 /* Write back the result */
1786 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= Result
;
1791 FAST486_OPCODE_HANDLER(Fast486OpcodeAndEax
)
1793 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1795 /* Make sure this is the right instruction */
1796 ASSERT(Opcode
== 0x25);
1799 TOGGLE_OPSIZE(Size
);
1803 ULONG FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
1804 ULONG SecondValue
, Result
;
1806 if (!Fast486FetchDword(State
, &SecondValue
))
1808 /* Exception occurred */
1812 /* Calculate the result */
1813 Result
= FirstValue
& SecondValue
;
1815 /* Update the flags */
1816 State
->Flags
.Cf
= FALSE
;
1817 State
->Flags
.Of
= FALSE
;
1818 State
->Flags
.Zf
= (Result
== 0);
1819 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
1820 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1822 /* Write back the result */
1823 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Result
;
1827 USHORT FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
1828 USHORT SecondValue
, Result
;
1830 if (!Fast486FetchWord(State
, &SecondValue
))
1832 /* Exception occurred */
1836 /* Calculate the result */
1837 Result
= FirstValue
& SecondValue
;
1839 /* Update the flags */
1840 State
->Flags
.Cf
= FALSE
;
1841 State
->Flags
.Of
= FALSE
;
1842 State
->Flags
.Zf
= (Result
== 0);
1843 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
1844 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1846 /* Write back the result */
1847 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Result
;
1853 FAST486_OPCODE_HANDLER(Fast486OpcodeXorByteModrm
)
1855 UCHAR FirstValue
, SecondValue
, Result
;
1856 FAST486_MOD_REG_RM ModRegRm
;
1857 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1859 /* Make sure this is the right instruction */
1860 ASSERT((Opcode
& 0xFD) == 0x30);
1862 TOGGLE_ADSIZE(AddressSize
);
1864 /* Get the operands */
1865 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1867 /* Exception occurred */
1871 if (!Fast486ReadModrmByteOperands(State
,
1876 /* Exception occurred */
1880 /* Calculate the result */
1881 Result
= FirstValue
^ SecondValue
;
1883 /* Update the flags */
1884 State
->Flags
.Cf
= FALSE
;
1885 State
->Flags
.Of
= FALSE
;
1886 State
->Flags
.Zf
= (Result
== 0);
1887 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
1888 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1890 /* Write back the result */
1891 return Fast486WriteModrmByteOperands(State
,
1893 Opcode
& FAST486_OPCODE_WRITE_REG
,
1897 FAST486_OPCODE_HANDLER(Fast486OpcodeXorModrm
)
1899 FAST486_MOD_REG_RM ModRegRm
;
1900 BOOLEAN OperandSize
, AddressSize
;
1902 /* Make sure this is the right instruction */
1903 ASSERT((Opcode
& 0xFD) == 0x31);
1905 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1907 TOGGLE_ADSIZE(AddressSize
);
1908 TOGGLE_OPSIZE(OperandSize
);
1910 /* Get the operands */
1911 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1913 /* Exception occurred */
1917 /* Check the operand size */
1920 ULONG FirstValue
, SecondValue
, Result
;
1922 if (!Fast486ReadModrmDwordOperands(State
,
1927 /* Exception occurred */
1931 /* Calculate the result */
1932 Result
= FirstValue
^ SecondValue
;
1934 /* Update the flags */
1935 State
->Flags
.Cf
= FALSE
;
1936 State
->Flags
.Of
= FALSE
;
1937 State
->Flags
.Zf
= (Result
== 0);
1938 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
1939 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1941 /* Write back the result */
1942 return Fast486WriteModrmDwordOperands(State
,
1944 Opcode
& FAST486_OPCODE_WRITE_REG
,
1949 USHORT FirstValue
, SecondValue
, Result
;
1951 if (!Fast486ReadModrmWordOperands(State
,
1956 /* Exception occurred */
1960 /* Calculate the result */
1961 Result
= FirstValue
^ SecondValue
;
1963 /* Update the flags */
1964 State
->Flags
.Cf
= FALSE
;
1965 State
->Flags
.Of
= FALSE
;
1966 State
->Flags
.Zf
= (Result
== 0);
1967 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
1968 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1970 /* Write back the result */
1971 return Fast486WriteModrmWordOperands(State
,
1973 Opcode
& FAST486_OPCODE_WRITE_REG
,
1978 FAST486_OPCODE_HANDLER(Fast486OpcodeXorAl
)
1980 UCHAR FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
1981 UCHAR SecondValue
, Result
;
1983 /* Make sure this is the right instruction */
1984 ASSERT(Opcode
== 0x34);
1986 if (State
->PrefixFlags
)
1988 /* This opcode doesn't take any prefixes */
1989 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1993 if (!Fast486FetchByte(State
, &SecondValue
))
1995 /* Exception occurred */
1999 /* Calculate the result */
2000 Result
= FirstValue
^ SecondValue
;
2002 /* Update the flags */
2003 State
->Flags
.Cf
= FALSE
;
2004 State
->Flags
.Of
= FALSE
;
2005 State
->Flags
.Zf
= (Result
== 0);
2006 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
2007 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2009 /* Write back the result */
2010 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= Result
;
2015 FAST486_OPCODE_HANDLER(Fast486OpcodeXorEax
)
2017 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2019 /* Make sure this is the right instruction */
2020 ASSERT(Opcode
== 0x35);
2023 TOGGLE_OPSIZE(Size
);
2027 ULONG FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
2028 ULONG SecondValue
, Result
;
2030 if (!Fast486FetchDword(State
, &SecondValue
))
2032 /* Exception occurred */
2036 /* Calculate the result */
2037 Result
= FirstValue
^ SecondValue
;
2039 /* Update the flags */
2040 State
->Flags
.Cf
= FALSE
;
2041 State
->Flags
.Of
= FALSE
;
2042 State
->Flags
.Zf
= (Result
== 0);
2043 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
2044 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2046 /* Write back the result */
2047 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Result
;
2051 USHORT FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
2052 USHORT SecondValue
, Result
;
2054 if (!Fast486FetchWord(State
, &SecondValue
))
2056 /* Exception occurred */
2060 /* Calculate the result */
2061 Result
= FirstValue
^ SecondValue
;
2063 /* Update the flags */
2064 State
->Flags
.Cf
= FALSE
;
2065 State
->Flags
.Of
= FALSE
;
2066 State
->Flags
.Zf
= (Result
== 0);
2067 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
2068 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2070 /* Write back the result */
2071 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Result
;
2077 FAST486_OPCODE_HANDLER(Fast486OpcodeTestByteModrm
)
2079 UCHAR FirstValue
, SecondValue
, Result
;
2080 FAST486_MOD_REG_RM ModRegRm
;
2081 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2083 /* Make sure this is the right instruction */
2084 ASSERT(Opcode
== 0x84);
2086 TOGGLE_ADSIZE(AddressSize
);
2088 /* Get the operands */
2089 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2091 /* Exception occurred */
2095 if (!Fast486ReadModrmByteOperands(State
,
2100 /* Exception occurred */
2103 /* Calculate the result */
2104 Result
= FirstValue
& SecondValue
;
2106 /* Update the flags */
2107 State
->Flags
.Cf
= FALSE
;
2108 State
->Flags
.Of
= FALSE
;
2109 State
->Flags
.Zf
= (Result
== 0);
2110 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
2111 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2113 /* The result is discarded */
2117 FAST486_OPCODE_HANDLER(Fast486OpcodeTestModrm
)
2119 FAST486_MOD_REG_RM ModRegRm
;
2120 BOOLEAN OperandSize
, AddressSize
;
2122 /* Make sure this is the right instruction */
2123 ASSERT(Opcode
== 0x85);
2125 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2127 TOGGLE_ADSIZE(AddressSize
);
2128 TOGGLE_OPSIZE(OperandSize
);
2130 /* Get the operands */
2131 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2133 /* Exception occurred */
2137 /* Check the operand size */
2140 ULONG FirstValue
, SecondValue
, Result
;
2142 if (!Fast486ReadModrmDwordOperands(State
,
2147 /* Exception occurred */
2151 /* Calculate the result */
2152 Result
= FirstValue
& SecondValue
;
2154 /* Update the flags */
2155 State
->Flags
.Cf
= FALSE
;
2156 State
->Flags
.Of
= FALSE
;
2157 State
->Flags
.Zf
= (Result
== 0);
2158 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
2159 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2163 USHORT FirstValue
, SecondValue
, Result
;
2165 if (!Fast486ReadModrmWordOperands(State
,
2170 /* Exception occurred */
2174 /* Calculate the result */
2175 Result
= FirstValue
& SecondValue
;
2177 /* Update the flags */
2178 State
->Flags
.Cf
= FALSE
;
2179 State
->Flags
.Of
= FALSE
;
2180 State
->Flags
.Zf
= (Result
== 0);
2181 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
2182 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2185 /* The result is discarded */
2189 FAST486_OPCODE_HANDLER(Fast486OpcodeTestAl
)
2191 UCHAR FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
2192 UCHAR SecondValue
, Result
;
2194 /* Make sure this is the right instruction */
2195 ASSERT(Opcode
== 0xA8);
2197 if (State
->PrefixFlags
)
2199 /* This opcode doesn't take any prefixes */
2200 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2204 if (!Fast486FetchByte(State
, &SecondValue
))
2206 /* Exception occurred */
2210 /* Calculate the result */
2211 Result
= FirstValue
& SecondValue
;
2213 /* Update the flags */
2214 State
->Flags
.Cf
= FALSE
;
2215 State
->Flags
.Of
= FALSE
;
2216 State
->Flags
.Zf
= (Result
== 0);
2217 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
2218 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2220 /* The result is discarded */
2224 FAST486_OPCODE_HANDLER(Fast486OpcodeTestEax
)
2226 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2228 /* Make sure this is the right instruction */
2229 ASSERT(Opcode
== 0xA9);
2232 TOGGLE_OPSIZE(Size
);
2236 ULONG FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
2237 ULONG SecondValue
, Result
;
2239 if (!Fast486FetchDword(State
, &SecondValue
))
2241 /* Exception occurred */
2245 /* Calculate the result */
2246 Result
= FirstValue
& SecondValue
;
2248 /* Update the flags */
2249 State
->Flags
.Cf
= FALSE
;
2250 State
->Flags
.Of
= FALSE
;
2251 State
->Flags
.Zf
= (Result
== 0);
2252 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
2253 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2257 USHORT FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
2258 USHORT SecondValue
, Result
;
2260 if (!Fast486FetchWord(State
, &SecondValue
))
2262 /* Exception occurred */
2266 /* Calculate the result */
2267 Result
= FirstValue
& SecondValue
;
2269 /* Update the flags */
2270 State
->Flags
.Cf
= FALSE
;
2271 State
->Flags
.Of
= FALSE
;
2272 State
->Flags
.Zf
= (Result
== 0);
2273 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
2274 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2277 /* The result is discarded */
2281 FAST486_OPCODE_HANDLER(Fast486OpcodeXchgByteModrm
)
2283 UCHAR FirstValue
, SecondValue
;
2284 FAST486_MOD_REG_RM ModRegRm
;
2285 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2287 /* Make sure this is the right instruction */
2288 ASSERT(Opcode
== 0x86);
2290 TOGGLE_ADSIZE(AddressSize
);
2292 /* Get the operands */
2293 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2295 /* Exception occurred */
2299 if (!Fast486ReadModrmByteOperands(State
,
2304 /* Exception occurred */
2308 /* Write the value from the register to the R/M */
2309 if (!Fast486WriteModrmByteOperands(State
,
2314 /* Exception occurred */
2318 /* Write the value from the R/M to the register */
2319 if (!Fast486WriteModrmByteOperands(State
,
2324 /* Exception occurred */
2331 FAST486_OPCODE_HANDLER(Fast486OpcodeXchgModrm
)
2333 FAST486_MOD_REG_RM ModRegRm
;
2334 BOOLEAN OperandSize
, AddressSize
;
2336 /* Make sure this is the right instruction */
2337 ASSERT(Opcode
== 0x87);
2339 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2341 TOGGLE_ADSIZE(AddressSize
);
2342 TOGGLE_OPSIZE(OperandSize
);
2344 /* Get the operands */
2345 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2347 /* Exception occurred */
2351 /* Check the operand size */
2354 ULONG FirstValue
, SecondValue
;
2356 if (!Fast486ReadModrmDwordOperands(State
,
2361 /* Exception occurred */
2365 /* Write the value from the register to the R/M */
2366 if (!Fast486WriteModrmDwordOperands(State
,
2371 /* Exception occurred */
2375 /* Write the value from the R/M to the register */
2376 if (!Fast486WriteModrmDwordOperands(State
,
2381 /* Exception occurred */
2387 USHORT FirstValue
, SecondValue
;
2389 if (!Fast486ReadModrmWordOperands(State
,
2394 /* Exception occurred */
2398 /* Write the value from the register to the R/M */
2399 if (!Fast486WriteModrmWordOperands(State
,
2404 /* Exception occurred */
2408 /* Write the value from the R/M to the register */
2409 if (!Fast486WriteModrmWordOperands(State
,
2414 /* Exception occurred */
2419 /* The result is discarded */
2423 FAST486_OPCODE_HANDLER(Fast486OpcodePushEs
)
2425 /* Call the internal API */
2426 return Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_ES
].Selector
);
2429 FAST486_OPCODE_HANDLER(Fast486OpcodePopEs
)
2433 if (!Fast486StackPop(State
, &NewSelector
))
2435 /* Exception occurred */
2439 /* Call the internal API */
2440 return Fast486LoadSegment(State
, FAST486_REG_ES
, LOWORD(NewSelector
));
2443 FAST486_OPCODE_HANDLER(Fast486OpcodePushCs
)
2445 /* Call the internal API */
2446 return Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_CS
].Selector
);
2449 FAST486_OPCODE_HANDLER(Fast486OpcodeAdcByteModrm
)
2451 UCHAR FirstValue
, SecondValue
, Result
;
2452 FAST486_MOD_REG_RM ModRegRm
;
2453 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2455 /* Make sure this is the right instruction */
2456 ASSERT((Opcode
& 0xFD) == 0x10);
2458 TOGGLE_ADSIZE(AddressSize
);
2460 /* Get the operands */
2461 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2463 /* Exception occurred */
2467 if (!Fast486ReadModrmByteOperands(State
,
2472 /* Exception occurred */
2476 /* Calculate the result */
2477 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2479 /* Special exception for CF */
2480 State
->Flags
.Cf
= State
->Flags
.Cf
2481 && ((FirstValue
== 0xFF) || (SecondValue
== 0xFF));
2483 /* Update the flags */
2484 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2485 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
2486 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
2487 State
->Flags
.Af
= ((FirstValue
^ SecondValue
^ Result
) & 0x10) != 0;
2488 State
->Flags
.Zf
= (Result
== 0);
2489 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
2490 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2492 /* Write back the result */
2493 return Fast486WriteModrmByteOperands(State
,
2495 Opcode
& FAST486_OPCODE_WRITE_REG
,
2499 FAST486_OPCODE_HANDLER(Fast486OpcodeAdcModrm
)
2501 FAST486_MOD_REG_RM ModRegRm
;
2502 BOOLEAN OperandSize
, AddressSize
;
2504 /* Make sure this is the right instruction */
2505 ASSERT((Opcode
& 0xFD) == 0x11);
2507 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2509 TOGGLE_ADSIZE(AddressSize
);
2510 TOGGLE_OPSIZE(OperandSize
);
2512 /* Get the operands */
2513 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2515 /* Exception occurred */
2519 /* Check the operand size */
2522 ULONG FirstValue
, SecondValue
, Result
;
2524 if (!Fast486ReadModrmDwordOperands(State
,
2529 /* Exception occurred */
2533 /* Calculate the result */
2534 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2536 /* Special exception for CF */
2537 State
->Flags
.Cf
= State
->Flags
.Cf
2538 && ((FirstValue
== 0xFFFFFFFF) || (SecondValue
== 0xFFFFFFFF));
2540 /* Update the flags */
2541 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2542 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
2543 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
2544 State
->Flags
.Af
= ((FirstValue
^ SecondValue
^ Result
) & 0x10) != 0;
2545 State
->Flags
.Zf
= (Result
== 0);
2546 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
2547 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2549 /* Write back the result */
2550 return Fast486WriteModrmDwordOperands(State
,
2552 Opcode
& FAST486_OPCODE_WRITE_REG
,
2557 USHORT FirstValue
, SecondValue
, Result
;
2559 if (!Fast486ReadModrmWordOperands(State
,
2564 /* Exception occurred */
2568 /* Calculate the result */
2569 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2571 /* Special exception for CF */
2572 State
->Flags
.Cf
= State
->Flags
.Cf
2573 && ((FirstValue
== 0xFFFF) || (SecondValue
== 0xFFFF));
2575 /* Update the flags */
2576 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2577 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
2578 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
2579 State
->Flags
.Af
= ((FirstValue
^ SecondValue
^ Result
) & 0x10) != 0;
2580 State
->Flags
.Zf
= (Result
== 0);
2581 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
2582 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2584 /* Write back the result */
2585 return Fast486WriteModrmWordOperands(State
,
2587 Opcode
& FAST486_OPCODE_WRITE_REG
,
2593 FAST486_OPCODE_HANDLER(Fast486OpcodeAdcAl
)
2595 UCHAR FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
2596 UCHAR SecondValue
, Result
;
2598 /* Make sure this is the right instruction */
2599 ASSERT(Opcode
== 0x14);
2601 if (State
->PrefixFlags
)
2603 /* This opcode doesn't take any prefixes */
2604 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2608 if (!Fast486FetchByte(State
, &SecondValue
))
2610 /* Exception occurred */
2614 /* Calculate the result */
2615 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2617 /* Special exception for CF */
2618 State
->Flags
.Cf
= State
->Flags
.Cf
&&
2619 ((FirstValue
== 0xFF) || (SecondValue
== 0xFF));
2621 /* Update the flags */
2622 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2623 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
2624 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
2625 State
->Flags
.Af
= ((FirstValue
^ SecondValue
^ Result
) & 0x10) != 0;
2626 State
->Flags
.Zf
= (Result
== 0);
2627 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
2628 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2630 /* Write back the result */
2631 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= Result
;
2636 FAST486_OPCODE_HANDLER(Fast486OpcodeAdcEax
)
2638 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2640 /* Make sure this is the right instruction */
2641 ASSERT(Opcode
== 0x15);
2644 TOGGLE_OPSIZE(Size
);
2648 ULONG FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
2649 ULONG SecondValue
, Result
;
2651 if (!Fast486FetchDword(State
, &SecondValue
))
2653 /* Exception occurred */
2657 /* Calculate the result */
2658 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2660 /* Special exception for CF */
2661 State
->Flags
.Cf
= State
->Flags
.Cf
&&
2662 ((FirstValue
== 0xFFFFFFFF) || (SecondValue
== 0xFFFFFFFF));
2664 /* Update the flags */
2665 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2666 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
2667 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
2668 State
->Flags
.Af
= ((FirstValue
^ SecondValue
^ Result
) & 0x10) != 0;
2669 State
->Flags
.Zf
= (Result
== 0);
2670 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
2671 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2673 /* Write back the result */
2674 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Result
;
2678 USHORT FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
2679 USHORT SecondValue
, Result
;
2681 if (!Fast486FetchWord(State
, &SecondValue
))
2683 /* Exception occurred */
2687 /* Calculate the result */
2688 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2690 /* Special exception for CF */
2691 State
->Flags
.Cf
= State
->Flags
.Cf
&&
2692 ((FirstValue
== 0xFFFF) || (SecondValue
== 0xFFFF));
2694 /* Update the flags */
2695 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2696 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
2697 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
2698 State
->Flags
.Af
= ((FirstValue
^ SecondValue
^ Result
) & 0x10) != 0;
2699 State
->Flags
.Zf
= (Result
== 0);
2700 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
2701 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2703 /* Write back the result */
2704 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Result
;
2710 FAST486_OPCODE_HANDLER(Fast486OpcodePushSs
)
2712 /* Call the internal API */
2713 return Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_SS
].Selector
);
2716 FAST486_OPCODE_HANDLER(Fast486OpcodePopSs
)
2720 if (!Fast486StackPop(State
, &NewSelector
))
2722 /* Exception occurred */
2726 /* Call the internal API */
2727 return Fast486LoadSegment(State
, FAST486_REG_SS
, LOWORD(NewSelector
));
2730 FAST486_OPCODE_HANDLER(Fast486OpcodeSbbByteModrm
)
2732 UCHAR FirstValue
, SecondValue
, Result
;
2733 FAST486_MOD_REG_RM ModRegRm
;
2734 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2735 INT Carry
= State
->Flags
.Cf
? 1 : 0;
2737 /* Make sure this is the right instruction */
2738 ASSERT((Opcode
& 0xFD) == 0x18);
2740 TOGGLE_ADSIZE(AddressSize
);
2742 /* Get the operands */
2743 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2745 /* Exception occurred */
2749 if (!Fast486ReadModrmByteOperands(State
,
2754 /* Exception occurred */
2758 /* Check if this is the instruction that writes to R/M */
2759 if (!(Opcode
& FAST486_OPCODE_WRITE_REG
))
2761 /* Swap the order */
2762 SWAP(FirstValue
, SecondValue
);
2765 /* Calculate the result */
2766 Result
= FirstValue
- SecondValue
- Carry
;
2768 /* Update the flags */
2769 State
->Flags
.Cf
= Carry
? (FirstValue
<= SecondValue
) : (FirstValue
< SecondValue
);
2770 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) != (SecondValue
& SIGN_FLAG_BYTE
))
2771 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
2772 State
->Flags
.Af
= ((FirstValue
^ SecondValue
^ Result
) & 0x10) != 0;
2773 State
->Flags
.Zf
= (Result
== 0);
2774 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
2775 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2777 /* Write back the result */
2778 return Fast486WriteModrmByteOperands(State
,
2780 Opcode
& FAST486_OPCODE_WRITE_REG
,
2784 FAST486_OPCODE_HANDLER(Fast486OpcodeSbbModrm
)
2786 FAST486_MOD_REG_RM ModRegRm
;
2787 BOOLEAN OperandSize
, AddressSize
;
2788 INT Carry
= State
->Flags
.Cf
? 1 : 0;
2790 /* Make sure this is the right instruction */
2791 ASSERT((Opcode
& 0xFD) == 0x19);
2793 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2795 TOGGLE_ADSIZE(AddressSize
);
2796 TOGGLE_OPSIZE(OperandSize
);
2798 /* Get the operands */
2799 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2801 /* Exception occurred */
2805 /* Check the operand size */
2808 ULONG FirstValue
, SecondValue
, Result
;
2810 if (!Fast486ReadModrmDwordOperands(State
,
2815 /* Exception occurred */
2819 /* Check if this is the instruction that writes to R/M */
2820 if (!(Opcode
& FAST486_OPCODE_WRITE_REG
))
2822 /* Swap the order */
2823 SWAP(FirstValue
, SecondValue
);
2826 /* Calculate the result */
2827 Result
= FirstValue
- SecondValue
- Carry
;
2829 /* Update the flags */
2830 State
->Flags
.Cf
= Carry
? (FirstValue
<= SecondValue
) : (FirstValue
< SecondValue
);
2831 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) != (SecondValue
& SIGN_FLAG_LONG
))
2832 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
2833 State
->Flags
.Af
= ((FirstValue
^ SecondValue
^ Result
) & 0x10) != 0;
2834 State
->Flags
.Zf
= (Result
== 0);
2835 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
2836 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2838 /* Write back the result */
2839 return Fast486WriteModrmDwordOperands(State
,
2841 Opcode
& FAST486_OPCODE_WRITE_REG
,
2846 USHORT FirstValue
, SecondValue
, Result
;
2848 if (!Fast486ReadModrmWordOperands(State
,
2853 /* Exception occurred */
2857 /* Check if this is the instruction that writes to R/M */
2858 if (!(Opcode
& FAST486_OPCODE_WRITE_REG
))
2860 /* Swap the order */
2861 SWAP(FirstValue
, SecondValue
);
2864 /* Calculate the result */
2865 Result
= FirstValue
- SecondValue
- Carry
;
2867 /* Update the flags */
2868 State
->Flags
.Cf
= Carry
? (FirstValue
<= SecondValue
) : (FirstValue
< SecondValue
);
2869 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) != (SecondValue
& SIGN_FLAG_WORD
))
2870 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
2871 State
->Flags
.Af
= ((FirstValue
^ SecondValue
^ Result
) & 0x10) != 0;
2872 State
->Flags
.Zf
= (Result
== 0);
2873 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
2874 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2876 /* Write back the result */
2877 return Fast486WriteModrmWordOperands(State
,
2879 Opcode
& FAST486_OPCODE_WRITE_REG
,
2884 FAST486_OPCODE_HANDLER(Fast486OpcodeSbbAl
)
2886 UCHAR FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
2887 UCHAR SecondValue
, Result
;
2888 INT Carry
= State
->Flags
.Cf
? 1 : 0;
2890 /* Make sure this is the right instruction */
2891 ASSERT(Opcode
== 0x1C);
2893 if (State
->PrefixFlags
)
2895 /* This opcode doesn't take any prefixes */
2896 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2900 if (!Fast486FetchByte(State
, &SecondValue
))
2902 /* Exception occurred */
2906 /* Calculate the result */
2907 Result
= FirstValue
- SecondValue
- Carry
;
2909 /* Update the flags */
2910 State
->Flags
.Cf
= Carry
? (FirstValue
<= SecondValue
) : (FirstValue
< SecondValue
);
2911 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) != (SecondValue
& SIGN_FLAG_BYTE
))
2912 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
2913 State
->Flags
.Af
= ((FirstValue
^ SecondValue
^ Result
) & 0x10) != 0;
2914 State
->Flags
.Zf
= (Result
== 0);
2915 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
2916 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2918 /* Write back the result */
2919 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= Result
;
2925 FAST486_OPCODE_HANDLER(Fast486OpcodeSbbEax
)
2927 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2928 INT Carry
= State
->Flags
.Cf
? 1 : 0;
2930 /* Make sure this is the right instruction */
2931 ASSERT(Opcode
== 0x1D);
2934 TOGGLE_OPSIZE(Size
);
2938 ULONG FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
2939 ULONG SecondValue
, Result
;
2941 if (!Fast486FetchDword(State
, &SecondValue
))
2943 /* Exception occurred */
2947 /* Calculate the result */
2948 Result
= FirstValue
- SecondValue
- Carry
;
2950 /* Update the flags */
2951 State
->Flags
.Cf
= Carry
? (FirstValue
<= SecondValue
) : (FirstValue
< SecondValue
);
2952 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) != (SecondValue
& SIGN_FLAG_LONG
))
2953 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
2954 State
->Flags
.Af
= ((FirstValue
^ SecondValue
^ Result
) & 0x10) != 0;
2955 State
->Flags
.Zf
= (Result
== 0);
2956 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
2957 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2959 /* Write back the result */
2960 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Result
;
2964 USHORT FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
2965 USHORT SecondValue
, Result
;
2967 if (!Fast486FetchWord(State
, &SecondValue
))
2969 /* Exception occurred */
2973 /* Calculate the result */
2974 Result
= FirstValue
- SecondValue
- Carry
;
2976 /* Update the flags */
2977 State
->Flags
.Cf
= Carry
? (FirstValue
<= SecondValue
) : (FirstValue
< SecondValue
);
2978 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) != (SecondValue
& SIGN_FLAG_WORD
))
2979 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
2980 State
->Flags
.Af
= ((FirstValue
^ SecondValue
^ Result
) & 0x10) != 0;
2981 State
->Flags
.Zf
= (Result
== 0);
2982 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
2983 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2985 /* Write back the result */
2986 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Result
;
2993 FAST486_OPCODE_HANDLER(Fast486OpcodePushDs
)
2995 /* Call the internal API */
2996 return Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_DS
].Selector
);
2999 FAST486_OPCODE_HANDLER(Fast486OpcodePopDs
)
3003 if (!Fast486StackPop(State
, &NewSelector
))
3005 /* Exception occurred */
3009 /* Call the internal API */
3010 return Fast486LoadSegment(State
, FAST486_REG_DS
, LOWORD(NewSelector
));
3013 FAST486_OPCODE_HANDLER(Fast486OpcodeDaa
)
3015 UCHAR Value
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
3016 BOOLEAN Carry
= State
->Flags
.Cf
;
3018 /* Clear the carry flag */
3019 State
->Flags
.Cf
= FALSE
;
3021 /* Check if the first BCD digit is invalid or there was a carry from it */
3022 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3025 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
+= 0x06;
3026 if (State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
< 0x06)
3028 /* A carry occurred */
3029 State
->Flags
.Cf
= TRUE
;
3032 /* Set the adjust flag */
3033 State
->Flags
.Af
= TRUE
;
3036 /* Check if the second BCD digit is invalid or there was a carry from it */
3037 if ((Value
> 0x99) || Carry
)
3040 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
+= 0x60;
3042 /* There was a carry */
3043 State
->Flags
.Cf
= TRUE
;
3046 Value
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
3048 /* Update the flags */
3049 State
->Flags
.Sf
= (Value
& SIGN_FLAG_BYTE
) != 0;
3050 State
->Flags
.Zf
= (Value
== 0);
3051 State
->Flags
.Pf
= Fast486CalculateParity(Value
);
3056 FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubByteModrm
)
3058 UCHAR FirstValue
, SecondValue
, Result
;
3059 FAST486_MOD_REG_RM ModRegRm
;
3060 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
3062 /* Make sure this is the right instruction */
3063 ASSERT((Opcode
& 0xED) == 0x28);
3065 TOGGLE_ADSIZE(AddressSize
);
3067 /* Get the operands */
3068 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3070 /* Exception occurred */
3074 if (!Fast486ReadModrmByteOperands(State
,
3079 /* Exception occurred */
3083 /* Check if this is the instruction that writes to R/M */
3084 if (!(Opcode
& FAST486_OPCODE_WRITE_REG
))
3086 /* Swap the order */
3087 SWAP(FirstValue
, SecondValue
);
3090 /* Calculate the result */
3091 Result
= FirstValue
- SecondValue
;
3093 /* Update the flags */
3094 State
->Flags
.Cf
= (FirstValue
< SecondValue
);
3095 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) != (SecondValue
& SIGN_FLAG_BYTE
))
3096 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
3097 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3098 State
->Flags
.Zf
= (Result
== 0);
3099 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
3100 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
3102 /* Check if this is not a CMP */
3103 if (!(Opcode
& 0x10))
3105 /* Write back the result */
3106 return Fast486WriteModrmByteOperands(State
,
3108 Opcode
& FAST486_OPCODE_WRITE_REG
,
3113 /* Discard the result */
3118 FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubModrm
)
3120 FAST486_MOD_REG_RM ModRegRm
;
3121 BOOLEAN OperandSize
, AddressSize
;
3123 /* Make sure this is the right instruction */
3124 ASSERT((Opcode
& 0xED) == 0x29);
3126 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
3128 TOGGLE_ADSIZE(AddressSize
);
3129 TOGGLE_OPSIZE(OperandSize
);
3131 /* Get the operands */
3132 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3134 /* Exception occurred */
3138 /* Check the operand size */
3141 ULONG FirstValue
, SecondValue
, Result
;
3143 if (!Fast486ReadModrmDwordOperands(State
,
3148 /* Exception occurred */
3152 /* Check if this is the instruction that writes to R/M */
3153 if (!(Opcode
& FAST486_OPCODE_WRITE_REG
))
3155 /* Swap the order */
3156 SWAP(FirstValue
, SecondValue
);
3159 /* Calculate the result */
3160 Result
= FirstValue
- SecondValue
;
3162 /* Update the flags */
3163 State
->Flags
.Cf
= (FirstValue
< SecondValue
);
3164 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) != (SecondValue
& SIGN_FLAG_LONG
))
3165 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
3166 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3167 State
->Flags
.Zf
= (Result
== 0);
3168 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
3169 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
3171 /* Check if this is not a CMP */
3172 if (!(Opcode
& 0x10))
3174 /* Write back the result */
3175 return Fast486WriteModrmDwordOperands(State
,
3177 Opcode
& FAST486_OPCODE_WRITE_REG
,
3182 /* Discard the result */
3188 USHORT FirstValue
, SecondValue
, Result
;
3190 if (!Fast486ReadModrmWordOperands(State
,
3195 /* Exception occurred */
3199 /* Check if this is the instruction that writes to R/M */
3200 if (!(Opcode
& FAST486_OPCODE_WRITE_REG
))
3202 /* Swap the order */
3203 SWAP(FirstValue
, SecondValue
);
3206 /* Calculate the result */
3207 Result
= FirstValue
- SecondValue
;
3209 /* Update the flags */
3210 State
->Flags
.Cf
= (FirstValue
< SecondValue
);
3211 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) != (SecondValue
& SIGN_FLAG_WORD
))
3212 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
3213 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3214 State
->Flags
.Zf
= (Result
== 0);
3215 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
3216 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
3218 /* Check if this is not a CMP */
3219 if (!(Opcode
& 0x10))
3221 /* Write back the result */
3222 return Fast486WriteModrmWordOperands(State
,
3224 Opcode
& FAST486_OPCODE_WRITE_REG
,
3229 /* Discard the result */
3235 FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubAl
)
3237 UCHAR FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
3238 UCHAR SecondValue
, Result
;
3240 /* Make sure this is the right instruction */
3241 ASSERT((Opcode
& 0xEF) == 0x2C);
3243 if (State
->PrefixFlags
)
3245 /* This opcode doesn't take any prefixes */
3246 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
3250 if (!Fast486FetchByte(State
, &SecondValue
))
3252 /* Exception occurred */
3256 /* Calculate the result */
3257 Result
= FirstValue
- SecondValue
;
3259 /* Update the flags */
3260 State
->Flags
.Cf
= (FirstValue
< SecondValue
);
3261 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) != (SecondValue
& SIGN_FLAG_BYTE
))
3262 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
3263 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3264 State
->Flags
.Zf
= (Result
== 0);
3265 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
3266 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
3268 /* Check if this is not a CMP */
3269 if (!(Opcode
& 0x10))
3271 /* Write back the result */
3272 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= Result
;
3278 FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubEax
)
3280 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
3282 /* Make sure this is the right instruction */
3283 ASSERT((Opcode
& 0xEF) == 0x2D);
3286 TOGGLE_OPSIZE(Size
);
3290 ULONG FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
3291 ULONG SecondValue
, Result
;
3293 if (!Fast486FetchDword(State
, &SecondValue
))
3295 /* Exception occurred */
3299 /* Calculate the result */
3300 Result
= FirstValue
- SecondValue
;
3302 /* Update the flags */
3303 State
->Flags
.Cf
= (FirstValue
< SecondValue
);
3304 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) != (SecondValue
& SIGN_FLAG_LONG
))
3305 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
3306 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3307 State
->Flags
.Zf
= (Result
== 0);
3308 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
3309 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
3311 /* Check if this is not a CMP */
3312 if (!(Opcode
& 0x10))
3314 /* Write back the result */
3315 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Result
;
3320 USHORT FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
3321 USHORT SecondValue
, Result
;
3323 if (!Fast486FetchWord(State
, &SecondValue
))
3325 /* Exception occurred */
3329 /* Calculate the result */
3330 Result
= FirstValue
- SecondValue
;
3332 /* Update the flags */
3333 State
->Flags
.Cf
= (FirstValue
< SecondValue
);
3334 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) != (SecondValue
& SIGN_FLAG_WORD
))
3335 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
3336 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3337 State
->Flags
.Zf
= (Result
== 0);
3338 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
3339 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
3341 /* Check if this is not a CMP */
3342 if (!(Opcode
& 0x10))
3344 /* Write back the result */
3345 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Result
;
3352 FAST486_OPCODE_HANDLER(Fast486OpcodeDas
)
3354 UCHAR Value
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
3355 BOOLEAN Carry
= State
->Flags
.Cf
;
3357 /* Clear the carry flag */
3358 State
->Flags
.Cf
= FALSE
;
3360 /* Check if the first BCD digit is invalid or there was a borrow */
3361 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3364 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
-= 0x06;
3365 if (State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
> 0xFB)
3367 /* A borrow occurred */
3368 State
->Flags
.Cf
= TRUE
;
3371 /* Set the adjust flag */
3372 State
->Flags
.Af
= TRUE
;
3375 /* Check if the second BCD digit is invalid or there was a borrow */
3376 if ((Value
> 0x99) || Carry
)
3379 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
-= 0x60;
3381 /* There was a borrow */
3382 State
->Flags
.Cf
= TRUE
;
3385 Value
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
3387 /* Update the flags */
3388 State
->Flags
.Sf
= (Value
& SIGN_FLAG_BYTE
) != 0;
3389 State
->Flags
.Zf
= (Value
== 0);
3390 State
->Flags
.Pf
= Fast486CalculateParity(Value
);
3395 FAST486_OPCODE_HANDLER(Fast486OpcodeAaa
)
3397 UCHAR Value
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
3400 * Check if the value in AL is not a valid BCD digit,
3401 * or there was a carry from the lowest 4 bits of AL
3403 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3406 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
+= 0x06;
3407 State
->GeneralRegs
[FAST486_REG_EAX
].HighByte
++;
3410 State
->Flags
.Cf
= State
->Flags
.Af
= TRUE
;
3414 /* Clear CF and AF */
3415 State
->Flags
.Cf
= State
->Flags
.Af
= FALSE
;
3418 /* Keep only the lowest 4 bits of AL */
3419 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
&= 0x0F;
3424 FAST486_OPCODE_HANDLER(Fast486OpcodeAas
)
3426 UCHAR Value
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;