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
,
33 NULL
, // TODO: OPCODE 0x06 NOT SUPPORTED
34 NULL
, // TODO: OPCODE 0x07 NOT SUPPORTED
35 Soft386OpcodeOrByteModrm
,
37 Soft386OpcodeOrByteModrm
,
41 NULL
, // TODO: OPCODE 0x0E NOT SUPPORTED
42 NULL
, // TODO: OPCODE 0x0F NOT SUPPORTED
43 NULL
, // TODO: OPCODE 0x10 NOT SUPPORTED
44 NULL
, // TODO: OPCODE 0x11 NOT SUPPORTED
45 NULL
, // TODO: OPCODE 0x12 NOT SUPPORTED
46 NULL
, // TODO: OPCODE 0x13 NOT SUPPORTED
47 NULL
, // TODO: OPCODE 0x14 NOT SUPPORTED
48 NULL
, // TODO: OPCODE 0x15 NOT SUPPORTED
49 NULL
, // TODO: OPCODE 0x16 NOT SUPPORTED
50 NULL
, // TODO: OPCODE 0x17 NOT SUPPORTED
51 NULL
, // TODO: OPCODE 0x18 NOT SUPPORTED
52 NULL
, // TODO: OPCODE 0x19 NOT SUPPORTED
53 NULL
, // TODO: OPCODE 0x1A NOT SUPPORTED
54 NULL
, // TODO: OPCODE 0x1B NOT SUPPORTED
55 NULL
, // TODO: OPCODE 0x1C NOT SUPPORTED
56 NULL
, // TODO: OPCODE 0x1D NOT SUPPORTED
57 NULL
, // TODO: OPCODE 0x1E NOT SUPPORTED
58 NULL
, // TODO: OPCODE 0x1F NOT SUPPORTED
59 Soft386OpcodeAndByteModrm
,
60 Soft386OpcodeAndModrm
,
61 Soft386OpcodeAndByteModrm
,
62 Soft386OpcodeAndModrm
,
66 NULL
, // TODO: OPCODE 0x27 NOT SUPPORTED
67 NULL
, // TODO: OPCODE 0x28 NOT SUPPORTED
68 NULL
, // TODO: OPCODE 0x29 NOT SUPPORTED
69 NULL
, // TODO: OPCODE 0x2A NOT SUPPORTED
70 NULL
, // TODO: OPCODE 0x2B NOT SUPPORTED
71 NULL
, // TODO: OPCODE 0x2C NOT SUPPORTED
72 NULL
, // TODO: OPCODE 0x2D NOT SUPPORTED
74 NULL
, // TODO: OPCODE 0x2F NOT SUPPORTED
75 Soft386OpcodeXorByteModrm
,
76 Soft386OpcodeXorModrm
,
77 Soft386OpcodeXorByteModrm
,
78 Soft386OpcodeXorModrm
,
82 NULL
, // TODO: OPCODE 0x37 NOT SUPPORTED
83 NULL
, // TODO: OPCODE 0x38 NOT SUPPORTED
84 NULL
, // TODO: OPCODE 0x39 NOT SUPPORTED
85 NULL
, // TODO: OPCODE 0x3A NOT SUPPORTED
86 NULL
, // TODO: OPCODE 0x3B NOT SUPPORTED
87 NULL
, // TODO: OPCODE 0x3C NOT SUPPORTED
88 NULL
, // TODO: OPCODE 0x3D NOT SUPPORTED
90 NULL
, // TODO: OPCODE 0x3F NOT SUPPORTED
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 NULL
, // TODO: OPCODE 0x60 NOT SUPPORTED
124 NULL
, // TODO: OPCODE 0x61 NOT SUPPORTED
125 NULL
, // TODO: OPCODE 0x62 NOT SUPPORTED
126 NULL
, // TODO: OPCODE 0x63 NOT SUPPORTED
131 NULL
, // TODO: OPCODE 0x68 NOT SUPPORTED
132 NULL
, // TODO: OPCODE 0x69 NOT SUPPORTED
133 NULL
, // TODO: OPCODE 0x6A NOT SUPPORTED
134 NULL
, // TODO: OPCODE 0x6B NOT SUPPORTED
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 NULL
, // TODO: OPCODE 0x88 NOT SUPPORTED
164 NULL
, // TODO: OPCODE 0x89 NOT SUPPORTED
165 NULL
, // TODO: OPCODE 0x8A NOT SUPPORTED
166 NULL
, // TODO: OPCODE 0x8B NOT SUPPORTED
167 NULL
, // TODO: OPCODE 0x8C NOT SUPPORTED
168 NULL
, // TODO: OPCODE 0x8D NOT SUPPORTED
169 NULL
, // TODO: OPCODE 0x8E NOT SUPPORTED
170 NULL
, // TODO: OPCODE 0x8F NOT SUPPORTED
172 Soft386OpcodeExchangeEax
,
173 Soft386OpcodeExchangeEax
,
174 Soft386OpcodeExchangeEax
,
175 Soft386OpcodeExchangeEax
,
176 Soft386OpcodeExchangeEax
,
177 Soft386OpcodeExchangeEax
,
178 Soft386OpcodeExchangeEax
,
179 NULL
, // TODO: OPCODE 0x98 NOT SUPPORTED
180 NULL
, // TODO: OPCODE 0x99 NOT SUPPORTED
181 NULL
, // TODO: OPCODE 0x9A NOT SUPPORTED
182 NULL
, // TODO: OPCODE 0x9B NOT SUPPORTED
183 NULL
, // TODO: OPCODE 0x9C NOT SUPPORTED
184 NULL
, // TODO: OPCODE 0x9D NOT SUPPORTED
185 NULL
, // TODO: OPCODE 0x9E NOT SUPPORTED
186 NULL
, // TODO: OPCODE 0x9F NOT SUPPORTED
187 NULL
, // TODO: OPCODE 0xA0 NOT SUPPORTED
188 NULL
, // TODO: OPCODE 0xA1 NOT SUPPORTED
189 NULL
, // TODO: OPCODE 0xA2 NOT SUPPORTED
190 NULL
, // TODO: OPCODE 0xA3 NOT SUPPORTED
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
195 NULL
, // TODO: OPCODE 0xA8 NOT SUPPORTED
196 NULL
, // TODO: OPCODE 0xA9 NOT SUPPORTED
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
221 NULL
, // TODO: OPCODE 0xC2 NOT SUPPORTED
222 NULL
, // TODO: OPCODE 0xC3 NOT SUPPORTED
223 NULL
, // TODO: OPCODE 0xC4 NOT SUPPORTED
224 NULL
, // TODO: OPCODE 0xC5 NOT SUPPORTED
225 NULL
, // TODO: OPCODE 0xC6 NOT SUPPORTED
226 NULL
, // TODO: OPCODE 0xC7 NOT SUPPORTED
227 NULL
, // TODO: OPCODE 0xC8 NOT SUPPORTED
228 NULL
, // TODO: OPCODE 0xC9 NOT SUPPORTED
229 NULL
, // TODO: OPCODE 0xCA NOT SUPPORTED
230 NULL
, // TODO: OPCODE 0xCB NOT SUPPORTED
231 NULL
, // TODO: OPCODE 0xCC NOT SUPPORTED
232 NULL
, // TODO: OPCODE 0xCD NOT SUPPORTED
233 NULL
, // TODO: OPCODE 0xCE NOT SUPPORTED
234 NULL
, // TODO: OPCODE 0xCF NOT SUPPORTED
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
239 NULL
, // TODO: OPCODE 0xD4 NOT SUPPORTED
240 NULL
, // TODO: OPCODE 0xD5 NOT SUPPORTED
241 NULL
, // TODO: OPCODE 0xD6 NOT SUPPORTED
242 NULL
, // TODO: OPCODE 0xD7 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
251 NULL
, // TODO: OPCODE 0xE0 NOT SUPPORTED
252 NULL
, // TODO: OPCODE 0xE1 NOT SUPPORTED
253 NULL
, // TODO: OPCODE 0xE2 NOT SUPPORTED
254 NULL
, // TODO: OPCODE 0xE3 NOT SUPPORTED
257 Soft386OpcodeOutByte
,
259 NULL
, // TODO: OPCODE 0xE8 NOT SUPPORTED
260 NULL
, // TODO: OPCODE 0xE9 NOT SUPPORTED
261 NULL
, // TODO: OPCODE 0xEA NOT SUPPORTED
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_OPSIZE
)
1430 /* The OPSIZE prefix toggles the size */
1435 /* Invalid prefix */
1436 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1442 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
1443 ULONG SecondValue
, Result
;
1445 if (!Soft386FetchDword(State
, &SecondValue
))
1447 /* Exception occurred */
1451 /* Calculate the result */
1452 Result
= FirstValue
+ SecondValue
;
1454 /* Update the flags */
1455 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1456 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
1457 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
1458 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
1459 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1460 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1461 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1463 /* Write back the result */
1464 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
1468 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
1469 USHORT SecondValue
, Result
;
1471 if (!Soft386FetchWord(State
, &SecondValue
))
1473 /* Exception occurred */
1477 /* Calculate the result */
1478 Result
= FirstValue
+ SecondValue
;
1480 /* Update the flags */
1481 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1482 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
1483 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
1484 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
1485 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1486 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
1487 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1489 /* Write back the result */
1490 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
1496 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrByteModrm
)
1498 UCHAR FirstValue
, SecondValue
, Result
;
1499 SOFT386_MOD_REG_RM ModRegRm
;
1500 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1502 /* Make sure this is the right instruction */
1503 ASSERT((Opcode
& 0xFD) == 0x08);
1505 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1507 /* The ADSIZE prefix toggles the size */
1508 AddressSize
= !AddressSize
;
1510 else if (State
->PrefixFlags
1511 & ~(SOFT386_PREFIX_ADSIZE
1512 | SOFT386_PREFIX_SEG
1513 | SOFT386_PREFIX_LOCK
))
1515 /* Invalid prefix */
1516 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1520 /* Get the operands */
1521 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1523 /* Exception occurred */
1527 if (!Soft386ReadModrmByteOperands(State
,
1532 /* Exception occurred */
1536 /* Calculate the result */
1537 Result
= FirstValue
| SecondValue
;
1539 /* Update the flags */
1540 State
->Flags
.Cf
= FALSE
;
1541 State
->Flags
.Of
= FALSE
;
1542 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1543 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1544 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1546 /* Write back the result */
1547 return Soft386WriteModrmByteOperands(State
,
1549 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1553 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrModrm
)
1555 SOFT386_MOD_REG_RM ModRegRm
;
1556 BOOLEAN OperandSize
, AddressSize
;
1558 /* Make sure this is the right instruction */
1559 ASSERT((Opcode
& 0xFD) == 0x09);
1561 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1563 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1565 /* The ADSIZE prefix toggles the address size */
1566 AddressSize
= !AddressSize
;
1569 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1571 /* The OPSIZE prefix toggles the operand size */
1572 OperandSize
= !OperandSize
;
1575 if (State
->PrefixFlags
1576 & ~(SOFT386_PREFIX_ADSIZE
1577 | SOFT386_PREFIX_OPSIZE
1578 | SOFT386_PREFIX_SEG
1579 | SOFT386_PREFIX_LOCK
))
1581 /* Invalid prefix */
1582 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1586 /* Get the operands */
1587 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1589 /* Exception occurred */
1593 /* Check the operand size */
1596 ULONG FirstValue
, SecondValue
, Result
;
1598 if (!Soft386ReadModrmDwordOperands(State
,
1603 /* Exception occurred */
1607 /* Calculate the result */
1608 Result
= FirstValue
| SecondValue
;
1610 /* Update the flags */
1611 State
->Flags
.Cf
= FALSE
;
1612 State
->Flags
.Of
= FALSE
;
1613 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1614 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1615 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1617 /* Write back the result */
1618 return Soft386WriteModrmDwordOperands(State
,
1620 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1625 USHORT FirstValue
, SecondValue
, Result
;
1627 if (!Soft386ReadModrmWordOperands(State
,
1632 /* Exception occurred */
1636 /* Calculate the result */
1637 Result
= FirstValue
| SecondValue
;
1639 /* Update the flags */
1640 State
->Flags
.Cf
= FALSE
;
1641 State
->Flags
.Of
= FALSE
;
1642 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1643 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1644 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1646 /* Write back the result */
1647 return Soft386WriteModrmWordOperands(State
,
1649 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1654 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrAl
)
1656 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
1657 UCHAR SecondValue
, Result
;
1659 /* Make sure this is the right instruction */
1660 ASSERT(Opcode
== 0x0C);
1662 if (State
->PrefixFlags
)
1664 /* This opcode doesn't take any prefixes */
1665 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1669 if (!Soft386FetchByte(State
, &SecondValue
))
1671 /* Exception occurred */
1675 /* Calculate the result */
1676 Result
= FirstValue
| SecondValue
;
1678 /* Update the flags */
1679 State
->Flags
.Cf
= FALSE
;
1680 State
->Flags
.Of
= FALSE
;
1681 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1682 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1683 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1685 /* Write back the result */
1686 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
1691 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrEax
)
1693 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1695 /* Make sure this is the right instruction */
1696 ASSERT(Opcode
== 0x0D);
1698 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
1700 /* The OPSIZE prefix toggles the size */
1705 /* Invalid prefix */
1706 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1712 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
1713 ULONG SecondValue
, Result
;
1715 if (!Soft386FetchDword(State
, &SecondValue
))
1717 /* Exception occurred */
1721 /* Calculate the result */
1722 Result
= FirstValue
| SecondValue
;
1724 /* Update the flags */
1725 State
->Flags
.Cf
= FALSE
;
1726 State
->Flags
.Of
= FALSE
;
1727 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1728 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1729 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1731 /* Write back the result */
1732 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
1736 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
1737 USHORT SecondValue
, Result
;
1739 if (!Soft386FetchWord(State
, &SecondValue
))
1741 /* Exception occurred */
1745 /* Calculate the result */
1746 Result
= FirstValue
| SecondValue
;
1748 /* Update the flags */
1749 State
->Flags
.Cf
= FALSE
;
1750 State
->Flags
.Of
= FALSE
;
1751 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1752 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
1753 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1755 /* Write back the result */
1756 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
1762 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndByteModrm
)
1764 UCHAR FirstValue
, SecondValue
, Result
;
1765 SOFT386_MOD_REG_RM ModRegRm
;
1766 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1768 /* Make sure this is the right instruction */
1769 ASSERT((Opcode
& 0xFD) == 0x20);
1771 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1773 /* The ADSIZE prefix toggles the size */
1774 AddressSize
= !AddressSize
;
1776 else if (State
->PrefixFlags
1777 & ~(SOFT386_PREFIX_ADSIZE
1778 | SOFT386_PREFIX_SEG
1779 | SOFT386_PREFIX_LOCK
))
1781 /* Invalid prefix */
1782 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1786 /* Get the operands */
1787 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1789 /* Exception occurred */
1793 if (!Soft386ReadModrmByteOperands(State
,
1798 /* Exception occurred */
1802 /* Calculate the result */
1803 Result
= FirstValue
& SecondValue
;
1805 /* Update the flags */
1806 State
->Flags
.Cf
= FALSE
;
1807 State
->Flags
.Of
= FALSE
;
1808 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1809 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1810 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1812 /* Write back the result */
1813 return Soft386WriteModrmByteOperands(State
,
1815 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1819 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndModrm
)
1821 SOFT386_MOD_REG_RM ModRegRm
;
1822 BOOLEAN OperandSize
, AddressSize
;
1824 /* Make sure this is the right instruction */
1825 ASSERT((Opcode
& 0xFD) == 0x21);
1827 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1829 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1831 /* The ADSIZE prefix toggles the address size */
1832 AddressSize
= !AddressSize
;
1835 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1837 /* The OPSIZE prefix toggles the operand size */
1838 OperandSize
= !OperandSize
;
1841 if (State
->PrefixFlags
1842 & ~(SOFT386_PREFIX_ADSIZE
1843 | SOFT386_PREFIX_OPSIZE
1844 | SOFT386_PREFIX_SEG
1845 | SOFT386_PREFIX_LOCK
))
1847 /* Invalid prefix */
1848 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1852 /* Get the operands */
1853 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1855 /* Exception occurred */
1859 /* Check the operand size */
1862 ULONG FirstValue
, SecondValue
, Result
;
1864 if (!Soft386ReadModrmDwordOperands(State
,
1869 /* Exception occurred */
1873 /* Calculate the result */
1874 Result
= FirstValue
& SecondValue
;
1876 /* Update the flags */
1877 State
->Flags
.Cf
= FALSE
;
1878 State
->Flags
.Of
= FALSE
;
1879 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1880 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1881 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1883 /* Write back the result */
1884 return Soft386WriteModrmDwordOperands(State
,
1886 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1891 USHORT FirstValue
, SecondValue
, Result
;
1893 if (!Soft386ReadModrmWordOperands(State
,
1898 /* Exception occurred */
1902 /* Calculate the result */
1903 Result
= FirstValue
& SecondValue
;
1905 /* Update the flags */
1906 State
->Flags
.Cf
= FALSE
;
1907 State
->Flags
.Of
= FALSE
;
1908 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1909 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1910 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1912 /* Write back the result */
1913 return Soft386WriteModrmWordOperands(State
,
1915 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1920 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndAl
)
1922 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
1923 UCHAR SecondValue
, Result
;
1925 /* Make sure this is the right instruction */
1926 ASSERT(Opcode
== 0x24);
1928 if (State
->PrefixFlags
)
1930 /* This opcode doesn't take any prefixes */
1931 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1935 if (!Soft386FetchByte(State
, &SecondValue
))
1937 /* Exception occurred */
1941 /* Calculate the result */
1942 Result
= FirstValue
& SecondValue
;
1944 /* Update the flags */
1945 State
->Flags
.Cf
= FALSE
;
1946 State
->Flags
.Of
= FALSE
;
1947 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1948 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1949 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1951 /* Write back the result */
1952 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
1957 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndEax
)
1959 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1961 /* Make sure this is the right instruction */
1962 ASSERT(Opcode
== 0x25);
1964 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
1966 /* The OPSIZE prefix toggles the size */
1971 /* Invalid prefix */
1972 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1978 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
1979 ULONG SecondValue
, Result
;
1981 if (!Soft386FetchDword(State
, &SecondValue
))
1983 /* Exception occurred */
1987 /* Calculate the result */
1988 Result
= FirstValue
& SecondValue
;
1990 /* Update the flags */
1991 State
->Flags
.Cf
= FALSE
;
1992 State
->Flags
.Of
= FALSE
;
1993 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1994 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1995 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1997 /* Write back the result */
1998 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
2002 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
2003 USHORT SecondValue
, Result
;
2005 if (!Soft386FetchWord(State
, &SecondValue
))
2007 /* Exception occurred */
2011 /* Calculate the result */
2012 Result
= FirstValue
& SecondValue
;
2014 /* Update the flags */
2015 State
->Flags
.Cf
= FALSE
;
2016 State
->Flags
.Of
= FALSE
;
2017 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2018 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
2019 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2021 /* Write back the result */
2022 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
2028 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorByteModrm
)
2030 UCHAR FirstValue
, SecondValue
, Result
;
2031 SOFT386_MOD_REG_RM ModRegRm
;
2032 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2034 /* Make sure this is the right instruction */
2035 ASSERT((Opcode
& 0xFD) == 0x30);
2037 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2039 /* The ADSIZE prefix toggles the size */
2040 AddressSize
= !AddressSize
;
2042 else if (State
->PrefixFlags
2043 & ~(SOFT386_PREFIX_ADSIZE
2044 | SOFT386_PREFIX_SEG
2045 | SOFT386_PREFIX_LOCK
))
2047 /* Invalid prefix */
2048 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2052 /* Get the operands */
2053 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2055 /* Exception occurred */
2059 if (!Soft386ReadModrmByteOperands(State
,
2064 /* Exception occurred */
2068 /* Calculate the result */
2069 Result
= FirstValue
^ SecondValue
;
2071 /* Update the flags */
2072 State
->Flags
.Cf
= FALSE
;
2073 State
->Flags
.Of
= FALSE
;
2074 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2075 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2076 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2078 /* Write back the result */
2079 return Soft386WriteModrmByteOperands(State
,
2081 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2085 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorModrm
)
2087 SOFT386_MOD_REG_RM ModRegRm
;
2088 BOOLEAN OperandSize
, AddressSize
;
2090 /* Make sure this is the right instruction */
2091 ASSERT((Opcode
& 0xFD) == 0x31);
2093 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2095 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2097 /* The ADSIZE prefix toggles the address size */
2098 AddressSize
= !AddressSize
;
2101 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2103 /* The OPSIZE prefix toggles the operand size */
2104 OperandSize
= !OperandSize
;
2107 if (State
->PrefixFlags
2108 & ~(SOFT386_PREFIX_ADSIZE
2109 | SOFT386_PREFIX_OPSIZE
2110 | SOFT386_PREFIX_SEG
2111 | SOFT386_PREFIX_LOCK
))
2113 /* Invalid prefix */
2114 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2118 /* Get the operands */
2119 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2121 /* Exception occurred */
2125 /* Check the operand size */
2128 ULONG FirstValue
, SecondValue
, Result
;
2130 if (!Soft386ReadModrmDwordOperands(State
,
2135 /* Exception occurred */
2139 /* Calculate the result */
2140 Result
= FirstValue
^ SecondValue
;
2142 /* Update the flags */
2143 State
->Flags
.Cf
= FALSE
;
2144 State
->Flags
.Of
= FALSE
;
2145 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2146 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2147 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2149 /* Write back the result */
2150 return Soft386WriteModrmDwordOperands(State
,
2152 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2157 USHORT FirstValue
, SecondValue
, Result
;
2159 if (!Soft386ReadModrmWordOperands(State
,
2164 /* Exception occurred */
2168 /* Calculate the result */
2169 Result
= FirstValue
^ SecondValue
;
2171 /* Update the flags */
2172 State
->Flags
.Cf
= FALSE
;
2173 State
->Flags
.Of
= FALSE
;
2174 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2175 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2176 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2178 /* Write back the result */
2179 return Soft386WriteModrmWordOperands(State
,
2181 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2186 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorAl
)
2188 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
2189 UCHAR SecondValue
, Result
;
2191 /* Make sure this is the right instruction */
2192 ASSERT(Opcode
== 0x34);
2194 if (State
->PrefixFlags
)
2196 /* This opcode doesn't take any prefixes */
2197 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2201 if (!Soft386FetchByte(State
, &SecondValue
))
2203 /* Exception occurred */
2207 /* Calculate the result */
2208 Result
= FirstValue
^ SecondValue
;
2210 /* Update the flags */
2211 State
->Flags
.Cf
= FALSE
;
2212 State
->Flags
.Of
= FALSE
;
2213 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2214 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2215 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2217 /* Write back the result */
2218 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
2223 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorEax
)
2225 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2227 /* Make sure this is the right instruction */
2228 ASSERT(Opcode
== 0x35);
2230 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
2232 /* The OPSIZE prefix toggles the size */
2237 /* Invalid prefix */
2238 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2244 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
2245 ULONG SecondValue
, Result
;
2247 if (!Soft386FetchDword(State
, &SecondValue
))
2249 /* Exception occurred */
2253 /* Calculate the result */
2254 Result
= FirstValue
^ SecondValue
;
2256 /* Update the flags */
2257 State
->Flags
.Cf
= FALSE
;
2258 State
->Flags
.Of
= FALSE
;
2259 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2260 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2261 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2263 /* Write back the result */
2264 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
2268 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
2269 USHORT SecondValue
, Result
;
2271 if (!Soft386FetchWord(State
, &SecondValue
))
2273 /* Exception occurred */
2277 /* Calculate the result */
2278 Result
= FirstValue
^ SecondValue
;
2280 /* Update the flags */
2281 State
->Flags
.Cf
= FALSE
;
2282 State
->Flags
.Of
= FALSE
;
2283 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2284 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
2285 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2287 /* Write back the result */
2288 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
2294 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestByteModrm
)
2296 UCHAR FirstValue
, SecondValue
, Result
;
2297 SOFT386_MOD_REG_RM ModRegRm
;
2298 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2300 /* Make sure this is the right instruction */
2301 ASSERT(Opcode
== 0x84);
2303 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2305 /* The ADSIZE prefix toggles the size */
2306 AddressSize
= !AddressSize
;
2308 else if (State
->PrefixFlags
2309 & ~(SOFT386_PREFIX_ADSIZE
2310 | SOFT386_PREFIX_SEG
2311 | SOFT386_PREFIX_LOCK
))
2313 /* Invalid prefix */
2314 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2318 /* Get the operands */
2319 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2321 /* Exception occurred */
2325 if (!Soft386ReadModrmByteOperands(State
,
2330 /* Exception occurred */
2333 /* Calculate the result */
2334 Result
= FirstValue
& SecondValue
;
2336 /* Update the flags */
2337 State
->Flags
.Cf
= FALSE
;
2338 State
->Flags
.Of
= FALSE
;
2339 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2340 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2341 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2343 /* The result is discarded */
2347 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestModrm
)
2349 SOFT386_MOD_REG_RM ModRegRm
;
2350 BOOLEAN OperandSize
, AddressSize
;
2352 /* Make sure this is the right instruction */
2353 ASSERT(Opcode
== 0x85);
2355 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2357 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2359 /* The ADSIZE prefix toggles the address size */
2360 AddressSize
= !AddressSize
;
2363 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2365 /* The OPSIZE prefix toggles the operand size */
2366 OperandSize
= !OperandSize
;
2369 if (State
->PrefixFlags
2370 & ~(SOFT386_PREFIX_ADSIZE
2371 | SOFT386_PREFIX_OPSIZE
2372 | SOFT386_PREFIX_SEG
2373 | SOFT386_PREFIX_LOCK
))
2375 /* Invalid prefix */
2376 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2380 /* Get the operands */
2381 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2383 /* Exception occurred */
2387 /* Check the operand size */
2390 ULONG FirstValue
, SecondValue
, Result
;
2392 if (!Soft386ReadModrmDwordOperands(State
,
2397 /* Exception occurred */
2401 /* Calculate the result */
2402 Result
= FirstValue
& SecondValue
;
2404 /* Update the flags */
2405 State
->Flags
.Cf
= FALSE
;
2406 State
->Flags
.Of
= FALSE
;
2407 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2408 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2409 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2413 USHORT FirstValue
, SecondValue
, Result
;
2415 if (!Soft386ReadModrmWordOperands(State
,
2420 /* Exception occurred */
2424 /* Calculate the result */
2425 Result
= FirstValue
& SecondValue
;
2427 /* Update the flags */
2428 State
->Flags
.Cf
= FALSE
;
2429 State
->Flags
.Of
= FALSE
;
2430 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2431 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2432 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2435 /* The result is discarded */
2439 SOFT386_OPCODE_HANDLER(Soft386OpcodeXchgByteModrm
)
2441 UCHAR FirstValue
, SecondValue
;
2442 SOFT386_MOD_REG_RM ModRegRm
;
2443 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2445 /* Make sure this is the right instruction */
2446 ASSERT(Opcode
== 0x86);
2448 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2450 /* The ADSIZE prefix toggles the size */
2451 AddressSize
= !AddressSize
;
2453 else if (State
->PrefixFlags
2454 & ~(SOFT386_PREFIX_ADSIZE
2455 | SOFT386_PREFIX_SEG
2456 | SOFT386_PREFIX_LOCK
))
2458 /* Invalid prefix */
2459 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2463 /* Get the operands */
2464 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2466 /* Exception occurred */
2470 if (!Soft386ReadModrmByteOperands(State
,
2475 /* Exception occurred */
2479 /* Write the value from the register to the R/M */
2480 if (!Soft386WriteModrmByteOperands(State
,
2485 /* Exception occurred */
2489 /* Write the value from the R/M to the register */
2490 if (!Soft386WriteModrmByteOperands(State
,
2495 /* Exception occurred */
2502 SOFT386_OPCODE_HANDLER(Soft386OpcodeXchgModrm
)
2504 SOFT386_MOD_REG_RM ModRegRm
;
2505 BOOLEAN OperandSize
, AddressSize
;
2507 /* Make sure this is the right instruction */
2508 ASSERT(Opcode
== 0x87);
2510 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2512 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2514 /* The ADSIZE prefix toggles the address size */
2515 AddressSize
= !AddressSize
;
2518 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2520 /* The OPSIZE prefix toggles the operand size */
2521 OperandSize
= !OperandSize
;
2524 if (State
->PrefixFlags
2525 & ~(SOFT386_PREFIX_ADSIZE
2526 | SOFT386_PREFIX_OPSIZE
2527 | SOFT386_PREFIX_SEG
2528 | SOFT386_PREFIX_LOCK
))
2530 /* Invalid prefix */
2531 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2535 /* Get the operands */
2536 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2538 /* Exception occurred */
2542 /* Check the operand size */
2545 ULONG FirstValue
, SecondValue
;
2547 if (!Soft386ReadModrmDwordOperands(State
,
2552 /* Exception occurred */
2556 /* Write the value from the register to the R/M */
2557 if (!Soft386WriteModrmDwordOperands(State
,
2562 /* Exception occurred */
2566 /* Write the value from the R/M to the register */
2567 if (!Soft386WriteModrmDwordOperands(State
,
2572 /* Exception occurred */
2578 USHORT FirstValue
, SecondValue
;
2580 if (!Soft386ReadModrmWordOperands(State
,
2585 /* Exception occurred */
2589 /* Write the value from the register to the R/M */
2590 if (!Soft386WriteModrmWordOperands(State
,
2595 /* Exception occurred */
2599 /* Write the value from the R/M to the register */
2600 if (!Soft386WriteModrmWordOperands(State
,
2605 /* Exception occurred */
2610 /* The result is discarded */