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(State
, (PUSHORT
)&Word
))
4152 /* Exception occurred */
4156 Multiplier
= (LONG
)Word
;
4162 LONG RegValue
, Multiplicand
;
4164 /* Read the operands */
4165 if (!Soft386ReadModrmDwordOperands(State
,
4168 (PULONG
)&Multiplicand
))
4170 /* Exception occurred */
4175 Product
= (LONGLONG
)Multiplicand
* (LONGLONG
)Multiplier
;
4179 SHORT RegValue
, Multiplicand
;
4181 /* Read the operands */
4182 if (!Soft386ReadModrmWordOperands(State
,
4185 (PUSHORT
)&Multiplicand
))
4187 /* Exception occurred */
4192 Product
= (LONGLONG
)Multiplicand
* (LONGLONG
)Multiplier
;
4195 /* Check for carry/overflow */
4196 if ((Product
< LONG_MIN
) || (Product
> LONG_MAX
))
4198 State
->Flags
.Cf
= State
->Flags
.Of
= TRUE
;
4200 else State
->Flags
.Cf
= State
->Flags
.Of
= FALSE
;
4202 /* Write-back the result */
4203 return Soft386WriteModrmDwordOperands(State
,
4206 (ULONG
)((LONG
)Product
));
4209 SOFT386_OPCODE_HANDLER(Soft386OpcodePushByteImm
)
4213 /* Make sure this is the right instruction */
4214 ASSERT(Opcode
== 0x6A);
4216 if (!Soft386FetchByte(State
, &Data
))
4218 /* Exception occurred */
4222 /* Call the internal API */
4223 return Soft386StackPush(State
, Data
);
4226 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovByteModrm
)
4228 UCHAR FirstValue
, SecondValue
, Result
;
4229 SOFT386_MOD_REG_RM ModRegRm
;
4230 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4232 /* Make sure this is the right instruction */
4233 ASSERT((Opcode
& 0xFD) == 0x88);
4235 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
4237 /* The ADSIZE prefix toggles the size */
4238 AddressSize
= !AddressSize
;
4240 else if (State
->PrefixFlags
4241 & ~(SOFT386_PREFIX_ADSIZE
4242 | SOFT386_PREFIX_SEG
4243 | SOFT386_PREFIX_LOCK
))
4245 /* Invalid prefix */
4246 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4250 /* Get the operands */
4251 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
4253 /* Exception occurred */
4257 if (!Soft386ReadModrmByteOperands(State
,
4262 /* Exception occurred */
4266 if (Opcode
& SOFT386_OPCODE_WRITE_REG
) Result
= SecondValue
;
4267 else Result
= FirstValue
;
4269 /* Write back the result */
4270 return Soft386WriteModrmByteOperands(State
,
4272 Opcode
& SOFT386_OPCODE_WRITE_REG
,
4277 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovModrm
)
4279 SOFT386_MOD_REG_RM ModRegRm
;
4280 BOOLEAN OperandSize
, AddressSize
;
4282 /* Make sure this is the right instruction */
4283 ASSERT((Opcode
& 0xFD) == 0x89);
4285 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4287 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
4289 /* The ADSIZE prefix toggles the address size */
4290 AddressSize
= !AddressSize
;
4293 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
4295 /* The OPSIZE prefix toggles the operand size */
4296 OperandSize
= !OperandSize
;
4299 if (State
->PrefixFlags
4300 & ~(SOFT386_PREFIX_ADSIZE
4301 | SOFT386_PREFIX_OPSIZE
4302 | SOFT386_PREFIX_SEG
4303 | SOFT386_PREFIX_LOCK
))
4305 /* Invalid prefix */
4306 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4310 /* Get the operands */
4311 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
4313 /* Exception occurred */
4317 /* Check the operand size */
4320 ULONG FirstValue
, SecondValue
, Result
;
4322 if (!Soft386ReadModrmDwordOperands(State
,
4327 /* Exception occurred */
4331 if (Opcode
& SOFT386_OPCODE_WRITE_REG
) Result
= SecondValue
;
4332 else Result
= FirstValue
;
4334 /* Write back the result */
4335 return Soft386WriteModrmDwordOperands(State
,
4337 Opcode
& SOFT386_OPCODE_WRITE_REG
,
4342 USHORT FirstValue
, SecondValue
, Result
;
4344 if (!Soft386ReadModrmWordOperands(State
,
4349 /* Exception occurred */
4353 if (Opcode
& SOFT386_OPCODE_WRITE_REG
) Result
= SecondValue
;
4354 else Result
= FirstValue
;
4356 /* Write back the result */
4357 return Soft386WriteModrmWordOperands(State
,
4359 Opcode
& SOFT386_OPCODE_WRITE_REG
,
4364 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovStoreSeg
)
4366 BOOLEAN OperandSize
, AddressSize
;
4367 SOFT386_MOD_REG_RM ModRegRm
;
4369 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4371 /* Make sure this is the right instruction */
4372 ASSERT(Opcode
== 0x8C);
4374 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
4376 /* The ADSIZE prefix toggles the address size */
4377 AddressSize
= !AddressSize
;
4380 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
4382 /* The OPSIZE prefix toggles the operand size */
4383 OperandSize
= !OperandSize
;
4386 /* Get the operands */
4387 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
4389 /* Exception occurred */
4393 if (ModRegRm
.Register
>= SOFT386_NUM_SEG_REGS
)
4396 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4402 return Soft386WriteModrmDwordOperands(State
,
4405 State
->SegmentRegs
[ModRegRm
.Register
].Selector
);
4409 return Soft386WriteModrmWordOperands(State
,
4412 State
->SegmentRegs
[ModRegRm
.Register
].Selector
);
4416 SOFT386_OPCODE_HANDLER(Soft386OpcodeLea
)
4418 SOFT386_MOD_REG_RM ModRegRm
;
4419 BOOLEAN OperandSize
, AddressSize
;
4421 /* Make sure this is the right instruction */
4422 ASSERT(Opcode
== 0x8D);
4424 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4426 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
4428 /* The ADSIZE prefix toggles the address size */
4429 AddressSize
= !AddressSize
;
4432 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
4434 /* The OPSIZE prefix toggles the operand size */
4435 OperandSize
= !OperandSize
;
4438 /* Get the operands */
4439 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
4441 /* Exception occurred */
4445 /* The second operand must be memory */
4446 if (!ModRegRm
.Memory
)
4449 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4453 /* Write the address to the register */
4456 return Soft386WriteModrmDwordOperands(State
,
4459 ModRegRm
.MemoryAddress
);
4463 return Soft386WriteModrmWordOperands(State
,
4466 ModRegRm
.MemoryAddress
);
4471 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovLoadSeg
)
4473 BOOLEAN OperandSize
, AddressSize
;
4474 SOFT386_MOD_REG_RM ModRegRm
;
4476 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4478 /* Make sure this is the right instruction */
4479 ASSERT(Opcode
== 0x8E);
4481 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
4483 /* The ADSIZE prefix toggles the address size */
4484 AddressSize
= !AddressSize
;
4487 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
4489 /* The OPSIZE prefix toggles the operand size */
4490 OperandSize
= !OperandSize
;
4493 /* Get the operands */
4494 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
4496 /* Exception occurred */
4500 if ((ModRegRm
.Register
>= SOFT386_NUM_SEG_REGS
)
4501 || ((SOFT386_SEG_REGS
)ModRegRm
.Register
== SOFT386_REG_CS
))
4504 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4510 ULONG Dummy
, Selector
;
4512 if (!Soft386ReadModrmDwordOperands(State
, &ModRegRm
, &Dummy
, &Selector
))
4514 /* Exception occurred */
4518 return Soft386LoadSegment(State
, ModRegRm
.Register
, LOWORD(Selector
));
4522 USHORT Dummy
, Selector
;
4524 if (!Soft386ReadModrmWordOperands(State
, &ModRegRm
, &Dummy
, &Selector
))
4526 /* Exception occurred */
4530 return Soft386LoadSegment(State
, ModRegRm
.Register
, Selector
);
4534 SOFT386_OPCODE_HANDLER(Soft386OpcodeCwde
)
4536 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4538 /* Make sure this is the right instruction */
4539 ASSERT(Opcode
== 0x98);
4541 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
4543 /* The OPSIZE prefix toggles the size */
4547 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4549 /* Invalid prefix */
4550 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4556 /* Sign extend AX to EAX */
4557 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= MAKELONG
4559 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
,
4560 (State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
& SIGN_FLAG_WORD
)
4566 /* Sign extend AL to AX */
4567 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
=
4568 (State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
& SIGN_FLAG_BYTE
)
4575 SOFT386_OPCODE_HANDLER(Soft386OpcodeCdq
)
4577 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4579 /* Make sure this is the right instruction */
4580 ASSERT(Opcode
== 0x99);
4582 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
4584 /* The OPSIZE prefix toggles the size */
4588 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4590 /* Invalid prefix */
4591 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4597 /* Sign extend EAX to EDX:EAX */
4598 State
->GeneralRegs
[SOFT386_REG_EDX
].Long
=
4599 (State
->GeneralRegs
[SOFT386_REG_EAX
].Long
& SIGN_FLAG_LONG
)
4600 ? 0xFFFFFFFF : 0x00000000;
4604 /* Sign extend AX to DX:AX */
4605 State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
=
4606 (State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
& SIGN_FLAG_WORD
)
4613 SOFT386_OPCODE_HANDLER(Soft386OpcodeCallAbs
)
4615 // TODO: NOT IMPLEMENTED
4621 SOFT386_OPCODE_HANDLER(Soft386OpcodeWait
)
4623 // TODO: NOT IMPLEMENTED
4629 SOFT386_OPCODE_HANDLER(Soft386OpcodePushFlags
)
4631 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4633 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4635 /* Invalid prefix */
4636 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4640 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
4642 /* This OPSIZE prefix toggles the size */
4646 /* Check for VM86 mode when IOPL is not 3 */
4647 if (State
->Flags
.Vm
&& (State
->Flags
.Iopl
!= 3))
4649 /* Call the VM86 monitor */
4650 Soft386ExceptionWithErrorCode(State
, SOFT386_EXCEPTION_GP
, 0);
4654 /* Push the flags */
4655 if (Size
) return Soft386StackPush(State
, State
->Flags
.Long
);
4656 else return Soft386StackPush(State
, LOWORD(State
->Flags
.Long
));
4659 SOFT386_OPCODE_HANDLER(Soft386OpcodePopFlags
)
4661 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4662 INT Cpl
= Soft386GetCurrentPrivLevel(State
);
4665 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4667 /* Invalid prefix */
4668 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4672 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
4674 /* This OPSIZE prefix toggles the size */
4678 /* Pop the new flags */
4679 if (!Soft386StackPop(State
, &NewFlags
))
4681 /* Exception occurred */
4685 if (!State
->Flags
.Vm
)
4687 /* Check the current privilege level */
4695 /* Memorize the old state of RF */
4696 BOOLEAN OldRf
= State
->Flags
.Rf
;
4698 State
->Flags
.Long
= NewFlags
;
4700 /* Restore VM and RF */
4701 State
->Flags
.Vm
= FALSE
;
4702 State
->Flags
.Rf
= OldRf
;
4704 /* Clear VIF and VIP */
4705 State
->Flags
.Vif
= State
->Flags
.Vip
= FALSE
;
4707 else State
->Flags
.LowWord
= LOWORD(NewFlags
);
4709 /* Restore the reserved bits */
4710 State
->Flags
.AlwaysSet
= TRUE
;
4711 State
->Flags
.Reserved0
= FALSE
;
4712 State
->Flags
.Reserved1
= FALSE
;
4718 /* Memorize the old state of IF and IOPL */
4719 BOOLEAN OldIf
= State
->Flags
.If
;
4720 UINT OldIopl
= State
->Flags
.Iopl
;
4725 /* Memorize the old state of RF */
4726 BOOLEAN OldRf
= State
->Flags
.Rf
;
4728 State
->Flags
.Long
= NewFlags
;
4730 /* Restore VM and RF */
4731 State
->Flags
.Vm
= FALSE
;
4732 State
->Flags
.Rf
= OldRf
;
4734 /* Clear VIF and VIP */
4735 State
->Flags
.Vif
= State
->Flags
.Vip
= FALSE
;
4737 else State
->Flags
.LowWord
= LOWORD(NewFlags
);
4739 /* Restore the reserved bits and IOPL */
4740 State
->Flags
.AlwaysSet
= TRUE
;
4741 State
->Flags
.Reserved0
= FALSE
;
4742 State
->Flags
.Reserved1
= FALSE
;
4743 State
->Flags
.Iopl
= OldIopl
;
4745 /* Check if the user doesn't have the privilege to change IF */
4746 if (Cpl
> State
->Flags
.Iopl
)
4749 State
->Flags
.If
= OldIf
;
4755 /* Check the IOPL */
4756 if (State
->Flags
.Iopl
== 3)
4760 /* Memorize the old state of RF, VIF and VIP */
4761 BOOLEAN OldRf
= State
->Flags
.Rf
;
4762 BOOLEAN OldVif
= State
->Flags
.Vif
;
4763 BOOLEAN OldVip
= State
->Flags
.Vip
;
4765 State
->Flags
.Long
= NewFlags
;
4767 /* Restore VM, RF, VIF and VIP */
4768 State
->Flags
.Vm
= TRUE
;
4769 State
->Flags
.Rf
= OldRf
;
4770 State
->Flags
.Vif
= OldVif
;
4771 State
->Flags
.Vip
= OldVip
;
4773 else State
->Flags
.LowWord
= LOWORD(NewFlags
);
4775 /* Restore the reserved bits and IOPL */
4776 State
->Flags
.AlwaysSet
= TRUE
;
4777 State
->Flags
.Reserved0
= FALSE
;
4778 State
->Flags
.Reserved1
= FALSE
;
4779 State
->Flags
.Iopl
= 3;
4783 /* Call the VM86 monitor */
4784 Soft386ExceptionWithErrorCode(State
, SOFT386_EXCEPTION_GP
, 0);
4792 SOFT386_OPCODE_HANDLER(Soft386OpcodeSahf
)
4794 /* Make sure this is the right instruction */
4795 ASSERT(Opcode
== 0x9E);
4797 /* Set the low-order byte of FLAGS to AH */
4798 State
->Flags
.Long
&= 0xFFFFFF00;
4799 State
->Flags
.Long
|= State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
;
4801 /* Restore the reserved bits of FLAGS */
4802 State
->Flags
.AlwaysSet
= TRUE
;
4803 State
->Flags
.Reserved0
= State
->Flags
.Reserved1
= FALSE
;
4808 SOFT386_OPCODE_HANDLER(Soft386OpcodeLahf
)
4810 /* Make sure this is the right instruction */
4811 ASSERT(Opcode
== 0x9F);
4813 /* Set AH to the low-order byte of FLAGS */
4814 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
= LOBYTE(State
->Flags
.Long
);
4819 SOFT386_OPCODE_HANDLER(Soft386OpcodeRet
)
4821 ULONG ReturnAddress
;
4822 USHORT BytesToPop
= 0;
4823 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4825 /* Make sure this is the right instruction */
4826 ASSERT((Opcode
& 0xFE) == 0xC2);
4828 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4830 /* Invalid prefix */
4831 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4835 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
4837 /* The OPSIZE prefix toggles the size */
4843 /* Fetch the number of bytes to pop after the return */
4844 if (!Soft386FetchWord(State
, &BytesToPop
)) return FALSE
;
4847 /* Pop the return address */
4848 if (!Soft386StackPop(State
, &ReturnAddress
)) return FALSE
;
4850 /* Return to the calling procedure, and if necessary, pop the parameters */
4853 State
->InstPtr
.Long
= ReturnAddress
;
4854 State
->GeneralRegs
[SOFT386_REG_ESP
].Long
+= BytesToPop
;
4858 State
->InstPtr
.LowWord
= LOWORD(ReturnAddress
);
4859 State
->GeneralRegs
[SOFT386_REG_ESP
].LowWord
+= BytesToPop
;
4865 SOFT386_OPCODE_HANDLER(Soft386OpcodeLdsLes
)
4867 UCHAR FarPointer
[6];
4868 BOOLEAN OperandSize
, AddressSize
;
4869 SOFT386_MOD_REG_RM ModRegRm
;
4871 /* Make sure this is the right instruction */
4872 ASSERT((Opcode
& 0xFE) == 0xC4);
4874 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4876 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
4878 /* The ADSIZE prefix toggles the size */
4879 AddressSize
= !AddressSize
;
4882 /* Get the operands */
4883 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
4885 /* Exception occurred */
4889 if (!ModRegRm
.Memory
)
4891 /* Check if this is a BOP and the host supports BOPs */
4892 if ((Opcode
== 0xC4)
4893 && (ModRegRm
.Register
== SOFT386_REG_EAX
)
4894 && (ModRegRm
.SecondRegister
== SOFT386_REG_ESP
)
4895 && (State
->BopCallback
!= NULL
))
4899 /* Fetch the BOP code */
4900 if (!Soft386FetchWord(State
, &BopCode
))
4902 /* Exception occurred */
4906 /* Call the BOP handler */
4907 State
->BopCallback(State
, BopCode
);
4909 /* Return success */
4914 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4918 if (!Soft386ReadMemory(State
,
4919 (State
->PrefixFlags
& SOFT386_PREFIX_SEG
)
4920 ? State
->SegmentOverride
: SOFT386_REG_DS
,
4921 ModRegRm
.MemoryAddress
,
4924 OperandSize
? 6 : 4))
4926 /* Exception occurred */
4932 ULONG Offset
= *((PULONG
)FarPointer
);
4933 USHORT Segment
= *((PUSHORT
)&FarPointer
[sizeof(ULONG
)]);
4935 /* Set the register to the offset */
4936 State
->GeneralRegs
[ModRegRm
.Register
].Long
= Offset
;
4938 /* Load the segment */
4939 return Soft386LoadSegment(State
,
4941 ? SOFT386_REG_ES
: SOFT386_REG_DS
,
4946 USHORT Offset
= *((PUSHORT
)FarPointer
);
4947 USHORT Segment
= *((PUSHORT
)&FarPointer
[sizeof(USHORT
)]);
4949 /* Set the register to the offset */
4950 State
->GeneralRegs
[ModRegRm
.Register
].LowWord
= Offset
;
4952 /* Load the segment */
4953 return Soft386LoadSegment(State
,
4955 ? SOFT386_REG_ES
: SOFT386_REG_DS
,
4960 SOFT386_OPCODE_HANDLER(Soft386OpcodeEnter
)
4963 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4966 SOFT386_REG FramePointer
;
4968 /* Make sure this is the right instruction */
4969 ASSERT(Opcode
== 0xC8);
4971 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4973 /* Invalid prefix */
4974 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4978 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
4980 /* The OPSIZE prefix toggles the size */
4984 if (!Soft386FetchWord(State
, &FrameSize
))
4986 /* Exception occurred */
4990 if (!Soft386FetchByte(State
, &NestingLevel
))
4992 /* Exception occurred */
4997 if (!Soft386StackPush(State
, State
->GeneralRegs
[SOFT386_REG_EBP
].Long
))
4999 /* Exception occurred */
5004 FramePointer
= State
->GeneralRegs
[SOFT386_REG_ESP
];
5006 /* Set up the nested procedure stacks */
5007 for (i
= 1; i
< NestingLevel
; i
++)
5011 State
->GeneralRegs
[SOFT386_REG_EBP
].Long
-= 4;
5012 Soft386StackPush(State
, State
->GeneralRegs
[SOFT386_REG_EBP
].Long
);
5016 State
->GeneralRegs
[SOFT386_REG_EBP
].LowWord
-= 2;
5017 Soft386StackPush(State
, State
->GeneralRegs
[SOFT386_REG_EBP
].LowWord
);
5021 if (NestingLevel
> 0) Soft386StackPush(State
, FramePointer
.Long
);
5023 /* Set EBP to the frame pointer */
5024 State
->GeneralRegs
[SOFT386_REG_EBP
] = FramePointer
;
5026 /* Reserve space for the frame */
5027 if (Size
) State
->GeneralRegs
[SOFT386_REG_ESP
].Long
-= (ULONG
)FrameSize
;
5028 else State
->GeneralRegs
[SOFT386_REG_ESP
].LowWord
-= FrameSize
;
5033 SOFT386_OPCODE_HANDLER(Soft386OpcodeLeave
)
5035 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
5037 /* Make sure this is the right instruction */
5038 ASSERT(Opcode
== 0xC9);
5040 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
5042 /* Invalid prefix */
5043 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
5047 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
5049 /* The OPSIZE prefix toggles the size */
5055 /* Set the stack pointer (ESP) to the base pointer (EBP) */
5056 State
->GeneralRegs
[SOFT386_REG_ESP
].Long
= State
->GeneralRegs
[SOFT386_REG_EBP
].Long
;
5058 /* Pop the saved base pointer from the stack */
5059 return Soft386StackPop(State
, &State
->GeneralRegs
[SOFT386_REG_EBP
].Long
);
5065 /* Set the stack pointer (SP) to the base pointer (BP) */
5066 State
->GeneralRegs
[SOFT386_REG_ESP
].LowWord
= State
->GeneralRegs
[SOFT386_REG_EBP
].LowWord
;
5068 /* Pop the saved base pointer from the stack */
5069 if (Soft386StackPop(State
, &Value
))
5071 State
->GeneralRegs
[SOFT386_REG_EBP
].LowWord
= LOWORD(Value
);
5078 SOFT386_OPCODE_HANDLER(Soft386OpcodeRetFarImm
)
5080 // TODO: NOT IMPLEMENTED
5086 SOFT386_OPCODE_HANDLER(Soft386OpcodeRetFar
)
5088 // TODO: NOT IMPLEMENTED
5094 SOFT386_OPCODE_HANDLER(Soft386OpcodeInt
)
5097 SOFT386_IDT_ENTRY IdtEntry
;
5103 /* This is the INT3 instruction */
5110 /* Fetch the interrupt number */
5111 if (!Soft386FetchByte(State
, &IntNum
))
5113 /* Exception occurred */
5122 /* Don't do anything if OF is cleared */
5123 if (!State
->Flags
.Of
) return TRUE
;
5126 IntNum
= SOFT386_EXCEPTION_OF
;
5133 /* Should not happen */
5138 /* Get the interrupt vector */
5139 if (!Soft386GetIntVector(State
, IntNum
, &IdtEntry
))
5141 /* Exception occurred */
5145 /* Perform the interrupt */
5146 if (!Soft386InterruptInternal(State
,
5148 MAKELONG(IdtEntry
.Offset
, IdtEntry
.OffsetHigh
),
5151 /* Exception occurred */
5158 SOFT386_OPCODE_HANDLER(Soft386OpcodeIret
)
5161 ULONG InstPtr
, CodeSel
, StackPtr
, StackSel
;
5162 SOFT386_FLAGS_REG NewFlags
;
5163 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
5165 /* Make sure this is the right instruction */
5166 ASSERT(Opcode
== 0xCF);
5168 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
5170 /* Invalid prefix */
5171 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
5175 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
5177 /* The OPSIZE prefix toggles the size */
5182 if (!Soft386StackPop(State
, &InstPtr
))
5184 /* Exception occurred */
5189 if (!Soft386StackPop(State
, &CodeSel
))
5191 /* Exception occurred */
5196 if (!Soft386StackPop(State
, &NewFlags
.Long
))
5198 /* Exception occurred */
5202 /* Check for protected mode */
5203 if (State
->ControlRegisters
[SOFT386_REG_CR0
] & SOFT386_CR0_PE
)
5205 INT Cpl
= Soft386GetCurrentPrivLevel(State
);
5207 if (State
->Flags
.Vm
)
5209 /* Return from VM86 mode */
5211 /* Check the IOPL */
5212 if (State
->Flags
.Iopl
== 3)
5215 State
->InstPtr
.Long
= LOWORD(InstPtr
);
5218 if (!Soft386LoadSegment(State
, SOFT386_REG_CS
, CodeSel
))
5220 /* Exception occurred */
5224 /* Set the new flags */
5225 if (Size
) State
->Flags
.Long
= NewFlags
.Long
& REAL_MODE_FLAGS_MASK
;
5226 else State
->Flags
.LowWord
= NewFlags
.LowWord
& REAL_MODE_FLAGS_MASK
;
5227 State
->Flags
.AlwaysSet
= State
->Flags
.Vm
= TRUE
;
5228 State
->Flags
.Iopl
= 3;
5232 /* Call the VM86 monitor */
5233 Soft386ExceptionWithErrorCode(State
, SOFT386_EXCEPTION_GP
, 0);
5240 if (State
->Flags
.Nt
)
5242 /* Nested task return */
5250 /* Return to VM86 mode */
5251 ULONG Es
, Ds
, Fs
, Gs
;
5253 /* Pop ESP, SS, ES, FS, GS */
5254 if (!Soft386StackPop(State
, &StackPtr
)) return FALSE
;
5255 if (!Soft386StackPop(State
, &StackSel
)) return FALSE
;
5256 if (!Soft386StackPop(State
, &Es
)) return FALSE
;
5257 if (!Soft386StackPop(State
, &Ds
)) return FALSE
;
5258 if (!Soft386StackPop(State
, &Fs
)) return FALSE
;
5259 if (!Soft386StackPop(State
, &Gs
)) return FALSE
;
5261 /* Set the new IP */
5262 State
->InstPtr
.Long
= LOWORD(InstPtr
);
5264 /* Set the new flags */
5265 if (Size
) State
->Flags
.Long
= NewFlags
.Long
& REAL_MODE_FLAGS_MASK
;
5266 else State
->Flags
.LowWord
= NewFlags
.LowWord
& REAL_MODE_FLAGS_MASK
;
5267 State
->Flags
.AlwaysSet
= State
->Flags
.Vm
= TRUE
;
5269 /* Load the new segments */
5270 if (!Soft386LoadSegment(State
, SOFT386_REG_CS
, CodeSel
)) return FALSE
;
5271 if (!Soft386LoadSegment(State
, SOFT386_REG_SS
, StackSel
)) return FALSE
;
5272 if (!Soft386LoadSegment(State
, SOFT386_REG_ES
, Es
)) return FALSE
;
5273 if (!Soft386LoadSegment(State
, SOFT386_REG_DS
, Ds
)) return FALSE
;
5274 if (!Soft386LoadSegment(State
, SOFT386_REG_FS
, Fs
)) return FALSE
;
5275 if (!Soft386LoadSegment(State
, SOFT386_REG_GS
, Gs
)) return FALSE
;
5280 /* Load the new CS */
5281 if (!Soft386LoadSegment(State
, SOFT386_REG_CS
, CodeSel
))
5283 /* Exception occurred */
5288 if (Size
) State
->InstPtr
.Long
= InstPtr
;
5289 else State
->InstPtr
.LowWord
= LOWORD(InstPtr
);
5291 if (GET_SEGMENT_RPL(CodeSel
) > Cpl
)
5294 if (!Soft386StackPop(State
, &StackPtr
))
5301 if (!Soft386StackPop(State
, &StackSel
))
5308 if (!Soft386LoadSegment(State
, SOFT386_REG_SS
, StackSel
))
5315 if (Size
) State
->GeneralRegs
[SOFT386_REG_ESP
].Long
= StackPtr
;
5316 else State
->GeneralRegs
[SOFT386_REG_ESP
].LowWord
= LOWORD(StackPtr
);
5319 /* Set the new flags */
5320 if (Size
) State
->Flags
.Long
= NewFlags
.Long
& PROT_MODE_FLAGS_MASK
;
5321 else State
->Flags
.LowWord
= NewFlags
.LowWord
& PROT_MODE_FLAGS_MASK
;
5322 State
->Flags
.AlwaysSet
= TRUE
;
5324 /* Set additional flags */
5325 if (Cpl
<= State
->Flags
.Iopl
) State
->Flags
.If
= NewFlags
.If
;
5326 if (Cpl
== 0) State
->Flags
.Iopl
= NewFlags
.Iopl
;
5328 if (GET_SEGMENT_RPL(CodeSel
) > Cpl
)
5330 /* Update the CPL */
5331 Cpl
= Soft386GetCurrentPrivLevel(State
);
5333 /* Check segment security */
5334 for (i
= 0; i
<= SOFT386_NUM_SEG_REGS
; i
++)
5336 /* Don't check CS or SS */
5337 if ((i
== SOFT386_REG_CS
) || (i
== SOFT386_REG_SS
)) continue;
5339 if ((Cpl
> State
->SegmentRegs
[i
].Dpl
)
5340 && (!State
->SegmentRegs
[i
].Executable
5341 || !State
->SegmentRegs
[i
].DirConf
))
5343 /* Load the NULL descriptor in the segment */
5344 if (!Soft386LoadSegment(State
, i
, 0)) return FALSE
;
5351 if (Size
&& (InstPtr
& 0xFFFF0000))
5354 Soft386ExceptionWithErrorCode(State
, SOFT386_EXCEPTION_GP
, 0);
5359 State
->InstPtr
.Long
= InstPtr
;
5362 if (!Soft386LoadSegment(State
, SOFT386_REG_CS
, CodeSel
))
5364 /* Exception occurred */
5368 /* Set the new flags */
5369 if (Size
) State
->Flags
.Long
= NewFlags
.Long
& REAL_MODE_FLAGS_MASK
;
5370 else State
->Flags
.LowWord
= NewFlags
.LowWord
& REAL_MODE_FLAGS_MASK
;
5371 State
->Flags
.AlwaysSet
= TRUE
;
5377 SOFT386_OPCODE_HANDLER(Soft386OpcodeAam
)
5380 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
5382 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
5384 /* Invalid prefix */
5385 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
5389 /* Fetch the base */
5390 if (!Soft386FetchByte(State
, &Base
))
5392 /* Exception occurred */
5396 /* Check if the base is zero */
5400 Soft386Exception(State
, SOFT386_EXCEPTION_DE
);
5405 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
= Value
/ Base
;
5406 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Value
%= Base
;
5409 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
5410 State
->Flags
.Sf
= (Value
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
5411 State
->Flags
.Pf
= Soft386CalculateParity(Value
);
5416 SOFT386_OPCODE_HANDLER(Soft386OpcodeAad
)
5419 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
5421 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
5423 /* Invalid prefix */
5424 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
5428 /* Fetch the base */
5429 if (!Soft386FetchByte(State
, &Base
))
5431 /* Exception occurred */
5436 Value
+= State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
* Base
;
5437 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Value
;
5440 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
5441 State
->Flags
.Sf
= (Value
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
5442 State
->Flags
.Pf
= Soft386CalculateParity(Value
);
5447 SOFT386_OPCODE_HANDLER(Soft386OpcodeXlat
)
5450 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
5452 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
5454 /* The ADSIZE prefix toggles the size */
5455 AddressSize
= !AddressSize
;
5458 /* Read a byte from DS:[(E)BX + AL] */
5459 if (!Soft386ReadMemory(State
,
5461 AddressSize
? State
->GeneralRegs
[SOFT386_REG_EBX
].Long
5462 : State
->GeneralRegs
[SOFT386_REG_EBX
].LowWord
5463 + State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
,
5468 /* Exception occurred */
5472 /* Set AL to the result */
5473 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Value
;
5475 /* Return success */
5479 SOFT386_OPCODE_HANDLER(Soft386OpcodeLoop
)
5482 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
5485 /* Make sure this is the right instruction */
5486 ASSERT((Opcode
>= 0xE0) && (Opcode
<= 0xE2));
5488 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
5490 /* Invalid prefix */
5491 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
5495 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
5497 /* The OPSIZE prefix toggles the size */
5501 if (Size
) Condition
= ((--State
->GeneralRegs
[SOFT386_REG_ECX
].Long
) != 0);
5502 else Condition
= ((--State
->GeneralRegs
[SOFT386_REG_ECX
].LowWord
) != 0);
5506 /* Additional rule for LOOPNZ */
5507 if (State
->Flags
.Zf
) Condition
= FALSE
;
5512 /* Additional rule for LOOPZ */
5513 if (!State
->Flags
.Zf
) Condition
= FALSE
;
5516 /* Fetch the offset */
5517 if (!Soft386FetchByte(State
, (PUCHAR
)&Offset
))
5519 /* An exception occurred */
5525 /* Move the instruction pointer */
5526 State
->InstPtr
.Long
+= Offset
;
5532 SOFT386_OPCODE_HANDLER(Soft386OpcodeJecxz
)
5535 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
5538 /* Make sure this is the right instruction */
5539 ASSERT(Opcode
== 0xE3);
5541 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
5543 /* Invalid prefix */
5544 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
5548 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
5550 /* The OPSIZE prefix toggles the size */
5554 if (Size
) Condition
= (State
->GeneralRegs
[SOFT386_REG_ECX
].Long
== 0);
5555 else Condition
= (State
->GeneralRegs
[SOFT386_REG_ECX
].LowWord
== 0);
5557 /* Fetch the offset */
5558 if (!Soft386FetchByte(State
, (PUCHAR
)&Offset
))
5560 /* An exception occurred */
5566 /* Move the instruction pointer */
5567 State
->InstPtr
.Long
+= Offset
;
5573 SOFT386_OPCODE_HANDLER(Soft386OpcodeCall
)
5575 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
5577 /* Make sure this is the right instruction */
5578 ASSERT(Opcode
== 0xE8);
5580 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
5582 /* The OPSIZE prefix toggles the size */
5586 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
5588 /* Invalid prefix */
5589 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
5597 /* Fetch the offset */
5598 if (!Soft386FetchDword(State
, (PULONG
)&Offset
))
5600 /* An exception occurred */
5604 /* Push the current value of the instruction pointer */
5605 if (!Soft386StackPush(State
, State
->InstPtr
.Long
))
5607 /* Exception occurred */
5611 /* Move the instruction pointer */
5612 State
->InstPtr
.Long
+= Offset
;
5618 /* Fetch the offset */
5619 if (!Soft386FetchWord(State
, (PUSHORT
)&Offset
))
5621 /* An exception occurred */
5625 /* Push the current value of the instruction pointer */
5626 if (!Soft386StackPush(State
, State
->InstPtr
.Long
))
5628 /* Exception occurred */
5632 /* Move the instruction pointer */
5633 State
->InstPtr
.LowWord
+= Offset
;
5639 SOFT386_OPCODE_HANDLER(Soft386OpcodeJmp
)
5641 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
5643 /* Make sure this is the right instruction */
5644 ASSERT(Opcode
== 0xE9);
5646 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
5648 /* The OPSIZE prefix toggles the size */
5652 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
5654 /* Invalid prefix */
5655 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
5663 /* Fetch the offset */
5664 if (!Soft386FetchDword(State
, (PULONG
)&Offset
))
5666 /* An exception occurred */
5670 /* Move the instruction pointer */
5671 State
->InstPtr
.Long
+= Offset
;
5677 /* Fetch the offset */
5678 if (!Soft386FetchWord(State
, (PUSHORT
)&Offset
))
5680 /* An exception occurred */
5684 /* Move the instruction pointer */
5685 State
->InstPtr
.LowWord
+= Offset
;
5691 SOFT386_OPCODE_HANDLER(Soft386OpcodeJmpAbs
)
5693 // TODO: NOT IMPLEMENTED
5699 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovAlOffset
)
5701 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
5704 /* Make sure this is the right instruction */
5705 ASSERT(Opcode
== 0xA0);
5707 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
5709 /* The OPSIZE prefix toggles the size */
5715 if (!Soft386FetchDword(State
, &Offset
))
5717 /* Exception occurred */
5725 if (!Soft386FetchWord(State
, &WordOffset
))
5727 /* Exception occurred */
5731 Offset
= (ULONG
)WordOffset
;
5734 /* Read from memory */
5735 return Soft386ReadMemory(State
,
5736 (State
->PrefixFlags
& SOFT386_PREFIX_SEG
) ?
5737 State
->SegmentOverride
: SOFT386_REG_DS
,
5740 &State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
,
5744 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovEaxOffset
)
5746 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
5748 /* Make sure this is the right instruction */
5749 ASSERT(Opcode
== 0xA1);
5751 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
5753 /* The OPSIZE prefix toggles the size */
5761 if (!Soft386FetchDword(State
, &Offset
))
5763 /* Exception occurred */
5767 /* Read from memory */
5768 return Soft386ReadMemory(State
,
5769 (State
->PrefixFlags
& SOFT386_PREFIX_SEG
) ?
5770 State
->SegmentOverride
: SOFT386_REG_DS
,
5773 &State
->GeneralRegs
[SOFT386_REG_EAX
].Long
,
5780 if (!Soft386FetchWord(State
, &Offset
))
5782 /* Exception occurred */
5786 /* Read from memory */
5787 return Soft386ReadMemory(State
,
5788 (State
->PrefixFlags
& SOFT386_PREFIX_SEG
) ?
5789 State
->SegmentOverride
: SOFT386_REG_DS
,
5792 &State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
,
5797 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovOffsetAl
)
5799 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
5802 /* Make sure this is the right instruction */
5803 ASSERT(Opcode
== 0xA2);
5805 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
5807 /* The OPSIZE prefix toggles the size */
5813 if (!Soft386FetchDword(State
, &Offset
))
5815 /* Exception occurred */
5823 if (!Soft386FetchWord(State
, &WordOffset
))
5825 /* Exception occurred */
5829 Offset
= (ULONG
)WordOffset
;
5832 /* Write to memory */
5833 return Soft386WriteMemory(State
,
5834 (State
->PrefixFlags
& SOFT386_PREFIX_SEG
) ?
5835 State
->SegmentOverride
: SOFT386_REG_DS
,
5837 &State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
,
5841 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovOffsetEax
)
5843 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
5845 /* Make sure this is the right instruction */
5846 ASSERT(Opcode
== 0xA3);
5848 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
5850 /* The OPSIZE prefix toggles the size */
5858 if (!Soft386FetchDword(State
, &Offset
))
5860 /* Exception occurred */
5864 /* Write to memory */
5865 return Soft386WriteMemory(State
,
5866 (State
->PrefixFlags
& SOFT386_PREFIX_SEG
) ?
5867 State
->SegmentOverride
: SOFT386_REG_DS
,
5869 &State
->GeneralRegs
[SOFT386_REG_EAX
].Long
,
5876 if (!Soft386FetchWord(State
, &Offset
))
5878 /* Exception occurred */
5882 /* Write to memory */
5883 return Soft386WriteMemory(State
,
5884 (State
->PrefixFlags
& SOFT386_PREFIX_SEG
) ?
5885 State
->SegmentOverride
: SOFT386_REG_DS
,
5887 &State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
,
5892 SOFT386_OPCODE_HANDLER(Soft386OpcodeSalc
)
5894 /* Make sure this is the right instruction */
5895 ASSERT(Opcode
== 0xD6);
5897 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
5899 /* Invalid prefix */
5900 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
5904 /* Set all the bits of AL to CF */
5905 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= State
->Flags
.Cf
? 0xFF : 0x00;
5910 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovs
)
5912 ULONG Data
, DataSize
;
5913 BOOLEAN OperandSize
, AddressSize
;
5915 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
5917 /* Make sure this is the right instruction */
5918 ASSERT((Opcode
& 0xFE) == 0xA4);
5920 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
5922 /* The OPSIZE prefix toggles the size */
5923 OperandSize
= !OperandSize
;
5926 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
5928 /* The ADSIZE prefix toggles the size */
5929 AddressSize
= !AddressSize
;
5932 if ((State
->PrefixFlags
& SOFT386_PREFIX_REP
)
5933 || (State
->PrefixFlags
& SOFT386_PREFIX_REPNZ
))
5935 // TODO: The REP/REPZ/REPNZ prefixes need to be implemented!
5936 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
5940 /* Calculate the size */
5941 if (Opcode
== 0xA4) DataSize
= sizeof(UCHAR
);
5942 else DataSize
= OperandSize
? sizeof(ULONG
) : sizeof(USHORT
);
5944 /* Read from the source operand */
5945 if (!Soft386ReadMemory(State
,
5947 AddressSize
? State
->GeneralRegs
[SOFT386_REG_ESI
].Long
5948 : State
->GeneralRegs
[SOFT386_REG_ESI
].LowWord
,
5953 /* Exception occurred */
5957 /* Write to the destination operand */
5958 if (!Soft386WriteMemory(State
,
5960 AddressSize
? State
->GeneralRegs
[SOFT386_REG_EDI
].Long
5961 : State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
,
5965 /* Exception occurred */
5969 /* Increment/decrement ESI and EDI */
5972 if (!State
->Flags
.Df
)
5974 State
->GeneralRegs
[SOFT386_REG_ESI
].Long
+= DataSize
;
5975 State
->GeneralRegs
[SOFT386_REG_EDI
].Long
+= DataSize
;
5979 State
->GeneralRegs
[SOFT386_REG_ESI
].Long
-= DataSize
;
5980 State
->GeneralRegs
[SOFT386_REG_EDI
].Long
-= DataSize
;
5985 if (!State
->Flags
.Df
)
5987 State
->GeneralRegs
[SOFT386_REG_ESI
].LowWord
+= DataSize
;
5988 State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
+= DataSize
;
5992 State
->GeneralRegs
[SOFT386_REG_ESI
].LowWord
-= DataSize
;
5993 State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
-= DataSize
;
5997 /* Return success */
6001 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmps
)
6003 ULONG FirstValue
= 0, SecondValue
= 0, Result
;
6004 ULONG DataSize
, DataMask
, SignFlag
;
6005 BOOLEAN OperandSize
, AddressSize
;
6007 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
6009 /* Make sure this is the right instruction */
6010 ASSERT((Opcode
& 0xFE) == 0xA6);
6012 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
6014 /* The OPSIZE prefix toggles the size */
6015 OperandSize
= !OperandSize
;
6018 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
6020 /* The ADSIZE prefix toggles the size */
6021 AddressSize
= !AddressSize
;
6024 if ((State
->PrefixFlags
& SOFT386_PREFIX_REP
)
6025 || (State
->PrefixFlags
& SOFT386_PREFIX_REPNZ
))
6027 // TODO: The REP/REPZ/REPNZ prefixes need to be implemented!
6028 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
6032 /* Calculate the size */
6033 if (Opcode
== 0xA6) DataSize
= sizeof(UCHAR
);
6034 else DataSize
= OperandSize
? sizeof(ULONG
) : sizeof(USHORT
);
6036 /* Calculate the mask and sign flag */
6037 DataMask
= (1 << (DataSize
* 8)) - 1;
6038 SignFlag
= 1 << ((DataSize
* 8) - 1);
6040 /* Read from the first source operand */
6041 if (!Soft386ReadMemory(State
,
6043 AddressSize
? State
->GeneralRegs
[SOFT386_REG_ESI
].Long
6044 : State
->GeneralRegs
[SOFT386_REG_ESI
].LowWord
,
6049 /* Exception occurred */
6053 /* Read from the second source operand */
6054 if (!Soft386ReadMemory(State
,
6056 AddressSize
? State
->GeneralRegs
[SOFT386_REG_EDI
].Long
6057 : State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
,
6062 /* Exception occurred */
6066 /* Calculate the result */
6067 FirstValue
&= DataMask
;
6068 SecondValue
&= DataMask
;
6069 Result
= (FirstValue
- SecondValue
) & DataMask
;
6071 /* Update the flags */
6072 State
->Flags
.Cf
= FirstValue
< SecondValue
;
6073 State
->Flags
.Of
= ((FirstValue
& SignFlag
) != (SecondValue
& SignFlag
))
6074 && ((FirstValue
& SignFlag
) != (Result
& SignFlag
));
6075 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
6076 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
6077 State
->Flags
.Sf
= (Result
& SignFlag
) ? TRUE
: FALSE
;
6078 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
6080 /* Increment/decrement ESI and EDI */
6083 if (!State
->Flags
.Df
)
6085 State
->GeneralRegs
[SOFT386_REG_ESI
].Long
+= DataSize
;
6086 State
->GeneralRegs
[SOFT386_REG_EDI
].Long
+= DataSize
;
6090 State
->GeneralRegs
[SOFT386_REG_ESI
].Long
-= DataSize
;
6091 State
->GeneralRegs
[SOFT386_REG_EDI
].Long
-= DataSize
;
6096 if (!State
->Flags
.Df
)
6098 State
->GeneralRegs
[SOFT386_REG_ESI
].LowWord
+= DataSize
;
6099 State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
+= DataSize
;
6103 State
->GeneralRegs
[SOFT386_REG_ESI
].LowWord
-= DataSize
;
6104 State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
-= DataSize
;
6108 /* Return success */
6112 SOFT386_OPCODE_HANDLER(Soft386OpcodeStos
)
6115 BOOLEAN OperandSize
, AddressSize
;
6117 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
6119 /* Make sure this is the right instruction */
6120 ASSERT((Opcode
& 0xFE) == 0xAA);
6122 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
6124 /* The OPSIZE prefix toggles the size */
6125 OperandSize
= !OperandSize
;
6128 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
6130 /* The ADSIZE prefix toggles the size */
6131 AddressSize
= !AddressSize
;
6134 /* Calculate the size */
6135 if (Opcode
== 0xAA) DataSize
= sizeof(UCHAR
);
6136 else DataSize
= OperandSize
? sizeof(ULONG
) : sizeof(USHORT
);
6138 if (State
->PrefixFlags
& SOFT386_PREFIX_REP
)
6140 UCHAR Block
[STRING_BLOCK_SIZE
];
6141 ULONG Count
= OperandSize
? State
->GeneralRegs
[SOFT386_REG_ECX
].Long
6142 : State
->GeneralRegs
[SOFT386_REG_ECX
].LowWord
;
6144 /* Fill the memory block with the data */
6145 if (DataSize
== sizeof(UCHAR
))
6147 RtlFillMemory(Block
, sizeof(Block
), State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
);
6153 for (i
= 0; i
< STRING_BLOCK_SIZE
/ DataSize
; i
++)
6155 if (DataSize
== sizeof(USHORT
))
6157 ((PUSHORT
)Block
)[i
] = State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
6161 ((PULONG
)Block
)[i
] = State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
6166 /* Transfer until finished */
6169 ULONG Processed
= min(Count
, STRING_BLOCK_SIZE
/ DataSize
);
6171 /* Simulate the 16-bit wrap-around of DI in 16-bit address mode */
6174 ULONG MaxBytes
= 0x10000 - (ULONG
)State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
;
6176 Processed
= min(Processed
, MaxBytes
/ DataSize
);
6177 if (Processed
== 0) Processed
= 1;
6180 if (State
->Flags
.Df
)
6182 /* Reduce EDI by the number of bytes to transfer */
6183 if (AddressSize
) State
->GeneralRegs
[SOFT386_REG_EDI
].Long
-= Processed
* DataSize
;
6184 else State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
-= Processed
* DataSize
;
6187 /* Write to memory */
6188 if (!Soft386WriteMemory(State
,
6190 AddressSize
? State
->GeneralRegs
[SOFT386_REG_EDI
].Long
6191 : State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
,
6193 Processed
* DataSize
))
6196 if (OperandSize
) State
->GeneralRegs
[SOFT386_REG_ECX
].Long
= Count
;
6197 else State
->GeneralRegs
[SOFT386_REG_ECX
].LowWord
= LOWORD(Count
);
6199 /* Exception occurred */
6203 if (!State
->Flags
.Df
)
6205 /* Increase EDI by the number of bytes transfered */
6206 if (AddressSize
) State
->GeneralRegs
[SOFT386_REG_EDI
].Long
+= Processed
* DataSize
;
6207 else State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
+= Processed
* DataSize
;
6210 /* Reduce the total count by the number processed in this run */
6215 if (OperandSize
) State
->GeneralRegs
[SOFT386_REG_ECX
].Long
= 0;
6216 else State
->GeneralRegs
[SOFT386_REG_ECX
].LowWord
= 0;
6220 /* Write to the destination operand */
6221 if (!Soft386WriteMemory(State
,
6223 AddressSize
? State
->GeneralRegs
[SOFT386_REG_EDI
].Long
6224 : State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
,
6225 &State
->GeneralRegs
[SOFT386_REG_EAX
].Long
,
6228 /* Exception occurred */
6232 /* Increment/decrement EDI */
6235 if (!State
->Flags
.Df
) State
->GeneralRegs
[SOFT386_REG_EDI
].Long
+= DataSize
;
6236 else State
->GeneralRegs
[SOFT386_REG_EDI
].Long
-= DataSize
;
6240 if (!State
->Flags
.Df
) State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
+= DataSize
;
6241 else State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
-= DataSize
;
6245 /* Return success */
6249 SOFT386_OPCODE_HANDLER(Soft386OpcodeLods
)
6252 BOOLEAN OperandSize
, AddressSize
;
6254 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
6256 /* Make sure this is the right instruction */
6257 ASSERT((Opcode
& 0xFE) == 0xAC);
6259 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
6261 /* The OPSIZE prefix toggles the size */
6262 OperandSize
= !OperandSize
;
6265 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
6267 /* The ADSIZE prefix toggles the size */
6268 AddressSize
= !AddressSize
;
6271 /* Calculate the size */
6272 if (Opcode
== 0xAC) DataSize
= sizeof(UCHAR
);
6273 else DataSize
= OperandSize
? sizeof(ULONG
) : sizeof(USHORT
);
6275 if (State
->PrefixFlags
& SOFT386_PREFIX_REP
)
6277 ULONG Count
= OperandSize
? State
->GeneralRegs
[SOFT386_REG_ECX
].Long
6278 : State
->GeneralRegs
[SOFT386_REG_ECX
].LowWord
;
6280 /* If the count is 0, do nothing */
6281 if (Count
== 0) return TRUE
;
6283 /* Only the last entry will be loaded */
6284 if (!State
->Flags
.Df
)
6286 if (AddressSize
) State
->GeneralRegs
[SOFT386_REG_ESI
].Long
+= (Count
- 1) * DataSize
;
6287 else State
->GeneralRegs
[SOFT386_REG_ESI
].LowWord
+= (Count
- 1) * DataSize
;
6291 if (AddressSize
) State
->GeneralRegs
[SOFT386_REG_ESI
].Long
-= (Count
- 1) * DataSize
;
6292 else State
->GeneralRegs
[SOFT386_REG_ESI
].LowWord
-= (Count
- 1) * DataSize
;
6296 /* Read from the source operand */
6297 if (!Soft386ReadMemory(State
,
6299 AddressSize
? State
->GeneralRegs
[SOFT386_REG_ESI
].Long
6300 : State
->GeneralRegs
[SOFT386_REG_ESI
].LowWord
,
6302 &State
->GeneralRegs
[SOFT386_REG_EAX
].Long
,
6305 /* Exception occurred */
6309 /* Increment/decrement ESI */
6312 if (!State
->Flags
.Df
) State
->GeneralRegs
[SOFT386_REG_ESI
].Long
+= DataSize
;
6313 else State
->GeneralRegs
[SOFT386_REG_ESI
].Long
-= DataSize
;
6317 if (!State
->Flags
.Df
) State
->GeneralRegs
[SOFT386_REG_ESI
].LowWord
+= DataSize
;
6318 else State
->GeneralRegs
[SOFT386_REG_ESI
].LowWord
-= DataSize
;
6321 /* Return success */
6325 SOFT386_OPCODE_HANDLER(Soft386OpcodeScas
)
6327 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
6328 ULONG SecondValue
= 0;
6330 ULONG DataSize
, DataMask
, SignFlag
;
6331 BOOLEAN OperandSize
, AddressSize
;
6333 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
6335 /* Make sure this is the right instruction */
6336 ASSERT((Opcode
& 0xFE) == 0xAE);
6338 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
6340 /* The OPSIZE prefix toggles the size */
6341 OperandSize
= !OperandSize
;
6344 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
6346 /* The ADSIZE prefix toggles the size */
6347 AddressSize
= !AddressSize
;
6350 if ((State
->PrefixFlags
& SOFT386_PREFIX_REP
)
6351 || (State
->PrefixFlags
& SOFT386_PREFIX_REPNZ
))
6353 // TODO: The REP/REPZ/REPNZ prefixes need to be implemented!
6354 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
6358 /* Calculate the size */
6359 if (Opcode
== 0xA6) DataSize
= sizeof(UCHAR
);
6360 else DataSize
= OperandSize
? sizeof(ULONG
) : sizeof(USHORT
);
6362 /* Calculate the mask and sign flag */
6363 DataMask
= (1 << (DataSize
* 8)) - 1;
6364 SignFlag
= 1 << ((DataSize
* 8) - 1);
6366 /* Read from the source operand */
6367 if (!Soft386ReadMemory(State
,
6369 AddressSize
? State
->GeneralRegs
[SOFT386_REG_EDI
].Long
6370 : State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
,
6375 /* Exception occurred */
6379 /* Calculate the result */
6380 FirstValue
&= DataMask
;
6381 SecondValue
&= DataMask
;
6382 Result
= (FirstValue
- SecondValue
) & DataMask
;
6384 /* Update the flags */
6385 State
->Flags
.Cf
= FirstValue
< SecondValue
;
6386 State
->Flags
.Of
= ((FirstValue
& SignFlag
) != (SecondValue
& SignFlag
))
6387 && ((FirstValue
& SignFlag
) != (Result
& SignFlag
));
6388 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
6389 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
6390 State
->Flags
.Sf
= (Result
& SignFlag
) ? TRUE
: FALSE
;
6391 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
6393 /* Increment/decrement EDI */
6396 if (!State
->Flags
.Df
) State
->GeneralRegs
[SOFT386_REG_EDI
].Long
+= DataSize
;
6397 else State
->GeneralRegs
[SOFT386_REG_EDI
].Long
-= DataSize
;
6401 if (!State
->Flags
.Df
) State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
+= DataSize
;
6402 else State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
-= DataSize
;
6405 /* Return success */
6409 SOFT386_OPCODE_HANDLER(Soft386OpcodeIns
)
6412 BOOLEAN OperandSize
, AddressSize
;
6414 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
6416 /* Make sure this is the right instruction */
6417 ASSERT((Opcode
& 0xFE) == 0x6C);
6419 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
6421 /* The OPSIZE prefix toggles the size */
6422 OperandSize
= !OperandSize
;
6425 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
6427 /* The ADSIZE prefix toggles the size */
6428 AddressSize
= !AddressSize
;
6431 /* Calculate the size */
6432 if (Opcode
== 0x6C) DataSize
= sizeof(UCHAR
);
6433 else DataSize
= OperandSize
? sizeof(ULONG
) : sizeof(USHORT
);
6435 if (State
->PrefixFlags
& SOFT386_PREFIX_REP
)
6437 UCHAR Block
[STRING_BLOCK_SIZE
];
6438 ULONG Count
= OperandSize
? State
->GeneralRegs
[SOFT386_REG_ECX
].Long
6439 : State
->GeneralRegs
[SOFT386_REG_ECX
].LowWord
;
6441 /* Clear the memory block */
6442 RtlZeroMemory(Block
, sizeof(Block
));
6444 /* Transfer until finished */
6447 ULONG Processed
= min(Count
, STRING_BLOCK_SIZE
/ DataSize
);
6449 /* Simulate the 16-bit wrap-around of DI in 16-bit address mode */
6452 ULONG MaxBytes
= 0x10000 - (ULONG
)State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
;
6454 Processed
= min(Processed
, MaxBytes
/ DataSize
);
6455 if (Processed
== 0) Processed
= 1;
6458 /* Read from the I/O port */
6459 State
->IoReadCallback(State
,
6460 State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
,
6462 Processed
* DataSize
);
6464 if (State
->Flags
.Df
)
6468 /* Reduce EDI by the number of bytes to transfer */
6469 if (AddressSize
) State
->GeneralRegs
[SOFT386_REG_EDI
].Long
-= Processed
* DataSize
;
6470 else State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
-= Processed
* DataSize
;
6472 /* Reverse the block data */
6473 for (i
= 0; i
< Processed
/ 2; i
++)
6475 /* Swap the values */
6476 for (j
= 0; j
< DataSize
; j
++)
6478 UCHAR Temp
= Block
[i
* DataSize
+ j
];
6479 Block
[i
* DataSize
+ j
] = Block
[(Processed
- i
- 1) * DataSize
+ j
];
6480 Block
[(Processed
- i
- 1) * DataSize
+ j
] = Temp
;
6485 /* Write to memory */
6486 if (!Soft386WriteMemory(State
,
6488 AddressSize
? State
->GeneralRegs
[SOFT386_REG_EDI
].Long
6489 : State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
,
6491 Processed
* DataSize
))
6494 if (OperandSize
) State
->GeneralRegs
[SOFT386_REG_ECX
].Long
= Count
;
6495 else State
->GeneralRegs
[SOFT386_REG_ECX
].LowWord
= LOWORD(Count
);
6497 /* Exception occurred */
6501 if (!State
->Flags
.Df
)
6503 /* Increase EDI by the number of bytes transfered */
6504 if (AddressSize
) State
->GeneralRegs
[SOFT386_REG_EDI
].Long
+= Processed
* DataSize
;
6505 else State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
+= Processed
* DataSize
;
6508 /* Reduce the total count by the number processed in this run */
6513 if (OperandSize
) State
->GeneralRegs
[SOFT386_REG_ECX
].Long
= 0;
6514 else State
->GeneralRegs
[SOFT386_REG_ECX
].LowWord
= 0;
6520 /* Read from the I/O port */
6521 State
->IoReadCallback(State
,
6522 State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
,
6526 /* Write to the destination operand */
6527 if (!Soft386WriteMemory(State
,
6529 AddressSize
? State
->GeneralRegs
[SOFT386_REG_EDI
].Long
6530 : State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
,
6534 /* Exception occurred */
6538 /* Increment/decrement EDI */
6541 if (!State
->Flags
.Df
) State
->GeneralRegs
[SOFT386_REG_EDI
].Long
+= DataSize
;
6542 else State
->GeneralRegs
[SOFT386_REG_EDI
].Long
-= DataSize
;
6546 if (!State
->Flags
.Df
) State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
+= DataSize
;
6547 else State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
-= DataSize
;
6551 /* Return success */
6555 SOFT386_OPCODE_HANDLER(Soft386OpcodeOuts
)
6558 BOOLEAN OperandSize
, AddressSize
;
6560 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
6562 /* Make sure this is the right instruction */
6563 ASSERT((Opcode
& 0xFE) == 0x6E);
6565 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
6567 /* The OPSIZE prefix toggles the size */
6568 OperandSize
= !OperandSize
;
6571 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
6573 /* The ADSIZE prefix toggles the size */
6574 AddressSize
= !AddressSize
;
6577 /* Calculate the size */
6578 if (Opcode
== 0x6E) DataSize
= sizeof(UCHAR
);
6579 else DataSize
= OperandSize
? sizeof(ULONG
) : sizeof(USHORT
);
6581 if (State
->PrefixFlags
& SOFT386_PREFIX_REP
)
6583 UCHAR Block
[STRING_BLOCK_SIZE
];
6584 ULONG Count
= OperandSize
? State
->GeneralRegs
[SOFT386_REG_ECX
].Long
6585 : State
->GeneralRegs
[SOFT386_REG_ECX
].LowWord
;
6587 /* Clear the memory block */
6588 RtlZeroMemory(Block
, sizeof(Block
));
6590 /* Transfer until finished */
6593 ULONG Processed
= min(Count
, STRING_BLOCK_SIZE
/ DataSize
);
6595 /* Simulate the 16-bit wrap-around of DI in 16-bit address mode */
6598 ULONG MaxBytes
= 0x10000 - (ULONG
)State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
;
6600 Processed
= min(Processed
, MaxBytes
/ DataSize
);
6601 if (Processed
== 0) Processed
= 1;
6604 /* Read from memory */
6605 if (!Soft386ReadMemory(State
,
6607 AddressSize
? State
->GeneralRegs
[SOFT386_REG_EDI
].Long
6608 : State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
,
6611 Processed
* DataSize
))
6614 if (OperandSize
) State
->GeneralRegs
[SOFT386_REG_ECX
].Long
= Count
;
6615 else State
->GeneralRegs
[SOFT386_REG_ECX
].LowWord
= LOWORD(Count
);
6617 /* Exception occurred */
6621 if (State
->Flags
.Df
)
6625 /* Reduce EDI by the number of bytes to transfer */
6626 if (AddressSize
) State
->GeneralRegs
[SOFT386_REG_EDI
].Long
-= Processed
* DataSize
;
6627 else State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
-= Processed
* DataSize
;
6629 /* Reverse the block data */
6630 for (i
= 0; i
< Processed
/ 2; i
++)
6632 /* Swap the values */
6633 for (j
= 0; j
< DataSize
; j
++)
6635 UCHAR Temp
= Block
[i
* DataSize
+ j
];
6636 Block
[i
* DataSize
+ j
] = Block
[(Processed
- i
- 1) * DataSize
+ j
];
6637 Block
[(Processed
- i
- 1) * DataSize
+ j
] = Temp
;
6642 /* Write to the I/O port */
6643 State
->IoWriteCallback(State
,
6644 State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
,
6646 Processed
* DataSize
);
6648 if (!State
->Flags
.Df
)
6650 /* Increase EDI by the number of bytes transfered */
6651 if (AddressSize
) State
->GeneralRegs
[SOFT386_REG_EDI
].Long
+= Processed
* DataSize
;
6652 else State
->GeneralRegs
[SOFT386_REG_EDI
].LowWord
+= Processed
* DataSize
;
6655 /* Reduce the total count by the number processed in this run */
6660 if (OperandSize
) State
->GeneralRegs
[SOFT386_REG_ECX
].Long
= 0;
6661 else State
->GeneralRegs
[SOFT386_REG_ECX
].LowWord
= 0;
6667 /* Read from the source operand */
6668 if (!Soft386ReadMemory(State
,
6670 AddressSize
? State
->GeneralRegs
[SOFT386_REG_ESI
].Long
6671 : State
->GeneralRegs
[SOFT386_REG_ESI
].LowWord
,
6676 /* Exception occurred */
6680 /* Write to the I/O port */
6681 State
->IoWriteCallback(State
,
6682 State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
,
6686 /* Increment/decrement ESI */
6689 if (!State
->Flags
.Df
) State
->GeneralRegs
[SOFT386_REG_ESI
].Long
+= DataSize
;
6690 else State
->GeneralRegs
[SOFT386_REG_ESI
].Long
-= DataSize
;
6694 if (!State
->Flags
.Df
) State
->GeneralRegs
[SOFT386_REG_ESI
].LowWord
+= DataSize
;
6695 else State
->GeneralRegs
[SOFT386_REG_ESI
].LowWord
-= DataSize
;
6699 /* Return success */