2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: 386/486 CPU Emulation Library
5 * PURPOSE: Opcode handlers.
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
9 /* INCLUDES *******************************************************************/
11 // #define WIN32_NO_STATUS
12 // #define _INC_WINDOWS
22 /* PUBLIC VARIABLES ***********************************************************/
24 SOFT386_OPCODE_HANDLER_PROC
25 Soft386OpcodeHandlers
[SOFT386_NUM_OPCODE_HANDLERS
] =
27 Soft386OpcodeAddByteModrm
,
28 Soft386OpcodeAddModrm
,
29 Soft386OpcodeAddByteModrm
,
30 Soft386OpcodeAddModrm
,
35 Soft386OpcodeOrByteModrm
,
37 Soft386OpcodeOrByteModrm
,
42 NULL
, // TODO: OPCODE 0x0F NOT SUPPORTED
43 Soft386OpcodeAdcByteModrm
,
44 Soft386OpcodeAdcModrm
,
45 Soft386OpcodeAdcByteModrm
,
46 Soft386OpcodeAdcModrm
,
51 Soft386OpcodeSbbByteModrm
,
52 Soft386OpcodeSbbModrm
,
53 Soft386OpcodeSbbByteModrm
,
54 Soft386OpcodeSbbModrm
,
59 Soft386OpcodeAndByteModrm
,
60 Soft386OpcodeAndModrm
,
61 Soft386OpcodeAndByteModrm
,
62 Soft386OpcodeAndModrm
,
67 Soft386OpcodeCmpSubByteModrm
,
68 Soft386OpcodeCmpSubModrm
,
69 Soft386OpcodeCmpSubByteModrm
,
70 Soft386OpcodeCmpSubModrm
,
71 Soft386OpcodeCmpSubAl
,
72 Soft386OpcodeCmpSubEax
,
75 Soft386OpcodeXorByteModrm
,
76 Soft386OpcodeXorModrm
,
77 Soft386OpcodeXorByteModrm
,
78 Soft386OpcodeXorModrm
,
83 Soft386OpcodeCmpSubByteModrm
,
84 Soft386OpcodeCmpSubModrm
,
85 Soft386OpcodeCmpSubByteModrm
,
86 Soft386OpcodeCmpSubModrm
,
87 Soft386OpcodeCmpSubAl
,
88 Soft386OpcodeCmpSubEax
,
91 Soft386OpcodeIncrement
,
92 Soft386OpcodeIncrement
,
93 Soft386OpcodeIncrement
,
94 Soft386OpcodeIncrement
,
95 Soft386OpcodeIncrement
,
96 Soft386OpcodeIncrement
,
97 Soft386OpcodeIncrement
,
98 Soft386OpcodeIncrement
,
99 Soft386OpcodeDecrement
,
100 Soft386OpcodeDecrement
,
101 Soft386OpcodeDecrement
,
102 Soft386OpcodeDecrement
,
103 Soft386OpcodeDecrement
,
104 Soft386OpcodeDecrement
,
105 Soft386OpcodeDecrement
,
106 Soft386OpcodeDecrement
,
107 Soft386OpcodePushReg
,
108 Soft386OpcodePushReg
,
109 Soft386OpcodePushReg
,
110 Soft386OpcodePushReg
,
111 Soft386OpcodePushReg
,
112 Soft386OpcodePushReg
,
113 Soft386OpcodePushReg
,
114 Soft386OpcodePushReg
,
123 Soft386OpcodePushAll
,
131 Soft386OpcodePushImm
,
132 Soft386OpcodeImulModrmImm
,
133 Soft386OpcodePushByteImm
,
134 Soft386OpcodeImulModrmByteImm
,
135 NULL
, // TODO: OPCODE 0x6C NOT SUPPORTED
136 NULL
, // TODO: OPCODE 0x6D NOT SUPPORTED
137 NULL
, // TODO: OPCODE 0x6E NOT SUPPORTED
138 NULL
, // TODO: OPCODE 0x6F NOT SUPPORTED
139 Soft386OpcodeShortConditionalJmp
,
140 Soft386OpcodeShortConditionalJmp
,
141 Soft386OpcodeShortConditionalJmp
,
142 Soft386OpcodeShortConditionalJmp
,
143 Soft386OpcodeShortConditionalJmp
,
144 Soft386OpcodeShortConditionalJmp
,
145 Soft386OpcodeShortConditionalJmp
,
146 Soft386OpcodeShortConditionalJmp
,
147 Soft386OpcodeShortConditionalJmp
,
148 Soft386OpcodeShortConditionalJmp
,
149 Soft386OpcodeShortConditionalJmp
,
150 Soft386OpcodeShortConditionalJmp
,
151 Soft386OpcodeShortConditionalJmp
,
152 Soft386OpcodeShortConditionalJmp
,
153 Soft386OpcodeShortConditionalJmp
,
154 Soft386OpcodeShortConditionalJmp
,
155 NULL
, // TODO: OPCODE 0x80 NOT SUPPORTED
156 NULL
, // TODO: OPCODE 0x81 NOT SUPPORTED
157 NULL
, // TODO: OPCODE 0x82 NOT SUPPORTED
158 NULL
, // TODO: OPCODE 0x83 NOT SUPPORTED
159 Soft386OpcodeTestByteModrm
,
160 Soft386OpcodeTestModrm
,
161 Soft386OpcodeXchgByteModrm
,
162 Soft386OpcodeXchgModrm
,
163 Soft386OpcodeMovByteModrm
,
164 Soft386OpcodeMovModrm
,
165 Soft386OpcodeMovByteModrm
,
166 Soft386OpcodeMovModrm
,
167 Soft386OpcodeMovStoreSeg
,
169 Soft386OpcodeMovLoadSeg
,
170 NULL
, // TODO: OPCODE 0x8F NOT SUPPORTED
172 Soft386OpcodeExchangeEax
,
173 Soft386OpcodeExchangeEax
,
174 Soft386OpcodeExchangeEax
,
175 Soft386OpcodeExchangeEax
,
176 Soft386OpcodeExchangeEax
,
177 Soft386OpcodeExchangeEax
,
178 Soft386OpcodeExchangeEax
,
181 Soft386OpcodeCallAbs
,
183 Soft386OpcodePushFlags
,
184 Soft386OpcodePopFlags
,
187 Soft386OpcodeMovAlOffset
,
188 Soft386OpcodeMovEaxOffset
,
189 Soft386OpcodeMovOffsetAl
,
190 Soft386OpcodeMovOffsetEax
,
191 NULL
, // TODO: OPCODE 0xA4 NOT SUPPORTED
192 NULL
, // TODO: OPCODE 0xA5 NOT SUPPORTED
193 NULL
, // TODO: OPCODE 0xA6 NOT SUPPORTED
194 NULL
, // TODO: OPCODE 0xA7 NOT SUPPORTED
196 Soft386OpcodeTestEax
,
197 NULL
, // TODO: OPCODE 0xAA NOT SUPPORTED
198 NULL
, // TODO: OPCODE 0xAB NOT SUPPORTED
199 NULL
, // TODO: OPCODE 0xAC NOT SUPPORTED
200 NULL
, // TODO: OPCODE 0xAD NOT SUPPORTED
201 NULL
, // TODO: OPCODE 0xAE NOT SUPPORTED
202 NULL
, // TODO: OPCODE 0xAF NOT SUPPORTED
203 Soft386OpcodeMovByteRegImm
,
204 Soft386OpcodeMovByteRegImm
,
205 Soft386OpcodeMovByteRegImm
,
206 Soft386OpcodeMovByteRegImm
,
207 Soft386OpcodeMovByteRegImm
,
208 Soft386OpcodeMovByteRegImm
,
209 Soft386OpcodeMovByteRegImm
,
210 Soft386OpcodeMovByteRegImm
,
211 Soft386OpcodeMovRegImm
,
212 Soft386OpcodeMovRegImm
,
213 Soft386OpcodeMovRegImm
,
214 Soft386OpcodeMovRegImm
,
215 Soft386OpcodeMovRegImm
,
216 Soft386OpcodeMovRegImm
,
217 Soft386OpcodeMovRegImm
,
218 Soft386OpcodeMovRegImm
,
219 NULL
, // TODO: OPCODE 0xC0 NOT SUPPORTED
220 NULL
, // TODO: OPCODE 0xC1 NOT SUPPORTED
225 NULL
, // TODO: OPCODE 0xC6 NOT SUPPORTED
226 NULL
, // TODO: OPCODE 0xC7 NOT SUPPORTED
229 Soft386OpcodeRetFarImm
,
235 NULL
, // TODO: OPCODE 0xD0 NOT SUPPORTED
236 NULL
, // TODO: OPCODE 0xD1 NOT SUPPORTED
237 NULL
, // TODO: OPCODE 0xD2 NOT SUPPORTED
238 NULL
, // TODO: OPCODE 0xD3 NOT SUPPORTED
241 NULL
, // TODO: OPCODE 0xD6 NOT SUPPORTED
243 NULL
, // TODO: OPCODE 0xD8 NOT SUPPORTED
244 NULL
, // TODO: OPCODE 0xD9 NOT SUPPORTED
245 NULL
, // TODO: OPCODE 0xDA NOT SUPPORTED
246 NULL
, // TODO: OPCODE 0xDB NOT SUPPORTED
247 NULL
, // TODO: OPCODE 0xDC NOT SUPPORTED
248 NULL
, // TODO: OPCODE 0xDD NOT SUPPORTED
249 NULL
, // TODO: OPCODE 0xDE NOT SUPPORTED
250 NULL
, // TODO: OPCODE 0xDF NOT SUPPORTED
257 Soft386OpcodeOutByte
,
262 Soft386OpcodeShortJump
,
265 Soft386OpcodeOutByte
,
272 Soft386OpcodeComplCarry
,
273 NULL
, // TODO: OPCODE 0xF6 NOT SUPPORTED
274 NULL
, // TODO: OPCODE 0xF7 NOT SUPPORTED
275 Soft386OpcodeClearCarry
,
276 Soft386OpcodeSetCarry
,
277 Soft386OpcodeClearInt
,
279 Soft386OpcodeClearDir
,
281 NULL
, // TODO: OPCODE 0xFE NOT SUPPORTED
282 NULL
, // TODO: OPCODE 0xFF NOT SUPPORTED
285 /* PUBLIC FUNCTIONS ***********************************************************/
287 SOFT386_OPCODE_HANDLER(Soft386OpcodePrefix
)
289 BOOLEAN Valid
= FALSE
;
296 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
298 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
299 State
->SegmentOverride
= SOFT386_REG_ES
;
309 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
311 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
312 State
->SegmentOverride
= SOFT386_REG_CS
;
322 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
324 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
325 State
->SegmentOverride
= SOFT386_REG_SS
;
335 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
337 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
338 State
->SegmentOverride
= SOFT386_REG_DS
;
348 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
350 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
351 State
->SegmentOverride
= SOFT386_REG_FS
;
361 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
363 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
364 State
->SegmentOverride
= SOFT386_REG_GS
;
374 if (!(State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
))
376 State
->PrefixFlags
|= SOFT386_PREFIX_OPSIZE
;
386 if (!(State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
))
388 State
->PrefixFlags
|= SOFT386_PREFIX_ADSIZE
;
397 if (!(State
->PrefixFlags
& SOFT386_PREFIX_LOCK
))
399 State
->PrefixFlags
|= SOFT386_PREFIX_LOCK
;
409 /* Mutually exclusive with REP */
410 if (!(State
->PrefixFlags
411 & (SOFT386_PREFIX_REPNZ
| SOFT386_PREFIX_REP
)))
413 State
->PrefixFlags
|= SOFT386_PREFIX_REPNZ
;
423 /* Mutually exclusive with REPNZ */
424 if (!(State
->PrefixFlags
425 & (SOFT386_PREFIX_REPNZ
| SOFT386_PREFIX_REP
)))
427 State
->PrefixFlags
|= SOFT386_PREFIX_REP
;
437 /* Clear all prefixes */
438 State
->PrefixFlags
= 0;
440 /* Throw an exception */
441 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
448 SOFT386_OPCODE_HANDLER(Soft386OpcodeIncrement
)
451 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
453 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
455 /* The OPSIZE prefix toggles the size */
458 else if (State
->PrefixFlags
!= 0)
461 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
465 /* Make sure this is the right instruction */
466 ASSERT((Opcode
& 0xF8) == 0x40);
470 Value
= ++State
->GeneralRegs
[Opcode
& 0x07].Long
;
472 State
->Flags
.Of
= (Value
== SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
473 State
->Flags
.Sf
= (Value
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
477 Value
= ++State
->GeneralRegs
[Opcode
& 0x07].LowWord
;
479 State
->Flags
.Of
= (Value
== SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
480 State
->Flags
.Sf
= (Value
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
483 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
484 State
->Flags
.Af
= ((Value
& 0x0F) == 0) ? TRUE
: FALSE
;
485 State
->Flags
.Pf
= Soft386CalculateParity(LOBYTE(Value
));
491 SOFT386_OPCODE_HANDLER(Soft386OpcodeDecrement
)
494 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
496 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
498 /* The OPSIZE prefix toggles the size */
501 else if (State
->PrefixFlags
!= 0)
504 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
508 /* Make sure this is the right instruction */
509 ASSERT((Opcode
& 0xF8) == 0x48);
513 Value
= --State
->GeneralRegs
[Opcode
& 0x07].Long
;
515 State
->Flags
.Of
= (Value
== (SIGN_FLAG_LONG
- 1)) ? TRUE
: FALSE
;
516 State
->Flags
.Sf
= (Value
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
520 Value
= --State
->GeneralRegs
[Opcode
& 0x07].LowWord
;
522 State
->Flags
.Of
= (Value
== (SIGN_FLAG_WORD
- 1)) ? TRUE
: FALSE
;
523 State
->Flags
.Sf
= (Value
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
526 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
527 State
->Flags
.Af
= ((Value
& 0x0F) == 0x0F) ? TRUE
: FALSE
;
528 State
->Flags
.Pf
= Soft386CalculateParity(LOBYTE(Value
));
534 SOFT386_OPCODE_HANDLER(Soft386OpcodePushReg
)
536 if ((State
->PrefixFlags
!= SOFT386_PREFIX_OPSIZE
)
537 && (State
->PrefixFlags
!= 0))
540 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
544 /* Make sure this is the right instruction */
545 ASSERT((Opcode
& 0xF8) == 0x50);
547 /* Call the internal function */
548 return Soft386StackPush(State
, State
->GeneralRegs
[Opcode
& 0x07].Long
);
551 SOFT386_OPCODE_HANDLER(Soft386OpcodePopReg
)
554 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_SS
].Size
;
556 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
558 /* The OPSIZE prefix toggles the size */
561 else if (State
->PrefixFlags
!= 0)
564 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
568 /* Make sure this is the right instruction */
569 ASSERT((Opcode
& 0xF8) == 0x58);
571 /* Call the internal function */
572 if (!Soft386StackPop(State
, &Value
)) return FALSE
;
574 /* Store the value */
575 if (Size
) State
->GeneralRegs
[Opcode
& 0x07].Long
= Value
;
576 else State
->GeneralRegs
[Opcode
& 0x07].LowWord
= Value
;
582 SOFT386_OPCODE_HANDLER(Soft386OpcodeNop
)
584 if (State
->PrefixFlags
& ~(SOFT386_PREFIX_OPSIZE
| SOFT386_PREFIX_REP
))
586 /* Allowed prefixes are REP and OPSIZE */
587 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
591 if (State
->PrefixFlags
& SOFT386_PREFIX_REP
)
594 State
->IdleCallback(State
);
600 SOFT386_OPCODE_HANDLER(Soft386OpcodeExchangeEax
)
602 INT Reg
= Opcode
& 0x07;
603 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
605 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
607 /* The OPSIZE prefix toggles the size */
610 else if (State
->PrefixFlags
!= 0)
613 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
617 /* Make sure this is the right instruction */
618 ASSERT((Opcode
& 0xF8) == 0x90);
620 /* Exchange the values */
625 Value
= State
->GeneralRegs
[Reg
].Long
;
626 State
->GeneralRegs
[Reg
].Long
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
627 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Value
;
633 Value
= State
->GeneralRegs
[Reg
].LowWord
;
634 State
->GeneralRegs
[Reg
].LowWord
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
635 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Value
;
641 SOFT386_OPCODE_HANDLER(Soft386OpcodeShortConditionalJmp
)
643 BOOLEAN Jump
= FALSE
;
646 /* Make sure this is the right instruction */
647 ASSERT((Opcode
& 0xF0) == 0x70);
649 /* Fetch the offset */
650 if (!Soft386FetchByte(State
, (PUCHAR
)&Offset
))
652 /* An exception occurred */
656 switch ((Opcode
& 0x0F) >> 1)
661 Jump
= State
->Flags
.Of
;
668 Jump
= State
->Flags
.Cf
;
675 Jump
= State
->Flags
.Zf
;
682 Jump
= State
->Flags
.Cf
|| State
->Flags
.Zf
;
689 Jump
= State
->Flags
.Sf
;
696 Jump
= State
->Flags
.Pf
;
703 Jump
= State
->Flags
.Sf
!= State
->Flags
.Of
;
710 Jump
= (State
->Flags
.Sf
!= State
->Flags
.Of
) || State
->Flags
.Zf
;
717 /* Invert the result */
723 /* Move the instruction pointer */
724 State
->InstPtr
.Long
+= Offset
;
731 SOFT386_OPCODE_HANDLER(Soft386OpcodeClearCarry
)
733 /* Make sure this is the right instruction */
734 ASSERT(Opcode
== 0xF8);
736 /* No prefixes allowed */
737 if (State
->PrefixFlags
)
739 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
743 /* Clear CF and return success */
744 State
->Flags
.Cf
= FALSE
;
748 SOFT386_OPCODE_HANDLER(Soft386OpcodeSetCarry
)
750 /* Make sure this is the right instruction */
751 ASSERT(Opcode
== 0xF9);
753 /* No prefixes allowed */
754 if (State
->PrefixFlags
)
756 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
760 /* Set CF and return success*/
761 State
->Flags
.Cf
= TRUE
;
765 SOFT386_OPCODE_HANDLER(Soft386OpcodeComplCarry
)
767 /* Make sure this is the right instruction */
768 ASSERT(Opcode
== 0xF5);
770 /* No prefixes allowed */
771 if (State
->PrefixFlags
)
773 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
777 /* Toggle CF and return success */
778 State
->Flags
.Cf
= !State
->Flags
.Cf
;
782 SOFT386_OPCODE_HANDLER(Soft386OpcodeClearInt
)
784 /* Make sure this is the right instruction */
785 ASSERT(Opcode
== 0xFA);
787 /* No prefixes allowed */
788 if (State
->PrefixFlags
)
790 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
794 /* Check for protected mode */
795 if (State
->ControlRegisters
[SOFT386_REG_CR0
] & SOFT386_CR0_PE
)
798 if (State
->Flags
.Iopl
>= State
->SegmentRegs
[SOFT386_REG_CS
].Dpl
)
800 /* Clear the interrupt flag */
801 State
->Flags
.If
= FALSE
;
805 /* General Protection Fault */
806 Soft386Exception(State
, SOFT386_EXCEPTION_GP
);
812 /* Just clear the interrupt flag */
813 State
->Flags
.If
= FALSE
;
820 SOFT386_OPCODE_HANDLER(Soft386OpcodeSetInt
)
822 /* Make sure this is the right instruction */
823 ASSERT(Opcode
== 0xFB);
825 /* No prefixes allowed */
826 if (State
->PrefixFlags
)
828 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
832 /* Check for protected mode */
833 if (State
->ControlRegisters
[SOFT386_REG_CR0
] & SOFT386_CR0_PE
)
836 if (State
->Flags
.Iopl
>= State
->SegmentRegs
[SOFT386_REG_CS
].Dpl
)
838 /* Set the interrupt flag */
839 State
->Flags
.If
= TRUE
;
843 /* General Protection Fault */
844 Soft386Exception(State
, SOFT386_EXCEPTION_GP
);
850 /* Just set the interrupt flag */
851 State
->Flags
.If
= TRUE
;
858 SOFT386_OPCODE_HANDLER(Soft386OpcodeClearDir
)
860 /* Make sure this is the right instruction */
861 ASSERT(Opcode
== 0xFC);
863 /* No prefixes allowed */
864 if (State
->PrefixFlags
)
866 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
870 /* Clear DF and return success */
871 State
->Flags
.Df
= FALSE
;
875 SOFT386_OPCODE_HANDLER(Soft386OpcodeSetDir
)
877 /* Make sure this is the right instruction */
878 ASSERT(Opcode
== 0xFD);
880 /* No prefixes allowed */
881 if (State
->PrefixFlags
)
883 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
887 /* Set DF and return success*/
888 State
->Flags
.Df
= TRUE
;
892 SOFT386_OPCODE_HANDLER(Soft386OpcodeHalt
)
894 /* Make sure this is the right instruction */
895 ASSERT(Opcode
== 0xF4);
897 /* No prefixes allowed */
898 if (State
->PrefixFlags
)
900 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
904 /* Privileged instructions can only be executed under CPL = 0 */
905 if (State
->SegmentRegs
[SOFT386_REG_CS
].Dpl
!= 0)
907 Soft386Exception(State
, SOFT386_EXCEPTION_GP
);
912 while (!State
->HardwareInt
) State
->IdleCallback(State
);
918 SOFT386_OPCODE_HANDLER(Soft386OpcodeInByte
)
923 /* Make sure this is the right instruction */
924 ASSERT((Opcode
& 0xF7) == 0xE4);
928 /* Fetch the parameter */
929 if (!Soft386FetchByte(State
, &Data
))
931 /* Exception occurred */
935 /* Set the port number to the parameter */
940 /* The port number is in DX */
941 Port
= State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
;
944 /* Read a byte from the I/O port */
945 State
->IoReadCallback(State
, Port
, &Data
, sizeof(UCHAR
));
947 /* Store the result in AL */
948 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Data
;
953 SOFT386_OPCODE_HANDLER(Soft386OpcodeIn
)
956 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
958 /* Make sure this is the right instruction */
959 ASSERT((Opcode
& 0xF7) == 0xE5);
961 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
963 /* The OPSIZE prefix toggles the size */
966 else if (State
->PrefixFlags
!= 0)
969 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
977 /* Fetch the parameter */
978 if (!Soft386FetchByte(State
, &Data
))
980 /* Exception occurred */
984 /* Set the port number to the parameter */
989 /* The port number is in DX */
990 Port
= State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
;
997 /* Read a dword from the I/O port */
998 State
->IoReadCallback(State
, Port
, &Data
, sizeof(ULONG
));
1000 /* Store the value in EAX */
1001 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Data
;
1007 /* Read a word from the I/O port */
1008 State
->IoReadCallback(State
, Port
, &Data
, sizeof(USHORT
));
1010 /* Store the value in AX */
1011 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Data
;
1017 SOFT386_OPCODE_HANDLER(Soft386OpcodeOutByte
)
1022 /* Make sure this is the right instruction */
1023 ASSERT((Opcode
& 0xF7) == 0xE6);
1027 /* Fetch the parameter */
1028 if (!Soft386FetchByte(State
, &Data
))
1030 /* Exception occurred */
1034 /* Set the port number to the parameter */
1039 /* The port number is in DX */
1040 Port
= State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
;
1043 /* Read the value from AL */
1044 Data
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
1046 /* Write the byte to the I/O port */
1047 State
->IoWriteCallback(State
, Port
, &Data
, sizeof(UCHAR
));
1052 SOFT386_OPCODE_HANDLER(Soft386OpcodeOut
)
1055 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1057 /* Make sure this is the right instruction */
1058 ASSERT((Opcode
& 0xF7) == 0xE7);
1060 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
1062 /* The OPSIZE prefix toggles the size */
1065 else if (State
->PrefixFlags
!= 0)
1067 /* Invalid prefix */
1068 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1076 /* Fetch the parameter */
1077 if (!Soft386FetchByte(State
, &Data
))
1079 /* Exception occurred */
1083 /* Set the port number to the parameter */
1088 /* The port number is in DX */
1089 Port
= State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
;
1094 /* Get the value from EAX */
1095 ULONG Data
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
1097 /* Write a dword to the I/O port */
1098 State
->IoReadCallback(State
, Port
, &Data
, sizeof(ULONG
));
1102 /* Get the value from AX */
1103 USHORT Data
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
1105 /* Write a word to the I/O port */
1106 State
->IoWriteCallback(State
, Port
, &Data
, sizeof(USHORT
));
1112 SOFT386_OPCODE_HANDLER(Soft386OpcodeShortJump
)
1116 /* Make sure this is the right instruction */
1117 ASSERT(Opcode
== 0xEB);
1119 /* Fetch the offset */
1120 if (!Soft386FetchByte(State
, (PUCHAR
)&Offset
))
1122 /* An exception occurred */
1126 /* Move the instruction pointer */
1127 State
->InstPtr
.Long
+= Offset
;
1132 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovRegImm
)
1134 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1136 /* Make sure this is the right instruction */
1137 ASSERT((Opcode
& 0xF8) == 0xB8);
1139 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
1141 /* The OPSIZE prefix toggles the size */
1144 else if (State
->PrefixFlags
!= 0)
1146 /* Invalid prefix */
1147 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1155 /* Fetch the dword */
1156 if (!Soft386FetchDword(State
, &Value
))
1158 /* Exception occurred */
1162 /* Store the value in the register */
1163 State
->GeneralRegs
[Opcode
& 0x07].Long
= Value
;
1169 /* Fetch the word */
1170 if (!Soft386FetchWord(State
, &Value
))
1172 /* Exception occurred */
1176 /* Store the value in the register */
1177 State
->GeneralRegs
[Opcode
& 0x07].LowWord
= Value
;
1183 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovByteRegImm
)
1187 /* Make sure this is the right instruction */
1188 ASSERT((Opcode
& 0xF8) == 0xB0);
1190 if (State
->PrefixFlags
!= 0)
1192 /* Invalid prefix */
1193 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1197 /* Fetch the byte */
1198 if (!Soft386FetchByte(State
, &Value
))
1200 /* Exception occurred */
1206 /* AH, CH, DH or BH */
1207 State
->GeneralRegs
[Opcode
& 0x03].HighByte
= Value
;
1211 /* AL, CL, DL or BL */
1212 State
->GeneralRegs
[Opcode
& 0x03].LowByte
= Value
;
1218 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddByteModrm
)
1220 UCHAR FirstValue
, SecondValue
, Result
;
1221 SOFT386_MOD_REG_RM ModRegRm
;
1222 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1224 /* Make sure this is the right instruction */
1225 ASSERT((Opcode
& 0xFD) == 0x00);
1227 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1229 /* The ADSIZE prefix toggles the size */
1230 AddressSize
= !AddressSize
;
1232 else if (State
->PrefixFlags
1233 & ~(SOFT386_PREFIX_ADSIZE
1234 | SOFT386_PREFIX_SEG
1235 | SOFT386_PREFIX_LOCK
))
1237 /* Invalid prefix */
1238 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1242 /* Get the operands */
1243 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1245 /* Exception occurred */
1249 if (!Soft386ReadModrmByteOperands(State
,
1254 /* Exception occurred */
1258 /* Calculate the result */
1259 Result
= FirstValue
+ SecondValue
;
1261 /* Update the flags */
1262 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1263 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
1264 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
1265 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
1266 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1267 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1268 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1270 /* Write back the result */
1271 return Soft386WriteModrmByteOperands(State
,
1273 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1277 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddModrm
)
1279 SOFT386_MOD_REG_RM ModRegRm
;
1280 BOOLEAN OperandSize
, AddressSize
;
1282 /* Make sure this is the right instruction */
1283 ASSERT((Opcode
& 0xFD) == 0x01);
1285 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1287 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1289 /* The ADSIZE prefix toggles the address size */
1290 AddressSize
= !AddressSize
;
1293 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1295 /* The OPSIZE prefix toggles the operand size */
1296 OperandSize
= !OperandSize
;
1299 if (State
->PrefixFlags
1300 & ~(SOFT386_PREFIX_ADSIZE
1301 | SOFT386_PREFIX_OPSIZE
1302 | SOFT386_PREFIX_SEG
1303 | SOFT386_PREFIX_LOCK
))
1305 /* Invalid prefix */
1306 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1310 /* Get the operands */
1311 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1313 /* Exception occurred */
1317 /* Check the operand size */
1320 ULONG FirstValue
, SecondValue
, Result
;
1322 if (!Soft386ReadModrmDwordOperands(State
,
1327 /* Exception occurred */
1331 /* Calculate the result */
1332 Result
= FirstValue
+ SecondValue
;
1334 /* Update the flags */
1335 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1336 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
1337 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
1338 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
1339 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1340 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1341 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1343 /* Write back the result */
1344 return Soft386WriteModrmDwordOperands(State
,
1346 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1351 USHORT FirstValue
, SecondValue
, Result
;
1353 if (!Soft386ReadModrmWordOperands(State
,
1358 /* Exception occurred */
1362 /* Calculate the result */
1363 Result
= FirstValue
+ SecondValue
;
1365 /* Update the flags */
1366 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1367 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
1368 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
1369 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
1370 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1371 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
1372 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1374 /* Write back the result */
1375 return Soft386WriteModrmWordOperands(State
,
1377 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1382 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddAl
)
1384 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
1385 UCHAR SecondValue
, Result
;
1387 /* Make sure this is the right instruction */
1388 ASSERT(Opcode
== 0x04);
1390 if (State
->PrefixFlags
)
1392 /* This opcode doesn't take any prefixes */
1393 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1397 if (!Soft386FetchByte(State
, &SecondValue
))
1399 /* Exception occurred */
1403 /* Calculate the result */
1404 Result
= FirstValue
+ SecondValue
;
1406 /* Update the flags */
1407 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1408 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
1409 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
1410 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
1411 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1412 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1413 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1415 /* Write back the result */
1416 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
1421 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddEax
)
1423 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1425 /* Make sure this is the right instruction */
1426 ASSERT(Opcode
== 0x05);
1428 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
1430 /* Invalid prefix */
1431 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1435 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1437 /* The OPSIZE prefix toggles the size */
1443 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
1444 ULONG SecondValue
, Result
;
1446 if (!Soft386FetchDword(State
, &SecondValue
))
1448 /* Exception occurred */
1452 /* Calculate the result */
1453 Result
= FirstValue
+ SecondValue
;
1455 /* Update the flags */
1456 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1457 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
1458 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
1459 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
1460 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1461 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1462 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1464 /* Write back the result */
1465 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
1469 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
1470 USHORT SecondValue
, Result
;
1472 if (!Soft386FetchWord(State
, &SecondValue
))
1474 /* Exception occurred */
1478 /* Calculate the result */
1479 Result
= FirstValue
+ SecondValue
;
1481 /* Update the flags */
1482 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1483 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
1484 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
1485 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
1486 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1487 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
1488 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1490 /* Write back the result */
1491 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
1497 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrByteModrm
)
1499 UCHAR FirstValue
, SecondValue
, Result
;
1500 SOFT386_MOD_REG_RM ModRegRm
;
1501 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1503 /* Make sure this is the right instruction */
1504 ASSERT((Opcode
& 0xFD) == 0x08);
1506 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1508 /* The ADSIZE prefix toggles the size */
1509 AddressSize
= !AddressSize
;
1511 else if (State
->PrefixFlags
1512 & ~(SOFT386_PREFIX_ADSIZE
1513 | SOFT386_PREFIX_SEG
1514 | SOFT386_PREFIX_LOCK
))
1516 /* Invalid prefix */
1517 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1521 /* Get the operands */
1522 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1524 /* Exception occurred */
1528 if (!Soft386ReadModrmByteOperands(State
,
1533 /* Exception occurred */
1537 /* Calculate the result */
1538 Result
= FirstValue
| SecondValue
;
1540 /* Update the flags */
1541 State
->Flags
.Cf
= FALSE
;
1542 State
->Flags
.Of
= FALSE
;
1543 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1544 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1545 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1547 /* Write back the result */
1548 return Soft386WriteModrmByteOperands(State
,
1550 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1554 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrModrm
)
1556 SOFT386_MOD_REG_RM ModRegRm
;
1557 BOOLEAN OperandSize
, AddressSize
;
1559 /* Make sure this is the right instruction */
1560 ASSERT((Opcode
& 0xFD) == 0x09);
1562 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1564 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1566 /* The ADSIZE prefix toggles the address size */
1567 AddressSize
= !AddressSize
;
1570 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1572 /* The OPSIZE prefix toggles the operand size */
1573 OperandSize
= !OperandSize
;
1576 if (State
->PrefixFlags
1577 & ~(SOFT386_PREFIX_ADSIZE
1578 | SOFT386_PREFIX_OPSIZE
1579 | SOFT386_PREFIX_SEG
1580 | SOFT386_PREFIX_LOCK
))
1582 /* Invalid prefix */
1583 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1587 /* Get the operands */
1588 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1590 /* Exception occurred */
1594 /* Check the operand size */
1597 ULONG FirstValue
, SecondValue
, Result
;
1599 if (!Soft386ReadModrmDwordOperands(State
,
1604 /* Exception occurred */
1608 /* Calculate the result */
1609 Result
= FirstValue
| SecondValue
;
1611 /* Update the flags */
1612 State
->Flags
.Cf
= FALSE
;
1613 State
->Flags
.Of
= FALSE
;
1614 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1615 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1616 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1618 /* Write back the result */
1619 return Soft386WriteModrmDwordOperands(State
,
1621 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1626 USHORT FirstValue
, SecondValue
, Result
;
1628 if (!Soft386ReadModrmWordOperands(State
,
1633 /* Exception occurred */
1637 /* Calculate the result */
1638 Result
= FirstValue
| SecondValue
;
1640 /* Update the flags */
1641 State
->Flags
.Cf
= FALSE
;
1642 State
->Flags
.Of
= FALSE
;
1643 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1644 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1645 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1647 /* Write back the result */
1648 return Soft386WriteModrmWordOperands(State
,
1650 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1655 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrAl
)
1657 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
1658 UCHAR SecondValue
, Result
;
1660 /* Make sure this is the right instruction */
1661 ASSERT(Opcode
== 0x0C);
1663 if (State
->PrefixFlags
)
1665 /* This opcode doesn't take any prefixes */
1666 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1670 if (!Soft386FetchByte(State
, &SecondValue
))
1672 /* Exception occurred */
1676 /* Calculate the result */
1677 Result
= FirstValue
| SecondValue
;
1679 /* Update the flags */
1680 State
->Flags
.Cf
= FALSE
;
1681 State
->Flags
.Of
= FALSE
;
1682 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1683 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1684 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1686 /* Write back the result */
1687 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
1692 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrEax
)
1694 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1696 /* Make sure this is the right instruction */
1697 ASSERT(Opcode
== 0x0D);
1699 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
1701 /* Invalid prefix */
1702 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1706 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1708 /* The OPSIZE prefix toggles the size */
1714 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
1715 ULONG SecondValue
, Result
;
1717 if (!Soft386FetchDword(State
, &SecondValue
))
1719 /* Exception occurred */
1723 /* Calculate the result */
1724 Result
= FirstValue
| SecondValue
;
1726 /* Update the flags */
1727 State
->Flags
.Cf
= FALSE
;
1728 State
->Flags
.Of
= FALSE
;
1729 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1730 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1731 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1733 /* Write back the result */
1734 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
1738 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
1739 USHORT SecondValue
, Result
;
1741 if (!Soft386FetchWord(State
, &SecondValue
))
1743 /* Exception occurred */
1747 /* Calculate the result */
1748 Result
= FirstValue
| SecondValue
;
1750 /* Update the flags */
1751 State
->Flags
.Cf
= FALSE
;
1752 State
->Flags
.Of
= FALSE
;
1753 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1754 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
1755 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1757 /* Write back the result */
1758 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
1764 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndByteModrm
)
1766 UCHAR FirstValue
, SecondValue
, Result
;
1767 SOFT386_MOD_REG_RM ModRegRm
;
1768 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1770 /* Make sure this is the right instruction */
1771 ASSERT((Opcode
& 0xFD) == 0x20);
1773 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1775 /* The ADSIZE prefix toggles the size */
1776 AddressSize
= !AddressSize
;
1778 else if (State
->PrefixFlags
1779 & ~(SOFT386_PREFIX_ADSIZE
1780 | SOFT386_PREFIX_SEG
1781 | SOFT386_PREFIX_LOCK
))
1783 /* Invalid prefix */
1784 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1788 /* Get the operands */
1789 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1791 /* Exception occurred */
1795 if (!Soft386ReadModrmByteOperands(State
,
1800 /* Exception occurred */
1804 /* Calculate the result */
1805 Result
= FirstValue
& SecondValue
;
1807 /* Update the flags */
1808 State
->Flags
.Cf
= FALSE
;
1809 State
->Flags
.Of
= FALSE
;
1810 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1811 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1812 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1814 /* Write back the result */
1815 return Soft386WriteModrmByteOperands(State
,
1817 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1821 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndModrm
)
1823 SOFT386_MOD_REG_RM ModRegRm
;
1824 BOOLEAN OperandSize
, AddressSize
;
1826 /* Make sure this is the right instruction */
1827 ASSERT((Opcode
& 0xFD) == 0x21);
1829 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1831 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1833 /* The ADSIZE prefix toggles the address size */
1834 AddressSize
= !AddressSize
;
1837 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1839 /* The OPSIZE prefix toggles the operand size */
1840 OperandSize
= !OperandSize
;
1843 if (State
->PrefixFlags
1844 & ~(SOFT386_PREFIX_ADSIZE
1845 | SOFT386_PREFIX_OPSIZE
1846 | SOFT386_PREFIX_SEG
1847 | SOFT386_PREFIX_LOCK
))
1849 /* Invalid prefix */
1850 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1854 /* Get the operands */
1855 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1857 /* Exception occurred */
1861 /* Check the operand size */
1864 ULONG FirstValue
, SecondValue
, Result
;
1866 if (!Soft386ReadModrmDwordOperands(State
,
1871 /* Exception occurred */
1875 /* Calculate the result */
1876 Result
= FirstValue
& SecondValue
;
1878 /* Update the flags */
1879 State
->Flags
.Cf
= FALSE
;
1880 State
->Flags
.Of
= FALSE
;
1881 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1882 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1883 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1885 /* Write back the result */
1886 return Soft386WriteModrmDwordOperands(State
,
1888 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1893 USHORT FirstValue
, SecondValue
, Result
;
1895 if (!Soft386ReadModrmWordOperands(State
,
1900 /* Exception occurred */
1904 /* Calculate the result */
1905 Result
= FirstValue
& SecondValue
;
1907 /* Update the flags */
1908 State
->Flags
.Cf
= FALSE
;
1909 State
->Flags
.Of
= FALSE
;
1910 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1911 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1912 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1914 /* Write back the result */
1915 return Soft386WriteModrmWordOperands(State
,
1917 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1922 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndAl
)
1924 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
1925 UCHAR SecondValue
, Result
;
1927 /* Make sure this is the right instruction */
1928 ASSERT(Opcode
== 0x24);
1930 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
1932 /* Invalid prefix */
1933 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1937 if (!Soft386FetchByte(State
, &SecondValue
))
1939 /* Exception occurred */
1943 /* Calculate the result */
1944 Result
= FirstValue
& SecondValue
;
1946 /* Update the flags */
1947 State
->Flags
.Cf
= FALSE
;
1948 State
->Flags
.Of
= FALSE
;
1949 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1950 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1951 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1953 /* Write back the result */
1954 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
1959 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndEax
)
1961 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1963 /* Make sure this is the right instruction */
1964 ASSERT(Opcode
== 0x25);
1966 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
1968 /* Invalid prefix */
1969 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1973 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1975 /* The OPSIZE prefix toggles the size */
1981 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
1982 ULONG SecondValue
, Result
;
1984 if (!Soft386FetchDword(State
, &SecondValue
))
1986 /* Exception occurred */
1990 /* Calculate the result */
1991 Result
= FirstValue
& SecondValue
;
1993 /* Update the flags */
1994 State
->Flags
.Cf
= FALSE
;
1995 State
->Flags
.Of
= FALSE
;
1996 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1997 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1998 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2000 /* Write back the result */
2001 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
2005 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
2006 USHORT SecondValue
, Result
;
2008 if (!Soft386FetchWord(State
, &SecondValue
))
2010 /* Exception occurred */
2014 /* Calculate the result */
2015 Result
= FirstValue
& SecondValue
;
2017 /* Update the flags */
2018 State
->Flags
.Cf
= FALSE
;
2019 State
->Flags
.Of
= FALSE
;
2020 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2021 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
2022 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2024 /* Write back the result */
2025 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
2031 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorByteModrm
)
2033 UCHAR FirstValue
, SecondValue
, Result
;
2034 SOFT386_MOD_REG_RM ModRegRm
;
2035 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2037 /* Make sure this is the right instruction */
2038 ASSERT((Opcode
& 0xFD) == 0x30);
2040 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2042 /* The ADSIZE prefix toggles the size */
2043 AddressSize
= !AddressSize
;
2045 else if (State
->PrefixFlags
2046 & ~(SOFT386_PREFIX_ADSIZE
2047 | SOFT386_PREFIX_SEG
2048 | SOFT386_PREFIX_LOCK
))
2050 /* Invalid prefix */
2051 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2055 /* Get the operands */
2056 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2058 /* Exception occurred */
2062 if (!Soft386ReadModrmByteOperands(State
,
2067 /* Exception occurred */
2071 /* Calculate the result */
2072 Result
= FirstValue
^ SecondValue
;
2074 /* Update the flags */
2075 State
->Flags
.Cf
= FALSE
;
2076 State
->Flags
.Of
= FALSE
;
2077 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2078 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2079 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2081 /* Write back the result */
2082 return Soft386WriteModrmByteOperands(State
,
2084 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2088 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorModrm
)
2090 SOFT386_MOD_REG_RM ModRegRm
;
2091 BOOLEAN OperandSize
, AddressSize
;
2093 /* Make sure this is the right instruction */
2094 ASSERT((Opcode
& 0xFD) == 0x31);
2096 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2098 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2100 /* The ADSIZE prefix toggles the address size */
2101 AddressSize
= !AddressSize
;
2104 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2106 /* The OPSIZE prefix toggles the operand size */
2107 OperandSize
= !OperandSize
;
2110 if (State
->PrefixFlags
2111 & ~(SOFT386_PREFIX_ADSIZE
2112 | SOFT386_PREFIX_OPSIZE
2113 | SOFT386_PREFIX_SEG
2114 | SOFT386_PREFIX_LOCK
))
2116 /* Invalid prefix */
2117 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2121 /* Get the operands */
2122 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2124 /* Exception occurred */
2128 /* Check the operand size */
2131 ULONG FirstValue
, SecondValue
, Result
;
2133 if (!Soft386ReadModrmDwordOperands(State
,
2138 /* Exception occurred */
2142 /* Calculate the result */
2143 Result
= FirstValue
^ SecondValue
;
2145 /* Update the flags */
2146 State
->Flags
.Cf
= FALSE
;
2147 State
->Flags
.Of
= FALSE
;
2148 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2149 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2150 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2152 /* Write back the result */
2153 return Soft386WriteModrmDwordOperands(State
,
2155 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2160 USHORT FirstValue
, SecondValue
, Result
;
2162 if (!Soft386ReadModrmWordOperands(State
,
2167 /* Exception occurred */
2171 /* Calculate the result */
2172 Result
= FirstValue
^ SecondValue
;
2174 /* Update the flags */
2175 State
->Flags
.Cf
= FALSE
;
2176 State
->Flags
.Of
= FALSE
;
2177 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2178 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2179 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2181 /* Write back the result */
2182 return Soft386WriteModrmWordOperands(State
,
2184 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2189 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorAl
)
2191 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
2192 UCHAR SecondValue
, Result
;
2194 /* Make sure this is the right instruction */
2195 ASSERT(Opcode
== 0x34);
2197 if (State
->PrefixFlags
)
2199 /* This opcode doesn't take any prefixes */
2200 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2204 if (!Soft386FetchByte(State
, &SecondValue
))
2206 /* Exception occurred */
2210 /* Calculate the result */
2211 Result
= FirstValue
^ SecondValue
;
2213 /* Update the flags */
2214 State
->Flags
.Cf
= FALSE
;
2215 State
->Flags
.Of
= FALSE
;
2216 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2217 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2218 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2220 /* Write back the result */
2221 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
2226 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorEax
)
2228 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2230 /* Make sure this is the right instruction */
2231 ASSERT(Opcode
== 0x35);
2233 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
2235 /* Invalid prefix */
2236 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2240 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2242 /* The OPSIZE prefix toggles the size */
2248 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
2249 ULONG SecondValue
, Result
;
2251 if (!Soft386FetchDword(State
, &SecondValue
))
2253 /* Exception occurred */
2257 /* Calculate the result */
2258 Result
= FirstValue
^ SecondValue
;
2260 /* Update the flags */
2261 State
->Flags
.Cf
= FALSE
;
2262 State
->Flags
.Of
= FALSE
;
2263 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2264 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2265 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2267 /* Write back the result */
2268 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
2272 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
2273 USHORT SecondValue
, Result
;
2275 if (!Soft386FetchWord(State
, &SecondValue
))
2277 /* Exception occurred */
2281 /* Calculate the result */
2282 Result
= FirstValue
^ SecondValue
;
2284 /* Update the flags */
2285 State
->Flags
.Cf
= FALSE
;
2286 State
->Flags
.Of
= FALSE
;
2287 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2288 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
2289 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2291 /* Write back the result */
2292 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
2298 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestByteModrm
)
2300 UCHAR FirstValue
, SecondValue
, Result
;
2301 SOFT386_MOD_REG_RM ModRegRm
;
2302 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2304 /* Make sure this is the right instruction */
2305 ASSERT(Opcode
== 0x84);
2307 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2309 /* The ADSIZE prefix toggles the size */
2310 AddressSize
= !AddressSize
;
2312 else if (State
->PrefixFlags
2313 & ~(SOFT386_PREFIX_ADSIZE
2314 | SOFT386_PREFIX_SEG
2315 | SOFT386_PREFIX_LOCK
))
2317 /* Invalid prefix */
2318 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2322 /* Get the operands */
2323 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2325 /* Exception occurred */
2329 if (!Soft386ReadModrmByteOperands(State
,
2334 /* Exception occurred */
2337 /* Calculate the result */
2338 Result
= FirstValue
& SecondValue
;
2340 /* Update the flags */
2341 State
->Flags
.Cf
= FALSE
;
2342 State
->Flags
.Of
= FALSE
;
2343 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2344 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2345 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2347 /* The result is discarded */
2351 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestModrm
)
2353 SOFT386_MOD_REG_RM ModRegRm
;
2354 BOOLEAN OperandSize
, AddressSize
;
2356 /* Make sure this is the right instruction */
2357 ASSERT(Opcode
== 0x85);
2359 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2361 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2363 /* The ADSIZE prefix toggles the address size */
2364 AddressSize
= !AddressSize
;
2367 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2369 /* The OPSIZE prefix toggles the operand size */
2370 OperandSize
= !OperandSize
;
2373 if (State
->PrefixFlags
2374 & ~(SOFT386_PREFIX_ADSIZE
2375 | SOFT386_PREFIX_OPSIZE
2376 | SOFT386_PREFIX_SEG
2377 | SOFT386_PREFIX_LOCK
))
2379 /* Invalid prefix */
2380 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2384 /* Get the operands */
2385 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2387 /* Exception occurred */
2391 /* Check the operand size */
2394 ULONG FirstValue
, SecondValue
, Result
;
2396 if (!Soft386ReadModrmDwordOperands(State
,
2401 /* Exception occurred */
2405 /* Calculate the result */
2406 Result
= FirstValue
& SecondValue
;
2408 /* Update the flags */
2409 State
->Flags
.Cf
= FALSE
;
2410 State
->Flags
.Of
= FALSE
;
2411 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2412 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2413 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2417 USHORT FirstValue
, SecondValue
, Result
;
2419 if (!Soft386ReadModrmWordOperands(State
,
2424 /* Exception occurred */
2428 /* Calculate the result */
2429 Result
= FirstValue
& SecondValue
;
2431 /* Update the flags */
2432 State
->Flags
.Cf
= FALSE
;
2433 State
->Flags
.Of
= FALSE
;
2434 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2435 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2436 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2439 /* The result is discarded */
2443 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestAl
)
2445 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
2446 UCHAR SecondValue
, Result
;
2448 /* Make sure this is the right instruction */
2449 ASSERT(Opcode
== 0xA8);
2451 if (State
->PrefixFlags
)
2453 /* This opcode doesn't take any prefixes */
2454 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2458 if (!Soft386FetchByte(State
, &SecondValue
))
2460 /* Exception occurred */
2464 /* Calculate the result */
2465 Result
= FirstValue
& SecondValue
;
2467 /* Update the flags */
2468 State
->Flags
.Cf
= FALSE
;
2469 State
->Flags
.Of
= FALSE
;
2470 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2471 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2472 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2474 /* The result is discarded */
2478 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestEax
)
2480 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2482 /* Make sure this is the right instruction */
2483 ASSERT(Opcode
== 0xA9);
2485 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
2487 /* Invalid prefix */
2488 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2492 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2494 /* The OPSIZE prefix toggles the size */
2500 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
2501 ULONG SecondValue
, Result
;
2503 if (!Soft386FetchDword(State
, &SecondValue
))
2505 /* Exception occurred */
2509 /* Calculate the result */
2510 Result
= FirstValue
& SecondValue
;
2512 /* Update the flags */
2513 State
->Flags
.Cf
= FALSE
;
2514 State
->Flags
.Of
= FALSE
;
2515 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2516 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2517 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2521 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
2522 USHORT SecondValue
, Result
;
2524 if (!Soft386FetchWord(State
, &SecondValue
))
2526 /* Exception occurred */
2530 /* Calculate the result */
2531 Result
= FirstValue
& SecondValue
;
2533 /* Update the flags */
2534 State
->Flags
.Cf
= FALSE
;
2535 State
->Flags
.Of
= FALSE
;
2536 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2537 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
2538 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2541 /* The result is discarded */
2545 SOFT386_OPCODE_HANDLER(Soft386OpcodeXchgByteModrm
)
2547 UCHAR FirstValue
, SecondValue
;
2548 SOFT386_MOD_REG_RM ModRegRm
;
2549 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2551 /* Make sure this is the right instruction */
2552 ASSERT(Opcode
== 0x86);
2554 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2556 /* The ADSIZE prefix toggles the size */
2557 AddressSize
= !AddressSize
;
2559 else if (State
->PrefixFlags
2560 & ~(SOFT386_PREFIX_ADSIZE
2561 | SOFT386_PREFIX_SEG
2562 | SOFT386_PREFIX_LOCK
))
2564 /* Invalid prefix */
2565 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2569 /* Get the operands */
2570 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2572 /* Exception occurred */
2576 if (!Soft386ReadModrmByteOperands(State
,
2581 /* Exception occurred */
2585 /* Write the value from the register to the R/M */
2586 if (!Soft386WriteModrmByteOperands(State
,
2591 /* Exception occurred */
2595 /* Write the value from the R/M to the register */
2596 if (!Soft386WriteModrmByteOperands(State
,
2601 /* Exception occurred */
2608 SOFT386_OPCODE_HANDLER(Soft386OpcodeXchgModrm
)
2610 SOFT386_MOD_REG_RM ModRegRm
;
2611 BOOLEAN OperandSize
, AddressSize
;
2613 /* Make sure this is the right instruction */
2614 ASSERT(Opcode
== 0x87);
2616 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2618 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2620 /* The ADSIZE prefix toggles the address size */
2621 AddressSize
= !AddressSize
;
2624 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2626 /* The OPSIZE prefix toggles the operand size */
2627 OperandSize
= !OperandSize
;
2630 if (State
->PrefixFlags
2631 & ~(SOFT386_PREFIX_ADSIZE
2632 | SOFT386_PREFIX_OPSIZE
2633 | SOFT386_PREFIX_SEG
2634 | SOFT386_PREFIX_LOCK
))
2636 /* Invalid prefix */
2637 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2641 /* Get the operands */
2642 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2644 /* Exception occurred */
2648 /* Check the operand size */
2651 ULONG FirstValue
, SecondValue
;
2653 if (!Soft386ReadModrmDwordOperands(State
,
2658 /* Exception occurred */
2662 /* Write the value from the register to the R/M */
2663 if (!Soft386WriteModrmDwordOperands(State
,
2668 /* Exception occurred */
2672 /* Write the value from the R/M to the register */
2673 if (!Soft386WriteModrmDwordOperands(State
,
2678 /* Exception occurred */
2684 USHORT FirstValue
, SecondValue
;
2686 if (!Soft386ReadModrmWordOperands(State
,
2691 /* Exception occurred */
2695 /* Write the value from the register to the R/M */
2696 if (!Soft386WriteModrmWordOperands(State
,
2701 /* Exception occurred */
2705 /* Write the value from the R/M to the register */
2706 if (!Soft386WriteModrmWordOperands(State
,
2711 /* Exception occurred */
2716 /* The result is discarded */
2720 SOFT386_OPCODE_HANDLER(Soft386OpcodePushEs
)
2722 /* Call the internal API */
2723 return Soft386StackPush(State
, State
->SegmentRegs
[SOFT386_REG_ES
].Selector
);
2726 SOFT386_OPCODE_HANDLER(Soft386OpcodePopEs
)
2730 if (!Soft386StackPop(State
, &NewSelector
))
2732 /* Exception occurred */
2736 /* Call the internal API */
2737 return Soft386LoadSegment(State
, SOFT386_REG_ES
, LOWORD(NewSelector
));
2740 SOFT386_OPCODE_HANDLER(Soft386OpcodePushCs
)
2742 /* Call the internal API */
2743 return Soft386StackPush(State
, State
->SegmentRegs
[SOFT386_REG_CS
].Selector
);
2746 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcByteModrm
)
2748 UCHAR FirstValue
, SecondValue
, Result
;
2749 SOFT386_MOD_REG_RM ModRegRm
;
2750 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2752 /* Make sure this is the right instruction */
2753 ASSERT((Opcode
& 0xFD) == 0x10);
2755 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2757 /* The ADSIZE prefix toggles the size */
2758 AddressSize
= !AddressSize
;
2760 else if (State
->PrefixFlags
2761 & ~(SOFT386_PREFIX_ADSIZE
2762 | SOFT386_PREFIX_SEG
2763 | SOFT386_PREFIX_LOCK
))
2765 /* Invalid prefix */
2766 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2770 /* Get the operands */
2771 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2773 /* Exception occurred */
2777 if (!Soft386ReadModrmByteOperands(State
,
2782 /* Exception occurred */
2786 /* Calculate the result */
2787 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2789 /* Special exception for CF */
2790 State
->Flags
.Cf
= State
->Flags
.Cf
2791 && ((FirstValue
== 0xFF) || (SecondValue
== 0xFF));
2793 /* Update the flags */
2794 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2795 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
2796 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
2797 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
2798 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2799 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2800 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2802 /* Write back the result */
2803 return Soft386WriteModrmByteOperands(State
,
2805 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2809 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcModrm
)
2811 SOFT386_MOD_REG_RM ModRegRm
;
2812 BOOLEAN OperandSize
, AddressSize
;
2814 /* Make sure this is the right instruction */
2815 ASSERT((Opcode
& 0xFD) == 0x11);
2817 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2819 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2821 /* The ADSIZE prefix toggles the address size */
2822 AddressSize
= !AddressSize
;
2825 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2827 /* The OPSIZE prefix toggles the operand size */
2828 OperandSize
= !OperandSize
;
2831 if (State
->PrefixFlags
2832 & ~(SOFT386_PREFIX_ADSIZE
2833 | SOFT386_PREFIX_OPSIZE
2834 | SOFT386_PREFIX_SEG
2835 | SOFT386_PREFIX_LOCK
))
2837 /* Invalid prefix */
2838 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2842 /* Get the operands */
2843 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2845 /* Exception occurred */
2849 /* Check the operand size */
2852 ULONG FirstValue
, SecondValue
, Result
;
2854 if (!Soft386ReadModrmDwordOperands(State
,
2859 /* Exception occurred */
2863 /* Calculate the result */
2864 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2866 /* Special exception for CF */
2867 State
->Flags
.Cf
= State
->Flags
.Cf
2868 && ((FirstValue
== 0xFFFFFFFF) || (SecondValue
== 0xFFFFFFFF));
2870 /* Update the flags */
2871 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2872 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
2873 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
2874 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
2875 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2876 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2877 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2879 /* Write back the result */
2880 return Soft386WriteModrmDwordOperands(State
,
2882 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2887 USHORT FirstValue
, SecondValue
, Result
;
2889 if (!Soft386ReadModrmWordOperands(State
,
2894 /* Exception occurred */
2898 /* Calculate the result */
2899 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2901 /* Special exception for CF */
2902 State
->Flags
.Cf
= State
->Flags
.Cf
2903 && ((FirstValue
== 0xFFFF) || (SecondValue
== 0xFFFF));
2905 /* Update the flags */
2906 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2907 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
2908 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
2909 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
2910 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2911 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
2912 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2914 /* Write back the result */
2915 return Soft386WriteModrmWordOperands(State
,
2917 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2923 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcAl
)
2925 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
2926 UCHAR SecondValue
, Result
;
2928 /* Make sure this is the right instruction */
2929 ASSERT(Opcode
== 0x14);
2931 if (State
->PrefixFlags
)
2933 /* This opcode doesn't take any prefixes */
2934 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2938 if (!Soft386FetchByte(State
, &SecondValue
))
2940 /* Exception occurred */
2944 /* Calculate the result */
2945 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2947 /* Special exception for CF */
2948 State
->Flags
.Cf
= State
->Flags
.Cf
&&
2949 ((FirstValue
== 0xFF) || (SecondValue
== 0xFF));
2951 /* Update the flags */
2952 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2953 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
2954 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
2955 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
2956 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2957 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2958 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2960 /* Write back the result */
2961 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
2966 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcEax
)
2968 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2970 /* Make sure this is the right instruction */
2971 ASSERT(Opcode
== 0x15);
2973 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
2975 /* Invalid prefix */
2976 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2980 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2982 /* The OPSIZE prefix toggles the size */
2988 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
2989 ULONG SecondValue
, Result
;
2991 if (!Soft386FetchDword(State
, &SecondValue
))
2993 /* Exception occurred */
2997 /* Calculate the result */
2998 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
3000 /* Special exception for CF */
3001 State
->Flags
.Cf
= State
->Flags
.Cf
&&
3002 ((FirstValue
== 0xFFFFFFFF) || (SecondValue
== 0xFFFFFFFF));
3004 /* Update the flags */
3005 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
3006 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
3007 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
3008 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
3009 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3010 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
3011 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3013 /* Write back the result */
3014 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
3018 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
3019 USHORT SecondValue
, Result
;
3021 if (!Soft386FetchWord(State
, &SecondValue
))
3023 /* Exception occurred */
3027 /* Calculate the result */
3028 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
3030 /* Special exception for CF */
3031 State
->Flags
.Cf
= State
->Flags
.Cf
&&
3032 ((FirstValue
== 0xFFFF) || (SecondValue
== 0xFFFF));
3034 /* Update the flags */
3035 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
3036 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
3037 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
3038 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
3039 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3040 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
3041 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3043 /* Write back the result */
3044 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
3050 SOFT386_OPCODE_HANDLER(Soft386OpcodePushSs
)
3052 /* Call the internal API */
3053 return Soft386StackPush(State
, State
->SegmentRegs
[SOFT386_REG_SS
].Selector
);
3056 SOFT386_OPCODE_HANDLER(Soft386OpcodePopSs
)
3060 if (!Soft386StackPop(State
, &NewSelector
))
3062 /* Exception occurred */
3066 /* Call the internal API */
3067 return Soft386LoadSegment(State
, SOFT386_REG_SS
, LOWORD(NewSelector
));
3070 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbByteModrm
)
3072 // TODO: NOT IMPLEMENTED
3078 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbModrm
)
3080 // TODO: NOT IMPLEMENTED
3086 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbAl
)
3088 // TODO: NOT IMPLEMENTED
3094 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbEax
)
3096 // TODO: NOT IMPLEMENTED
3102 SOFT386_OPCODE_HANDLER(Soft386OpcodePushDs
)
3104 /* Call the internal API */
3105 return Soft386StackPush(State
, State
->SegmentRegs
[SOFT386_REG_DS
].Selector
);
3108 SOFT386_OPCODE_HANDLER(Soft386OpcodePopDs
)
3112 if (!Soft386StackPop(State
, &NewSelector
))
3114 /* Exception occurred */
3118 /* Call the internal API */
3119 return Soft386LoadSegment(State
, SOFT386_REG_DS
, LOWORD(NewSelector
));
3122 SOFT386_OPCODE_HANDLER(Soft386OpcodeDaa
)
3124 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3125 BOOLEAN Carry
= State
->Flags
.Cf
;
3127 /* Clear the carry flag */
3128 State
->Flags
.Cf
= FALSE
;
3130 /* Check if the first BCD digit is invalid or there was a carry from it */
3131 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3134 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
+= 0x06;
3135 if (State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
< 0x06)
3137 /* A carry occurred */
3138 State
->Flags
.Cf
= TRUE
;
3141 /* Set the adjust flag */
3142 State
->Flags
.Af
= TRUE
;
3145 /* Check if the second BCD digit is invalid or there was a carry from it */
3146 if ((Value
> 0x99) || Carry
)
3149 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
+= 0x60;
3151 /* There was a carry */
3152 State
->Flags
.Cf
= TRUE
;
3158 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubByteModrm
)
3160 UCHAR FirstValue
, SecondValue
, Result
;
3161 SOFT386_MOD_REG_RM ModRegRm
;
3162 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3164 /* Make sure this is the right instruction */
3165 ASSERT((Opcode
& 0xED) == 0x28);
3167 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3169 /* The ADSIZE prefix toggles the size */
3170 AddressSize
= !AddressSize
;
3172 else if (State
->PrefixFlags
3173 & ~(SOFT386_PREFIX_ADSIZE
3174 | SOFT386_PREFIX_SEG
3175 | SOFT386_PREFIX_LOCK
))
3177 /* Invalid prefix */
3178 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3182 /* Get the operands */
3183 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3185 /* Exception occurred */
3189 if (!Soft386ReadModrmByteOperands(State
,
3194 /* Exception occurred */
3198 /* Check if this is the instruction that writes to R/M */
3199 if (!(Opcode
& SOFT386_OPCODE_WRITE_REG
))
3201 /* Swap the order */
3202 FirstValue
^= SecondValue
;
3203 SecondValue
^= FirstValue
;
3204 FirstValue
^= SecondValue
;
3207 /* Calculate the result */
3208 Result
= FirstValue
- SecondValue
;
3210 /* Update the flags */
3211 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3212 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) != (SecondValue
& SIGN_FLAG_BYTE
))
3213 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
3214 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3215 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3216 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
3217 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3219 /* Check if this is not a CMP */
3220 if (!(Opcode
& 0x10))
3222 /* Write back the result */
3223 return Soft386WriteModrmByteOperands(State
,
3225 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3230 /* Discard the result */
3235 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubModrm
)
3237 SOFT386_MOD_REG_RM ModRegRm
;
3238 BOOLEAN OperandSize
, AddressSize
;
3240 /* Make sure this is the right instruction */
3241 ASSERT((Opcode
& 0xED) == 0x29);
3243 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3245 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3247 /* The ADSIZE prefix toggles the address size */
3248 AddressSize
= !AddressSize
;
3251 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
3253 /* The OPSIZE prefix toggles the operand size */
3254 OperandSize
= !OperandSize
;
3257 if (State
->PrefixFlags
3258 & ~(SOFT386_PREFIX_ADSIZE
3259 | SOFT386_PREFIX_OPSIZE
3260 | SOFT386_PREFIX_SEG
3261 | SOFT386_PREFIX_LOCK
))
3263 /* Invalid prefix */
3264 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3268 /* Get the operands */
3269 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3271 /* Exception occurred */
3275 /* Check the operand size */
3278 ULONG FirstValue
, SecondValue
, Result
;
3280 if (!Soft386ReadModrmDwordOperands(State
,
3285 /* Exception occurred */
3289 /* Check if this is the instruction that writes to R/M */
3290 if (!(Opcode
& SOFT386_OPCODE_WRITE_REG
))
3292 /* Swap the order */
3293 FirstValue
^= SecondValue
;
3294 SecondValue
^= FirstValue
;
3295 FirstValue
^= SecondValue
;
3298 /* Calculate the result */
3299 Result
= FirstValue
- SecondValue
;
3301 /* Update the flags */
3302 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3303 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) != (SecondValue
& SIGN_FLAG_LONG
))
3304 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
3305 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3306 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3307 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
3308 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3310 /* Check if this is not a CMP */
3311 if (!(Opcode
& 0x10))
3313 /* Write back the result */
3314 return Soft386WriteModrmDwordOperands(State
,
3316 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3321 /* Discard the result */
3327 USHORT FirstValue
, SecondValue
, Result
;
3329 if (!Soft386ReadModrmWordOperands(State
,
3334 /* Exception occurred */
3338 /* Check if this is the instruction that writes to R/M */
3339 if (!(Opcode
& SOFT386_OPCODE_WRITE_REG
))
3341 /* Swap the order */
3342 FirstValue
^= SecondValue
;
3343 SecondValue
^= FirstValue
;
3344 FirstValue
^= SecondValue
;
3347 /* Calculate the result */
3348 Result
= FirstValue
- SecondValue
;
3350 /* Update the flags */
3351 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3352 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) != (SecondValue
& SIGN_FLAG_WORD
))
3353 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
3354 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3355 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3356 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
3357 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3359 /* Check if this is not a CMP */
3360 if (!(Opcode
& 0x10))
3362 /* Write back the result */
3363 return Soft386WriteModrmWordOperands(State
,
3365 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3370 /* Discard the result */
3377 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubAl
)
3379 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3380 UCHAR SecondValue
, Result
;
3382 /* Make sure this is the right instruction */
3383 ASSERT((Opcode
& 0xEF) == 0x2C);
3385 if (State
->PrefixFlags
)
3387 /* This opcode doesn't take any prefixes */
3388 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3392 if (!Soft386FetchByte(State
, &SecondValue
))
3394 /* Exception occurred */
3398 /* Calculate the result */
3399 Result
= FirstValue
- SecondValue
;
3401 /* Update the flags */
3402 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3403 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) != (SecondValue
& SIGN_FLAG_BYTE
))
3404 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
3405 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3406 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3407 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
3408 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3410 /* Check if this is not a CMP */
3411 if (!(Opcode
& 0x10))
3413 /* Write back the result */
3414 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
3420 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubEax
)
3422 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3424 /* Make sure this is the right instruction */
3425 ASSERT((Opcode
& 0xEF) == 0x2D);
3427 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
3429 /* Invalid prefix */
3430 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3434 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
3436 /* The OPSIZE prefix toggles the size */
3442 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
3443 ULONG SecondValue
, Result
;
3445 if (!Soft386FetchDword(State
, &SecondValue
))
3447 /* Exception occurred */
3451 /* Calculate the result */
3452 Result
= FirstValue
- SecondValue
;
3454 /* Update the flags */
3455 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3456 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) != (SecondValue
& SIGN_FLAG_LONG
))
3457 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
3458 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3459 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3460 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
3461 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3463 /* Check if this is not a CMP */
3464 if (!(Opcode
& 0x10))
3466 /* Write back the result */
3467 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
3472 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
3473 USHORT SecondValue
, Result
;
3475 if (!Soft386FetchWord(State
, &SecondValue
))
3477 /* Exception occurred */
3481 /* Calculate the result */
3482 Result
= FirstValue
- SecondValue
;
3484 /* Update the flags */
3485 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3486 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) != (SecondValue
& SIGN_FLAG_WORD
))
3487 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
3488 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3489 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3490 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
3491 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3493 /* Write back the result */
3494 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
3500 SOFT386_OPCODE_HANDLER(Soft386OpcodeDas
)
3502 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3503 BOOLEAN Carry
= State
->Flags
.Cf
;
3505 /* Clear the carry flag */
3506 State
->Flags
.Cf
= FALSE
;
3508 /* Check if the first BCD digit is invalid or there was a borrow */
3509 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3512 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
-= 0x06;
3513 if (State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
> 0xFB)
3515 /* A borrow occurred */
3516 State
->Flags
.Cf
= TRUE
;
3519 /* Set the adjust flag */
3520 State
->Flags
.Af
= TRUE
;
3523 /* Check if the second BCD digit is invalid or there was a borrow */
3524 if ((Value
> 0x99) || Carry
)
3527 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
-= 0x60;
3529 /* There was a borrow */
3530 State
->Flags
.Cf
= TRUE
;
3536 SOFT386_OPCODE_HANDLER(Soft386OpcodeAaa
)
3538 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3541 * Check if the value in AL is not a valid BCD digit,
3542 * or there was a carry from the lowest 4 bits of AL
3544 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3547 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
+= 0x06;
3548 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
++;
3551 State
->Flags
.Cf
= State
->Flags
.Af
= TRUE
;
3555 /* Clear CF and AF */
3556 State
->Flags
.Cf
= State
->Flags
.Af
= FALSE
;
3559 /* Keep only the lowest 4 bits of AL */
3560 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
&= 0x0F;
3565 SOFT386_OPCODE_HANDLER(Soft386OpcodeAas
)
3567 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3570 * Check if the value in AL is not a valid BCD digit,
3571 * or there was a borrow from the lowest 4 bits of AL
3573 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3576 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
-= 0x06;
3577 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
--;
3580 State
->Flags
.Cf
= State
->Flags
.Af
= TRUE
;
3584 /* Clear CF and AF */
3585 State
->Flags
.Cf
= State
->Flags
.Af
= FALSE
;
3588 /* Keep only the lowest 4 bits of AL */
3589 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
&= 0x0F;
3594 SOFT386_OPCODE_HANDLER(Soft386OpcodePushAll
)
3597 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3598 SOFT386_REG SavedEsp
= State
->GeneralRegs
[SOFT386_REG_ESP
];
3600 /* Make sure this is the right instruction */
3601 ASSERT(Opcode
== 0x60);
3603 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
3605 /* The OPSIZE prefix toggles the size */
3610 /* Invalid prefix */
3611 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3615 /* Push all the registers in order */
3616 for (i
= 0; i
< SOFT386_NUM_GEN_REGS
; i
++)
3618 if (i
== SOFT386_REG_ESP
)
3620 /* Use the saved ESP instead */
3621 if (!Soft386StackPush(State
, Size
? SavedEsp
.Long
: SavedEsp
.LowWord
))
3623 /* Exception occurred */
3629 /* Push the register */
3630 if (!Soft386StackPush(State
, Size
? State
->GeneralRegs
[i
].Long
3631 : State
->GeneralRegs
[i
].LowWord
))
3633 /* Exception occurred */
3642 SOFT386_OPCODE_HANDLER(Soft386OpcodePopAll
)
3645 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3648 /* Make sure this is the right instruction */
3649 ASSERT(Opcode
== 0x61);
3651 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
3653 /* The OPSIZE prefix toggles the size */
3658 /* Invalid prefix */
3659 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3663 /* Pop all the registers in reverse order */
3664 for (i
= SOFT386_NUM_GEN_REGS
- 1; i
>= 0; i
--)
3667 if (!Soft386StackPop(State
, &Value
))
3669 /* Exception occurred */
3673 /* Don't modify ESP */
3674 if (i
!= SOFT386_REG_ESP
)
3676 if (Size
) State
->GeneralRegs
[i
].Long
= Value
;
3677 else State
->GeneralRegs
[i
].LowWord
= LOWORD(Value
);
3684 SOFT386_OPCODE_HANDLER(Soft386OpcodeBound
)
3686 // TODO: NOT IMPLEMENTED
3692 SOFT386_OPCODE_HANDLER(Soft386OpcodeArpl
)
3694 USHORT FirstValue
, SecondValue
;
3695 SOFT386_MOD_REG_RM ModRegRm
;
3696 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3698 if (!(State
->ControlRegisters
[SOFT386_REG_CR0
] & SOFT386_CR0_PE
)
3700 || (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
))
3702 /* Cannot be used in real mode or with a LOCK prefix */
3703 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3707 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3709 /* The ADSIZE prefix toggles the size */
3710 AddressSize
= !AddressSize
;
3713 /* Get the operands */
3714 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3716 /* Exception occurred */
3720 /* Read the operands */
3721 if (!Soft386ReadModrmWordOperands(State
,
3726 /* Exception occurred */
3730 /* Check if the RPL needs adjusting */
3731 if ((SecondValue
& 3) < (FirstValue
& 3))
3733 /* Adjust the RPL */
3735 SecondValue
|= FirstValue
& 3;
3738 State
->Flags
.Zf
= TRUE
;
3740 /* Write back the result */
3741 return Soft386WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, SecondValue
);
3746 State
->Flags
.Zf
= FALSE
;
3751 SOFT386_OPCODE_HANDLER(Soft386OpcodePushImm
)
3753 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3755 /* Make sure this is the right instruction */
3756 ASSERT(Opcode
== 0x68);
3758 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
3760 /* The OPSIZE prefix toggles the size */
3765 /* Invalid prefix */
3766 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3774 if (!Soft386FetchDword(State
, &Data
))
3776 /* Exception occurred */
3780 /* Call the internal API */
3781 return Soft386StackPush(State
, Data
);
3787 if (!Soft386FetchWord(State
, &Data
))
3789 /* Exception occurred */
3793 /* Call the internal API */
3794 return Soft386StackPush(State
, Data
);
3798 SOFT386_OPCODE_HANDLER(Soft386OpcodeImulModrmImm
)
3800 // TODO: NOT IMPLEMENTED
3806 SOFT386_OPCODE_HANDLER(Soft386OpcodePushByteImm
)
3810 /* Make sure this is the right instruction */
3811 ASSERT(Opcode
== 0x6A);
3813 if (!Soft386FetchByte(State
, &Data
))
3815 /* Exception occurred */
3819 /* Call the internal API */
3820 return Soft386StackPush(State
, Data
);
3823 SOFT386_OPCODE_HANDLER(Soft386OpcodeImulModrmByteImm
)
3825 // TODO: NOT IMPLEMENTED
3831 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovByteModrm
)
3833 UCHAR FirstValue
, SecondValue
, Result
;
3834 SOFT386_MOD_REG_RM ModRegRm
;
3835 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3837 /* Make sure this is the right instruction */
3838 ASSERT((Opcode
& 0xFD) == 0x88);
3840 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3842 /* The ADSIZE prefix toggles the size */
3843 AddressSize
= !AddressSize
;
3845 else if (State
->PrefixFlags
3846 & ~(SOFT386_PREFIX_ADSIZE
3847 | SOFT386_PREFIX_SEG
3848 | SOFT386_PREFIX_LOCK
))
3850 /* Invalid prefix */
3851 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3855 /* Get the operands */
3856 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3858 /* Exception occurred */
3862 if (!Soft386ReadModrmByteOperands(State
,
3867 /* Exception occurred */
3871 if (Opcode
& SOFT386_OPCODE_WRITE_REG
) Result
= SecondValue
;
3872 else Result
= FirstValue
;
3874 /* Write back the result */
3875 return Soft386WriteModrmByteOperands(State
,
3877 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3882 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovModrm
)
3884 SOFT386_MOD_REG_RM ModRegRm
;
3885 BOOLEAN OperandSize
, AddressSize
;
3887 /* Make sure this is the right instruction */
3888 ASSERT((Opcode
& 0xFD) == 0x89);
3890 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3892 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3894 /* The ADSIZE prefix toggles the address size */
3895 AddressSize
= !AddressSize
;
3898 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
3900 /* The OPSIZE prefix toggles the operand size */
3901 OperandSize
= !OperandSize
;
3904 if (State
->PrefixFlags
3905 & ~(SOFT386_PREFIX_ADSIZE
3906 | SOFT386_PREFIX_OPSIZE
3907 | SOFT386_PREFIX_SEG
3908 | SOFT386_PREFIX_LOCK
))
3910 /* Invalid prefix */
3911 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3915 /* Get the operands */
3916 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3918 /* Exception occurred */
3922 /* Check the operand size */
3925 ULONG FirstValue
, SecondValue
, Result
;
3927 if (!Soft386ReadModrmDwordOperands(State
,
3932 /* Exception occurred */
3936 if (Opcode
& SOFT386_OPCODE_WRITE_REG
) Result
= SecondValue
;
3937 else Result
= FirstValue
;
3939 /* Write back the result */
3940 return Soft386WriteModrmDwordOperands(State
,
3942 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3947 USHORT FirstValue
, SecondValue
, Result
;
3949 if (!Soft386ReadModrmWordOperands(State
,
3954 /* Exception occurred */
3958 if (Opcode
& SOFT386_OPCODE_WRITE_REG
) Result
= SecondValue
;
3959 else Result
= FirstValue
;
3961 /* Write back the result */
3962 return Soft386WriteModrmWordOperands(State
,
3964 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3969 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovStoreSeg
)
3971 // TODO: NOT IMPLEMENTED
3977 SOFT386_OPCODE_HANDLER(Soft386OpcodeLea
)
3979 SOFT386_MOD_REG_RM ModRegRm
;
3980 BOOLEAN OperandSize
, AddressSize
;
3982 /* Make sure this is the right instruction */
3983 ASSERT(Opcode
== 0x8D);
3985 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3987 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3989 /* The ADSIZE prefix toggles the address size */
3990 AddressSize
= !AddressSize
;
3993 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
3995 /* The OPSIZE prefix toggles the operand size */
3996 OperandSize
= !OperandSize
;
3999 /* Get the operands */
4000 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
4002 /* Exception occurred */
4006 /* The second operand must be memory */
4007 if (!ModRegRm
.Memory
)
4010 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4014 /* Write the address to the register */
4017 return Soft386WriteModrmDwordOperands(State
,
4020 ModRegRm
.MemoryAddress
);
4024 return Soft386WriteModrmWordOperands(State
,
4027 ModRegRm
.MemoryAddress
);
4032 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovLoadSeg
)
4034 // TODO: NOT IMPLEMENTED
4040 SOFT386_OPCODE_HANDLER(Soft386OpcodeCwde
)
4042 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4044 /* Make sure this is the right instruction */
4045 ASSERT(Opcode
== 0x98);
4047 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
4049 /* The OPSIZE prefix toggles the size */
4052 else if (State
->PrefixFlags
!= 0)
4054 /* Invalid prefix */
4055 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4061 /* Sign extend AX to EAX */
4062 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= MAKELONG
4064 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
,
4065 (State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
& SIGN_FLAG_WORD
)
4071 /* Sign extend AL to AX */
4072 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
=
4073 (State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
& SIGN_FLAG_BYTE
)
4080 SOFT386_OPCODE_HANDLER(Soft386OpcodeCdq
)
4082 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4084 /* Make sure this is the right instruction */
4085 ASSERT(Opcode
== 0x99);
4087 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
4089 /* The OPSIZE prefix toggles the size */
4092 else if (State
->PrefixFlags
!= 0)
4094 /* Invalid prefix */
4095 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4101 /* Sign extend EAX to EDX:EAX */
4102 State
->GeneralRegs
[SOFT386_REG_EDX
].Long
=
4103 (State
->GeneralRegs
[SOFT386_REG_EAX
].Long
& SIGN_FLAG_LONG
)
4104 ? 0xFFFFFFFF : 0x00000000;
4108 /* Sign extend AX to DX:AX */
4109 State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
=
4110 (State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
& SIGN_FLAG_WORD
)
4117 SOFT386_OPCODE_HANDLER(Soft386OpcodeCallAbs
)
4119 // TODO: NOT IMPLEMENTED
4125 SOFT386_OPCODE_HANDLER(Soft386OpcodeWait
)
4127 // TODO: NOT IMPLEMENTED
4133 SOFT386_OPCODE_HANDLER(Soft386OpcodePushFlags
)
4135 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4137 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4139 /* Invalid prefix */
4140 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4144 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
4146 /* This OPSIZE prefix toggles the size */
4150 /* Check for VM86 mode when IOPL is not 3 */
4151 if (State
->Flags
.Vm
&& (State
->Flags
.Iopl
!= 3))
4153 /* Call the VM86 monitor */
4154 Soft386ExceptionWithErrorCode(State
, SOFT386_EXCEPTION_GP
, 0);
4158 /* Push the flags */
4159 if (Size
) return Soft386StackPush(State
, State
->Flags
.Long
);
4160 else return Soft386StackPush(State
, LOWORD(State
->Flags
.Long
));
4163 SOFT386_OPCODE_HANDLER(Soft386OpcodePopFlags
)
4165 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4166 INT Cpl
= Soft386GetCurrentPrivLevel(State
);
4169 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4171 /* Invalid prefix */
4172 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4176 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
4178 /* This OPSIZE prefix toggles the size */
4182 /* Pop the new flags */
4183 if (!Soft386StackPop(State
, &NewFlags
))
4185 /* Exception occurred */
4189 if (!State
->Flags
.Vm
)
4191 /* Check the current privilege level */
4199 /* Memorize the old state of RF */
4200 BOOLEAN OldRf
= State
->Flags
.Rf
;
4202 State
->Flags
.Long
= NewFlags
;
4204 /* Restore VM and RF */
4205 State
->Flags
.Vm
= FALSE
;
4206 State
->Flags
.Rf
= OldRf
;
4208 /* Clear VIF and VIP */
4209 State
->Flags
.Vif
= State
->Flags
.Vip
= FALSE
;
4211 else State
->Flags
.LowWord
= LOWORD(NewFlags
);
4213 /* Restore the reserved bits */
4214 State
->Flags
.AlwaysSet
= TRUE
;
4215 State
->Flags
.Reserved0
= FALSE
;
4216 State
->Flags
.Reserved1
= FALSE
;
4222 /* Memorize the old state of IF and IOPL */
4223 BOOLEAN OldIf
= State
->Flags
.If
;
4224 UINT OldIopl
= State
->Flags
.Iopl
;
4229 /* Memorize the old state of RF */
4230 BOOLEAN OldRf
= State
->Flags
.Rf
;
4232 State
->Flags
.Long
= NewFlags
;
4234 /* Restore VM and RF */
4235 State
->Flags
.Vm
= FALSE
;
4236 State
->Flags
.Rf
= OldRf
;
4238 /* Clear VIF and VIP */
4239 State
->Flags
.Vif
= State
->Flags
.Vip
= FALSE
;
4241 else State
->Flags
.LowWord
= LOWORD(NewFlags
);
4243 /* Restore the reserved bits and IOPL */
4244 State
->Flags
.AlwaysSet
= TRUE
;
4245 State
->Flags
.Reserved0
= FALSE
;
4246 State
->Flags
.Reserved1
= FALSE
;
4247 State
->Flags
.Iopl
= OldIopl
;
4249 /* Check if the user doesn't have the privilege to change IF */
4250 if (Cpl
> State
->Flags
.Iopl
)
4253 State
->Flags
.If
= OldIf
;
4259 /* Check the IOPL */
4260 if (State
->Flags
.Iopl
== 3)
4264 /* Memorize the old state of RF, VIF and VIP */
4265 BOOLEAN OldRf
= State
->Flags
.Rf
;
4266 BOOLEAN OldVif
= State
->Flags
.Vif
;
4267 BOOLEAN OldVip
= State
->Flags
.Vip
;
4269 State
->Flags
.Long
= NewFlags
;
4271 /* Restore VM, RF, VIF and VIP */
4272 State
->Flags
.Vm
= TRUE
;
4273 State
->Flags
.Rf
= OldRf
;
4274 State
->Flags
.Vif
= OldVif
;
4275 State
->Flags
.Vip
= OldVip
;
4277 else State
->Flags
.LowWord
= LOWORD(NewFlags
);
4279 /* Restore the reserved bits and IOPL */
4280 State
->Flags
.AlwaysSet
= TRUE
;
4281 State
->Flags
.Reserved0
= FALSE
;
4282 State
->Flags
.Reserved1
= FALSE
;
4283 State
->Flags
.Iopl
= 3;
4287 /* Call the VM86 monitor */
4288 Soft386ExceptionWithErrorCode(State
, SOFT386_EXCEPTION_GP
, 0);
4296 SOFT386_OPCODE_HANDLER(Soft386OpcodeSahf
)
4298 /* Make sure this is the right instruction */
4299 ASSERT(Opcode
== 0x9E);
4301 /* Set the low-order byte of FLAGS to AH */
4302 State
->Flags
.Long
&= 0xFFFFFF00;
4303 State
->Flags
.Long
|= State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
;
4305 /* Restore the reserved bits of FLAGS */
4306 State
->Flags
.AlwaysSet
= TRUE
;
4307 State
->Flags
.Reserved0
= State
->Flags
.Reserved1
= FALSE
;
4312 SOFT386_OPCODE_HANDLER(Soft386OpcodeLahf
)
4314 /* Make sure this is the right instruction */
4315 ASSERT(Opcode
== 0x9F);
4317 /* Set AH to the low-order byte of FLAGS */
4318 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
= LOBYTE(State
->Flags
.Long
);
4323 SOFT386_OPCODE_HANDLER(Soft386OpcodeRet
)
4325 ULONG ReturnAddress
;
4326 USHORT BytesToPop
= 0;
4327 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4329 /* Make sure this is the right instruction */
4330 ASSERT((Opcode
& 0xFE) == 0xC2);
4332 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4334 /* Invalid prefix */
4335 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4339 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
4341 /* The OPSIZE prefix toggles the size */
4347 /* Fetch the number of bytes to pop after the return */
4348 if (!Soft386FetchWord(State
, &BytesToPop
)) return FALSE
;
4351 /* Pop the return address */
4352 if (!Soft386StackPop(State
, &ReturnAddress
)) return FALSE
;
4354 /* Return to the calling procedure, and if necessary, pop the parameters */
4357 State
->InstPtr
.Long
= ReturnAddress
;
4358 State
->GeneralRegs
[SOFT386_REG_ESP
].Long
+= BytesToPop
;
4362 State
->InstPtr
.LowWord
= LOWORD(ReturnAddress
);
4363 State
->GeneralRegs
[SOFT386_REG_ESP
].LowWord
+= BytesToPop
;
4369 SOFT386_OPCODE_HANDLER(Soft386OpcodeLes
)
4371 // TODO: NOT IMPLEMENTED
4377 SOFT386_OPCODE_HANDLER(Soft386OpcodeLds
)
4379 // TODO: NOT IMPLEMENTED
4385 SOFT386_OPCODE_HANDLER(Soft386OpcodeEnter
)
4387 // TODO: NOT IMPLEMENTED
4393 SOFT386_OPCODE_HANDLER(Soft386OpcodeLeave
)
4395 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4397 /* Make sure this is the right instruction */
4398 ASSERT(Opcode
== 0xC9);
4400 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4402 /* Invalid prefix */
4403 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4407 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
4409 /* The OPSIZE prefix toggles the size */
4415 /* Set the stack pointer (ESP) to the base pointer (EBP) */
4416 State
->GeneralRegs
[SOFT386_REG_ESP
].Long
= State
->GeneralRegs
[SOFT386_REG_EBP
].Long
;
4418 /* Pop the saved base pointer from the stack */
4419 return Soft386StackPop(State
, &State
->GeneralRegs
[SOFT386_REG_EBP
].Long
);
4425 /* Set the stack pointer (SP) to the base pointer (BP) */
4426 State
->GeneralRegs
[SOFT386_REG_ESP
].LowWord
= State
->GeneralRegs
[SOFT386_REG_EBP
].LowWord
;
4428 /* Pop the saved base pointer from the stack */
4429 if (Soft386StackPop(State
, &Value
))
4431 State
->GeneralRegs
[SOFT386_REG_EBP
].LowWord
= LOWORD(Value
);
4438 SOFT386_OPCODE_HANDLER(Soft386OpcodeRetFarImm
)
4440 // TODO: NOT IMPLEMENTED
4446 SOFT386_OPCODE_HANDLER(Soft386OpcodeRetFar
)
4448 // TODO: NOT IMPLEMENTED
4454 SOFT386_OPCODE_HANDLER(Soft386OpcodeInt
)
4457 SOFT386_IDT_ENTRY IdtEntry
;
4463 /* This is the INT3 instruction */
4470 /* Fetch the interrupt number */
4471 if (!Soft386FetchByte(State
, &IntNum
))
4473 /* Exception occurred */
4482 /* Don't do anything if OF is cleared */
4483 if (!State
->Flags
.Of
) return TRUE
;
4486 IntNum
= SOFT386_EXCEPTION_OF
;
4493 /* Should not happen */
4498 /* Get the interrupt vector */
4499 if (!Soft386GetIntVector(State
, IntNum
, &IdtEntry
))
4501 /* Exception occurred */
4505 /* Perform the interrupt */
4506 if (!Soft386InterruptInternal(State
,
4508 MAKELONG(IdtEntry
.Offset
, IdtEntry
.OffsetHigh
),
4511 /* Exception occurred */
4518 SOFT386_OPCODE_HANDLER(Soft386OpcodeIret
)
4520 // TODO: NOT IMPLEMENTED
4526 SOFT386_OPCODE_HANDLER(Soft386OpcodeAam
)
4529 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
4531 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4533 /* Invalid prefix */
4534 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4538 /* Fetch the base */
4539 if (!Soft386FetchByte(State
, &Base
))
4541 /* Exception occurred */
4545 /* Check if the base is zero */
4549 Soft386Exception(State
, SOFT386_EXCEPTION_DE
);
4554 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
= Value
/ Base
;
4555 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Value
%= Base
;
4558 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
4559 State
->Flags
.Sf
= (Value
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
4560 State
->Flags
.Pf
= Soft386CalculateParity(Value
);
4565 SOFT386_OPCODE_HANDLER(Soft386OpcodeAad
)
4568 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
4570 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4572 /* Invalid prefix */
4573 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4577 /* Fetch the base */
4578 if (!Soft386FetchByte(State
, &Base
))
4580 /* Exception occurred */
4585 Value
+= State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
* Base
;
4586 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Value
;
4589 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
4590 State
->Flags
.Sf
= (Value
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
4591 State
->Flags
.Pf
= Soft386CalculateParity(Value
);
4596 SOFT386_OPCODE_HANDLER(Soft386OpcodeXlat
)
4598 // TODO: NOT IMPLEMENTED
4604 SOFT386_OPCODE_HANDLER(Soft386OpcodeLoop
)
4607 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4610 /* Make sure this is the right instruction */
4611 ASSERT((Opcode
>= 0xE0) && (Opcode
<= 0xE2));
4613 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4615 /* Invalid prefix */
4616 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4620 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
4622 /* The OPSIZE prefix toggles the size */
4626 if (Size
) Condition
= ((--State
->GeneralRegs
[SOFT386_REG_ECX
].Long
) == 0);
4627 else Condition
= ((--State
->GeneralRegs
[SOFT386_REG_ECX
].LowWord
) == 0);
4631 /* Additional rule for LOOPNZ */
4632 if (State
->Flags
.Zf
) Condition
= FALSE
;
4637 /* Additional rule for LOOPZ */
4638 if (!State
->Flags
.Zf
) Condition
= FALSE
;
4641 /* Fetch the offset */
4642 if (!Soft386FetchByte(State
, (PUCHAR
)&Offset
))
4644 /* An exception occurred */
4650 /* Move the instruction pointer */
4651 State
->InstPtr
.Long
+= Offset
;
4657 SOFT386_OPCODE_HANDLER(Soft386OpcodeJecxz
)
4660 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4663 /* Make sure this is the right instruction */
4664 ASSERT(Opcode
== 0xE3);
4666 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4668 /* Invalid prefix */
4669 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4673 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
4675 /* The OPSIZE prefix toggles the size */
4679 if (Size
) Condition
= (State
->GeneralRegs
[SOFT386_REG_ECX
].Long
== 0);
4680 else Condition
= (State
->GeneralRegs
[SOFT386_REG_ECX
].LowWord
== 0);
4682 /* Fetch the offset */
4683 if (!Soft386FetchByte(State
, (PUCHAR
)&Offset
))
4685 /* An exception occurred */
4691 /* Move the instruction pointer */
4692 State
->InstPtr
.Long
+= Offset
;
4698 SOFT386_OPCODE_HANDLER(Soft386OpcodeCall
)
4700 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4702 /* Make sure this is the right instruction */
4703 ASSERT(Opcode
== 0xE8);
4705 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
4707 /* The OPSIZE prefix toggles the size */
4710 else if (State
->PrefixFlags
!= 0)
4712 /* Invalid prefix */
4713 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4721 /* Fetch the offset */
4722 if (!Soft386FetchDword(State
, (PULONG
)&Offset
))
4724 /* An exception occurred */
4728 /* Push the current value of the instruction pointer */
4729 if (!Soft386StackPush(State
, State
->InstPtr
.Long
))
4731 /* Exception occurred */
4735 /* Move the instruction pointer */
4736 State
->InstPtr
.Long
+= Offset
;
4742 /* Fetch the offset */
4743 if (!Soft386FetchWord(State
, (PUSHORT
)&Offset
))
4745 /* An exception occurred */
4749 /* Push the current value of the instruction pointer */
4750 if (!Soft386StackPush(State
, State
->InstPtr
.Long
))
4752 /* Exception occurred */
4756 /* Move the instruction pointer */
4757 State
->InstPtr
.LowWord
+= Offset
;
4763 SOFT386_OPCODE_HANDLER(Soft386OpcodeJmp
)
4765 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4767 /* Make sure this is the right instruction */
4768 ASSERT(Opcode
== 0xE9);
4770 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
4772 /* The OPSIZE prefix toggles the size */
4775 else if (State
->PrefixFlags
!= 0)
4777 /* Invalid prefix */
4778 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4786 /* Fetch the offset */
4787 if (!Soft386FetchDword(State
, (PULONG
)&Offset
))
4789 /* An exception occurred */
4793 /* Move the instruction pointer */
4794 State
->InstPtr
.Long
+= Offset
;
4800 /* Fetch the offset */
4801 if (!Soft386FetchWord(State
, (PUSHORT
)&Offset
))
4803 /* An exception occurred */
4807 /* Move the instruction pointer */
4808 State
->InstPtr
.LowWord
+= Offset
;
4814 SOFT386_OPCODE_HANDLER(Soft386OpcodeJmpAbs
)
4816 // TODO: NOT IMPLEMENTED
4822 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovAlOffset
)
4824 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4827 /* Make sure this is the right instruction */
4828 ASSERT(Opcode
== 0xA0);
4830 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
4832 /* The OPSIZE prefix toggles the size */
4838 if (!Soft386FetchDword(State
, &Offset
))
4840 /* Exception occurred */
4848 if (!Soft386FetchWord(State
, &WordOffset
))
4850 /* Exception occurred */
4854 Offset
= (ULONG
)WordOffset
;
4857 /* Read from memory */
4858 return Soft386ReadMemory(State
,
4859 (State
->PrefixFlags
& SOFT386_PREFIX_SEG
) ?
4860 State
->SegmentOverride
: SOFT386_REG_DS
,
4863 &State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
,
4867 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovEaxOffset
)
4869 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4871 /* Make sure this is the right instruction */
4872 ASSERT(Opcode
== 0xA1);
4874 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
4876 /* The OPSIZE prefix toggles the size */
4884 if (!Soft386FetchDword(State
, &Offset
))
4886 /* Exception occurred */
4890 /* Read from memory */
4891 return Soft386ReadMemory(State
,
4892 (State
->PrefixFlags
& SOFT386_PREFIX_SEG
) ?
4893 State
->SegmentOverride
: SOFT386_REG_DS
,
4896 &State
->GeneralRegs
[SOFT386_REG_EAX
].Long
,
4903 if (!Soft386FetchWord(State
, &Offset
))
4905 /* Exception occurred */
4909 /* Read from memory */
4910 return Soft386ReadMemory(State
,
4911 (State
->PrefixFlags
& SOFT386_PREFIX_SEG
) ?
4912 State
->SegmentOverride
: SOFT386_REG_DS
,
4915 &State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
,
4920 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovOffsetAl
)
4922 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4925 /* Make sure this is the right instruction */
4926 ASSERT(Opcode
== 0xA2);
4928 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
4930 /* The OPSIZE prefix toggles the size */
4936 if (!Soft386FetchDword(State
, &Offset
))
4938 /* Exception occurred */
4946 if (!Soft386FetchWord(State
, &WordOffset
))
4948 /* Exception occurred */
4952 Offset
= (ULONG
)WordOffset
;
4955 /* Write to memory */
4956 return Soft386WriteMemory(State
,
4957 (State
->PrefixFlags
& SOFT386_PREFIX_SEG
) ?
4958 State
->SegmentOverride
: SOFT386_REG_DS
,
4960 &State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
,
4964 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovOffsetEax
)
4966 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4968 /* Make sure this is the right instruction */
4969 ASSERT(Opcode
== 0xA3);
4971 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
4973 /* The OPSIZE prefix toggles the size */
4981 if (!Soft386FetchDword(State
, &Offset
))
4983 /* Exception occurred */
4987 /* Write to memory */
4988 return Soft386WriteMemory(State
,
4989 (State
->PrefixFlags
& SOFT386_PREFIX_SEG
) ?
4990 State
->SegmentOverride
: SOFT386_REG_DS
,
4992 &State
->GeneralRegs
[SOFT386_REG_EAX
].Long
,
4999 if (!Soft386FetchWord(State
, &Offset
))
5001 /* Exception occurred */
5005 /* Write to memory */
5006 return Soft386WriteMemory(State
,
5007 (State
->PrefixFlags
& SOFT386_PREFIX_SEG
) ?
5008 State
->SegmentOverride
: SOFT386_REG_DS
,
5010 &State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
,