2 * Soft386 386/486 CPU Emulation Library
5 * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 /* INCLUDES *******************************************************************/
24 // #define WIN32_NO_STATUS
25 // #define _INC_WINDOWS
38 /* PUBLIC VARIABLES ***********************************************************/
40 SOFT386_OPCODE_HANDLER_PROC
41 Soft386OpcodeHandlers
[SOFT386_NUM_OPCODE_HANDLERS
] =
43 Soft386OpcodeAddByteModrm
,
44 Soft386OpcodeAddModrm
,
45 Soft386OpcodeAddByteModrm
,
46 Soft386OpcodeAddModrm
,
51 Soft386OpcodeOrByteModrm
,
53 Soft386OpcodeOrByteModrm
,
58 Soft386OpcodeExtended
,
59 Soft386OpcodeAdcByteModrm
,
60 Soft386OpcodeAdcModrm
,
61 Soft386OpcodeAdcByteModrm
,
62 Soft386OpcodeAdcModrm
,
67 Soft386OpcodeSbbByteModrm
,
68 Soft386OpcodeSbbModrm
,
69 Soft386OpcodeSbbByteModrm
,
70 Soft386OpcodeSbbModrm
,
75 Soft386OpcodeAndByteModrm
,
76 Soft386OpcodeAndModrm
,
77 Soft386OpcodeAndByteModrm
,
78 Soft386OpcodeAndModrm
,
83 Soft386OpcodeCmpSubByteModrm
,
84 Soft386OpcodeCmpSubModrm
,
85 Soft386OpcodeCmpSubByteModrm
,
86 Soft386OpcodeCmpSubModrm
,
87 Soft386OpcodeCmpSubAl
,
88 Soft386OpcodeCmpSubEax
,
91 Soft386OpcodeXorByteModrm
,
92 Soft386OpcodeXorModrm
,
93 Soft386OpcodeXorByteModrm
,
94 Soft386OpcodeXorModrm
,
99 Soft386OpcodeCmpSubByteModrm
,
100 Soft386OpcodeCmpSubModrm
,
101 Soft386OpcodeCmpSubByteModrm
,
102 Soft386OpcodeCmpSubModrm
,
103 Soft386OpcodeCmpSubAl
,
104 Soft386OpcodeCmpSubEax
,
107 Soft386OpcodeIncrement
,
108 Soft386OpcodeIncrement
,
109 Soft386OpcodeIncrement
,
110 Soft386OpcodeIncrement
,
111 Soft386OpcodeIncrement
,
112 Soft386OpcodeIncrement
,
113 Soft386OpcodeIncrement
,
114 Soft386OpcodeIncrement
,
115 Soft386OpcodeDecrement
,
116 Soft386OpcodeDecrement
,
117 Soft386OpcodeDecrement
,
118 Soft386OpcodeDecrement
,
119 Soft386OpcodeDecrement
,
120 Soft386OpcodeDecrement
,
121 Soft386OpcodeDecrement
,
122 Soft386OpcodeDecrement
,
123 Soft386OpcodePushReg
,
124 Soft386OpcodePushReg
,
125 Soft386OpcodePushReg
,
126 Soft386OpcodePushReg
,
127 Soft386OpcodePushReg
,
128 Soft386OpcodePushReg
,
129 Soft386OpcodePushReg
,
130 Soft386OpcodePushReg
,
139 Soft386OpcodePushAll
,
147 Soft386OpcodePushImm
,
148 Soft386OpcodeImulModrmImm
,
149 Soft386OpcodePushByteImm
,
150 Soft386OpcodeImulModrmImm
,
155 Soft386OpcodeShortConditionalJmp
,
156 Soft386OpcodeShortConditionalJmp
,
157 Soft386OpcodeShortConditionalJmp
,
158 Soft386OpcodeShortConditionalJmp
,
159 Soft386OpcodeShortConditionalJmp
,
160 Soft386OpcodeShortConditionalJmp
,
161 Soft386OpcodeShortConditionalJmp
,
162 Soft386OpcodeShortConditionalJmp
,
163 Soft386OpcodeShortConditionalJmp
,
164 Soft386OpcodeShortConditionalJmp
,
165 Soft386OpcodeShortConditionalJmp
,
166 Soft386OpcodeShortConditionalJmp
,
167 Soft386OpcodeShortConditionalJmp
,
168 Soft386OpcodeShortConditionalJmp
,
169 Soft386OpcodeShortConditionalJmp
,
170 Soft386OpcodeShortConditionalJmp
,
171 Soft386OpcodeGroup8082
,
172 Soft386OpcodeGroup81
,
173 Soft386OpcodeGroup8082
,
174 Soft386OpcodeGroup83
,
175 Soft386OpcodeTestByteModrm
,
176 Soft386OpcodeTestModrm
,
177 Soft386OpcodeXchgByteModrm
,
178 Soft386OpcodeXchgModrm
,
179 Soft386OpcodeMovByteModrm
,
180 Soft386OpcodeMovModrm
,
181 Soft386OpcodeMovByteModrm
,
182 Soft386OpcodeMovModrm
,
183 Soft386OpcodeMovStoreSeg
,
185 Soft386OpcodeMovLoadSeg
,
186 Soft386OpcodeGroup8F
,
188 Soft386OpcodeExchangeEax
,
189 Soft386OpcodeExchangeEax
,
190 Soft386OpcodeExchangeEax
,
191 Soft386OpcodeExchangeEax
,
192 Soft386OpcodeExchangeEax
,
193 Soft386OpcodeExchangeEax
,
194 Soft386OpcodeExchangeEax
,
197 Soft386OpcodeCallAbs
,
199 Soft386OpcodePushFlags
,
200 Soft386OpcodePopFlags
,
203 Soft386OpcodeMovAlOffset
,
204 Soft386OpcodeMovEaxOffset
,
205 Soft386OpcodeMovOffsetAl
,
206 Soft386OpcodeMovOffsetEax
,
212 Soft386OpcodeTestEax
,
219 Soft386OpcodeMovByteRegImm
,
220 Soft386OpcodeMovByteRegImm
,
221 Soft386OpcodeMovByteRegImm
,
222 Soft386OpcodeMovByteRegImm
,
223 Soft386OpcodeMovByteRegImm
,
224 Soft386OpcodeMovByteRegImm
,
225 Soft386OpcodeMovByteRegImm
,
226 Soft386OpcodeMovByteRegImm
,
227 Soft386OpcodeMovRegImm
,
228 Soft386OpcodeMovRegImm
,
229 Soft386OpcodeMovRegImm
,
230 Soft386OpcodeMovRegImm
,
231 Soft386OpcodeMovRegImm
,
232 Soft386OpcodeMovRegImm
,
233 Soft386OpcodeMovRegImm
,
234 Soft386OpcodeMovRegImm
,
235 Soft386OpcodeGroupC0
,
236 Soft386OpcodeGroupC1
,
241 Soft386OpcodeGroupC6
,
242 Soft386OpcodeGroupC7
,
245 Soft386OpcodeRetFarImm
,
251 Soft386OpcodeGroupD0
,
252 Soft386OpcodeGroupD1
,
253 Soft386OpcodeGroupD2
,
254 Soft386OpcodeGroupD3
,
259 NULL
, // TODO: OPCODE 0xD8 NOT SUPPORTED
260 NULL
, // TODO: OPCODE 0xD9 NOT SUPPORTED
261 NULL
, // TODO: OPCODE 0xDA NOT SUPPORTED
262 NULL
, // TODO: OPCODE 0xDB NOT SUPPORTED
263 NULL
, // TODO: OPCODE 0xDC NOT SUPPORTED
264 NULL
, // TODO: OPCODE 0xDD NOT SUPPORTED
265 NULL
, // TODO: OPCODE 0xDE NOT SUPPORTED
266 NULL
, // TODO: OPCODE 0xDF NOT SUPPORTED
273 Soft386OpcodeOutByte
,
278 Soft386OpcodeShortJump
,
281 Soft386OpcodeOutByte
,
288 Soft386OpcodeComplCarry
,
289 Soft386OpcodeGroupF6
,
290 Soft386OpcodeGroupF7
,
291 Soft386OpcodeClearCarry
,
292 Soft386OpcodeSetCarry
,
293 Soft386OpcodeClearInt
,
295 Soft386OpcodeClearDir
,
297 Soft386OpcodeGroupFE
,
298 Soft386OpcodeGroupFF
,
301 /* PUBLIC FUNCTIONS ***********************************************************/
303 SOFT386_OPCODE_HANDLER(Soft386OpcodePrefix
)
305 BOOLEAN Valid
= FALSE
;
312 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
314 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
315 State
->SegmentOverride
= SOFT386_REG_ES
;
325 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
327 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
328 State
->SegmentOverride
= SOFT386_REG_CS
;
338 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
340 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
341 State
->SegmentOverride
= SOFT386_REG_SS
;
351 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
353 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
354 State
->SegmentOverride
= SOFT386_REG_DS
;
364 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
366 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
367 State
->SegmentOverride
= SOFT386_REG_FS
;
377 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
379 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
380 State
->SegmentOverride
= SOFT386_REG_GS
;
390 if (!(State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
))
392 State
->PrefixFlags
|= SOFT386_PREFIX_OPSIZE
;
402 if (!(State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
))
404 State
->PrefixFlags
|= SOFT386_PREFIX_ADSIZE
;
413 if (!(State
->PrefixFlags
& SOFT386_PREFIX_LOCK
))
415 State
->PrefixFlags
|= SOFT386_PREFIX_LOCK
;
425 /* Mutually exclusive with REP */
426 if (!(State
->PrefixFlags
427 & (SOFT386_PREFIX_REPNZ
| SOFT386_PREFIX_REP
)))
429 State
->PrefixFlags
|= SOFT386_PREFIX_REPNZ
;
439 /* Mutually exclusive with REPNZ */
440 if (!(State
->PrefixFlags
441 & (SOFT386_PREFIX_REPNZ
| SOFT386_PREFIX_REP
)))
443 State
->PrefixFlags
|= SOFT386_PREFIX_REP
;
453 /* Clear all prefixes */
454 State
->PrefixFlags
= 0;
456 /* Throw an exception */
457 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
464 SOFT386_OPCODE_HANDLER(Soft386OpcodeIncrement
)
467 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
469 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
471 /* The OPSIZE prefix toggles the size */
475 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
478 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
482 /* Make sure this is the right instruction */
483 ASSERT((Opcode
& 0xF8) == 0x40);
487 Value
= ++State
->GeneralRegs
[Opcode
& 0x07].Long
;
489 State
->Flags
.Of
= (Value
== SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
490 State
->Flags
.Sf
= (Value
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
494 Value
= ++State
->GeneralRegs
[Opcode
& 0x07].LowWord
;
496 State
->Flags
.Of
= (Value
== SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
497 State
->Flags
.Sf
= (Value
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
500 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
501 State
->Flags
.Af
= ((Value
& 0x0F) == 0) ? TRUE
: FALSE
;
502 State
->Flags
.Pf
= Soft386CalculateParity(LOBYTE(Value
));
508 SOFT386_OPCODE_HANDLER(Soft386OpcodeDecrement
)
511 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
513 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
515 /* The OPSIZE prefix toggles the size */
519 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
522 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
526 /* Make sure this is the right instruction */
527 ASSERT((Opcode
& 0xF8) == 0x48);
531 Value
= --State
->GeneralRegs
[Opcode
& 0x07].Long
;
533 State
->Flags
.Of
= (Value
== (SIGN_FLAG_LONG
- 1)) ? TRUE
: FALSE
;
534 State
->Flags
.Sf
= (Value
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
538 Value
= --State
->GeneralRegs
[Opcode
& 0x07].LowWord
;
540 State
->Flags
.Of
= (Value
== (SIGN_FLAG_WORD
- 1)) ? TRUE
: FALSE
;
541 State
->Flags
.Sf
= (Value
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
544 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
545 State
->Flags
.Af
= ((Value
& 0x0F) == 0x0F) ? TRUE
: FALSE
;
546 State
->Flags
.Pf
= Soft386CalculateParity(LOBYTE(Value
));
552 SOFT386_OPCODE_HANDLER(Soft386OpcodePushReg
)
554 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
557 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
561 /* Make sure this is the right instruction */
562 ASSERT((Opcode
& 0xF8) == 0x50);
564 /* Call the internal function */
565 return Soft386StackPush(State
, State
->GeneralRegs
[Opcode
& 0x07].Long
);
568 SOFT386_OPCODE_HANDLER(Soft386OpcodePopReg
)
571 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_SS
].Size
;
573 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
575 /* The OPSIZE prefix toggles the size */
579 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
582 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
586 /* Make sure this is the right instruction */
587 ASSERT((Opcode
& 0xF8) == 0x58);
589 /* Call the internal function */
590 if (!Soft386StackPop(State
, &Value
)) return FALSE
;
592 /* Store the value */
593 if (Size
) State
->GeneralRegs
[Opcode
& 0x07].Long
= Value
;
594 else State
->GeneralRegs
[Opcode
& 0x07].LowWord
= Value
;
600 SOFT386_OPCODE_HANDLER(Soft386OpcodeNop
)
602 if (State
->PrefixFlags
& ~(SOFT386_PREFIX_OPSIZE
| SOFT386_PREFIX_REP
))
604 /* Allowed prefixes are REP and OPSIZE */
605 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
609 if (State
->PrefixFlags
& SOFT386_PREFIX_REP
)
612 State
->IdleCallback(State
);
618 SOFT386_OPCODE_HANDLER(Soft386OpcodeExchangeEax
)
620 INT Reg
= Opcode
& 0x07;
621 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
623 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
625 /* The OPSIZE prefix toggles the size */
629 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
632 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
636 /* Make sure this is the right instruction */
637 ASSERT((Opcode
& 0xF8) == 0x90);
639 /* Exchange the values */
644 Value
= State
->GeneralRegs
[Reg
].Long
;
645 State
->GeneralRegs
[Reg
].Long
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
646 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Value
;
652 Value
= State
->GeneralRegs
[Reg
].LowWord
;
653 State
->GeneralRegs
[Reg
].LowWord
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
654 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Value
;
660 SOFT386_OPCODE_HANDLER(Soft386OpcodeShortConditionalJmp
)
662 BOOLEAN Jump
= FALSE
;
665 /* Make sure this is the right instruction */
666 ASSERT((Opcode
& 0xF0) == 0x70);
668 /* Fetch the offset */
669 if (!Soft386FetchByte(State
, (PUCHAR
)&Offset
))
671 /* An exception occurred */
675 switch ((Opcode
& 0x0F) >> 1)
680 Jump
= State
->Flags
.Of
;
687 Jump
= State
->Flags
.Cf
;
694 Jump
= State
->Flags
.Zf
;
701 Jump
= State
->Flags
.Cf
|| State
->Flags
.Zf
;
708 Jump
= State
->Flags
.Sf
;
715 Jump
= State
->Flags
.Pf
;
722 Jump
= State
->Flags
.Sf
!= State
->Flags
.Of
;
729 Jump
= (State
->Flags
.Sf
!= State
->Flags
.Of
) || State
->Flags
.Zf
;
736 /* Invert the result */
742 /* Move the instruction pointer */
743 State
->InstPtr
.Long
+= Offset
;
750 SOFT386_OPCODE_HANDLER(Soft386OpcodeClearCarry
)
752 /* Make sure this is the right instruction */
753 ASSERT(Opcode
== 0xF8);
755 /* No prefixes allowed */
756 if (State
->PrefixFlags
)
758 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
762 /* Clear CF and return success */
763 State
->Flags
.Cf
= FALSE
;
767 SOFT386_OPCODE_HANDLER(Soft386OpcodeSetCarry
)
769 /* Make sure this is the right instruction */
770 ASSERT(Opcode
== 0xF9);
772 /* No prefixes allowed */
773 if (State
->PrefixFlags
)
775 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
779 /* Set CF and return success*/
780 State
->Flags
.Cf
= TRUE
;
784 SOFT386_OPCODE_HANDLER(Soft386OpcodeComplCarry
)
786 /* Make sure this is the right instruction */
787 ASSERT(Opcode
== 0xF5);
789 /* No prefixes allowed */
790 if (State
->PrefixFlags
)
792 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
796 /* Toggle CF and return success */
797 State
->Flags
.Cf
= !State
->Flags
.Cf
;
801 SOFT386_OPCODE_HANDLER(Soft386OpcodeClearInt
)
803 /* Make sure this is the right instruction */
804 ASSERT(Opcode
== 0xFA);
806 /* No prefixes allowed */
807 if (State
->PrefixFlags
)
809 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
813 /* Check for protected mode */
814 if (State
->ControlRegisters
[SOFT386_REG_CR0
] & SOFT386_CR0_PE
)
817 if (State
->Flags
.Iopl
>= State
->SegmentRegs
[SOFT386_REG_CS
].Dpl
)
819 /* Clear the interrupt flag */
820 State
->Flags
.If
= FALSE
;
824 /* General Protection Fault */
825 Soft386Exception(State
, SOFT386_EXCEPTION_GP
);
831 /* Just clear the interrupt flag */
832 State
->Flags
.If
= FALSE
;
839 SOFT386_OPCODE_HANDLER(Soft386OpcodeSetInt
)
841 /* Make sure this is the right instruction */
842 ASSERT(Opcode
== 0xFB);
844 /* No prefixes allowed */
845 if (State
->PrefixFlags
)
847 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
851 /* Check for protected mode */
852 if (State
->ControlRegisters
[SOFT386_REG_CR0
] & SOFT386_CR0_PE
)
855 if (State
->Flags
.Iopl
>= State
->SegmentRegs
[SOFT386_REG_CS
].Dpl
)
857 /* Set the interrupt flag */
858 State
->Flags
.If
= TRUE
;
862 /* General Protection Fault */
863 Soft386Exception(State
, SOFT386_EXCEPTION_GP
);
869 /* Just set the interrupt flag */
870 State
->Flags
.If
= TRUE
;
877 SOFT386_OPCODE_HANDLER(Soft386OpcodeClearDir
)
879 /* Make sure this is the right instruction */
880 ASSERT(Opcode
== 0xFC);
882 /* No prefixes allowed */
883 if (State
->PrefixFlags
)
885 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
889 /* Clear DF and return success */
890 State
->Flags
.Df
= FALSE
;
894 SOFT386_OPCODE_HANDLER(Soft386OpcodeSetDir
)
896 /* Make sure this is the right instruction */
897 ASSERT(Opcode
== 0xFD);
899 /* No prefixes allowed */
900 if (State
->PrefixFlags
)
902 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
906 /* Set DF and return success*/
907 State
->Flags
.Df
= TRUE
;
911 SOFT386_OPCODE_HANDLER(Soft386OpcodeHalt
)
913 /* Make sure this is the right instruction */
914 ASSERT(Opcode
== 0xF4);
916 /* No prefixes allowed */
917 if (State
->PrefixFlags
)
919 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
923 /* Privileged instructions can only be executed under CPL = 0 */
924 if (State
->SegmentRegs
[SOFT386_REG_CS
].Dpl
!= 0)
926 Soft386Exception(State
, SOFT386_EXCEPTION_GP
);
931 while (!State
->HardwareInt
) State
->IdleCallback(State
);
937 SOFT386_OPCODE_HANDLER(Soft386OpcodeInByte
)
942 /* Make sure this is the right instruction */
943 ASSERT((Opcode
& 0xF7) == 0xE4);
947 /* Fetch the parameter */
948 if (!Soft386FetchByte(State
, &Data
))
950 /* Exception occurred */
954 /* Set the port number to the parameter */
959 /* The port number is in DX */
960 Port
= State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
;
963 /* Read a byte from the I/O port */
964 State
->IoReadCallback(State
, Port
, &Data
, sizeof(UCHAR
));
966 /* Store the result in AL */
967 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Data
;
972 SOFT386_OPCODE_HANDLER(Soft386OpcodeIn
)
975 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
977 /* Make sure this is the right instruction */
978 ASSERT((Opcode
& 0xF7) == 0xE5);
980 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
982 /* The OPSIZE prefix toggles the size */
986 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
989 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
997 /* Fetch the parameter */
998 if (!Soft386FetchByte(State
, &Data
))
1000 /* Exception occurred */
1004 /* Set the port number to the parameter */
1009 /* The port number is in DX */
1010 Port
= State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
;
1017 /* Read a dword from the I/O port */
1018 State
->IoReadCallback(State
, Port
, &Data
, sizeof(ULONG
));
1020 /* Store the value in EAX */
1021 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Data
;
1027 /* Read a word from the I/O port */
1028 State
->IoReadCallback(State
, Port
, &Data
, sizeof(USHORT
));
1030 /* Store the value in AX */
1031 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Data
;
1037 SOFT386_OPCODE_HANDLER(Soft386OpcodeOutByte
)
1042 /* Make sure this is the right instruction */
1043 ASSERT((Opcode
& 0xF7) == 0xE6);
1047 /* Fetch the parameter */
1048 if (!Soft386FetchByte(State
, &Data
))
1050 /* Exception occurred */
1054 /* Set the port number to the parameter */
1059 /* The port number is in DX */
1060 Port
= State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
;
1063 /* Read the value from AL */
1064 Data
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
1066 /* Write the byte to the I/O port */
1067 State
->IoWriteCallback(State
, Port
, &Data
, sizeof(UCHAR
));
1072 SOFT386_OPCODE_HANDLER(Soft386OpcodeOut
)
1075 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1077 /* Make sure this is the right instruction */
1078 ASSERT((Opcode
& 0xF7) == 0xE7);
1080 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1082 /* The OPSIZE prefix toggles the size */
1086 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
1088 /* Invalid prefix */
1089 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1097 /* Fetch the parameter */
1098 if (!Soft386FetchByte(State
, &Data
))
1100 /* Exception occurred */
1104 /* Set the port number to the parameter */
1109 /* The port number is in DX */
1110 Port
= State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
;
1115 /* Get the value from EAX */
1116 ULONG Data
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
1118 /* Write a dword to the I/O port */
1119 State
->IoReadCallback(State
, Port
, &Data
, sizeof(ULONG
));
1123 /* Get the value from AX */
1124 USHORT Data
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
1126 /* Write a word to the I/O port */
1127 State
->IoWriteCallback(State
, Port
, &Data
, sizeof(USHORT
));
1133 SOFT386_OPCODE_HANDLER(Soft386OpcodeShortJump
)
1137 /* Make sure this is the right instruction */
1138 ASSERT(Opcode
== 0xEB);
1140 /* Fetch the offset */
1141 if (!Soft386FetchByte(State
, (PUCHAR
)&Offset
))
1143 /* An exception occurred */
1147 /* Move the instruction pointer */
1148 State
->InstPtr
.Long
+= Offset
;
1153 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovRegImm
)
1155 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1157 /* Make sure this is the right instruction */
1158 ASSERT((Opcode
& 0xF8) == 0xB8);
1160 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1162 /* The OPSIZE prefix toggles the size */
1166 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
1168 /* Invalid prefix */
1169 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1177 /* Fetch the dword */
1178 if (!Soft386FetchDword(State
, &Value
))
1180 /* Exception occurred */
1184 /* Store the value in the register */
1185 State
->GeneralRegs
[Opcode
& 0x07].Long
= Value
;
1191 /* Fetch the word */
1192 if (!Soft386FetchWord(State
, &Value
))
1194 /* Exception occurred */
1198 /* Store the value in the register */
1199 State
->GeneralRegs
[Opcode
& 0x07].LowWord
= Value
;
1205 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovByteRegImm
)
1209 /* Make sure this is the right instruction */
1210 ASSERT((Opcode
& 0xF8) == 0xB0);
1212 if (State
->PrefixFlags
!= 0)
1214 /* Invalid prefix */
1215 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1219 /* Fetch the byte */
1220 if (!Soft386FetchByte(State
, &Value
))
1222 /* Exception occurred */
1228 /* AH, CH, DH or BH */
1229 State
->GeneralRegs
[Opcode
& 0x03].HighByte
= Value
;
1233 /* AL, CL, DL or BL */
1234 State
->GeneralRegs
[Opcode
& 0x03].LowByte
= Value
;
1240 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddByteModrm
)
1242 UCHAR FirstValue
, SecondValue
, Result
;
1243 SOFT386_MOD_REG_RM ModRegRm
;
1244 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1246 /* Make sure this is the right instruction */
1247 ASSERT((Opcode
& 0xFD) == 0x00);
1249 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1251 /* The ADSIZE prefix toggles the size */
1252 AddressSize
= !AddressSize
;
1254 else if (State
->PrefixFlags
1255 & ~(SOFT386_PREFIX_ADSIZE
1256 | SOFT386_PREFIX_SEG
1257 | SOFT386_PREFIX_LOCK
))
1259 /* Invalid prefix */
1260 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1264 /* Get the operands */
1265 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1267 /* Exception occurred */
1271 if (!Soft386ReadModrmByteOperands(State
,
1276 /* Exception occurred */
1280 /* Calculate the result */
1281 Result
= FirstValue
+ SecondValue
;
1283 /* Update the flags */
1284 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1285 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
1286 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
1287 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
1288 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1289 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1290 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1292 /* Write back the result */
1293 return Soft386WriteModrmByteOperands(State
,
1295 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1299 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddModrm
)
1301 SOFT386_MOD_REG_RM ModRegRm
;
1302 BOOLEAN OperandSize
, AddressSize
;
1304 /* Make sure this is the right instruction */
1305 ASSERT((Opcode
& 0xFD) == 0x01);
1307 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1309 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1311 /* The ADSIZE prefix toggles the address size */
1312 AddressSize
= !AddressSize
;
1315 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1317 /* The OPSIZE prefix toggles the operand size */
1318 OperandSize
= !OperandSize
;
1321 if (State
->PrefixFlags
1322 & ~(SOFT386_PREFIX_ADSIZE
1323 | SOFT386_PREFIX_OPSIZE
1324 | SOFT386_PREFIX_SEG
1325 | SOFT386_PREFIX_LOCK
))
1327 /* Invalid prefix */
1328 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1332 /* Get the operands */
1333 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1335 /* Exception occurred */
1339 /* Check the operand size */
1342 ULONG FirstValue
, SecondValue
, Result
;
1344 if (!Soft386ReadModrmDwordOperands(State
,
1349 /* Exception occurred */
1353 /* Calculate the result */
1354 Result
= FirstValue
+ SecondValue
;
1356 /* Update the flags */
1357 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1358 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
1359 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
1360 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
1361 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1362 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1363 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1365 /* Write back the result */
1366 return Soft386WriteModrmDwordOperands(State
,
1368 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1373 USHORT FirstValue
, SecondValue
, Result
;
1375 if (!Soft386ReadModrmWordOperands(State
,
1380 /* Exception occurred */
1384 /* Calculate the result */
1385 Result
= FirstValue
+ SecondValue
;
1387 /* Update the flags */
1388 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1389 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
1390 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
1391 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
1392 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1393 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
1394 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1396 /* Write back the result */
1397 return Soft386WriteModrmWordOperands(State
,
1399 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1404 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddAl
)
1406 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
1407 UCHAR SecondValue
, Result
;
1409 /* Make sure this is the right instruction */
1410 ASSERT(Opcode
== 0x04);
1412 if (State
->PrefixFlags
)
1414 /* This opcode doesn't take any prefixes */
1415 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1419 if (!Soft386FetchByte(State
, &SecondValue
))
1421 /* Exception occurred */
1425 /* Calculate the result */
1426 Result
= FirstValue
+ SecondValue
;
1428 /* Update the flags */
1429 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1430 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
1431 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
1432 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
1433 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1434 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1435 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1437 /* Write back the result */
1438 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
1443 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddEax
)
1445 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1447 /* Make sure this is the right instruction */
1448 ASSERT(Opcode
== 0x05);
1450 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
1452 /* Invalid prefix */
1453 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1457 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1459 /* The OPSIZE prefix toggles the size */
1465 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
1466 ULONG SecondValue
, Result
;
1468 if (!Soft386FetchDword(State
, &SecondValue
))
1470 /* Exception occurred */
1474 /* Calculate the result */
1475 Result
= FirstValue
+ SecondValue
;
1477 /* Update the flags */
1478 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1479 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
1480 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
1481 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
1482 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1483 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1484 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1486 /* Write back the result */
1487 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
1491 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
1492 USHORT SecondValue
, Result
;
1494 if (!Soft386FetchWord(State
, &SecondValue
))
1496 /* Exception occurred */
1500 /* Calculate the result */
1501 Result
= FirstValue
+ SecondValue
;
1503 /* Update the flags */
1504 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1505 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
1506 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
1507 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
1508 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1509 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
1510 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1512 /* Write back the result */
1513 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
1519 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrByteModrm
)
1521 UCHAR FirstValue
, SecondValue
, Result
;
1522 SOFT386_MOD_REG_RM ModRegRm
;
1523 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1525 /* Make sure this is the right instruction */
1526 ASSERT((Opcode
& 0xFD) == 0x08);
1528 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1530 /* The ADSIZE prefix toggles the size */
1531 AddressSize
= !AddressSize
;
1533 else if (State
->PrefixFlags
1534 & ~(SOFT386_PREFIX_ADSIZE
1535 | SOFT386_PREFIX_SEG
1536 | SOFT386_PREFIX_LOCK
))
1538 /* Invalid prefix */
1539 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1543 /* Get the operands */
1544 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1546 /* Exception occurred */
1550 if (!Soft386ReadModrmByteOperands(State
,
1555 /* Exception occurred */
1559 /* Calculate the result */
1560 Result
= FirstValue
| SecondValue
;
1562 /* Update the flags */
1563 State
->Flags
.Cf
= FALSE
;
1564 State
->Flags
.Of
= FALSE
;
1565 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1566 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1567 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1569 /* Write back the result */
1570 return Soft386WriteModrmByteOperands(State
,
1572 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1576 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrModrm
)
1578 SOFT386_MOD_REG_RM ModRegRm
;
1579 BOOLEAN OperandSize
, AddressSize
;
1581 /* Make sure this is the right instruction */
1582 ASSERT((Opcode
& 0xFD) == 0x09);
1584 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1586 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1588 /* The ADSIZE prefix toggles the address size */
1589 AddressSize
= !AddressSize
;
1592 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1594 /* The OPSIZE prefix toggles the operand size */
1595 OperandSize
= !OperandSize
;
1598 if (State
->PrefixFlags
1599 & ~(SOFT386_PREFIX_ADSIZE
1600 | SOFT386_PREFIX_OPSIZE
1601 | SOFT386_PREFIX_SEG
1602 | SOFT386_PREFIX_LOCK
))
1604 /* Invalid prefix */
1605 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1609 /* Get the operands */
1610 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1612 /* Exception occurred */
1616 /* Check the operand size */
1619 ULONG FirstValue
, SecondValue
, Result
;
1621 if (!Soft386ReadModrmDwordOperands(State
,
1626 /* Exception occurred */
1630 /* Calculate the result */
1631 Result
= FirstValue
| SecondValue
;
1633 /* Update the flags */
1634 State
->Flags
.Cf
= FALSE
;
1635 State
->Flags
.Of
= FALSE
;
1636 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1637 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1638 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1640 /* Write back the result */
1641 return Soft386WriteModrmDwordOperands(State
,
1643 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1648 USHORT FirstValue
, SecondValue
, Result
;
1650 if (!Soft386ReadModrmWordOperands(State
,
1655 /* Exception occurred */
1659 /* Calculate the result */
1660 Result
= FirstValue
| SecondValue
;
1662 /* Update the flags */
1663 State
->Flags
.Cf
= FALSE
;
1664 State
->Flags
.Of
= FALSE
;
1665 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1666 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1667 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1669 /* Write back the result */
1670 return Soft386WriteModrmWordOperands(State
,
1672 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1677 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrAl
)
1679 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
1680 UCHAR SecondValue
, Result
;
1682 /* Make sure this is the right instruction */
1683 ASSERT(Opcode
== 0x0C);
1685 if (State
->PrefixFlags
)
1687 /* This opcode doesn't take any prefixes */
1688 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1692 if (!Soft386FetchByte(State
, &SecondValue
))
1694 /* Exception occurred */
1698 /* Calculate the result */
1699 Result
= FirstValue
| SecondValue
;
1701 /* Update the flags */
1702 State
->Flags
.Cf
= FALSE
;
1703 State
->Flags
.Of
= FALSE
;
1704 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1705 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1706 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1708 /* Write back the result */
1709 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
1714 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrEax
)
1716 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1718 /* Make sure this is the right instruction */
1719 ASSERT(Opcode
== 0x0D);
1721 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
1723 /* Invalid prefix */
1724 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1728 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1730 /* The OPSIZE prefix toggles the size */
1736 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
1737 ULONG SecondValue
, Result
;
1739 if (!Soft386FetchDword(State
, &SecondValue
))
1741 /* Exception occurred */
1745 /* Calculate the result */
1746 Result
= FirstValue
| SecondValue
;
1748 /* Update the flags */
1749 State
->Flags
.Cf
= FALSE
;
1750 State
->Flags
.Of
= FALSE
;
1751 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1752 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1753 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1755 /* Write back the result */
1756 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
1760 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
1761 USHORT SecondValue
, Result
;
1763 if (!Soft386FetchWord(State
, &SecondValue
))
1765 /* Exception occurred */
1769 /* Calculate the result */
1770 Result
= FirstValue
| SecondValue
;
1772 /* Update the flags */
1773 State
->Flags
.Cf
= FALSE
;
1774 State
->Flags
.Of
= FALSE
;
1775 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1776 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
1777 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1779 /* Write back the result */
1780 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
1786 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndByteModrm
)
1788 UCHAR FirstValue
, SecondValue
, Result
;
1789 SOFT386_MOD_REG_RM ModRegRm
;
1790 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1792 /* Make sure this is the right instruction */
1793 ASSERT((Opcode
& 0xFD) == 0x20);
1795 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1797 /* The ADSIZE prefix toggles the size */
1798 AddressSize
= !AddressSize
;
1800 else if (State
->PrefixFlags
1801 & ~(SOFT386_PREFIX_ADSIZE
1802 | SOFT386_PREFIX_SEG
1803 | SOFT386_PREFIX_LOCK
))
1805 /* Invalid prefix */
1806 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1810 /* Get the operands */
1811 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1813 /* Exception occurred */
1817 if (!Soft386ReadModrmByteOperands(State
,
1822 /* Exception occurred */
1826 /* Calculate the result */
1827 Result
= FirstValue
& SecondValue
;
1829 /* Update the flags */
1830 State
->Flags
.Cf
= FALSE
;
1831 State
->Flags
.Of
= FALSE
;
1832 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1833 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1834 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1836 /* Write back the result */
1837 return Soft386WriteModrmByteOperands(State
,
1839 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1843 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndModrm
)
1845 SOFT386_MOD_REG_RM ModRegRm
;
1846 BOOLEAN OperandSize
, AddressSize
;
1848 /* Make sure this is the right instruction */
1849 ASSERT((Opcode
& 0xFD) == 0x21);
1851 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1853 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1855 /* The ADSIZE prefix toggles the address size */
1856 AddressSize
= !AddressSize
;
1859 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1861 /* The OPSIZE prefix toggles the operand size */
1862 OperandSize
= !OperandSize
;
1865 if (State
->PrefixFlags
1866 & ~(SOFT386_PREFIX_ADSIZE
1867 | SOFT386_PREFIX_OPSIZE
1868 | SOFT386_PREFIX_SEG
1869 | SOFT386_PREFIX_LOCK
))
1871 /* Invalid prefix */
1872 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1876 /* Get the operands */
1877 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1879 /* Exception occurred */
1883 /* Check the operand size */
1886 ULONG FirstValue
, SecondValue
, Result
;
1888 if (!Soft386ReadModrmDwordOperands(State
,
1893 /* Exception occurred */
1897 /* Calculate the result */
1898 Result
= FirstValue
& SecondValue
;
1900 /* Update the flags */
1901 State
->Flags
.Cf
= FALSE
;
1902 State
->Flags
.Of
= FALSE
;
1903 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1904 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1905 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1907 /* Write back the result */
1908 return Soft386WriteModrmDwordOperands(State
,
1910 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1915 USHORT FirstValue
, SecondValue
, Result
;
1917 if (!Soft386ReadModrmWordOperands(State
,
1922 /* Exception occurred */
1926 /* Calculate the result */
1927 Result
= FirstValue
& SecondValue
;
1929 /* Update the flags */
1930 State
->Flags
.Cf
= FALSE
;
1931 State
->Flags
.Of
= FALSE
;
1932 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1933 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1934 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1936 /* Write back the result */
1937 return Soft386WriteModrmWordOperands(State
,
1939 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1944 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndAl
)
1946 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
1947 UCHAR SecondValue
, Result
;
1949 /* Make sure this is the right instruction */
1950 ASSERT(Opcode
== 0x24);
1952 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
1954 /* Invalid prefix */
1955 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1959 if (!Soft386FetchByte(State
, &SecondValue
))
1961 /* Exception occurred */
1965 /* Calculate the result */
1966 Result
= FirstValue
& SecondValue
;
1968 /* Update the flags */
1969 State
->Flags
.Cf
= FALSE
;
1970 State
->Flags
.Of
= FALSE
;
1971 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1972 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1973 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1975 /* Write back the result */
1976 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
1981 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndEax
)
1983 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1985 /* Make sure this is the right instruction */
1986 ASSERT(Opcode
== 0x25);
1988 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
1990 /* Invalid prefix */
1991 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1995 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1997 /* The OPSIZE prefix toggles the size */
2003 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
2004 ULONG SecondValue
, Result
;
2006 if (!Soft386FetchDword(State
, &SecondValue
))
2008 /* Exception occurred */
2012 /* Calculate the result */
2013 Result
= FirstValue
& SecondValue
;
2015 /* Update the flags */
2016 State
->Flags
.Cf
= FALSE
;
2017 State
->Flags
.Of
= FALSE
;
2018 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2019 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2020 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2022 /* Write back the result */
2023 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
2027 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
2028 USHORT SecondValue
, Result
;
2030 if (!Soft386FetchWord(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) ? TRUE
: FALSE
;
2043 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
2044 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2046 /* Write back the result */
2047 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
2053 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorByteModrm
)
2055 UCHAR FirstValue
, SecondValue
, Result
;
2056 SOFT386_MOD_REG_RM ModRegRm
;
2057 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2059 /* Make sure this is the right instruction */
2060 ASSERT((Opcode
& 0xFD) == 0x30);
2062 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2064 /* The ADSIZE prefix toggles the size */
2065 AddressSize
= !AddressSize
;
2067 else if (State
->PrefixFlags
2068 & ~(SOFT386_PREFIX_ADSIZE
2069 | SOFT386_PREFIX_SEG
2070 | SOFT386_PREFIX_LOCK
))
2072 /* Invalid prefix */
2073 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2077 /* Get the operands */
2078 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2080 /* Exception occurred */
2084 if (!Soft386ReadModrmByteOperands(State
,
2089 /* Exception occurred */
2093 /* Calculate the result */
2094 Result
= FirstValue
^ SecondValue
;
2096 /* Update the flags */
2097 State
->Flags
.Cf
= FALSE
;
2098 State
->Flags
.Of
= FALSE
;
2099 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2100 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2101 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2103 /* Write back the result */
2104 return Soft386WriteModrmByteOperands(State
,
2106 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2110 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorModrm
)
2112 SOFT386_MOD_REG_RM ModRegRm
;
2113 BOOLEAN OperandSize
, AddressSize
;
2115 /* Make sure this is the right instruction */
2116 ASSERT((Opcode
& 0xFD) == 0x31);
2118 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2120 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2122 /* The ADSIZE prefix toggles the address size */
2123 AddressSize
= !AddressSize
;
2126 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2128 /* The OPSIZE prefix toggles the operand size */
2129 OperandSize
= !OperandSize
;
2132 if (State
->PrefixFlags
2133 & ~(SOFT386_PREFIX_ADSIZE
2134 | SOFT386_PREFIX_OPSIZE
2135 | SOFT386_PREFIX_SEG
2136 | SOFT386_PREFIX_LOCK
))
2138 /* Invalid prefix */
2139 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2143 /* Get the operands */
2144 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2146 /* Exception occurred */
2150 /* Check the operand size */
2153 ULONG FirstValue
, SecondValue
, Result
;
2155 if (!Soft386ReadModrmDwordOperands(State
,
2160 /* Exception occurred */
2164 /* Calculate the result */
2165 Result
= FirstValue
^ SecondValue
;
2167 /* Update the flags */
2168 State
->Flags
.Cf
= FALSE
;
2169 State
->Flags
.Of
= FALSE
;
2170 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2171 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2172 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2174 /* Write back the result */
2175 return Soft386WriteModrmDwordOperands(State
,
2177 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2182 USHORT FirstValue
, SecondValue
, Result
;
2184 if (!Soft386ReadModrmWordOperands(State
,
2189 /* Exception occurred */
2193 /* Calculate the result */
2194 Result
= FirstValue
^ SecondValue
;
2196 /* Update the flags */
2197 State
->Flags
.Cf
= FALSE
;
2198 State
->Flags
.Of
= FALSE
;
2199 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2200 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2201 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2203 /* Write back the result */
2204 return Soft386WriteModrmWordOperands(State
,
2206 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2211 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorAl
)
2213 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
2214 UCHAR SecondValue
, Result
;
2216 /* Make sure this is the right instruction */
2217 ASSERT(Opcode
== 0x34);
2219 if (State
->PrefixFlags
)
2221 /* This opcode doesn't take any prefixes */
2222 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2226 if (!Soft386FetchByte(State
, &SecondValue
))
2228 /* Exception occurred */
2232 /* Calculate the result */
2233 Result
= FirstValue
^ SecondValue
;
2235 /* Update the flags */
2236 State
->Flags
.Cf
= FALSE
;
2237 State
->Flags
.Of
= FALSE
;
2238 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2239 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2240 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2242 /* Write back the result */
2243 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
2248 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorEax
)
2250 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2252 /* Make sure this is the right instruction */
2253 ASSERT(Opcode
== 0x35);
2255 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
2257 /* Invalid prefix */
2258 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2262 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2264 /* The OPSIZE prefix toggles the size */
2270 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
2271 ULONG SecondValue
, Result
;
2273 if (!Soft386FetchDword(State
, &SecondValue
))
2275 /* Exception occurred */
2279 /* Calculate the result */
2280 Result
= FirstValue
^ SecondValue
;
2282 /* Update the flags */
2283 State
->Flags
.Cf
= FALSE
;
2284 State
->Flags
.Of
= FALSE
;
2285 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2286 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2287 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2289 /* Write back the result */
2290 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
2294 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
2295 USHORT SecondValue
, Result
;
2297 if (!Soft386FetchWord(State
, &SecondValue
))
2299 /* Exception occurred */
2303 /* Calculate the result */
2304 Result
= FirstValue
^ SecondValue
;
2306 /* Update the flags */
2307 State
->Flags
.Cf
= FALSE
;
2308 State
->Flags
.Of
= FALSE
;
2309 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2310 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
2311 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2313 /* Write back the result */
2314 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
2320 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestByteModrm
)
2322 UCHAR FirstValue
, SecondValue
, Result
;
2323 SOFT386_MOD_REG_RM ModRegRm
;
2324 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2326 /* Make sure this is the right instruction */
2327 ASSERT(Opcode
== 0x84);
2329 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2331 /* The ADSIZE prefix toggles the size */
2332 AddressSize
= !AddressSize
;
2334 else if (State
->PrefixFlags
2335 & ~(SOFT386_PREFIX_ADSIZE
2336 | SOFT386_PREFIX_SEG
2337 | SOFT386_PREFIX_LOCK
))
2339 /* Invalid prefix */
2340 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2344 /* Get the operands */
2345 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2347 /* Exception occurred */
2351 if (!Soft386ReadModrmByteOperands(State
,
2356 /* Exception occurred */
2359 /* Calculate the result */
2360 Result
= FirstValue
& SecondValue
;
2362 /* Update the flags */
2363 State
->Flags
.Cf
= FALSE
;
2364 State
->Flags
.Of
= FALSE
;
2365 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2366 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2367 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2369 /* The result is discarded */
2373 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestModrm
)
2375 SOFT386_MOD_REG_RM ModRegRm
;
2376 BOOLEAN OperandSize
, AddressSize
;
2378 /* Make sure this is the right instruction */
2379 ASSERT(Opcode
== 0x85);
2381 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2383 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2385 /* The ADSIZE prefix toggles the address size */
2386 AddressSize
= !AddressSize
;
2389 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2391 /* The OPSIZE prefix toggles the operand size */
2392 OperandSize
= !OperandSize
;
2395 if (State
->PrefixFlags
2396 & ~(SOFT386_PREFIX_ADSIZE
2397 | SOFT386_PREFIX_OPSIZE
2398 | SOFT386_PREFIX_SEG
2399 | SOFT386_PREFIX_LOCK
))
2401 /* Invalid prefix */
2402 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2406 /* Get the operands */
2407 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2409 /* Exception occurred */
2413 /* Check the operand size */
2416 ULONG FirstValue
, SecondValue
, Result
;
2418 if (!Soft386ReadModrmDwordOperands(State
,
2423 /* Exception occurred */
2427 /* Calculate the result */
2428 Result
= FirstValue
& SecondValue
;
2430 /* Update the flags */
2431 State
->Flags
.Cf
= FALSE
;
2432 State
->Flags
.Of
= FALSE
;
2433 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2434 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2435 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2439 USHORT FirstValue
, SecondValue
, Result
;
2441 if (!Soft386ReadModrmWordOperands(State
,
2446 /* Exception occurred */
2450 /* Calculate the result */
2451 Result
= FirstValue
& SecondValue
;
2453 /* Update the flags */
2454 State
->Flags
.Cf
= FALSE
;
2455 State
->Flags
.Of
= FALSE
;
2456 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2457 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2458 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2461 /* The result is discarded */
2465 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestAl
)
2467 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
2468 UCHAR SecondValue
, Result
;
2470 /* Make sure this is the right instruction */
2471 ASSERT(Opcode
== 0xA8);
2473 if (State
->PrefixFlags
)
2475 /* This opcode doesn't take any prefixes */
2476 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2480 if (!Soft386FetchByte(State
, &SecondValue
))
2482 /* Exception occurred */
2486 /* Calculate the result */
2487 Result
= FirstValue
& SecondValue
;
2489 /* Update the flags */
2490 State
->Flags
.Cf
= FALSE
;
2491 State
->Flags
.Of
= FALSE
;
2492 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2493 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2494 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2496 /* The result is discarded */
2500 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestEax
)
2502 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2504 /* Make sure this is the right instruction */
2505 ASSERT(Opcode
== 0xA9);
2507 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
2509 /* Invalid prefix */
2510 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2514 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2516 /* The OPSIZE prefix toggles the size */
2522 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
2523 ULONG SecondValue
, Result
;
2525 if (!Soft386FetchDword(State
, &SecondValue
))
2527 /* Exception occurred */
2531 /* Calculate the result */
2532 Result
= FirstValue
& SecondValue
;
2534 /* Update the flags */
2535 State
->Flags
.Cf
= FALSE
;
2536 State
->Flags
.Of
= FALSE
;
2537 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2538 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2539 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2543 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
2544 USHORT SecondValue
, Result
;
2546 if (!Soft386FetchWord(State
, &SecondValue
))
2548 /* Exception occurred */
2552 /* Calculate the result */
2553 Result
= FirstValue
& SecondValue
;
2555 /* Update the flags */
2556 State
->Flags
.Cf
= FALSE
;
2557 State
->Flags
.Of
= FALSE
;
2558 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2559 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
2560 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2563 /* The result is discarded */
2567 SOFT386_OPCODE_HANDLER(Soft386OpcodeXchgByteModrm
)
2569 UCHAR FirstValue
, SecondValue
;
2570 SOFT386_MOD_REG_RM ModRegRm
;
2571 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2573 /* Make sure this is the right instruction */
2574 ASSERT(Opcode
== 0x86);
2576 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2578 /* The ADSIZE prefix toggles the size */
2579 AddressSize
= !AddressSize
;
2581 else if (State
->PrefixFlags
2582 & ~(SOFT386_PREFIX_ADSIZE
2583 | SOFT386_PREFIX_SEG
2584 | SOFT386_PREFIX_LOCK
))
2586 /* Invalid prefix */
2587 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2591 /* Get the operands */
2592 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2594 /* Exception occurred */
2598 if (!Soft386ReadModrmByteOperands(State
,
2603 /* Exception occurred */
2607 /* Write the value from the register to the R/M */
2608 if (!Soft386WriteModrmByteOperands(State
,
2613 /* Exception occurred */
2617 /* Write the value from the R/M to the register */
2618 if (!Soft386WriteModrmByteOperands(State
,
2623 /* Exception occurred */
2630 SOFT386_OPCODE_HANDLER(Soft386OpcodeXchgModrm
)
2632 SOFT386_MOD_REG_RM ModRegRm
;
2633 BOOLEAN OperandSize
, AddressSize
;
2635 /* Make sure this is the right instruction */
2636 ASSERT(Opcode
== 0x87);
2638 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2640 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2642 /* The ADSIZE prefix toggles the address size */
2643 AddressSize
= !AddressSize
;
2646 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2648 /* The OPSIZE prefix toggles the operand size */
2649 OperandSize
= !OperandSize
;
2652 if (State
->PrefixFlags
2653 & ~(SOFT386_PREFIX_ADSIZE
2654 | SOFT386_PREFIX_OPSIZE
2655 | SOFT386_PREFIX_SEG
2656 | SOFT386_PREFIX_LOCK
))
2658 /* Invalid prefix */
2659 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2663 /* Get the operands */
2664 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2666 /* Exception occurred */
2670 /* Check the operand size */
2673 ULONG FirstValue
, SecondValue
;
2675 if (!Soft386ReadModrmDwordOperands(State
,
2680 /* Exception occurred */
2684 /* Write the value from the register to the R/M */
2685 if (!Soft386WriteModrmDwordOperands(State
,
2690 /* Exception occurred */
2694 /* Write the value from the R/M to the register */
2695 if (!Soft386WriteModrmDwordOperands(State
,
2700 /* Exception occurred */
2706 USHORT FirstValue
, SecondValue
;
2708 if (!Soft386ReadModrmWordOperands(State
,
2713 /* Exception occurred */
2717 /* Write the value from the register to the R/M */
2718 if (!Soft386WriteModrmWordOperands(State
,
2723 /* Exception occurred */
2727 /* Write the value from the R/M to the register */
2728 if (!Soft386WriteModrmWordOperands(State
,
2733 /* Exception occurred */
2738 /* The result is discarded */
2742 SOFT386_OPCODE_HANDLER(Soft386OpcodePushEs
)
2744 /* Call the internal API */
2745 return Soft386StackPush(State
, State
->SegmentRegs
[SOFT386_REG_ES
].Selector
);
2748 SOFT386_OPCODE_HANDLER(Soft386OpcodePopEs
)
2752 if (!Soft386StackPop(State
, &NewSelector
))
2754 /* Exception occurred */
2758 /* Call the internal API */
2759 return Soft386LoadSegment(State
, SOFT386_REG_ES
, LOWORD(NewSelector
));
2762 SOFT386_OPCODE_HANDLER(Soft386OpcodePushCs
)
2764 /* Call the internal API */
2765 return Soft386StackPush(State
, State
->SegmentRegs
[SOFT386_REG_CS
].Selector
);
2768 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcByteModrm
)
2770 UCHAR FirstValue
, SecondValue
, Result
;
2771 SOFT386_MOD_REG_RM ModRegRm
;
2772 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2774 /* Make sure this is the right instruction */
2775 ASSERT((Opcode
& 0xFD) == 0x10);
2777 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2779 /* The ADSIZE prefix toggles the size */
2780 AddressSize
= !AddressSize
;
2782 else if (State
->PrefixFlags
2783 & ~(SOFT386_PREFIX_ADSIZE
2784 | SOFT386_PREFIX_SEG
2785 | SOFT386_PREFIX_LOCK
))
2787 /* Invalid prefix */
2788 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2792 /* Get the operands */
2793 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2795 /* Exception occurred */
2799 if (!Soft386ReadModrmByteOperands(State
,
2804 /* Exception occurred */
2808 /* Calculate the result */
2809 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2811 /* Special exception for CF */
2812 State
->Flags
.Cf
= State
->Flags
.Cf
2813 && ((FirstValue
== 0xFF) || (SecondValue
== 0xFF));
2815 /* Update the flags */
2816 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2817 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
2818 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
2819 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
2820 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2821 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2822 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2824 /* Write back the result */
2825 return Soft386WriteModrmByteOperands(State
,
2827 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2831 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcModrm
)
2833 SOFT386_MOD_REG_RM ModRegRm
;
2834 BOOLEAN OperandSize
, AddressSize
;
2836 /* Make sure this is the right instruction */
2837 ASSERT((Opcode
& 0xFD) == 0x11);
2839 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2841 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2843 /* The ADSIZE prefix toggles the address size */
2844 AddressSize
= !AddressSize
;
2847 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2849 /* The OPSIZE prefix toggles the operand size */
2850 OperandSize
= !OperandSize
;
2853 if (State
->PrefixFlags
2854 & ~(SOFT386_PREFIX_ADSIZE
2855 | SOFT386_PREFIX_OPSIZE
2856 | SOFT386_PREFIX_SEG
2857 | SOFT386_PREFIX_LOCK
))
2859 /* Invalid prefix */
2860 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2864 /* Get the operands */
2865 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2867 /* Exception occurred */
2871 /* Check the operand size */
2874 ULONG FirstValue
, SecondValue
, Result
;
2876 if (!Soft386ReadModrmDwordOperands(State
,
2881 /* Exception occurred */
2885 /* Calculate the result */
2886 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2888 /* Special exception for CF */
2889 State
->Flags
.Cf
= State
->Flags
.Cf
2890 && ((FirstValue
== 0xFFFFFFFF) || (SecondValue
== 0xFFFFFFFF));
2892 /* Update the flags */
2893 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2894 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
2895 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
2896 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
2897 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2898 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2899 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2901 /* Write back the result */
2902 return Soft386WriteModrmDwordOperands(State
,
2904 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2909 USHORT FirstValue
, SecondValue
, Result
;
2911 if (!Soft386ReadModrmWordOperands(State
,
2916 /* Exception occurred */
2920 /* Calculate the result */
2921 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2923 /* Special exception for CF */
2924 State
->Flags
.Cf
= State
->Flags
.Cf
2925 && ((FirstValue
== 0xFFFF) || (SecondValue
== 0xFFFF));
2927 /* Update the flags */
2928 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2929 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
2930 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
2931 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
2932 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2933 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
2934 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2936 /* Write back the result */
2937 return Soft386WriteModrmWordOperands(State
,
2939 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2945 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcAl
)
2947 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
2948 UCHAR SecondValue
, Result
;
2950 /* Make sure this is the right instruction */
2951 ASSERT(Opcode
== 0x14);
2953 if (State
->PrefixFlags
)
2955 /* This opcode doesn't take any prefixes */
2956 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2960 if (!Soft386FetchByte(State
, &SecondValue
))
2962 /* Exception occurred */
2966 /* Calculate the result */
2967 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2969 /* Special exception for CF */
2970 State
->Flags
.Cf
= State
->Flags
.Cf
&&
2971 ((FirstValue
== 0xFF) || (SecondValue
== 0xFF));
2973 /* Update the flags */
2974 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2975 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
2976 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
2977 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
2978 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2979 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2980 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2982 /* Write back the result */
2983 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
2988 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcEax
)
2990 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2992 /* Make sure this is the right instruction */
2993 ASSERT(Opcode
== 0x15);
2995 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
2997 /* Invalid prefix */
2998 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3002 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
3004 /* The OPSIZE prefix toggles the size */
3010 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
3011 ULONG SecondValue
, Result
;
3013 if (!Soft386FetchDword(State
, &SecondValue
))
3015 /* Exception occurred */
3019 /* Calculate the result */
3020 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
3022 /* Special exception for CF */
3023 State
->Flags
.Cf
= State
->Flags
.Cf
&&
3024 ((FirstValue
== 0xFFFFFFFF) || (SecondValue
== 0xFFFFFFFF));
3026 /* Update the flags */
3027 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
3028 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
3029 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
3030 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
3031 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3032 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
3033 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3035 /* Write back the result */
3036 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
3040 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
3041 USHORT SecondValue
, Result
;
3043 if (!Soft386FetchWord(State
, &SecondValue
))
3045 /* Exception occurred */
3049 /* Calculate the result */
3050 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
3052 /* Special exception for CF */
3053 State
->Flags
.Cf
= State
->Flags
.Cf
&&
3054 ((FirstValue
== 0xFFFF) || (SecondValue
== 0xFFFF));
3056 /* Update the flags */
3057 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
3058 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
3059 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
3060 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
3061 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3062 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
3063 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3065 /* Write back the result */
3066 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
3072 SOFT386_OPCODE_HANDLER(Soft386OpcodePushSs
)
3074 /* Call the internal API */
3075 return Soft386StackPush(State
, State
->SegmentRegs
[SOFT386_REG_SS
].Selector
);
3078 SOFT386_OPCODE_HANDLER(Soft386OpcodePopSs
)
3082 if (!Soft386StackPop(State
, &NewSelector
))
3084 /* Exception occurred */
3088 /* Call the internal API */
3089 return Soft386LoadSegment(State
, SOFT386_REG_SS
, LOWORD(NewSelector
));
3092 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbByteModrm
)
3094 UCHAR FirstValue
, SecondValue
, Result
;
3095 SOFT386_MOD_REG_RM ModRegRm
;
3096 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3097 INT Carry
= State
->Flags
.Cf
? 1 : 0;
3099 /* Make sure this is the right instruction */
3100 ASSERT((Opcode
& 0xFD) == 0x18);
3102 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3104 /* The ADSIZE prefix toggles the size */
3105 AddressSize
= !AddressSize
;
3108 /* Get the operands */
3109 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3111 /* Exception occurred */
3115 if (!Soft386ReadModrmByteOperands(State
,
3120 /* Exception occurred */
3124 /* Check if this is the instruction that writes to R/M */
3125 if (!(Opcode
& SOFT386_OPCODE_WRITE_REG
))
3127 /* Swap the order */
3128 FirstValue
^= SecondValue
;
3129 SecondValue
^= FirstValue
;
3130 FirstValue
^= SecondValue
;
3133 /* Calculate the result */
3134 Result
= FirstValue
- SecondValue
- Carry
;
3136 /* Update the flags */
3137 State
->Flags
.Cf
= FirstValue
< (SecondValue
+ 1);
3138 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) != (SecondValue
& SIGN_FLAG_BYTE
))
3139 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
3140 State
->Flags
.Af
= (FirstValue
& 0x0F) < ((SecondValue
+ 1) & 0x0F);
3141 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3142 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
3143 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3145 /* Write back the result */
3146 return Soft386WriteModrmByteOperands(State
,
3148 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3152 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbModrm
)
3154 SOFT386_MOD_REG_RM ModRegRm
;
3155 BOOLEAN OperandSize
, AddressSize
;
3156 INT Carry
= State
->Flags
.Cf
? 1 : 0;
3158 /* Make sure this is the right instruction */
3159 ASSERT((Opcode
& 0xFD) == 0x19);
3161 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3163 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3165 /* The ADSIZE prefix toggles the address size */
3166 AddressSize
= !AddressSize
;
3169 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
3171 /* The OPSIZE prefix toggles the operand size */
3172 OperandSize
= !OperandSize
;
3175 /* Get the operands */
3176 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3178 /* Exception occurred */
3182 /* Check the operand size */
3185 ULONG FirstValue
, SecondValue
, Result
;
3187 if (!Soft386ReadModrmDwordOperands(State
,
3192 /* Exception occurred */
3196 /* Check if this is the instruction that writes to R/M */
3197 if (!(Opcode
& SOFT386_OPCODE_WRITE_REG
))
3199 /* Swap the order */
3200 FirstValue
^= SecondValue
;
3201 SecondValue
^= FirstValue
;
3202 FirstValue
^= SecondValue
;
3205 /* Calculate the result */
3206 Result
= FirstValue
- SecondValue
- Carry
;
3208 /* Update the flags */
3209 State
->Flags
.Cf
= FirstValue
< (SecondValue
+ Carry
);
3210 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) != (SecondValue
& SIGN_FLAG_LONG
))
3211 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
3212 State
->Flags
.Af
= (FirstValue
& 0x0F) < ((SecondValue
+ 1) & 0x0F);
3213 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3214 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
3215 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3217 /* Write back the result */
3218 return Soft386WriteModrmDwordOperands(State
,
3220 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3225 USHORT FirstValue
, SecondValue
, Result
;
3227 if (!Soft386ReadModrmWordOperands(State
,
3232 /* Exception occurred */
3236 /* Check if this is the instruction that writes to R/M */
3237 if (!(Opcode
& SOFT386_OPCODE_WRITE_REG
))
3239 /* Swap the order */
3240 FirstValue
^= SecondValue
;
3241 SecondValue
^= FirstValue
;
3242 FirstValue
^= SecondValue
;
3245 /* Calculate the result */
3246 Result
= FirstValue
- SecondValue
- Carry
;
3248 /* Update the flags */
3249 State
->Flags
.Cf
= FirstValue
< (SecondValue
+ Carry
);
3250 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) != (SecondValue
& SIGN_FLAG_WORD
))
3251 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
3252 State
->Flags
.Af
= (FirstValue
& 0x0F) < ((SecondValue
+ 1) & 0x0F);
3253 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3254 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
3255 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3257 /* Write back the result */
3258 return Soft386WriteModrmWordOperands(State
,
3260 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3265 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbAl
)
3267 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3268 UCHAR SecondValue
, Result
;
3269 INT Carry
= State
->Flags
.Cf
? 1 : 0;
3271 /* Make sure this is the right instruction */
3272 ASSERT(Opcode
== 0x1C);
3274 if (State
->PrefixFlags
)
3276 /* This opcode doesn't take any prefixes */
3277 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3281 if (!Soft386FetchByte(State
, &SecondValue
))
3283 /* Exception occurred */
3287 /* Calculate the result */
3288 Result
= FirstValue
- SecondValue
- Carry
;
3290 /* Update the flags */
3291 State
->Flags
.Cf
= FirstValue
< (SecondValue
+ Carry
);
3292 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) != (SecondValue
& SIGN_FLAG_BYTE
))
3293 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
3294 State
->Flags
.Af
= (FirstValue
& 0x0F) < ((SecondValue
+ 1) & 0x0F);
3295 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3296 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
3297 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3299 /* Write back the result */
3300 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
3306 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbEax
)
3308 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3309 INT Carry
= State
->Flags
.Cf
? 1 : 0;
3311 /* Make sure this is the right instruction */
3312 ASSERT(Opcode
== 0x1D);
3314 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
3316 /* Invalid prefix */
3317 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3321 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
3323 /* The OPSIZE prefix toggles the size */
3329 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
3330 ULONG SecondValue
, Result
;
3332 if (!Soft386FetchDword(State
, &SecondValue
))
3334 /* Exception occurred */
3338 /* Calculate the result */
3339 Result
= FirstValue
- SecondValue
- Carry
;
3341 /* Update the flags */
3342 State
->Flags
.Cf
= FirstValue
< (SecondValue
+ Carry
);
3343 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) != (SecondValue
& SIGN_FLAG_LONG
))
3344 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
3345 State
->Flags
.Af
= (FirstValue
& 0x0F) < ((SecondValue
+ Carry
) & 0x0F);
3346 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3347 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
3348 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3350 /* Write back the result */
3351 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
3355 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
3356 USHORT SecondValue
, Result
;
3358 if (!Soft386FetchWord(State
, &SecondValue
))
3360 /* Exception occurred */
3364 /* Calculate the result */
3365 Result
= FirstValue
- SecondValue
- Carry
;
3367 /* Update the flags */
3368 State
->Flags
.Cf
= FirstValue
< (SecondValue
+ Carry
);
3369 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) != (SecondValue
& SIGN_FLAG_WORD
))
3370 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
3371 State
->Flags
.Af
= (FirstValue
& 0x0F) < ((SecondValue
+ Carry
) & 0x0F);
3372 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3373 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
3374 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3376 /* Write back the result */
3377 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
3384 SOFT386_OPCODE_HANDLER(Soft386OpcodePushDs
)
3386 /* Call the internal API */
3387 return Soft386StackPush(State
, State
->SegmentRegs
[SOFT386_REG_DS
].Selector
);
3390 SOFT386_OPCODE_HANDLER(Soft386OpcodePopDs
)
3394 if (!Soft386StackPop(State
, &NewSelector
))
3396 /* Exception occurred */
3400 /* Call the internal API */
3401 return Soft386LoadSegment(State
, SOFT386_REG_DS
, LOWORD(NewSelector
));
3404 SOFT386_OPCODE_HANDLER(Soft386OpcodeDaa
)
3406 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3407 BOOLEAN Carry
= State
->Flags
.Cf
;
3409 /* Clear the carry flag */
3410 State
->Flags
.Cf
= FALSE
;
3412 /* Check if the first BCD digit is invalid or there was a carry from it */
3413 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3416 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
+= 0x06;
3417 if (State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
< 0x06)
3419 /* A carry occurred */
3420 State
->Flags
.Cf
= TRUE
;
3423 /* Set the adjust flag */
3424 State
->Flags
.Af
= TRUE
;
3427 /* Check if the second BCD digit is invalid or there was a carry from it */
3428 if ((Value
> 0x99) || Carry
)
3431 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
+= 0x60;
3433 /* There was a carry */
3434 State
->Flags
.Cf
= TRUE
;
3440 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubByteModrm
)
3442 UCHAR FirstValue
, SecondValue
, Result
;
3443 SOFT386_MOD_REG_RM ModRegRm
;
3444 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3446 /* Make sure this is the right instruction */
3447 ASSERT((Opcode
& 0xED) == 0x28);
3449 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3451 /* The ADSIZE prefix toggles the size */
3452 AddressSize
= !AddressSize
;
3454 else if (State
->PrefixFlags
3455 & ~(SOFT386_PREFIX_ADSIZE
3456 | SOFT386_PREFIX_SEG
3457 | SOFT386_PREFIX_LOCK
))
3459 /* Invalid prefix */
3460 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3464 /* Get the operands */
3465 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3467 /* Exception occurred */
3471 if (!Soft386ReadModrmByteOperands(State
,
3476 /* Exception occurred */
3480 /* Check if this is the instruction that writes to R/M */
3481 if (!(Opcode
& SOFT386_OPCODE_WRITE_REG
))
3483 /* Swap the order */
3484 FirstValue
^= SecondValue
;
3485 SecondValue
^= FirstValue
;
3486 FirstValue
^= SecondValue
;
3489 /* Calculate the result */
3490 Result
= FirstValue
- SecondValue
;
3492 /* Update the flags */
3493 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3494 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) != (SecondValue
& SIGN_FLAG_BYTE
))
3495 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
3496 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3497 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3498 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
3499 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3501 /* Check if this is not a CMP */
3502 if (!(Opcode
& 0x10))
3504 /* Write back the result */
3505 return Soft386WriteModrmByteOperands(State
,
3507 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3512 /* Discard the result */
3517 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubModrm
)
3519 SOFT386_MOD_REG_RM ModRegRm
;
3520 BOOLEAN OperandSize
, AddressSize
;
3522 /* Make sure this is the right instruction */
3523 ASSERT((Opcode
& 0xED) == 0x29);
3525 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3527 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3529 /* The ADSIZE prefix toggles the address size */
3530 AddressSize
= !AddressSize
;
3533 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
3535 /* The OPSIZE prefix toggles the operand size */
3536 OperandSize
= !OperandSize
;
3539 if (State
->PrefixFlags
3540 & ~(SOFT386_PREFIX_ADSIZE
3541 | SOFT386_PREFIX_OPSIZE
3542 | SOFT386_PREFIX_SEG
3543 | SOFT386_PREFIX_LOCK
))
3545 /* Invalid prefix */
3546 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3550 /* Get the operands */
3551 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3553 /* Exception occurred */
3557 /* Check the operand size */
3560 ULONG FirstValue
, SecondValue
, Result
;
3562 if (!Soft386ReadModrmDwordOperands(State
,
3567 /* Exception occurred */
3571 /* Check if this is the instruction that writes to R/M */
3572 if (!(Opcode
& SOFT386_OPCODE_WRITE_REG
))
3574 /* Swap the order */
3575 FirstValue
^= SecondValue
;
3576 SecondValue
^= FirstValue
;
3577 FirstValue
^= SecondValue
;
3580 /* Calculate the result */
3581 Result
= FirstValue
- SecondValue
;
3583 /* Update the flags */
3584 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3585 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) != (SecondValue
& SIGN_FLAG_LONG
))
3586 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
3587 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3588 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3589 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
3590 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3592 /* Check if this is not a CMP */
3593 if (!(Opcode
& 0x10))
3595 /* Write back the result */
3596 return Soft386WriteModrmDwordOperands(State
,
3598 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3603 /* Discard the result */
3609 USHORT FirstValue
, SecondValue
, Result
;
3611 if (!Soft386ReadModrmWordOperands(State
,
3616 /* Exception occurred */
3620 /* Check if this is the instruction that writes to R/M */
3621 if (!(Opcode
& SOFT386_OPCODE_WRITE_REG
))
3623 /* Swap the order */
3624 FirstValue
^= SecondValue
;
3625 SecondValue
^= FirstValue
;
3626 FirstValue
^= SecondValue
;
3629 /* Calculate the result */
3630 Result
= FirstValue
- SecondValue
;
3632 /* Update the flags */
3633 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3634 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) != (SecondValue
& SIGN_FLAG_WORD
))
3635 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
3636 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3637 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3638 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
3639 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3641 /* Check if this is not a CMP */
3642 if (!(Opcode
& 0x10))
3644 /* Write back the result */
3645 return Soft386WriteModrmWordOperands(State
,
3647 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3652 /* Discard the result */
3658 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubAl
)
3660 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3661 UCHAR SecondValue
, Result
;
3663 /* Make sure this is the right instruction */
3664 ASSERT((Opcode
& 0xEF) == 0x2C);
3666 if (State
->PrefixFlags
)
3668 /* This opcode doesn't take any prefixes */
3669 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3673 if (!Soft386FetchByte(State
, &SecondValue
))
3675 /* Exception occurred */
3679 /* Calculate the result */
3680 Result
= FirstValue
- SecondValue
;
3682 /* Update the flags */
3683 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3684 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) != (SecondValue
& SIGN_FLAG_BYTE
))
3685 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
3686 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3687 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3688 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
3689 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3691 /* Check if this is not a CMP */
3692 if (!(Opcode
& 0x10))
3694 /* Write back the result */
3695 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
3701 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubEax
)
3703 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3705 /* Make sure this is the right instruction */
3706 ASSERT((Opcode
& 0xEF) == 0x2D);
3708 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
3710 /* Invalid prefix */
3711 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3715 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
3717 /* The OPSIZE prefix toggles the size */
3723 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
3724 ULONG SecondValue
, Result
;
3726 if (!Soft386FetchDword(State
, &SecondValue
))
3728 /* Exception occurred */
3732 /* Calculate the result */
3733 Result
= FirstValue
- SecondValue
;
3735 /* Update the flags */
3736 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3737 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) != (SecondValue
& SIGN_FLAG_LONG
))
3738 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
3739 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3740 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3741 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
3742 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3744 /* Check if this is not a CMP */
3745 if (!(Opcode
& 0x10))
3747 /* Write back the result */
3748 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
3753 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
3754 USHORT SecondValue
, Result
;
3756 if (!Soft386FetchWord(State
, &SecondValue
))
3758 /* Exception occurred */
3762 /* Calculate the result */
3763 Result
= FirstValue
- SecondValue
;
3765 /* Update the flags */
3766 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3767 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) != (SecondValue
& SIGN_FLAG_WORD
))
3768 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
3769 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3770 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3771 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
3772 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3774 /* Check if this is not a CMP */
3775 if (!(Opcode
& 0x10))
3777 /* Write back the result */
3778 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
3785 SOFT386_OPCODE_HANDLER(Soft386OpcodeDas
)
3787 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3788 BOOLEAN Carry
= State
->Flags
.Cf
;
3790 /* Clear the carry flag */
3791 State
->Flags
.Cf
= FALSE
;
3793 /* Check if the first BCD digit is invalid or there was a borrow */
3794 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3797 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
-= 0x06;
3798 if (State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
> 0xFB)
3800 /* A borrow occurred */
3801 State
->Flags
.Cf
= TRUE
;
3804 /* Set the adjust flag */
3805 State
->Flags
.Af
= TRUE
;
3808 /* Check if the second BCD digit is invalid or there was a borrow */
3809 if ((Value
> 0x99) || Carry
)
3812 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
-= 0x60;
3814 /* There was a borrow */
3815 State
->Flags
.Cf
= TRUE
;
3821 SOFT386_OPCODE_HANDLER(Soft386OpcodeAaa
)
3823 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3826 * Check if the value in AL is not a valid BCD digit,
3827 * or there was a carry from the lowest 4 bits of AL
3829 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3832 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
+= 0x06;
3833 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
++;
3836 State
->Flags
.Cf
= State
->Flags
.Af
= TRUE
;
3840 /* Clear CF and AF */
3841 State
->Flags
.Cf
= State
->Flags
.Af
= FALSE
;
3844 /* Keep only the lowest 4 bits of AL */
3845 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
&= 0x0F;
3850 SOFT386_OPCODE_HANDLER(Soft386OpcodeAas
)
3852 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3855 * Check if the value in AL is not a valid BCD digit,
3856 * or there was a borrow from the lowest 4 bits of AL
3858 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3861 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
-= 0x06;
3862 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
--;
3865 State
->Flags
.Cf
= State
->Flags
.Af
= TRUE
;
3869 /* Clear CF and AF */
3870 State
->Flags
.Cf
= State
->Flags
.Af
= FALSE
;
3873 /* Keep only the lowest 4 bits of AL */
3874 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
&= 0x0F;
3879 SOFT386_OPCODE_HANDLER(Soft386OpcodePushAll
)
3882 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3883 SOFT386_REG SavedEsp
= State
->GeneralRegs
[SOFT386_REG_ESP
];
3885 /* Make sure this is the right instruction */
3886 ASSERT(Opcode
== 0x60);
3888 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
3890 /* The OPSIZE prefix toggles the size */
3894 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
3896 /* Invalid prefix */
3897 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3901 /* Push all the registers in order */
3902 for (i
= 0; i
< SOFT386_NUM_GEN_REGS
; i
++)
3904 if (i
== SOFT386_REG_ESP
)
3906 /* Use the saved ESP instead */
3907 if (!Soft386StackPush(State
, Size
? SavedEsp
.Long
: SavedEsp
.LowWord
))
3909 /* Exception occurred */
3915 /* Push the register */
3916 if (!Soft386StackPush(State
, Size
? State
->GeneralRegs
[i
].Long
3917 : State
->GeneralRegs
[i
].LowWord
))
3919 /* Exception occurred */
3928 SOFT386_OPCODE_HANDLER(Soft386OpcodePopAll
)
3931 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3934 /* Make sure this is the right instruction */
3935 ASSERT(Opcode
== 0x61);
3937 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
3939 /* The OPSIZE prefix toggles the size */
3943 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
3945 /* Invalid prefix */
3946 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3950 /* Pop all the registers in reverse order */
3951 for (i
= SOFT386_NUM_GEN_REGS
- 1; i
>= 0; i
--)
3954 if (!Soft386StackPop(State
, &Value
))
3956 /* Exception occurred */
3960 /* Don't modify ESP */
3961 if (i
!= SOFT386_REG_ESP
)
3963 if (Size
) State
->GeneralRegs
[i
].Long
= Value
;
3964 else State
->GeneralRegs
[i
].LowWord
= LOWORD(Value
);
3971 SOFT386_OPCODE_HANDLER(Soft386OpcodeBound
)
3973 // TODO: NOT IMPLEMENTED
3979 SOFT386_OPCODE_HANDLER(Soft386OpcodeArpl
)
3981 USHORT FirstValue
, SecondValue
;
3982 SOFT386_MOD_REG_RM ModRegRm
;
3983 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3985 if (!(State
->ControlRegisters
[SOFT386_REG_CR0
] & SOFT386_CR0_PE
)
3987 || (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
))
3989 /* Cannot be used in real mode or with a LOCK prefix */
3990 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3994 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3996 /* The ADSIZE prefix toggles the size */
3997 AddressSize
= !AddressSize
;
4000 /* Get the operands */
4001 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
4003 /* Exception occurred */
4007 /* Read the operands */
4008 if (!Soft386ReadModrmWordOperands(State
,
4013 /* Exception occurred */
4017 /* Check if the RPL needs adjusting */
4018 if ((SecondValue
& 3) < (FirstValue
& 3))
4020 /* Adjust the RPL */
4022 SecondValue
|= FirstValue
& 3;
4025 State
->Flags
.Zf
= TRUE
;
4027 /* Write back the result */
4028 return Soft386WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, SecondValue
);
4033 State
->Flags
.Zf
= FALSE
;
4038 SOFT386_OPCODE_HANDLER(Soft386OpcodePushImm
)
4040 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4042 /* Make sure this is the right instruction */
4043 ASSERT(Opcode
== 0x68);
4045 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4047 /* Invalid prefix */
4048 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4052 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
4054 /* The OPSIZE prefix toggles the size */
4062 if (!Soft386FetchDword(State
, &Data
))
4064 /* Exception occurred */
4068 /* Call the internal API */
4069 return Soft386StackPush(State
, Data
);
4075 if (!Soft386FetchWord(State
, &Data
))
4077 /* Exception occurred */
4081 /* Call the internal API */
4082 return Soft386StackPush(State
, Data
);
4086 SOFT386_OPCODE_HANDLER(Soft386OpcodeImulModrmImm
)
4088 BOOLEAN OperandSize
, AddressSize
;
4089 SOFT386_MOD_REG_RM ModRegRm
;
4093 /* Make sure this is the right instruction */
4094 ASSERT((Opcode
& 0xFD) == 0x69);
4096 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4098 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
4100 /* The ADSIZE prefix toggles the address size */
4101 AddressSize
= !AddressSize
;
4104 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
4106 /* The OPSIZE prefix toggles the operand size */
4107 OperandSize
= !OperandSize
;
4110 /* Fetch the parameters */
4111 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
4113 /* Exception occurred */
4121 /* Fetch the immediate operand */
4122 if (!Soft386FetchByte(State
, (PUCHAR
)&Byte
))
4124 /* Exception occurred */
4128 Multiplier
= (LONG
)Byte
;
4136 /* Fetch the immediate operand */
4137 if (!Soft386FetchDword(State
, (PULONG
)&Dword
))
4139 /* Exception occurred */
4149 /* Fetch the immediate operand */
4150 if (!Soft386FetchWord