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 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
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
,
233 Soft386OpcodeIntOverflow
,
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_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 */
2614 SOFT386_OPCODE_HANDLER(Soft386OpcodePushEs
)
2616 /* Call the internal API */
2617 return Soft386StackPush(State
, State
->SegmentRegs
[SOFT386_REG_ES
].Selector
);
2620 SOFT386_OPCODE_HANDLER(Soft386OpcodePopEs
)
2624 if (!Soft386StackPop(State
, &NewSelector
))
2626 /* Exception occurred */
2630 /* Call the internal API */
2631 return Soft386LoadSegment(State
, SOFT386_REG_ES
, LOWORD(NewSelector
));
2634 SOFT386_OPCODE_HANDLER(Soft386OpcodePushCs
)
2636 /* Call the internal API */
2637 return Soft386StackPush(State
, State
->SegmentRegs
[SOFT386_REG_CS
].Selector
);
2640 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcByteModrm
)
2642 UCHAR FirstValue
, SecondValue
, Result
;
2643 SOFT386_MOD_REG_RM ModRegRm
;
2644 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2646 /* Make sure this is the right instruction */
2647 ASSERT((Opcode
& 0xFD) == 0x10);
2649 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2651 /* The ADSIZE prefix toggles the size */
2652 AddressSize
= !AddressSize
;
2654 else if (State
->PrefixFlags
2655 & ~(SOFT386_PREFIX_ADSIZE
2656 | SOFT386_PREFIX_SEG
2657 | SOFT386_PREFIX_LOCK
))
2659 /* Invalid prefix */
2660 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2664 /* Get the operands */
2665 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2667 /* Exception occurred */
2671 if (!Soft386ReadModrmByteOperands(State
,
2676 /* Exception occurred */
2680 /* Calculate the result */
2681 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2683 /* Special exception for CF */
2684 State
->Flags
.Cf
= State
->Flags
.Cf
2685 && ((FirstValue
== 0xFF) || (SecondValue
== 0xFF));
2687 /* Update the flags */
2688 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2689 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
2690 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
2691 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
2692 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2693 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2694 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2696 /* Write back the result */
2697 return Soft386WriteModrmByteOperands(State
,
2699 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2703 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcModrm
)
2705 SOFT386_MOD_REG_RM ModRegRm
;
2706 BOOLEAN OperandSize
, AddressSize
;
2708 /* Make sure this is the right instruction */
2709 ASSERT((Opcode
& 0xFD) == 0x11);
2711 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2713 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2715 /* The ADSIZE prefix toggles the address size */
2716 AddressSize
= !AddressSize
;
2719 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2721 /* The OPSIZE prefix toggles the operand size */
2722 OperandSize
= !OperandSize
;
2725 if (State
->PrefixFlags
2726 & ~(SOFT386_PREFIX_ADSIZE
2727 | SOFT386_PREFIX_OPSIZE
2728 | SOFT386_PREFIX_SEG
2729 | SOFT386_PREFIX_LOCK
))
2731 /* Invalid prefix */
2732 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2736 /* Get the operands */
2737 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2739 /* Exception occurred */
2743 /* Check the operand size */
2746 ULONG FirstValue
, SecondValue
, Result
;
2748 if (!Soft386ReadModrmDwordOperands(State
,
2753 /* Exception occurred */
2757 /* Calculate the result */
2758 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2760 /* Special exception for CF */
2761 State
->Flags
.Cf
= State
->Flags
.Cf
2762 && ((FirstValue
== 0xFFFFFFFF) || (SecondValue
== 0xFFFFFFFF));
2764 /* Update the flags */
2765 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2766 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
2767 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
2768 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
2769 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2770 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2771 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2773 /* Write back the result */
2774 return Soft386WriteModrmDwordOperands(State
,
2776 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2781 USHORT FirstValue
, SecondValue
, Result
;
2783 if (!Soft386ReadModrmWordOperands(State
,
2788 /* Exception occurred */
2792 /* Calculate the result */
2793 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2795 /* Special exception for CF */
2796 State
->Flags
.Cf
= State
->Flags
.Cf
2797 && ((FirstValue
== 0xFFFF) || (SecondValue
== 0xFFFF));
2799 /* Update the flags */
2800 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2801 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
2802 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
2803 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
2804 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2805 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
2806 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2808 /* Write back the result */
2809 return Soft386WriteModrmWordOperands(State
,
2811 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2817 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcAl
)
2819 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
2820 UCHAR SecondValue
, Result
;
2822 /* Make sure this is the right instruction */
2823 ASSERT(Opcode
== 0x14);
2825 if (State
->PrefixFlags
)
2827 /* This opcode doesn't take any prefixes */
2828 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2832 if (!Soft386FetchByte(State
, &SecondValue
))
2834 /* Exception occurred */
2838 /* Calculate the result */
2839 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2841 /* Special exception for CF */
2842 State
->Flags
.Cf
= State
->Flags
.Cf
&&
2843 ((FirstValue
== 0xFF) || (SecondValue
== 0xFF));
2845 /* Update the flags */
2846 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2847 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
2848 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
2849 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
2850 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2851 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2852 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2854 /* Write back the result */
2855 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
2860 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcEax
)
2862 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2864 /* Make sure this is the right instruction */
2865 ASSERT(Opcode
== 0x15);
2867 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
2869 /* The OPSIZE prefix toggles the size */
2874 /* Invalid prefix */
2875 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2881 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
2882 ULONG SecondValue
, Result
;
2884 if (!Soft386FetchDword(State
, &SecondValue
))
2886 /* Exception occurred */
2890 /* Calculate the result */
2891 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2893 /* Special exception for CF */
2894 State
->Flags
.Cf
= State
->Flags
.Cf
&&
2895 ((FirstValue
== 0xFFFFFFFF) || (SecondValue
== 0xFFFFFFFF));
2897 /* Update the flags */
2898 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2899 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
2900 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
2901 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
2902 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2903 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2904 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2906 /* Write back the result */
2907 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
2911 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
2912 USHORT SecondValue
, Result
;
2914 if (!Soft386FetchWord(State
, &SecondValue
))
2916 /* Exception occurred */
2920 /* Calculate the result */
2921 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2923 /* Special exception for CF */
2924 State
->Flags
.Cf
= State
->Flags
.Cf
&&
2925 ((FirstValue
== 0xFFFF) || (SecondValue
== 0xFFFF));
2927 /* Update the flags */
2928 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2929 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
2930 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
2931 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
2932 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2933 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
2934 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2936 /* Write back the result */
2937 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
2943 SOFT386_OPCODE_HANDLER(Soft386OpcodePushSs
)
2945 /* Call the internal API */
2946 return Soft386StackPush(State
, State
->SegmentRegs
[SOFT386_REG_SS
].Selector
);
2949 SOFT386_OPCODE_HANDLER(Soft386OpcodePopSs
)
2953 if (!Soft386StackPop(State
, &NewSelector
))
2955 /* Exception occurred */
2959 /* Call the internal API */
2960 return Soft386LoadSegment(State
, SOFT386_REG_SS
, LOWORD(NewSelector
));
2963 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbByteModrm
)
2965 // TODO: NOT IMPLEMENTED
2971 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbModrm
)
2973 // TODO: NOT IMPLEMENTED
2979 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbAl
)
2981 // TODO: NOT IMPLEMENTED
2987 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbEax
)
2989 // TODO: NOT IMPLEMENTED
2995 SOFT386_OPCODE_HANDLER(Soft386OpcodePushDs
)
2997 /* Call the internal API */
2998 return Soft386StackPush(State
, State
->SegmentRegs
[SOFT386_REG_DS
].Selector
);
3001 SOFT386_OPCODE_HANDLER(Soft386OpcodePopDs
)
3005 if (!Soft386StackPop(State
, &NewSelector
))
3007 /* Exception occurred */
3011 /* Call the internal API */
3012 return Soft386LoadSegment(State
, SOFT386_REG_DS
, LOWORD(NewSelector
));
3015 SOFT386_OPCODE_HANDLER(Soft386OpcodeDaa
)
3017 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3018 BOOLEAN Carry
= State
->Flags
.Cf
;
3020 /* Clear the carry flag */
3021 State
->Flags
.Cf
= FALSE
;
3023 /* Check if the first BCD digit is invalid or there was a carry from it */
3024 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3027 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
+= 0x06;
3028 if (State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
< 0x06)
3030 /* A carry occurred */
3031 State
->Flags
.Cf
= TRUE
;
3034 /* Set the adjust flag */
3035 State
->Flags
.Af
= TRUE
;
3038 /* Check if the second BCD digit is invalid or there was a carry from it */
3039 if ((Value
> 0x99) || Carry
)
3042 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
+= 0x60;
3044 /* There was a carry */
3045 State
->Flags
.Cf
= TRUE
;
3051 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubByteModrm
)
3053 UCHAR FirstValue
, SecondValue
, Result
;
3054 SOFT386_MOD_REG_RM ModRegRm
;
3055 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3057 /* Make sure this is the right instruction */
3058 ASSERT((Opcode
& 0xED) == 0x28);
3060 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3062 /* The ADSIZE prefix toggles the size */
3063 AddressSize
= !AddressSize
;
3065 else if (State
->PrefixFlags
3066 & ~(SOFT386_PREFIX_ADSIZE
3067 | SOFT386_PREFIX_SEG
3068 | SOFT386_PREFIX_LOCK
))
3070 /* Invalid prefix */
3071 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3075 /* Get the operands */
3076 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3078 /* Exception occurred */
3082 if (!Soft386ReadModrmByteOperands(State
,
3087 /* Exception occurred */
3091 /* Check if this is the instruction that writes to R/M */
3092 if (!(Opcode
& SOFT386_OPCODE_WRITE_REG
))
3094 /* Swap the order */
3095 FirstValue
^= SecondValue
;
3096 SecondValue
^= FirstValue
;
3097 FirstValue
^= SecondValue
;
3100 /* Calculate the result */
3101 Result
= FirstValue
- SecondValue
;
3103 /* Update the flags */
3104 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3105 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) != (SecondValue
& SIGN_FLAG_BYTE
))
3106 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
3107 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3108 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3109 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
3110 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3112 /* Check if this is not a CMP */
3113 if (!(Opcode
& 0x10))
3115 /* Write back the result */
3116 return Soft386WriteModrmByteOperands(State
,
3118 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3123 /* Discard the result */
3128 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubModrm
)
3130 SOFT386_MOD_REG_RM ModRegRm
;
3131 BOOLEAN OperandSize
, AddressSize
;
3133 /* Make sure this is the right instruction */
3134 ASSERT((Opcode
& 0xED) == 0x29);
3136 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3138 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3140 /* The ADSIZE prefix toggles the address size */
3141 AddressSize
= !AddressSize
;
3144 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
3146 /* The OPSIZE prefix toggles the operand size */
3147 OperandSize
= !OperandSize
;
3150 if (State
->PrefixFlags
3151 & ~(SOFT386_PREFIX_ADSIZE
3152 | SOFT386_PREFIX_OPSIZE
3153 | SOFT386_PREFIX_SEG
3154 | SOFT386_PREFIX_LOCK
))
3156 /* Invalid prefix */
3157 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3161 /* Get the operands */
3162 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3164 /* Exception occurred */
3168 /* Check the operand size */
3171 ULONG FirstValue
, SecondValue
, Result
;
3173 if (!Soft386ReadModrmDwordOperands(State
,
3178 /* Exception occurred */
3182 /* Check if this is the instruction that writes to R/M */
3183 if (!(Opcode
& SOFT386_OPCODE_WRITE_REG
))
3185 /* Swap the order */
3186 FirstValue
^= SecondValue
;
3187 SecondValue
^= FirstValue
;
3188 FirstValue
^= SecondValue
;
3191 /* Calculate the result */
3192 Result
= FirstValue
- SecondValue
;
3194 /* Update the flags */
3195 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3196 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) != (SecondValue
& SIGN_FLAG_LONG
))
3197 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
3198 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3199 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3200 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
3201 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3203 /* Check if this is not a CMP */
3204 if (!(Opcode
& 0x10))
3206 /* Write back the result */
3207 return Soft386WriteModrmDwordOperands(State
,
3209 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3214 /* Discard the result */
3220 USHORT FirstValue
, SecondValue
, Result
;
3222 if (!Soft386ReadModrmWordOperands(State
,
3227 /* Exception occurred */
3231 /* Check if this is the instruction that writes to R/M */
3232 if (!(Opcode
& SOFT386_OPCODE_WRITE_REG
))
3234 /* Swap the order */
3235 FirstValue
^= SecondValue
;
3236 SecondValue
^= FirstValue
;
3237 FirstValue
^= SecondValue
;
3240 /* Calculate the result */
3241 Result
= FirstValue
- SecondValue
;
3243 /* Update the flags */
3244 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3245 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) != (SecondValue
& SIGN_FLAG_WORD
))
3246 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
3247 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3248 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3249 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
3250 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3252 /* Check if this is not a CMP */
3253 if (!(Opcode
& 0x10))
3255 /* Write back the result */
3256 return Soft386WriteModrmWordOperands(State
,
3258 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3263 /* Discard the result */
3270 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubAl
)
3272 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3273 UCHAR SecondValue
, Result
;
3275 /* Make sure this is the right instruction */
3276 ASSERT((Opcode
& 0xEF) == 0x2C);
3278 if (State
->PrefixFlags
)
3280 /* This opcode doesn't take any prefixes */
3281 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3285 if (!Soft386FetchByte(State
, &SecondValue
))
3287 /* Exception occurred */
3291 /* Calculate the result */
3292 Result
= FirstValue
- SecondValue
;
3294 /* Update the flags */
3295 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3296 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) != (SecondValue
& SIGN_FLAG_BYTE
))
3297 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
3298 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3299 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3300 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
3301 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3303 /* Check if this is not a CMP */
3304 if (!(Opcode
& 0x10))
3306 /* Write back the result */
3307 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
3313 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubEax
)
3315 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3317 /* Make sure this is the right instruction */
3318 ASSERT((Opcode
& 0xEF) == 0x2D);
3320 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
3322 /* The OPSIZE prefix toggles the size */
3327 /* Invalid prefix */
3328 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3334 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
3335 ULONG SecondValue
, Result
;
3337 if (!Soft386FetchDword(State
, &SecondValue
))
3339 /* Exception occurred */
3343 /* Calculate the result */
3344 Result
= FirstValue
- SecondValue
;
3346 /* Update the flags */
3347 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3348 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) != (SecondValue
& SIGN_FLAG_LONG
))
3349 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
3350 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3351 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3352 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
3353 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3355 /* Check if this is not a CMP */
3356 if (!(Opcode
& 0x10))
3358 /* Write back the result */
3359 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
3364 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
3365 USHORT SecondValue
, Result
;
3367 if (!Soft386FetchWord(State
, &SecondValue
))
3369 /* Exception occurred */
3373 /* Calculate the result */
3374 Result
= FirstValue
- SecondValue
;
3376 /* Update the flags */
3377 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3378 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) != (SecondValue
& SIGN_FLAG_WORD
))
3379 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
3380 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3381 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3382 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
3383 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3385 /* Write back the result */
3386 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
3392 SOFT386_OPCODE_HANDLER(Soft386OpcodeDas
)
3394 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3395 BOOLEAN Carry
= State
->Flags
.Cf
;
3397 /* Clear the carry flag */
3398 State
->Flags
.Cf
= FALSE
;
3400 /* Check if the first BCD digit is invalid or there was a borrow */
3401 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3404 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
-= 0x06;
3405 if (State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
> 0xFB)
3407 /* A borrow occurred */
3408 State
->Flags
.Cf
= TRUE
;
3411 /* Set the adjust flag */
3412 State
->Flags
.Af
= TRUE
;
3415 /* Check if the second BCD digit is invalid or there was a borrow */
3416 if ((Value
> 0x99) || Carry
)
3419 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
-= 0x60;
3421 /* There was a borrow */
3422 State
->Flags
.Cf
= TRUE
;
3428 SOFT386_OPCODE_HANDLER(Soft386OpcodeAaa
)
3430 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3433 * Check if the value in AL is not a valid BCD digit,
3434 * or there was a carry from the lowest 4 bits of AL
3436 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3439 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
+= 0x06;
3440 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
++;
3443 State
->Flags
.Cf
= State
->Flags
.Af
= TRUE
;
3447 /* Clear CF and AF */
3448 State
->Flags
.Cf
= State
->Flags
.Af
= FALSE
;
3451 /* Keep only the lowest 4 bits of AL */
3452 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
&= 0x0F;
3457 SOFT386_OPCODE_HANDLER(Soft386OpcodeAas
)
3459 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3462 * Check if the value in AL is not a valid BCD digit,
3463 * or there was a borrow from the lowest 4 bits of AL
3465 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3468 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
-= 0x06;
3469 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
--;
3472 State
->Flags
.Cf
= State
->Flags
.Af
= TRUE
;
3476 /* Clear CF and AF */
3477 State
->Flags
.Cf
= State
->Flags
.Af
= FALSE
;
3480 /* Keep only the lowest 4 bits of AL */
3481 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
&= 0x0F;
3486 SOFT386_OPCODE_HANDLER(Soft386OpcodePushAll
)
3488 // TODO: NOT IMPLEMENTED
3494 SOFT386_OPCODE_HANDLER(Soft386OpcodePopAll
)
3496 // TODO: NOT IMPLEMENTED
3502 SOFT386_OPCODE_HANDLER(Soft386OpcodeBound
)
3504 // TODO: NOT IMPLEMENTED
3510 SOFT386_OPCODE_HANDLER(Soft386OpcodeArpl
)
3512 // TODO: NOT IMPLEMENTED
3518 SOFT386_OPCODE_HANDLER(Soft386OpcodePushImm
)
3520 // TODO: NOT IMPLEMENTED
3526 SOFT386_OPCODE_HANDLER(Soft386OpcodeImulModrmImm
)
3528 // TODO: NOT IMPLEMENTED
3534 SOFT386_OPCODE_HANDLER(Soft386OpcodePushByteImm
)
3538 if (!Soft386FetchByte(State
, &Data
))
3540 /* Exception occurred */
3544 /* Call the internal API */
3545 return Soft386StackPush(State
, Data
);
3548 SOFT386_OPCODE_HANDLER(Soft386OpcodeImulModrmByteImm
)
3550 // TODO: NOT IMPLEMENTED
3556 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovByteModrm
)
3558 // TODO: NOT IMPLEMENTED
3564 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovModrm
)
3566 // TODO: NOT IMPLEMENTED
3572 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovStoreSeg
)
3574 // TODO: NOT IMPLEMENTED
3580 SOFT386_OPCODE_HANDLER(Soft386OpcodeLea
)
3582 // TODO: NOT IMPLEMENTED
3588 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovLoadSeg
)
3590 // TODO: NOT IMPLEMENTED
3596 SOFT386_OPCODE_HANDLER(Soft386OpcodeCwde
)
3598 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3600 /* Make sure this is the right instruction */
3601 ASSERT(Opcode
== 0x98);
3603 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
3605 /* The OPSIZE prefix toggles the size */
3608 else if (State
->PrefixFlags
!= 0)
3610 /* Invalid prefix */
3611 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3617 /* Sign extend AX to EAX */
3618 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= MAKELONG
3620 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
,
3621 (State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
& SIGN_FLAG_WORD
)
3627 /* Sign extend AL to AX */
3628 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
=
3629 (State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
& SIGN_FLAG_BYTE
)
3636 SOFT386_OPCODE_HANDLER(Soft386OpcodeCdq
)
3638 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3640 /* Make sure this is the right instruction */
3641 ASSERT(Opcode
== 0x99);
3643 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
3645 /* The OPSIZE prefix toggles the size */
3648 else if (State
->PrefixFlags
!= 0)
3650 /* Invalid prefix */
3651 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3657 /* Sign extend EAX to EDX:EAX */
3658 State
->GeneralRegs
[SOFT386_REG_EDX
].Long
=
3659 (State
->GeneralRegs
[SOFT386_REG_EAX
].Long
& SIGN_FLAG_LONG
)
3660 ? 0xFFFFFFFF : 0x00000000;
3664 /* Sign extend AX to DX:AX */
3665 State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
=
3666 (State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
& SIGN_FLAG_WORD
)
3673 SOFT386_OPCODE_HANDLER(Soft386OpcodeCallAbs
)
3675 // TODO: NOT IMPLEMENTED
3681 SOFT386_OPCODE_HANDLER(Soft386OpcodeWait
)
3683 // TODO: NOT IMPLEMENTED
3689 SOFT386_OPCODE_HANDLER(Soft386OpcodePushFlags
)
3691 // TODO: NOT IMPLEMENTED
3697 SOFT386_OPCODE_HANDLER(Soft386OpcodePopFlags
)
3699 // TODO: NOT IMPLEMENTED
3705 SOFT386_OPCODE_HANDLER(Soft386OpcodeSahf
)
3707 // TODO: NOT IMPLEMENTED
3713 SOFT386_OPCODE_HANDLER(Soft386OpcodeLahf
)
3715 // TODO: NOT IMPLEMENTED
3721 SOFT386_OPCODE_HANDLER(Soft386OpcodeRetImm
)
3723 // TODO: NOT IMPLEMENTED
3729 SOFT386_OPCODE_HANDLER(Soft386OpcodeRet
)
3731 // TODO: NOT IMPLEMENTED
3737 SOFT386_OPCODE_HANDLER(Soft386OpcodeLes
)
3739 // TODO: NOT IMPLEMENTED
3745 SOFT386_OPCODE_HANDLER(Soft386OpcodeLds
)
3747 // TODO: NOT IMPLEMENTED
3753 SOFT386_OPCODE_HANDLER(Soft386OpcodeEnter
)
3755 // TODO: NOT IMPLEMENTED
3761 SOFT386_OPCODE_HANDLER(Soft386OpcodeLeave
)
3763 // TODO: NOT IMPLEMENTED
3769 SOFT386_OPCODE_HANDLER(Soft386OpcodeRetFarImm
)
3771 // TODO: NOT IMPLEMENTED
3777 SOFT386_OPCODE_HANDLER(Soft386OpcodeRetFar
)
3779 // TODO: NOT IMPLEMENTED
3785 SOFT386_OPCODE_HANDLER(Soft386OpcodeInt3
)
3787 // TODO: NOT IMPLEMENTED
3793 SOFT386_OPCODE_HANDLER(Soft386OpcodeInt
)
3795 // TODO: NOT IMPLEMENTED
3801 SOFT386_OPCODE_HANDLER(Soft386OpcodeIntOverflow
)
3803 // TODO: NOT IMPLEMENTED
3809 SOFT386_OPCODE_HANDLER(Soft386OpcodeIret
)
3811 // TODO: NOT IMPLEMENTED
3817 SOFT386_OPCODE_HANDLER(Soft386OpcodeAam
)
3819 // TODO: NOT IMPLEMENTED
3825 SOFT386_OPCODE_HANDLER(Soft386OpcodeAad
)
3827 // TODO: NOT IMPLEMENTED
3833 SOFT386_OPCODE_HANDLER(Soft386OpcodeXlat
)
3835 // TODO: NOT IMPLEMENTED
3841 SOFT386_OPCODE_HANDLER(Soft386OpcodeLoopnz
)
3843 // TODO: NOT IMPLEMENTED
3849 SOFT386_OPCODE_HANDLER(Soft386OpcodeLoopz
)
3851 // TODO: NOT IMPLEMENTED
3857 SOFT386_OPCODE_HANDLER(Soft386OpcodeLoop
)
3859 // TODO: NOT IMPLEMENTED
3865 SOFT386_OPCODE_HANDLER(Soft386OpcodeJecxz
)
3867 // TODO: NOT IMPLEMENTED
3873 SOFT386_OPCODE_HANDLER(Soft386OpcodeCall
)
3875 // TODO: NOT IMPLEMENTED
3881 SOFT386_OPCODE_HANDLER(Soft386OpcodeJmp
)
3883 // TODO: NOT IMPLEMENTED
3889 SOFT386_OPCODE_HANDLER(Soft386OpcodeJmpAbs
)
3891 // TODO: NOT IMPLEMENTED