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 *******************************************************************/
35 /* PUBLIC VARIABLES ***********************************************************/
37 FAST486_OPCODE_HANDLER_PROC
38 Fast486OpcodeHandlers
[FAST486_NUM_OPCODE_HANDLERS
] =
40 Fast486OpcodeAddByteModrm
,
41 Fast486OpcodeAddModrm
,
42 Fast486OpcodeAddByteModrm
,
43 Fast486OpcodeAddModrm
,
48 Fast486OpcodeOrByteModrm
,
50 Fast486OpcodeOrByteModrm
,
55 Fast486OpcodeExtended
,
56 Fast486OpcodeAdcByteModrm
,
57 Fast486OpcodeAdcModrm
,
58 Fast486OpcodeAdcByteModrm
,
59 Fast486OpcodeAdcModrm
,
64 Fast486OpcodeSbbByteModrm
,
65 Fast486OpcodeSbbModrm
,
66 Fast486OpcodeSbbByteModrm
,
67 Fast486OpcodeSbbModrm
,
72 Fast486OpcodeAndByteModrm
,
73 Fast486OpcodeAndModrm
,
74 Fast486OpcodeAndByteModrm
,
75 Fast486OpcodeAndModrm
,
80 Fast486OpcodeCmpSubByteModrm
,
81 Fast486OpcodeCmpSubModrm
,
82 Fast486OpcodeCmpSubByteModrm
,
83 Fast486OpcodeCmpSubModrm
,
84 Fast486OpcodeCmpSubAl
,
85 Fast486OpcodeCmpSubEax
,
88 Fast486OpcodeXorByteModrm
,
89 Fast486OpcodeXorModrm
,
90 Fast486OpcodeXorByteModrm
,
91 Fast486OpcodeXorModrm
,
96 Fast486OpcodeCmpSubByteModrm
,
97 Fast486OpcodeCmpSubModrm
,
98 Fast486OpcodeCmpSubByteModrm
,
99 Fast486OpcodeCmpSubModrm
,
100 Fast486OpcodeCmpSubAl
,
101 Fast486OpcodeCmpSubEax
,
104 Fast486OpcodeIncrement
,
105 Fast486OpcodeIncrement
,
106 Fast486OpcodeIncrement
,
107 Fast486OpcodeIncrement
,
108 Fast486OpcodeIncrement
,
109 Fast486OpcodeIncrement
,
110 Fast486OpcodeIncrement
,
111 Fast486OpcodeIncrement
,
112 Fast486OpcodeDecrement
,
113 Fast486OpcodeDecrement
,
114 Fast486OpcodeDecrement
,
115 Fast486OpcodeDecrement
,
116 Fast486OpcodeDecrement
,
117 Fast486OpcodeDecrement
,
118 Fast486OpcodeDecrement
,
119 Fast486OpcodeDecrement
,
120 Fast486OpcodePushReg
,
121 Fast486OpcodePushReg
,
122 Fast486OpcodePushReg
,
123 Fast486OpcodePushReg
,
124 Fast486OpcodePushReg
,
125 Fast486OpcodePushReg
,
126 Fast486OpcodePushReg
,
127 Fast486OpcodePushReg
,
136 Fast486OpcodePushAll
,
144 Fast486OpcodePushImm
,
145 Fast486OpcodeImulModrmImm
,
146 Fast486OpcodePushByteImm
,
147 Fast486OpcodeImulModrmImm
,
152 Fast486OpcodeShortConditionalJmp
,
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 Fast486OpcodeGroup8082
,
169 Fast486OpcodeGroup81
,
170 Fast486OpcodeGroup8082
,
171 Fast486OpcodeGroup83
,
172 Fast486OpcodeTestByteModrm
,
173 Fast486OpcodeTestModrm
,
174 Fast486OpcodeXchgByteModrm
,
175 Fast486OpcodeXchgModrm
,
176 Fast486OpcodeMovByteModrm
,
177 Fast486OpcodeMovModrm
,
178 Fast486OpcodeMovByteModrm
,
179 Fast486OpcodeMovModrm
,
180 Fast486OpcodeMovStoreSeg
,
182 Fast486OpcodeMovLoadSeg
,
183 Fast486OpcodeGroup8F
,
185 Fast486OpcodeExchangeEax
,
186 Fast486OpcodeExchangeEax
,
187 Fast486OpcodeExchangeEax
,
188 Fast486OpcodeExchangeEax
,
189 Fast486OpcodeExchangeEax
,
190 Fast486OpcodeExchangeEax
,
191 Fast486OpcodeExchangeEax
,
194 Fast486OpcodeCallAbs
,
196 Fast486OpcodePushFlags
,
197 Fast486OpcodePopFlags
,
200 Fast486OpcodeMovAlOffset
,
201 Fast486OpcodeMovEaxOffset
,
202 Fast486OpcodeMovOffsetAl
,
203 Fast486OpcodeMovOffsetEax
,
209 Fast486OpcodeTestEax
,
216 Fast486OpcodeMovByteRegImm
,
217 Fast486OpcodeMovByteRegImm
,
218 Fast486OpcodeMovByteRegImm
,
219 Fast486OpcodeMovByteRegImm
,
220 Fast486OpcodeMovByteRegImm
,
221 Fast486OpcodeMovByteRegImm
,
222 Fast486OpcodeMovByteRegImm
,
223 Fast486OpcodeMovByteRegImm
,
224 Fast486OpcodeMovRegImm
,
225 Fast486OpcodeMovRegImm
,
226 Fast486OpcodeMovRegImm
,
227 Fast486OpcodeMovRegImm
,
228 Fast486OpcodeMovRegImm
,
229 Fast486OpcodeMovRegImm
,
230 Fast486OpcodeMovRegImm
,
231 Fast486OpcodeMovRegImm
,
232 Fast486OpcodeGroupC0
,
233 Fast486OpcodeGroupC1
,
238 Fast486OpcodeGroupC6
,
239 Fast486OpcodeGroupC7
,
248 Fast486OpcodeGroupD0
,
249 Fast486OpcodeGroupD1
,
250 Fast486OpcodeGroupD2
,
251 Fast486OpcodeGroupD3
,
256 NULL
, // TODO: OPCODE 0xD8 NOT SUPPORTED
257 NULL
, // TODO: OPCODE 0xD9 NOT SUPPORTED
258 NULL
, // TODO: OPCODE 0xDA NOT SUPPORTED
259 NULL
, // TODO: OPCODE 0xDB NOT SUPPORTED
260 NULL
, // TODO: OPCODE 0xDC NOT SUPPORTED
261 NULL
, // TODO: OPCODE 0xDD NOT SUPPORTED
262 NULL
, // TODO: OPCODE 0xDE NOT SUPPORTED
263 NULL
, // TODO: OPCODE 0xDF NOT SUPPORTED
270 Fast486OpcodeOutByte
,
275 Fast486OpcodeShortJump
,
278 Fast486OpcodeOutByte
,
285 Fast486OpcodeComplCarry
,
286 Fast486OpcodeGroupF6
,
287 Fast486OpcodeGroupF7
,
288 Fast486OpcodeClearCarry
,
289 Fast486OpcodeSetCarry
,
290 Fast486OpcodeClearInt
,
292 Fast486OpcodeClearDir
,
294 Fast486OpcodeGroupFE
,
295 Fast486OpcodeGroupFF
,
298 /* PUBLIC FUNCTIONS ***********************************************************/
300 FAST486_OPCODE_HANDLER(Fast486OpcodePrefix
)
302 BOOLEAN Valid
= FALSE
;
309 if (!(State
->PrefixFlags
& FAST486_PREFIX_SEG
))
311 State
->PrefixFlags
|= FAST486_PREFIX_SEG
;
312 State
->SegmentOverride
= FAST486_REG_ES
;
322 if (!(State
->PrefixFlags
& FAST486_PREFIX_SEG
))
324 State
->PrefixFlags
|= FAST486_PREFIX_SEG
;
325 State
->SegmentOverride
= FAST486_REG_CS
;
335 if (!(State
->PrefixFlags
& FAST486_PREFIX_SEG
))
337 State
->PrefixFlags
|= FAST486_PREFIX_SEG
;
338 State
->SegmentOverride
= FAST486_REG_SS
;
348 if (!(State
->PrefixFlags
& FAST486_PREFIX_SEG
))
350 State
->PrefixFlags
|= FAST486_PREFIX_SEG
;
351 State
->SegmentOverride
= FAST486_REG_DS
;
361 if (!(State
->PrefixFlags
& FAST486_PREFIX_SEG
))
363 State
->PrefixFlags
|= FAST486_PREFIX_SEG
;
364 State
->SegmentOverride
= FAST486_REG_FS
;
374 if (!(State
->PrefixFlags
& FAST486_PREFIX_SEG
))
376 State
->PrefixFlags
|= FAST486_PREFIX_SEG
;
377 State
->SegmentOverride
= FAST486_REG_GS
;
387 if (!(State
->PrefixFlags
& FAST486_PREFIX_OPSIZE
))
389 State
->PrefixFlags
|= FAST486_PREFIX_OPSIZE
;
399 if (!(State
->PrefixFlags
& FAST486_PREFIX_ADSIZE
))
401 State
->PrefixFlags
|= FAST486_PREFIX_ADSIZE
;
410 if (!(State
->PrefixFlags
& FAST486_PREFIX_LOCK
))
412 State
->PrefixFlags
|= FAST486_PREFIX_LOCK
;
422 /* Mutually exclusive with REP */
423 if (!(State
->PrefixFlags
424 & (FAST486_PREFIX_REPNZ
| FAST486_PREFIX_REP
)))
426 State
->PrefixFlags
|= FAST486_PREFIX_REPNZ
;
436 /* Mutually exclusive with REPNZ */
437 if (!(State
->PrefixFlags
438 & (FAST486_PREFIX_REPNZ
| FAST486_PREFIX_REP
)))
440 State
->PrefixFlags
|= FAST486_PREFIX_REP
;
450 /* Clear all prefixes */
451 State
->PrefixFlags
= 0;
453 /* Throw an exception */
454 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
461 FAST486_OPCODE_HANDLER(Fast486OpcodeIncrement
)
464 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
469 /* Make sure this is the right instruction */
470 ASSERT((Opcode
& 0xF8) == 0x40);
474 Value
= ++State
->GeneralRegs
[Opcode
& 0x07].Long
;
476 State
->Flags
.Of
= (Value
== SIGN_FLAG_LONG
);
477 State
->Flags
.Sf
= ((Value
& SIGN_FLAG_LONG
) != 0);
481 Value
= ++State
->GeneralRegs
[Opcode
& 0x07].LowWord
;
483 State
->Flags
.Of
= (Value
== SIGN_FLAG_WORD
);
484 State
->Flags
.Sf
= ((Value
& SIGN_FLAG_WORD
) != 0);
487 State
->Flags
.Zf
= (Value
== 0);
488 State
->Flags
.Af
= ((Value
& 0x0F) == 0);
489 State
->Flags
.Pf
= Fast486CalculateParity(LOBYTE(Value
));
495 FAST486_OPCODE_HANDLER(Fast486OpcodeDecrement
)
498 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
503 /* Make sure this is the right instruction */
504 ASSERT((Opcode
& 0xF8) == 0x48);
508 Value
= --State
->GeneralRegs
[Opcode
& 0x07].Long
;
510 State
->Flags
.Of
= (Value
== (SIGN_FLAG_LONG
- 1));
511 State
->Flags
.Sf
= ((Value
& SIGN_FLAG_LONG
) != 0);
515 Value
= --State
->GeneralRegs
[Opcode
& 0x07].LowWord
;
517 State
->Flags
.Of
= (Value
== (SIGN_FLAG_WORD
- 1));
518 State
->Flags
.Sf
= ((Value
& SIGN_FLAG_WORD
) != 0);
521 State
->Flags
.Zf
= (Value
== 0);
522 State
->Flags
.Af
= ((Value
& 0x0F) == 0x0F);
523 State
->Flags
.Pf
= Fast486CalculateParity(LOBYTE(Value
));
529 FAST486_OPCODE_HANDLER(Fast486OpcodePushReg
)
533 /* Make sure this is the right instruction */
534 ASSERT((Opcode
& 0xF8) == 0x50);
536 /* Call the internal function */
537 return Fast486StackPush(State
, State
->GeneralRegs
[Opcode
& 0x07].Long
);
540 FAST486_OPCODE_HANDLER(Fast486OpcodePopReg
)
543 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_SS
].Size
;
548 /* Make sure this is the right instruction */
549 ASSERT((Opcode
& 0xF8) == 0x58);
551 /* Call the internal function */
552 if (!Fast486StackPop(State
, &Value
)) return FALSE
;
554 /* Store the value */
555 if (Size
) State
->GeneralRegs
[Opcode
& 0x07].Long
= Value
;
556 else State
->GeneralRegs
[Opcode
& 0x07].LowWord
= Value
;
562 FAST486_OPCODE_HANDLER(Fast486OpcodeNop
)
564 if (State
->PrefixFlags
& FAST486_PREFIX_REP
)
567 State
->IdleCallback(State
);
573 FAST486_OPCODE_HANDLER(Fast486OpcodeExchangeEax
)
575 INT Reg
= Opcode
& 0x07;
576 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
581 /* Make sure this is the right instruction */
582 ASSERT((Opcode
& 0xF8) == 0x90);
584 /* Exchange the values */
589 Value
= State
->GeneralRegs
[Reg
].Long
;
590 State
->GeneralRegs
[Reg
].Long
= State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
591 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Value
;
597 Value
= State
->GeneralRegs
[Reg
].LowWord
;
598 State
->GeneralRegs
[Reg
].LowWord
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
599 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Value
;
605 FAST486_OPCODE_HANDLER(Fast486OpcodeShortConditionalJmp
)
607 BOOLEAN Jump
= FALSE
;
610 /* Make sure this is the right instruction */
611 ASSERT((Opcode
& 0xF0) == 0x70);
613 /* Fetch the offset */
614 if (!Fast486FetchByte(State
, (PUCHAR
)&Offset
))
616 /* An exception occurred */
620 switch ((Opcode
& 0x0F) >> 1)
625 Jump
= State
->Flags
.Of
;
632 Jump
= State
->Flags
.Cf
;
639 Jump
= State
->Flags
.Zf
;
646 Jump
= State
->Flags
.Cf
|| State
->Flags
.Zf
;
653 Jump
= State
->Flags
.Sf
;
660 Jump
= State
->Flags
.Pf
;
667 Jump
= State
->Flags
.Sf
!= State
->Flags
.Of
;
674 Jump
= (State
->Flags
.Sf
!= State
->Flags
.Of
) || State
->Flags
.Zf
;
681 /* Invert the result */
687 /* Move the instruction pointer */
688 State
->InstPtr
.Long
+= Offset
;
695 FAST486_OPCODE_HANDLER(Fast486OpcodeClearCarry
)
697 /* Make sure this is the right instruction */
698 ASSERT(Opcode
== 0xF8);
700 /* No prefixes allowed */
701 if (State
->PrefixFlags
)
703 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
707 /* Clear CF and return success */
708 State
->Flags
.Cf
= FALSE
;
712 FAST486_OPCODE_HANDLER(Fast486OpcodeSetCarry
)
714 /* Make sure this is the right instruction */
715 ASSERT(Opcode
== 0xF9);
717 /* No prefixes allowed */
718 if (State
->PrefixFlags
)
720 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
724 /* Set CF and return success*/
725 State
->Flags
.Cf
= TRUE
;
729 FAST486_OPCODE_HANDLER(Fast486OpcodeComplCarry
)
731 /* Make sure this is the right instruction */
732 ASSERT(Opcode
== 0xF5);
734 /* No prefixes allowed */
735 if (State
->PrefixFlags
)
737 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
741 /* Toggle CF and return success */
742 State
->Flags
.Cf
= !State
->Flags
.Cf
;
746 FAST486_OPCODE_HANDLER(Fast486OpcodeClearInt
)
748 /* Make sure this is the right instruction */
749 ASSERT(Opcode
== 0xFA);
751 /* No prefixes allowed */
752 if (State
->PrefixFlags
)
754 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
758 /* Check for protected mode */
759 if (State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
762 if (State
->Flags
.Iopl
>= State
->SegmentRegs
[FAST486_REG_CS
].Dpl
)
764 /* Clear the interrupt flag */
765 State
->Flags
.If
= FALSE
;
769 /* General Protection Fault */
770 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
776 /* Just clear the interrupt flag */
777 State
->Flags
.If
= FALSE
;
784 FAST486_OPCODE_HANDLER(Fast486OpcodeSetInt
)
786 /* Make sure this is the right instruction */
787 ASSERT(Opcode
== 0xFB);
789 /* No prefixes allowed */
790 if (State
->PrefixFlags
)
792 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
796 /* Check for protected mode */
797 if (State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
800 if (State
->Flags
.Iopl
>= State
->SegmentRegs
[FAST486_REG_CS
].Dpl
)
802 /* Set the interrupt flag */
803 State
->Flags
.If
= TRUE
;
807 /* General Protection Fault */
808 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
814 /* Just set the interrupt flag */
815 State
->Flags
.If
= TRUE
;
822 FAST486_OPCODE_HANDLER(Fast486OpcodeClearDir
)
824 /* Make sure this is the right instruction */
825 ASSERT(Opcode
== 0xFC);
827 /* No prefixes allowed */
828 if (State
->PrefixFlags
)
830 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
834 /* Clear DF and return success */
835 State
->Flags
.Df
= FALSE
;
839 FAST486_OPCODE_HANDLER(Fast486OpcodeSetDir
)
841 /* Make sure this is the right instruction */
842 ASSERT(Opcode
== 0xFD);
844 /* No prefixes allowed */
845 if (State
->PrefixFlags
)
847 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
851 /* Set DF and return success*/
852 State
->Flags
.Df
= TRUE
;
856 FAST486_OPCODE_HANDLER(Fast486OpcodeHalt
)
858 /* Make sure this is the right instruction */
859 ASSERT(Opcode
== 0xF4);
861 /* No prefixes allowed */
862 if (State
->PrefixFlags
)
864 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
868 /* Privileged instructions can only be executed under CPL = 0 */
869 if (State
->SegmentRegs
[FAST486_REG_CS
].Dpl
!= 0)
871 Fast486Exception(State
, FAST486_EXCEPTION_GP
);
876 while (State
->IntStatus
!= FAST486_INT_SIGNAL
) State
->IdleCallback(State
);
882 FAST486_OPCODE_HANDLER(Fast486OpcodeInByte
)
887 /* Make sure this is the right instruction */
888 ASSERT((Opcode
& 0xF7) == 0xE4);
892 /* Fetch the parameter */
893 if (!Fast486FetchByte(State
, &Data
))
895 /* Exception occurred */
899 /* Set the port number to the parameter */
904 /* The port number is in DX */
905 Port
= State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
;
908 /* Read a byte from the I/O port */
909 State
->IoReadCallback(State
, Port
, &Data
, 1, sizeof(UCHAR
));
911 /* Store the result in AL */
912 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= Data
;
917 FAST486_OPCODE_HANDLER(Fast486OpcodeIn
)
920 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
922 /* Make sure this is the right instruction */
923 ASSERT((Opcode
& 0xF7) == 0xE5);
932 /* Fetch the parameter */
933 if (!Fast486FetchByte(State
, &Data
))
935 /* Exception occurred */
939 /* Set the port number to the parameter */
944 /* The port number is in DX */
945 Port
= State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
;
952 /* Read a dword from the I/O port */
953 State
->IoReadCallback(State
, Port
, &Data
, 1, sizeof(ULONG
));
955 /* Store the value in EAX */
956 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Data
;
962 /* Read a word from the I/O port */
963 State
->IoReadCallback(State
, Port
, &Data
, 1, sizeof(USHORT
));
965 /* Store the value in AX */
966 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Data
;
972 FAST486_OPCODE_HANDLER(Fast486OpcodeOutByte
)
977 /* Make sure this is the right instruction */
978 ASSERT((Opcode
& 0xF7) == 0xE6);
982 /* Fetch the parameter */
983 if (!Fast486FetchByte(State
, &Data
))
985 /* Exception occurred */
989 /* Set the port number to the parameter */
994 /* The port number is in DX */
995 Port
= State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
;
998 /* Read the value from AL */
999 Data
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
1001 /* Write the byte to the I/O port */
1002 State
->IoWriteCallback(State
, Port
, &Data
, 1, sizeof(UCHAR
));
1007 FAST486_OPCODE_HANDLER(Fast486OpcodeOut
)
1010 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1012 /* Make sure this is the right instruction */
1013 ASSERT((Opcode
& 0xF7) == 0xE7);
1015 TOGGLE_OPSIZE(Size
);
1022 /* Fetch the parameter */
1023 if (!Fast486FetchByte(State
, &Data
))
1025 /* Exception occurred */
1029 /* Set the port number to the parameter */
1034 /* The port number is in DX */
1035 Port
= State
->GeneralRegs
[FAST486_REG_EDX
].LowWord
;
1040 /* Get the value from EAX */
1041 ULONG Data
= State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
1043 /* Write a dword to the I/O port */
1044 State
->IoWriteCallback(State
, Port
, &Data
, 1, sizeof(ULONG
));
1048 /* Get the value from AX */
1049 USHORT Data
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
1051 /* Write a word to the I/O port */
1052 State
->IoWriteCallback(State
, Port
, &Data
, 1, sizeof(USHORT
));
1058 FAST486_OPCODE_HANDLER(Fast486OpcodeShortJump
)
1062 /* Make sure this is the right instruction */
1063 ASSERT(Opcode
== 0xEB);
1065 /* Fetch the offset */
1066 if (!Fast486FetchByte(State
, (PUCHAR
)&Offset
))
1068 /* An exception occurred */
1072 /* Move the instruction pointer */
1073 State
->InstPtr
.Long
+= Offset
;
1078 FAST486_OPCODE_HANDLER(Fast486OpcodeMovRegImm
)
1080 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1082 /* Make sure this is the right instruction */
1083 ASSERT((Opcode
& 0xF8) == 0xB8);
1085 TOGGLE_OPSIZE(Size
);
1092 /* Fetch the dword */
1093 if (!Fast486FetchDword(State
, &Value
))
1095 /* Exception occurred */
1099 /* Store the value in the register */
1100 State
->GeneralRegs
[Opcode
& 0x07].Long
= Value
;
1106 /* Fetch the word */
1107 if (!Fast486FetchWord(State
, &Value
))
1109 /* Exception occurred */
1113 /* Store the value in the register */
1114 State
->GeneralRegs
[Opcode
& 0x07].LowWord
= Value
;
1120 FAST486_OPCODE_HANDLER(Fast486OpcodeMovByteRegImm
)
1124 /* Make sure this is the right instruction */
1125 ASSERT((Opcode
& 0xF8) == 0xB0);
1127 if (State
->PrefixFlags
!= 0)
1129 /* Invalid prefix */
1130 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1134 /* Fetch the byte */
1135 if (!Fast486FetchByte(State
, &Value
))
1137 /* Exception occurred */
1143 /* AH, CH, DH or BH */
1144 State
->GeneralRegs
[Opcode
& 0x03].HighByte
= Value
;
1148 /* AL, CL, DL or BL */
1149 State
->GeneralRegs
[Opcode
& 0x03].LowByte
= Value
;
1155 FAST486_OPCODE_HANDLER(Fast486OpcodeAddByteModrm
)
1157 UCHAR FirstValue
, SecondValue
, Result
;
1158 FAST486_MOD_REG_RM ModRegRm
;
1159 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1161 /* Make sure this is the right instruction */
1162 ASSERT((Opcode
& 0xFD) == 0x00);
1164 TOGGLE_ADSIZE(AddressSize
);
1166 /* Get the operands */
1167 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1169 /* Exception occurred */
1173 if (!Fast486ReadModrmByteOperands(State
,
1178 /* Exception occurred */
1182 /* Calculate the result */
1183 Result
= FirstValue
+ SecondValue
;
1185 /* Update the flags */
1186 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1187 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
1188 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
1189 State
->Flags
.Af
= ((((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) != 0);
1190 State
->Flags
.Zf
= (Result
== 0);
1191 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
1192 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1194 /* Write back the result */
1195 return Fast486WriteModrmByteOperands(State
,
1197 Opcode
& FAST486_OPCODE_WRITE_REG
,
1201 FAST486_OPCODE_HANDLER(Fast486OpcodeAddModrm
)
1203 FAST486_MOD_REG_RM ModRegRm
;
1204 BOOLEAN OperandSize
, AddressSize
;
1206 /* Make sure this is the right instruction */
1207 ASSERT((Opcode
& 0xFD) == 0x01);
1209 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1211 TOGGLE_ADSIZE(AddressSize
);
1212 TOGGLE_OPSIZE(OperandSize
);
1214 /* Get the operands */
1215 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1217 /* Exception occurred */
1221 /* Check the operand size */
1224 ULONG FirstValue
, SecondValue
, Result
;
1226 if (!Fast486ReadModrmDwordOperands(State
,
1231 /* Exception occurred */
1235 /* Calculate the result */
1236 Result
= FirstValue
+ SecondValue
;
1238 /* Update the flags */
1239 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1240 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
1241 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
1242 State
->Flags
.Af
= ((((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) != 0);
1243 State
->Flags
.Zf
= (Result
== 0);
1244 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
1245 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1247 /* Write back the result */
1248 return Fast486WriteModrmDwordOperands(State
,
1250 Opcode
& FAST486_OPCODE_WRITE_REG
,
1255 USHORT FirstValue
, SecondValue
, Result
;
1257 if (!Fast486ReadModrmWordOperands(State
,
1262 /* Exception occurred */
1266 /* Calculate the result */
1267 Result
= FirstValue
+ SecondValue
;
1269 /* Update the flags */
1270 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1271 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
1272 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
1273 State
->Flags
.Af
= ((((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) != 0);
1274 State
->Flags
.Zf
= (Result
== 0);
1275 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
1276 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1278 /* Write back the result */
1279 return Fast486WriteModrmWordOperands(State
,
1281 Opcode
& FAST486_OPCODE_WRITE_REG
,
1286 FAST486_OPCODE_HANDLER(Fast486OpcodeAddAl
)
1288 UCHAR FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
1289 UCHAR SecondValue
, Result
;
1291 /* Make sure this is the right instruction */
1292 ASSERT(Opcode
== 0x04);
1294 if (State
->PrefixFlags
)
1296 /* This opcode doesn't take any prefixes */
1297 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1301 if (!Fast486FetchByte(State
, &SecondValue
))
1303 /* Exception occurred */
1307 /* Calculate the result */
1308 Result
= FirstValue
+ SecondValue
;
1310 /* Update the flags */
1311 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1312 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
1313 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
1314 State
->Flags
.Af
= ((((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) != 0);
1315 State
->Flags
.Zf
= (Result
== 0);
1316 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
1317 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1319 /* Write back the result */
1320 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= Result
;
1325 FAST486_OPCODE_HANDLER(Fast486OpcodeAddEax
)
1327 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1329 /* Make sure this is the right instruction */
1330 ASSERT(Opcode
== 0x05);
1333 TOGGLE_OPSIZE(Size
);
1337 ULONG FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
1338 ULONG SecondValue
, Result
;
1340 if (!Fast486FetchDword(State
, &SecondValue
))
1342 /* Exception occurred */
1346 /* Calculate the result */
1347 Result
= FirstValue
+ SecondValue
;
1349 /* Update the flags */
1350 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1351 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
1352 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
1353 State
->Flags
.Af
= ((((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) != 0);
1354 State
->Flags
.Zf
= (Result
== 0);
1355 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
1356 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1358 /* Write back the result */
1359 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Result
;
1363 USHORT FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
1364 USHORT SecondValue
, Result
;
1366 if (!Fast486FetchWord(State
, &SecondValue
))
1368 /* Exception occurred */
1372 /* Calculate the result */
1373 Result
= FirstValue
+ SecondValue
;
1375 /* Update the flags */
1376 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1377 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
1378 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
1379 State
->Flags
.Af
= ((((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) != 0);
1380 State
->Flags
.Zf
= (Result
== 0);
1381 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
1382 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1384 /* Write back the result */
1385 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Result
;
1391 FAST486_OPCODE_HANDLER(Fast486OpcodeOrByteModrm
)
1393 UCHAR FirstValue
, SecondValue
, Result
;
1394 FAST486_MOD_REG_RM ModRegRm
;
1395 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1397 /* Make sure this is the right instruction */
1398 ASSERT((Opcode
& 0xFD) == 0x08);
1400 TOGGLE_ADSIZE(AddressSize
);
1402 /* Get the operands */
1403 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1405 /* Exception occurred */
1409 if (!Fast486ReadModrmByteOperands(State
,
1414 /* Exception occurred */
1418 /* Calculate the result */
1419 Result
= FirstValue
| SecondValue
;
1421 /* Update the flags */
1422 State
->Flags
.Cf
= FALSE
;
1423 State
->Flags
.Of
= FALSE
;
1424 State
->Flags
.Zf
= (Result
== 0);
1425 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
1426 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1428 /* Write back the result */
1429 return Fast486WriteModrmByteOperands(State
,
1431 Opcode
& FAST486_OPCODE_WRITE_REG
,
1435 FAST486_OPCODE_HANDLER(Fast486OpcodeOrModrm
)
1437 FAST486_MOD_REG_RM ModRegRm
;
1438 BOOLEAN OperandSize
, AddressSize
;
1440 /* Make sure this is the right instruction */
1441 ASSERT((Opcode
& 0xFD) == 0x09);
1443 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1445 TOGGLE_ADSIZE(AddressSize
);
1446 TOGGLE_OPSIZE(OperandSize
);
1448 /* Get the operands */
1449 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1451 /* Exception occurred */
1455 /* Check the operand size */
1458 ULONG FirstValue
, SecondValue
, Result
;
1460 if (!Fast486ReadModrmDwordOperands(State
,
1465 /* Exception occurred */
1469 /* Calculate the result */
1470 Result
= FirstValue
| SecondValue
;
1472 /* Update the flags */
1473 State
->Flags
.Cf
= FALSE
;
1474 State
->Flags
.Of
= FALSE
;
1475 State
->Flags
.Zf
= (Result
== 0);
1476 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
1477 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1479 /* Write back the result */
1480 return Fast486WriteModrmDwordOperands(State
,
1482 Opcode
& FAST486_OPCODE_WRITE_REG
,
1487 USHORT FirstValue
, SecondValue
, Result
;
1489 if (!Fast486ReadModrmWordOperands(State
,
1494 /* Exception occurred */
1498 /* Calculate the result */
1499 Result
= FirstValue
| SecondValue
;
1501 /* Update the flags */
1502 State
->Flags
.Cf
= FALSE
;
1503 State
->Flags
.Of
= FALSE
;
1504 State
->Flags
.Zf
= (Result
== 0);
1505 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
1506 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1508 /* Write back the result */
1509 return Fast486WriteModrmWordOperands(State
,
1511 Opcode
& FAST486_OPCODE_WRITE_REG
,
1516 FAST486_OPCODE_HANDLER(Fast486OpcodeOrAl
)
1518 UCHAR FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
1519 UCHAR SecondValue
, Result
;
1521 /* Make sure this is the right instruction */
1522 ASSERT(Opcode
== 0x0C);
1524 if (State
->PrefixFlags
)
1526 /* This opcode doesn't take any prefixes */
1527 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1531 if (!Fast486FetchByte(State
, &SecondValue
))
1533 /* Exception occurred */
1537 /* Calculate the result */
1538 Result
= FirstValue
| SecondValue
;
1540 /* Update the flags */
1541 State
->Flags
.Cf
= FALSE
;
1542 State
->Flags
.Of
= FALSE
;
1543 State
->Flags
.Zf
= (Result
== 0);
1544 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
1545 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1547 /* Write back the result */
1548 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= Result
;
1553 FAST486_OPCODE_HANDLER(Fast486OpcodeOrEax
)
1555 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1557 /* Make sure this is the right instruction */
1558 ASSERT(Opcode
== 0x0D);
1561 TOGGLE_OPSIZE(Size
);
1565 ULONG FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
1566 ULONG SecondValue
, Result
;
1568 if (!Fast486FetchDword(State
, &SecondValue
))
1570 /* Exception occurred */
1574 /* Calculate the result */
1575 Result
= FirstValue
| SecondValue
;
1577 /* Update the flags */
1578 State
->Flags
.Cf
= FALSE
;
1579 State
->Flags
.Of
= FALSE
;
1580 State
->Flags
.Zf
= (Result
== 0);
1581 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
1582 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1584 /* Write back the result */
1585 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Result
;
1589 USHORT FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
1590 USHORT SecondValue
, Result
;
1592 if (!Fast486FetchWord(State
, &SecondValue
))
1594 /* Exception occurred */
1598 /* Calculate the result */
1599 Result
= FirstValue
| SecondValue
;
1601 /* Update the flags */
1602 State
->Flags
.Cf
= FALSE
;
1603 State
->Flags
.Of
= FALSE
;
1604 State
->Flags
.Zf
= (Result
== 0);
1605 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
1606 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1608 /* Write back the result */
1609 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Result
;
1615 FAST486_OPCODE_HANDLER(Fast486OpcodeAndByteModrm
)
1617 UCHAR FirstValue
, SecondValue
, Result
;
1618 FAST486_MOD_REG_RM ModRegRm
;
1619 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1621 /* Make sure this is the right instruction */
1622 ASSERT((Opcode
& 0xFD) == 0x20);
1624 TOGGLE_ADSIZE(AddressSize
);
1626 /* Get the operands */
1627 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1629 /* Exception occurred */
1633 if (!Fast486ReadModrmByteOperands(State
,
1638 /* Exception occurred */
1642 /* Calculate the result */
1643 Result
= FirstValue
& SecondValue
;
1645 /* Update the flags */
1646 State
->Flags
.Cf
= FALSE
;
1647 State
->Flags
.Of
= FALSE
;
1648 State
->Flags
.Zf
= (Result
== 0);
1649 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
1650 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1652 /* Write back the result */
1653 return Fast486WriteModrmByteOperands(State
,
1655 Opcode
& FAST486_OPCODE_WRITE_REG
,
1659 FAST486_OPCODE_HANDLER(Fast486OpcodeAndModrm
)
1661 FAST486_MOD_REG_RM ModRegRm
;
1662 BOOLEAN OperandSize
, AddressSize
;
1664 /* Make sure this is the right instruction */
1665 ASSERT((Opcode
& 0xFD) == 0x21);
1667 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1669 TOGGLE_ADSIZE(AddressSize
);
1670 TOGGLE_OPSIZE(OperandSize
);
1672 /* Get the operands */
1673 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1675 /* Exception occurred */
1679 /* Check the operand size */
1682 ULONG FirstValue
, SecondValue
, Result
;
1684 if (!Fast486ReadModrmDwordOperands(State
,
1689 /* Exception occurred */
1693 /* Calculate the result */
1694 Result
= FirstValue
& SecondValue
;
1696 /* Update the flags */
1697 State
->Flags
.Cf
= FALSE
;
1698 State
->Flags
.Of
= FALSE
;
1699 State
->Flags
.Zf
= (Result
== 0);
1700 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
1701 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1703 /* Write back the result */
1704 return Fast486WriteModrmDwordOperands(State
,
1706 Opcode
& FAST486_OPCODE_WRITE_REG
,
1711 USHORT FirstValue
, SecondValue
, Result
;
1713 if (!Fast486ReadModrmWordOperands(State
,
1718 /* Exception occurred */
1722 /* Calculate the result */
1723 Result
= FirstValue
& SecondValue
;
1725 /* Update the flags */
1726 State
->Flags
.Cf
= FALSE
;
1727 State
->Flags
.Of
= FALSE
;
1728 State
->Flags
.Zf
= (Result
== 0);
1729 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
1730 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1732 /* Write back the result */
1733 return Fast486WriteModrmWordOperands(State
,
1735 Opcode
& FAST486_OPCODE_WRITE_REG
,
1740 FAST486_OPCODE_HANDLER(Fast486OpcodeAndAl
)
1742 UCHAR FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
1743 UCHAR SecondValue
, Result
;
1745 /* Make sure this is the right instruction */
1746 ASSERT(Opcode
== 0x24);
1750 if (!Fast486FetchByte(State
, &SecondValue
))
1752 /* Exception occurred */
1756 /* Calculate the result */
1757 Result
= FirstValue
& SecondValue
;
1759 /* Update the flags */
1760 State
->Flags
.Cf
= FALSE
;
1761 State
->Flags
.Of
= FALSE
;
1762 State
->Flags
.Zf
= (Result
== 0);
1763 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
1764 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1766 /* Write back the result */
1767 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= Result
;
1772 FAST486_OPCODE_HANDLER(Fast486OpcodeAndEax
)
1774 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1776 /* Make sure this is the right instruction */
1777 ASSERT(Opcode
== 0x25);
1780 TOGGLE_OPSIZE(Size
);
1784 ULONG FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
1785 ULONG SecondValue
, Result
;
1787 if (!Fast486FetchDword(State
, &SecondValue
))
1789 /* Exception occurred */
1793 /* Calculate the result */
1794 Result
= FirstValue
& SecondValue
;
1796 /* Update the flags */
1797 State
->Flags
.Cf
= FALSE
;
1798 State
->Flags
.Of
= FALSE
;
1799 State
->Flags
.Zf
= (Result
== 0);
1800 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
1801 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1803 /* Write back the result */
1804 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Result
;
1808 USHORT FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
1809 USHORT SecondValue
, Result
;
1811 if (!Fast486FetchWord(State
, &SecondValue
))
1813 /* Exception occurred */
1817 /* Calculate the result */
1818 Result
= FirstValue
& SecondValue
;
1820 /* Update the flags */
1821 State
->Flags
.Cf
= FALSE
;
1822 State
->Flags
.Of
= FALSE
;
1823 State
->Flags
.Zf
= (Result
== 0);
1824 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
1825 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1827 /* Write back the result */
1828 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Result
;
1834 FAST486_OPCODE_HANDLER(Fast486OpcodeXorByteModrm
)
1836 UCHAR FirstValue
, SecondValue
, Result
;
1837 FAST486_MOD_REG_RM ModRegRm
;
1838 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1840 /* Make sure this is the right instruction */
1841 ASSERT((Opcode
& 0xFD) == 0x30);
1843 TOGGLE_ADSIZE(AddressSize
);
1845 /* Get the operands */
1846 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1848 /* Exception occurred */
1852 if (!Fast486ReadModrmByteOperands(State
,
1857 /* Exception occurred */
1861 /* Calculate the result */
1862 Result
= FirstValue
^ SecondValue
;
1864 /* Update the flags */
1865 State
->Flags
.Cf
= FALSE
;
1866 State
->Flags
.Of
= FALSE
;
1867 State
->Flags
.Zf
= (Result
== 0);
1868 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
1869 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1871 /* Write back the result */
1872 return Fast486WriteModrmByteOperands(State
,
1874 Opcode
& FAST486_OPCODE_WRITE_REG
,
1878 FAST486_OPCODE_HANDLER(Fast486OpcodeXorModrm
)
1880 FAST486_MOD_REG_RM ModRegRm
;
1881 BOOLEAN OperandSize
, AddressSize
;
1883 /* Make sure this is the right instruction */
1884 ASSERT((Opcode
& 0xFD) == 0x31);
1886 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
1888 TOGGLE_ADSIZE(AddressSize
);
1889 TOGGLE_OPSIZE(OperandSize
);
1891 /* Get the operands */
1892 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1894 /* Exception occurred */
1898 /* Check the operand size */
1901 ULONG FirstValue
, SecondValue
, Result
;
1903 if (!Fast486ReadModrmDwordOperands(State
,
1908 /* Exception occurred */
1912 /* Calculate the result */
1913 Result
= FirstValue
^ SecondValue
;
1915 /* Update the flags */
1916 State
->Flags
.Cf
= FALSE
;
1917 State
->Flags
.Of
= FALSE
;
1918 State
->Flags
.Zf
= (Result
== 0);
1919 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
1920 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1922 /* Write back the result */
1923 return Fast486WriteModrmDwordOperands(State
,
1925 Opcode
& FAST486_OPCODE_WRITE_REG
,
1930 USHORT FirstValue
, SecondValue
, Result
;
1932 if (!Fast486ReadModrmWordOperands(State
,
1937 /* Exception occurred */
1941 /* Calculate the result */
1942 Result
= FirstValue
^ SecondValue
;
1944 /* Update the flags */
1945 State
->Flags
.Cf
= FALSE
;
1946 State
->Flags
.Of
= FALSE
;
1947 State
->Flags
.Zf
= (Result
== 0);
1948 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
1949 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1951 /* Write back the result */
1952 return Fast486WriteModrmWordOperands(State
,
1954 Opcode
& FAST486_OPCODE_WRITE_REG
,
1959 FAST486_OPCODE_HANDLER(Fast486OpcodeXorAl
)
1961 UCHAR FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
1962 UCHAR SecondValue
, Result
;
1964 /* Make sure this is the right instruction */
1965 ASSERT(Opcode
== 0x34);
1967 if (State
->PrefixFlags
)
1969 /* This opcode doesn't take any prefixes */
1970 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
1974 if (!Fast486FetchByte(State
, &SecondValue
))
1976 /* Exception occurred */
1980 /* Calculate the result */
1981 Result
= FirstValue
^ SecondValue
;
1983 /* Update the flags */
1984 State
->Flags
.Cf
= FALSE
;
1985 State
->Flags
.Of
= FALSE
;
1986 State
->Flags
.Zf
= (Result
== 0);
1987 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
1988 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
1990 /* Write back the result */
1991 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= Result
;
1996 FAST486_OPCODE_HANDLER(Fast486OpcodeXorEax
)
1998 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2000 /* Make sure this is the right instruction */
2001 ASSERT(Opcode
== 0x35);
2004 TOGGLE_OPSIZE(Size
);
2008 ULONG FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
2009 ULONG SecondValue
, Result
;
2011 if (!Fast486FetchDword(State
, &SecondValue
))
2013 /* Exception occurred */
2017 /* Calculate the result */
2018 Result
= FirstValue
^ SecondValue
;
2020 /* Update the flags */
2021 State
->Flags
.Cf
= FALSE
;
2022 State
->Flags
.Of
= FALSE
;
2023 State
->Flags
.Zf
= (Result
== 0);
2024 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
2025 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2027 /* Write back the result */
2028 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Result
;
2032 USHORT FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
2033 USHORT SecondValue
, Result
;
2035 if (!Fast486FetchWord(State
, &SecondValue
))
2037 /* Exception occurred */
2041 /* Calculate the result */
2042 Result
= FirstValue
^ SecondValue
;
2044 /* Update the flags */
2045 State
->Flags
.Cf
= FALSE
;
2046 State
->Flags
.Of
= FALSE
;
2047 State
->Flags
.Zf
= (Result
== 0);
2048 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
2049 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2051 /* Write back the result */
2052 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Result
;
2058 FAST486_OPCODE_HANDLER(Fast486OpcodeTestByteModrm
)
2060 UCHAR FirstValue
, SecondValue
, Result
;
2061 FAST486_MOD_REG_RM ModRegRm
;
2062 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2064 /* Make sure this is the right instruction */
2065 ASSERT(Opcode
== 0x84);
2067 TOGGLE_ADSIZE(AddressSize
);
2069 /* Get the operands */
2070 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2072 /* Exception occurred */
2076 if (!Fast486ReadModrmByteOperands(State
,
2081 /* Exception occurred */
2084 /* Calculate the result */
2085 Result
= FirstValue
& SecondValue
;
2087 /* Update the flags */
2088 State
->Flags
.Cf
= FALSE
;
2089 State
->Flags
.Of
= FALSE
;
2090 State
->Flags
.Zf
= (Result
== 0);
2091 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
2092 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2094 /* The result is discarded */
2098 FAST486_OPCODE_HANDLER(Fast486OpcodeTestModrm
)
2100 FAST486_MOD_REG_RM ModRegRm
;
2101 BOOLEAN OperandSize
, AddressSize
;
2103 /* Make sure this is the right instruction */
2104 ASSERT(Opcode
== 0x85);
2106 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2108 TOGGLE_ADSIZE(AddressSize
);
2109 TOGGLE_OPSIZE(OperandSize
);
2111 /* Get the operands */
2112 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2114 /* Exception occurred */
2118 /* Check the operand size */
2121 ULONG FirstValue
, SecondValue
, Result
;
2123 if (!Fast486ReadModrmDwordOperands(State
,
2128 /* Exception occurred */
2132 /* Calculate the result */
2133 Result
= FirstValue
& SecondValue
;
2135 /* Update the flags */
2136 State
->Flags
.Cf
= FALSE
;
2137 State
->Flags
.Of
= FALSE
;
2138 State
->Flags
.Zf
= (Result
== 0);
2139 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
2140 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2144 USHORT FirstValue
, SecondValue
, Result
;
2146 if (!Fast486ReadModrmWordOperands(State
,
2151 /* Exception occurred */
2155 /* Calculate the result */
2156 Result
= FirstValue
& SecondValue
;
2158 /* Update the flags */
2159 State
->Flags
.Cf
= FALSE
;
2160 State
->Flags
.Of
= FALSE
;
2161 State
->Flags
.Zf
= (Result
== 0);
2162 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
2163 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2166 /* The result is discarded */
2170 FAST486_OPCODE_HANDLER(Fast486OpcodeTestAl
)
2172 UCHAR FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
2173 UCHAR SecondValue
, Result
;
2175 /* Make sure this is the right instruction */
2176 ASSERT(Opcode
== 0xA8);
2178 if (State
->PrefixFlags
)
2180 /* This opcode doesn't take any prefixes */
2181 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2185 if (!Fast486FetchByte(State
, &SecondValue
))
2187 /* Exception occurred */
2191 /* Calculate the result */
2192 Result
= FirstValue
& SecondValue
;
2194 /* Update the flags */
2195 State
->Flags
.Cf
= FALSE
;
2196 State
->Flags
.Of
= FALSE
;
2197 State
->Flags
.Zf
= (Result
== 0);
2198 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
2199 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2201 /* The result is discarded */
2205 FAST486_OPCODE_HANDLER(Fast486OpcodeTestEax
)
2207 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2209 /* Make sure this is the right instruction */
2210 ASSERT(Opcode
== 0xA9);
2213 TOGGLE_OPSIZE(Size
);
2217 ULONG FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
2218 ULONG SecondValue
, Result
;
2220 if (!Fast486FetchDword(State
, &SecondValue
))
2222 /* Exception occurred */
2226 /* Calculate the result */
2227 Result
= FirstValue
& SecondValue
;
2229 /* Update the flags */
2230 State
->Flags
.Cf
= FALSE
;
2231 State
->Flags
.Of
= FALSE
;
2232 State
->Flags
.Zf
= (Result
== 0);
2233 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
2234 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2238 USHORT FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
2239 USHORT SecondValue
, Result
;
2241 if (!Fast486FetchWord(State
, &SecondValue
))
2243 /* Exception occurred */
2247 /* Calculate the result */
2248 Result
= FirstValue
& SecondValue
;
2250 /* Update the flags */
2251 State
->Flags
.Cf
= FALSE
;
2252 State
->Flags
.Of
= FALSE
;
2253 State
->Flags
.Zf
= (Result
== 0);
2254 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
2255 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2258 /* The result is discarded */
2262 FAST486_OPCODE_HANDLER(Fast486OpcodeXchgByteModrm
)
2264 UCHAR FirstValue
, SecondValue
;
2265 FAST486_MOD_REG_RM ModRegRm
;
2266 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2268 /* Make sure this is the right instruction */
2269 ASSERT(Opcode
== 0x86);
2271 TOGGLE_ADSIZE(AddressSize
);
2273 /* Get the operands */
2274 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2276 /* Exception occurred */
2280 if (!Fast486ReadModrmByteOperands(State
,
2285 /* Exception occurred */
2289 /* Write the value from the register to the R/M */
2290 if (!Fast486WriteModrmByteOperands(State
,
2295 /* Exception occurred */
2299 /* Write the value from the R/M to the register */
2300 if (!Fast486WriteModrmByteOperands(State
,
2305 /* Exception occurred */
2312 FAST486_OPCODE_HANDLER(Fast486OpcodeXchgModrm
)
2314 FAST486_MOD_REG_RM ModRegRm
;
2315 BOOLEAN OperandSize
, AddressSize
;
2317 /* Make sure this is the right instruction */
2318 ASSERT(Opcode
== 0x87);
2320 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2322 TOGGLE_ADSIZE(AddressSize
);
2323 TOGGLE_OPSIZE(OperandSize
);
2325 /* Get the operands */
2326 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2328 /* Exception occurred */
2332 /* Check the operand size */
2335 ULONG FirstValue
, SecondValue
;
2337 if (!Fast486ReadModrmDwordOperands(State
,
2342 /* Exception occurred */
2346 /* Write the value from the register to the R/M */
2347 if (!Fast486WriteModrmDwordOperands(State
,
2352 /* Exception occurred */
2356 /* Write the value from the R/M to the register */
2357 if (!Fast486WriteModrmDwordOperands(State
,
2362 /* Exception occurred */
2368 USHORT FirstValue
, SecondValue
;
2370 if (!Fast486ReadModrmWordOperands(State
,
2375 /* Exception occurred */
2379 /* Write the value from the register to the R/M */
2380 if (!Fast486WriteModrmWordOperands(State
,
2385 /* Exception occurred */
2389 /* Write the value from the R/M to the register */
2390 if (!Fast486WriteModrmWordOperands(State
,
2395 /* Exception occurred */
2400 /* The result is discarded */
2404 FAST486_OPCODE_HANDLER(Fast486OpcodePushEs
)
2406 /* Call the internal API */
2407 return Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_ES
].Selector
);
2410 FAST486_OPCODE_HANDLER(Fast486OpcodePopEs
)
2414 if (!Fast486StackPop(State
, &NewSelector
))
2416 /* Exception occurred */
2420 /* Call the internal API */
2421 return Fast486LoadSegment(State
, FAST486_REG_ES
, LOWORD(NewSelector
));
2424 FAST486_OPCODE_HANDLER(Fast486OpcodePushCs
)
2426 /* Call the internal API */
2427 return Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_CS
].Selector
);
2430 FAST486_OPCODE_HANDLER(Fast486OpcodeAdcByteModrm
)
2432 UCHAR FirstValue
, SecondValue
, Result
;
2433 FAST486_MOD_REG_RM ModRegRm
;
2434 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2436 /* Make sure this is the right instruction */
2437 ASSERT((Opcode
& 0xFD) == 0x10);
2439 TOGGLE_ADSIZE(AddressSize
);
2441 /* Get the operands */
2442 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2444 /* Exception occurred */
2448 if (!Fast486ReadModrmByteOperands(State
,
2453 /* Exception occurred */
2457 /* Calculate the result */
2458 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2460 /* Special exception for CF */
2461 State
->Flags
.Cf
= State
->Flags
.Cf
2462 && ((FirstValue
== 0xFF) || (SecondValue
== 0xFF));
2464 /* Update the flags */
2465 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2466 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
2467 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
2468 State
->Flags
.Af
= ((((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) != 0);
2469 State
->Flags
.Zf
= (Result
== 0);
2470 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
2471 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2473 /* Write back the result */
2474 return Fast486WriteModrmByteOperands(State
,
2476 Opcode
& FAST486_OPCODE_WRITE_REG
,
2480 FAST486_OPCODE_HANDLER(Fast486OpcodeAdcModrm
)
2482 FAST486_MOD_REG_RM ModRegRm
;
2483 BOOLEAN OperandSize
, AddressSize
;
2485 /* Make sure this is the right instruction */
2486 ASSERT((Opcode
& 0xFD) == 0x11);
2488 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2490 TOGGLE_ADSIZE(AddressSize
);
2491 TOGGLE_OPSIZE(OperandSize
);
2493 /* Get the operands */
2494 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2496 /* Exception occurred */
2500 /* Check the operand size */
2503 ULONG FirstValue
, SecondValue
, Result
;
2505 if (!Fast486ReadModrmDwordOperands(State
,
2510 /* Exception occurred */
2514 /* Calculate the result */
2515 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2517 /* Special exception for CF */
2518 State
->Flags
.Cf
= State
->Flags
.Cf
2519 && ((FirstValue
== 0xFFFFFFFF) || (SecondValue
== 0xFFFFFFFF));
2521 /* Update the flags */
2522 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2523 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
2524 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
2525 State
->Flags
.Af
= ((((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) != 0);
2526 State
->Flags
.Zf
= (Result
== 0);
2527 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
2528 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2530 /* Write back the result */
2531 return Fast486WriteModrmDwordOperands(State
,
2533 Opcode
& FAST486_OPCODE_WRITE_REG
,
2538 USHORT FirstValue
, SecondValue
, Result
;
2540 if (!Fast486ReadModrmWordOperands(State
,
2545 /* Exception occurred */
2549 /* Calculate the result */
2550 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2552 /* Special exception for CF */
2553 State
->Flags
.Cf
= State
->Flags
.Cf
2554 && ((FirstValue
== 0xFFFF) || (SecondValue
== 0xFFFF));
2556 /* Update the flags */
2557 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2558 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
2559 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
2560 State
->Flags
.Af
= ((((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) != 0);
2561 State
->Flags
.Zf
= (Result
== 0);
2562 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
2563 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2565 /* Write back the result */
2566 return Fast486WriteModrmWordOperands(State
,
2568 Opcode
& FAST486_OPCODE_WRITE_REG
,
2574 FAST486_OPCODE_HANDLER(Fast486OpcodeAdcAl
)
2576 UCHAR FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
2577 UCHAR SecondValue
, Result
;
2579 /* Make sure this is the right instruction */
2580 ASSERT(Opcode
== 0x14);
2582 if (State
->PrefixFlags
)
2584 /* This opcode doesn't take any prefixes */
2585 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2589 if (!Fast486FetchByte(State
, &SecondValue
))
2591 /* Exception occurred */
2595 /* Calculate the result */
2596 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2598 /* Special exception for CF */
2599 State
->Flags
.Cf
= State
->Flags
.Cf
&&
2600 ((FirstValue
== 0xFF) || (SecondValue
== 0xFF));
2602 /* Update the flags */
2603 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2604 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
2605 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
2606 State
->Flags
.Af
= ((((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) != 0);
2607 State
->Flags
.Zf
= (Result
== 0);
2608 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
2609 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2611 /* Write back the result */
2612 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= Result
;
2617 FAST486_OPCODE_HANDLER(Fast486OpcodeAdcEax
)
2619 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2621 /* Make sure this is the right instruction */
2622 ASSERT(Opcode
== 0x15);
2625 TOGGLE_OPSIZE(Size
);
2629 ULONG FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
2630 ULONG SecondValue
, Result
;
2632 if (!Fast486FetchDword(State
, &SecondValue
))
2634 /* Exception occurred */
2638 /* Calculate the result */
2639 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2641 /* Special exception for CF */
2642 State
->Flags
.Cf
= State
->Flags
.Cf
&&
2643 ((FirstValue
== 0xFFFFFFFF) || (SecondValue
== 0xFFFFFFFF));
2645 /* Update the flags */
2646 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2647 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
2648 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
2649 State
->Flags
.Af
= ((((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) != 0);
2650 State
->Flags
.Zf
= (Result
== 0);
2651 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
2652 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2654 /* Write back the result */
2655 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Result
;
2659 USHORT FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
2660 USHORT SecondValue
, Result
;
2662 if (!Fast486FetchWord(State
, &SecondValue
))
2664 /* Exception occurred */
2668 /* Calculate the result */
2669 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2671 /* Special exception for CF */
2672 State
->Flags
.Cf
= State
->Flags
.Cf
&&
2673 ((FirstValue
== 0xFFFF) || (SecondValue
== 0xFFFF));
2675 /* Update the flags */
2676 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2677 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
2678 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
2679 State
->Flags
.Af
= ((((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) != 0);
2680 State
->Flags
.Zf
= (Result
== 0);
2681 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
2682 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2684 /* Write back the result */
2685 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Result
;
2691 FAST486_OPCODE_HANDLER(Fast486OpcodePushSs
)
2693 /* Call the internal API */
2694 return Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_SS
].Selector
);
2697 FAST486_OPCODE_HANDLER(Fast486OpcodePopSs
)
2701 if (!Fast486StackPop(State
, &NewSelector
))
2703 /* Exception occurred */
2707 /* Call the internal API */
2708 return Fast486LoadSegment(State
, FAST486_REG_SS
, LOWORD(NewSelector
));
2711 FAST486_OPCODE_HANDLER(Fast486OpcodeSbbByteModrm
)
2713 UCHAR FirstValue
, SecondValue
, Result
;
2714 FAST486_MOD_REG_RM ModRegRm
;
2715 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2716 INT Carry
= State
->Flags
.Cf
? 1 : 0;
2718 /* Make sure this is the right instruction */
2719 ASSERT((Opcode
& 0xFD) == 0x18);
2721 TOGGLE_ADSIZE(AddressSize
);
2723 /* Get the operands */
2724 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2726 /* Exception occurred */
2730 if (!Fast486ReadModrmByteOperands(State
,
2735 /* Exception occurred */
2739 /* Check if this is the instruction that writes to R/M */
2740 if (!(Opcode
& FAST486_OPCODE_WRITE_REG
))
2742 /* Swap the order */
2743 SWAP(FirstValue
, SecondValue
);
2746 /* Calculate the result */
2747 Result
= FirstValue
- SecondValue
- Carry
;
2749 /* Update the flags */
2750 State
->Flags
.Cf
= FirstValue
< (SecondValue
+ 1);
2751 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) != (SecondValue
& SIGN_FLAG_BYTE
))
2752 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
2753 State
->Flags
.Af
= (FirstValue
& 0x0F) < ((SecondValue
+ 1) & 0x0F);
2754 State
->Flags
.Zf
= (Result
== 0);
2755 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
2756 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2758 /* Write back the result */
2759 return Fast486WriteModrmByteOperands(State
,
2761 Opcode
& FAST486_OPCODE_WRITE_REG
,
2765 FAST486_OPCODE_HANDLER(Fast486OpcodeSbbModrm
)
2767 FAST486_MOD_REG_RM ModRegRm
;
2768 BOOLEAN OperandSize
, AddressSize
;
2769 INT Carry
= State
->Flags
.Cf
? 1 : 0;
2771 /* Make sure this is the right instruction */
2772 ASSERT((Opcode
& 0xFD) == 0x19);
2774 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2776 TOGGLE_ADSIZE(AddressSize
);
2777 TOGGLE_OPSIZE(OperandSize
);
2779 /* Get the operands */
2780 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2782 /* Exception occurred */
2786 /* Check the operand size */
2789 ULONG FirstValue
, SecondValue
, Result
;
2791 if (!Fast486ReadModrmDwordOperands(State
,
2796 /* Exception occurred */
2800 /* Check if this is the instruction that writes to R/M */
2801 if (!(Opcode
& FAST486_OPCODE_WRITE_REG
))
2803 /* Swap the order */
2804 SWAP(FirstValue
, SecondValue
);
2807 /* Calculate the result */
2808 Result
= FirstValue
- SecondValue
- Carry
;
2810 /* Update the flags */
2811 State
->Flags
.Cf
= FirstValue
< (SecondValue
+ Carry
);
2812 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) != (SecondValue
& SIGN_FLAG_LONG
))
2813 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
2814 State
->Flags
.Af
= (FirstValue
& 0x0F) < ((SecondValue
+ 1) & 0x0F);
2815 State
->Flags
.Zf
= (Result
== 0);
2816 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
2817 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2819 /* Write back the result */
2820 return Fast486WriteModrmDwordOperands(State
,
2822 Opcode
& FAST486_OPCODE_WRITE_REG
,
2827 USHORT FirstValue
, SecondValue
, Result
;
2829 if (!Fast486ReadModrmWordOperands(State
,
2834 /* Exception occurred */
2838 /* Check if this is the instruction that writes to R/M */
2839 if (!(Opcode
& FAST486_OPCODE_WRITE_REG
))
2841 /* Swap the order */
2842 SWAP(FirstValue
, SecondValue
);
2845 /* Calculate the result */
2846 Result
= FirstValue
- SecondValue
- Carry
;
2848 /* Update the flags */
2849 State
->Flags
.Cf
= FirstValue
< (SecondValue
+ Carry
);
2850 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) != (SecondValue
& SIGN_FLAG_WORD
))
2851 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
2852 State
->Flags
.Af
= (FirstValue
& 0x0F) < ((SecondValue
+ 1) & 0x0F);
2853 State
->Flags
.Zf
= (Result
== 0);
2854 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
2855 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2857 /* Write back the result */
2858 return Fast486WriteModrmWordOperands(State
,
2860 Opcode
& FAST486_OPCODE_WRITE_REG
,
2865 FAST486_OPCODE_HANDLER(Fast486OpcodeSbbAl
)
2867 UCHAR FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
2868 UCHAR SecondValue
, Result
;
2869 INT Carry
= State
->Flags
.Cf
? 1 : 0;
2871 /* Make sure this is the right instruction */
2872 ASSERT(Opcode
== 0x1C);
2874 if (State
->PrefixFlags
)
2876 /* This opcode doesn't take any prefixes */
2877 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
2881 if (!Fast486FetchByte(State
, &SecondValue
))
2883 /* Exception occurred */
2887 /* Calculate the result */
2888 Result
= FirstValue
- SecondValue
- Carry
;
2890 /* Update the flags */
2891 State
->Flags
.Cf
= FirstValue
< (SecondValue
+ Carry
);
2892 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) != (SecondValue
& SIGN_FLAG_BYTE
))
2893 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
2894 State
->Flags
.Af
= (FirstValue
& 0x0F) < ((SecondValue
+ 1) & 0x0F);
2895 State
->Flags
.Zf
= (Result
== 0);
2896 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
2897 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2899 /* Write back the result */
2900 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= Result
;
2906 FAST486_OPCODE_HANDLER(Fast486OpcodeSbbEax
)
2908 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
2909 INT Carry
= State
->Flags
.Cf
? 1 : 0;
2911 /* Make sure this is the right instruction */
2912 ASSERT(Opcode
== 0x1D);
2915 TOGGLE_OPSIZE(Size
);
2919 ULONG FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
2920 ULONG SecondValue
, Result
;
2922 if (!Fast486FetchDword(State
, &SecondValue
))
2924 /* Exception occurred */
2928 /* Calculate the result */
2929 Result
= FirstValue
- SecondValue
- Carry
;
2931 /* Update the flags */
2932 State
->Flags
.Cf
= FirstValue
< (SecondValue
+ Carry
);
2933 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) != (SecondValue
& SIGN_FLAG_LONG
))
2934 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
2935 State
->Flags
.Af
= (FirstValue
& 0x0F) < ((SecondValue
+ Carry
) & 0x0F);
2936 State
->Flags
.Zf
= (Result
== 0);
2937 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
2938 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2940 /* Write back the result */
2941 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Result
;
2945 USHORT FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
2946 USHORT SecondValue
, Result
;
2948 if (!Fast486FetchWord(State
, &SecondValue
))
2950 /* Exception occurred */
2954 /* Calculate the result */
2955 Result
= FirstValue
- SecondValue
- Carry
;
2957 /* Update the flags */
2958 State
->Flags
.Cf
= FirstValue
< (SecondValue
+ Carry
);
2959 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) != (SecondValue
& SIGN_FLAG_WORD
))
2960 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
2961 State
->Flags
.Af
= (FirstValue
& 0x0F) < ((SecondValue
+ Carry
) & 0x0F);
2962 State
->Flags
.Zf
= (Result
== 0);
2963 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
2964 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
2966 /* Write back the result */
2967 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Result
;
2974 FAST486_OPCODE_HANDLER(Fast486OpcodePushDs
)
2976 /* Call the internal API */
2977 return Fast486StackPush(State
, State
->SegmentRegs
[FAST486_REG_DS
].Selector
);
2980 FAST486_OPCODE_HANDLER(Fast486OpcodePopDs
)
2984 if (!Fast486StackPop(State
, &NewSelector
))
2986 /* Exception occurred */
2990 /* Call the internal API */
2991 return Fast486LoadSegment(State
, FAST486_REG_DS
, LOWORD(NewSelector
));
2994 FAST486_OPCODE_HANDLER(Fast486OpcodeDaa
)
2996 UCHAR Value
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
2997 BOOLEAN Carry
= State
->Flags
.Cf
;
2999 /* Clear the carry flag */
3000 State
->Flags
.Cf
= FALSE
;
3002 /* Check if the first BCD digit is invalid or there was a carry from it */
3003 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3006 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
+= 0x06;
3007 if (State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
< 0x06)
3009 /* A carry occurred */
3010 State
->Flags
.Cf
= TRUE
;
3013 /* Set the adjust flag */
3014 State
->Flags
.Af
= TRUE
;
3017 /* Check if the second BCD digit is invalid or there was a carry from it */
3018 if ((Value
> 0x99) || Carry
)
3021 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
+= 0x60;
3023 /* There was a carry */
3024 State
->Flags
.Cf
= TRUE
;
3030 FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubByteModrm
)
3032 UCHAR FirstValue
, SecondValue
, Result
;
3033 FAST486_MOD_REG_RM ModRegRm
;
3034 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
3036 /* Make sure this is the right instruction */
3037 ASSERT((Opcode
& 0xED) == 0x28);
3039 TOGGLE_ADSIZE(AddressSize
);
3041 /* Get the operands */
3042 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3044 /* Exception occurred */
3048 if (!Fast486ReadModrmByteOperands(State
,
3053 /* Exception occurred */
3057 /* Check if this is the instruction that writes to R/M */
3058 if (!(Opcode
& FAST486_OPCODE_WRITE_REG
))
3060 /* Swap the order */
3061 SWAP(FirstValue
, SecondValue
);
3064 /* Calculate the result */
3065 Result
= FirstValue
- SecondValue
;
3067 /* Update the flags */
3068 State
->Flags
.Cf
= (FirstValue
< SecondValue
);
3069 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) != (SecondValue
& SIGN_FLAG_BYTE
))
3070 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
3071 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3072 State
->Flags
.Zf
= (Result
== 0);
3073 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
3074 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
3076 /* Check if this is not a CMP */
3077 if (!(Opcode
& 0x10))
3079 /* Write back the result */
3080 return Fast486WriteModrmByteOperands(State
,
3082 Opcode
& FAST486_OPCODE_WRITE_REG
,
3087 /* Discard the result */
3092 FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubModrm
)
3094 FAST486_MOD_REG_RM ModRegRm
;
3095 BOOLEAN OperandSize
, AddressSize
;
3097 /* Make sure this is the right instruction */
3098 ASSERT((Opcode
& 0xED) == 0x29);
3100 OperandSize
= AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
3102 TOGGLE_ADSIZE(AddressSize
);
3103 TOGGLE_OPSIZE(OperandSize
);
3105 /* Get the operands */
3106 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3108 /* Exception occurred */
3112 /* Check the operand size */
3115 ULONG FirstValue
, SecondValue
, Result
;
3117 if (!Fast486ReadModrmDwordOperands(State
,
3122 /* Exception occurred */
3126 /* Check if this is the instruction that writes to R/M */
3127 if (!(Opcode
& FAST486_OPCODE_WRITE_REG
))
3129 /* Swap the order */
3130 SWAP(FirstValue
, SecondValue
);
3133 /* Calculate the result */
3134 Result
= FirstValue
- SecondValue
;
3136 /* Update the flags */
3137 State
->Flags
.Cf
= (FirstValue
< SecondValue
);
3138 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) != (SecondValue
& SIGN_FLAG_LONG
))
3139 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
3140 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3141 State
->Flags
.Zf
= (Result
== 0);
3142 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
3143 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
3145 /* Check if this is not a CMP */
3146 if (!(Opcode
& 0x10))
3148 /* Write back the result */
3149 return Fast486WriteModrmDwordOperands(State
,
3151 Opcode
& FAST486_OPCODE_WRITE_REG
,
3156 /* Discard the result */
3162 USHORT FirstValue
, SecondValue
, Result
;
3164 if (!Fast486ReadModrmWordOperands(State
,
3169 /* Exception occurred */
3173 /* Check if this is the instruction that writes to R/M */
3174 if (!(Opcode
& FAST486_OPCODE_WRITE_REG
))
3176 /* Swap the order */
3177 SWAP(FirstValue
, SecondValue
);
3180 /* Calculate the result */
3181 Result
= FirstValue
- SecondValue
;
3183 /* Update the flags */
3184 State
->Flags
.Cf
= (FirstValue
< SecondValue
);
3185 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) != (SecondValue
& SIGN_FLAG_WORD
))
3186 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
3187 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3188 State
->Flags
.Zf
= (Result
== 0);
3189 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
3190 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
3192 /* Check if this is not a CMP */
3193 if (!(Opcode
& 0x10))
3195 /* Write back the result */
3196 return Fast486WriteModrmWordOperands(State
,
3198 Opcode
& FAST486_OPCODE_WRITE_REG
,
3203 /* Discard the result */
3209 FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubAl
)
3211 UCHAR FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
3212 UCHAR SecondValue
, Result
;
3214 /* Make sure this is the right instruction */
3215 ASSERT((Opcode
& 0xEF) == 0x2C);
3217 if (State
->PrefixFlags
)
3219 /* This opcode doesn't take any prefixes */
3220 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
3224 if (!Fast486FetchByte(State
, &SecondValue
))
3226 /* Exception occurred */
3230 /* Calculate the result */
3231 Result
= FirstValue
- SecondValue
;
3233 /* Update the flags */
3234 State
->Flags
.Cf
= (FirstValue
< SecondValue
);
3235 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) != (SecondValue
& SIGN_FLAG_BYTE
))
3236 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
3237 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3238 State
->Flags
.Zf
= (Result
== 0);
3239 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_BYTE
) != 0);
3240 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
3242 /* Check if this is not a CMP */
3243 if (!(Opcode
& 0x10))
3245 /* Write back the result */
3246 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
= Result
;
3252 FAST486_OPCODE_HANDLER(Fast486OpcodeCmpSubEax
)
3254 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
3256 /* Make sure this is the right instruction */
3257 ASSERT((Opcode
& 0xEF) == 0x2D);
3260 TOGGLE_OPSIZE(Size
);
3264 ULONG FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].Long
;
3265 ULONG SecondValue
, Result
;
3267 if (!Fast486FetchDword(State
, &SecondValue
))
3269 /* Exception occurred */
3273 /* Calculate the result */
3274 Result
= FirstValue
- SecondValue
;
3276 /* Update the flags */
3277 State
->Flags
.Cf
= (FirstValue
< SecondValue
);
3278 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) != (SecondValue
& SIGN_FLAG_LONG
))
3279 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
3280 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3281 State
->Flags
.Zf
= (Result
== 0);
3282 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_LONG
) != 0);
3283 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
3285 /* Check if this is not a CMP */
3286 if (!(Opcode
& 0x10))
3288 /* Write back the result */
3289 State
->GeneralRegs
[FAST486_REG_EAX
].Long
= Result
;
3294 USHORT FirstValue
= State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
;
3295 USHORT SecondValue
, Result
;
3297 if (!Fast486FetchWord(State
, &SecondValue
))
3299 /* Exception occurred */
3303 /* Calculate the result */
3304 Result
= FirstValue
- SecondValue
;
3306 /* Update the flags */
3307 State
->Flags
.Cf
= (FirstValue
< SecondValue
);
3308 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) != (SecondValue
& SIGN_FLAG_WORD
))
3309 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
3310 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3311 State
->Flags
.Zf
= (Result
== 0);
3312 State
->Flags
.Sf
= ((Result
& SIGN_FLAG_WORD
) != 0);
3313 State
->Flags
.Pf
= Fast486CalculateParity(Result
);
3315 /* Check if this is not a CMP */
3316 if (!(Opcode
& 0x10))
3318 /* Write back the result */
3319 State
->GeneralRegs
[FAST486_REG_EAX
].LowWord
= Result
;
3326 FAST486_OPCODE_HANDLER(Fast486OpcodeDas
)
3328 UCHAR Value
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
3329 BOOLEAN Carry
= State
->Flags
.Cf
;
3331 /* Clear the carry flag */
3332 State
->Flags
.Cf
= FALSE
;
3334 /* Check if the first BCD digit is invalid or there was a borrow */
3335 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3338 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
-= 0x06;
3339 if (State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
> 0xFB)
3341 /* A borrow occurred */
3342 State
->Flags
.Cf
= TRUE
;
3345 /* Set the adjust flag */
3346 State
->Flags
.Af
= TRUE
;
3349 /* Check if the second BCD digit is invalid or there was a borrow */
3350 if ((Value
> 0x99) || Carry
)
3353 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
-= 0x60;
3355 /* There was a borrow */
3356 State
->Flags
.Cf
= TRUE
;
3362 FAST486_OPCODE_HANDLER(Fast486OpcodeAaa
)
3364 UCHAR Value
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
3367 * Check if the value in AL is not a valid BCD digit,
3368 * or there was a carry from the lowest 4 bits of AL
3370 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3373 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
+= 0x06;
3374 State
->GeneralRegs
[FAST486_REG_EAX
].HighByte
++;
3377 State
->Flags
.Cf
= State
->Flags
.Af
= TRUE
;
3381 /* Clear CF and AF */
3382 State
->Flags
.Cf
= State
->Flags
.Af
= FALSE
;
3385 /* Keep only the lowest 4 bits of AL */
3386 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
&= 0x0F;
3391 FAST486_OPCODE_HANDLER(Fast486OpcodeAas
)
3393 UCHAR Value
= State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
;
3396 * Check if the value in AL is not a valid BCD digit,
3397 * or there was a borrow from the lowest 4 bits of AL
3399 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3402 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
-= 0x06;
3403 State
->GeneralRegs
[FAST486_REG_EAX
].HighByte
--;
3406 State
->Flags
.Cf
= State
->Flags
.Af
= TRUE
;
3410 /* Clear CF and AF */
3411 State
->Flags
.Cf
= State
->Flags
.Af
= FALSE
;
3414 /* Keep only the lowest 4 bits of AL */
3415 State
->GeneralRegs
[FAST486_REG_EAX
].LowByte
&= 0x0F;
3420 FAST486_OPCODE_HANDLER(Fast486OpcodePushAll
)
3423 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
3424 FAST486_REG SavedEsp
= State
->GeneralRegs
[FAST486_REG_ESP
];
3426 /* Make sure this is the right instruction */
3427 ASSERT(Opcode
== 0x60);
3429 TOGGLE_OPSIZE(Size
);
3432 /* Push all the registers in order */
3433 for (i
= 0; i
< FAST486_NUM_GEN_REGS
; i
++)
3435 if (i
== FAST486_REG_ESP
)
3437 /* Use the saved ESP instead */
3438 if (!Fast486StackPush(State
, Size
? SavedEsp
.Long
: SavedEsp
.LowWord
))
3440 /* Exception occurred */
3446 /* Push the register */
3447 if (!Fast486StackPush(State
, Size
? State
->GeneralRegs
[i
].Long
3448 : State
->GeneralRegs
[i
].LowWord
))
3450 /* Exception occurred */
3459 FAST486_OPCODE_HANDLER(Fast486OpcodePopAll
)
3462 BOOLEAN Size
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
3465 /* Make sure this is the right instruction */
3466 ASSERT(Opcode
== 0x61);
3468 TOGGLE_OPSIZE(Size
);
3471 /* Pop all the registers in reverse order */
3472 for (i
= FAST486_NUM_GEN_REGS
- 1; i
>= 0; i
--)
3475 if (!Fast486StackPop(State
, &Value
))
3477 /* Exception occurred */
3481 /* Don't modify ESP */
3482 if (i
!= FAST486_REG_ESP
)
3484 if (Size
) State
->GeneralRegs
[i
].Long
= Value
;
3485 else State
->GeneralRegs
[i
].LowWord
= LOWORD(Value
);
3492 FAST486_OPCODE_HANDLER(Fast486OpcodeBound
)
3494 // TODO: NOT IMPLEMENTED
3500 FAST486_OPCODE_HANDLER(Fast486OpcodeArpl
)
3502 USHORT FirstValue
, SecondValue
;
3503 FAST486_MOD_REG_RM ModRegRm
;
3504 BOOLEAN AddressSize
= State
->SegmentRegs
[FAST486_REG_CS
].Size
;
3506 if (!(State
->ControlRegisters
[FAST486_REG_CR0
] & FAST486_CR0_PE
)
3508 || (State
->PrefixFlags
& FAST486_PREFIX_LOCK
))
3510 /* Cannot be used in real mode or with a LOCK prefix */
3511 Fast486Exception(State
, FAST486_EXCEPTION_UD
);
3515 TOGGLE_ADSIZE(AddressSize
);
3517 /* Get the operands */
3518 if (!Fast486ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3520 /* Exception occurred */
<