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(Soft386OpcodeTestAl
)
2441 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
2442 UCHAR SecondValue
, Result
;
2444 /* Make sure this is the right instruction */
2445 ASSERT(Opcode
== 0xA8);
2447 if (State
->PrefixFlags
)
2449 /* This opcode doesn't take any prefixes */
2450 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2454 if (!Soft386FetchByte(State
, &SecondValue
))
2456 /* Exception occurred */
2460 /* Calculate the result */
2461 Result
= FirstValue
& SecondValue
;
2463 /* Update the flags */
2464 State
->Flags
.Cf
= FALSE
;
2465 State
->Flags
.Of
= FALSE
;
2466 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2467 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2468 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2470 /* The result is discarded */
2474 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestEax
)
2476 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2478 /* Make sure this is the right instruction */
2479 ASSERT(Opcode
== 0xA9);
2481 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
2483 /* The OPSIZE prefix toggles the size */
2488 /* Invalid prefix */
2489 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2495 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
2496 ULONG SecondValue
, Result
;
2498 if (!Soft386FetchDword(State
, &SecondValue
))
2500 /* Exception occurred */
2504 /* Calculate the result */
2505 Result
= FirstValue
& SecondValue
;
2507 /* Update the flags */
2508 State
->Flags
.Cf
= FALSE
;
2509 State
->Flags
.Of
= FALSE
;
2510 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2511 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2512 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2516 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
2517 USHORT SecondValue
, Result
;
2519 if (!Soft386FetchWord(State
, &SecondValue
))
2521 /* Exception occurred */
2525 /* Calculate the result */
2526 Result
= FirstValue
& SecondValue
;
2528 /* Update the flags */
2529 State
->Flags
.Cf
= FALSE
;
2530 State
->Flags
.Of
= FALSE
;
2531 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2532 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
2533 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2536 /* The result is discarded */
2540 SOFT386_OPCODE_HANDLER(Soft386OpcodeXchgByteModrm
)
2542 UCHAR FirstValue
, SecondValue
;
2543 SOFT386_MOD_REG_RM ModRegRm
;
2544 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2546 /* Make sure this is the right instruction */
2547 ASSERT(Opcode
== 0x86);
2549 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2551 /* The ADSIZE prefix toggles the size */
2552 AddressSize
= !AddressSize
;
2554 else if (State
->PrefixFlags
2555 & ~(SOFT386_PREFIX_ADSIZE
2556 | SOFT386_PREFIX_SEG
2557 | SOFT386_PREFIX_LOCK
))
2559 /* Invalid prefix */
2560 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2564 /* Get the operands */
2565 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2567 /* Exception occurred */
2571 if (!Soft386ReadModrmByteOperands(State
,
2576 /* Exception occurred */
2580 /* Write the value from the register to the R/M */
2581 if (!Soft386WriteModrmByteOperands(State
,
2586 /* Exception occurred */
2590 /* Write the value from the R/M to the register */
2591 if (!Soft386WriteModrmByteOperands(State
,
2596 /* Exception occurred */
2603 SOFT386_OPCODE_HANDLER(Soft386OpcodeXchgModrm
)
2605 SOFT386_MOD_REG_RM ModRegRm
;
2606 BOOLEAN OperandSize
, AddressSize
;
2608 /* Make sure this is the right instruction */
2609 ASSERT(Opcode
== 0x87);
2611 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2613 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2615 /* The ADSIZE prefix toggles the address size */
2616 AddressSize
= !AddressSize
;
2619 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2621 /* The OPSIZE prefix toggles the operand size */
2622 OperandSize
= !OperandSize
;
2625 if (State
->PrefixFlags
2626 & ~(SOFT386_PREFIX_ADSIZE
2627 | SOFT386_PREFIX_OPSIZE
2628 | SOFT386_PREFIX_SEG
2629 | SOFT386_PREFIX_LOCK
))
2631 /* Invalid prefix */
2632 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2636 /* Get the operands */
2637 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2639 /* Exception occurred */
2643 /* Check the operand size */
2646 ULONG FirstValue
, SecondValue
;
2648 if (!Soft386ReadModrmDwordOperands(State
,
2653 /* Exception occurred */
2657 /* Write the value from the register to the R/M */
2658 if (!Soft386WriteModrmDwordOperands(State
,
2663 /* Exception occurred */
2667 /* Write the value from the R/M to the register */
2668 if (!Soft386WriteModrmDwordOperands(State
,
2673 /* Exception occurred */
2679 USHORT FirstValue
, SecondValue
;
2681 if (!Soft386ReadModrmWordOperands(State
,
2686 /* Exception occurred */
2690 /* Write the value from the register to the R/M */
2691 if (!Soft386WriteModrmWordOperands(State
,
2696 /* Exception occurred */
2700 /* Write the value from the R/M to the register */
2701 if (!Soft386WriteModrmWordOperands(State
,
2706 /* Exception occurred */
2711 /* The result is discarded */
2715 SOFT386_OPCODE_HANDLER(Soft386OpcodePushEs
)
2717 /* Call the internal API */
2718 return Soft386StackPush(State
, State
->SegmentRegs
[SOFT386_REG_ES
].Selector
);
2721 SOFT386_OPCODE_HANDLER(Soft386OpcodePopEs
)
2725 if (!Soft386StackPop(State
, &NewSelector
))
2727 /* Exception occurred */
2731 /* Call the internal API */
2732 return Soft386LoadSegment(State
, SOFT386_REG_ES
, LOWORD(NewSelector
));
2735 SOFT386_OPCODE_HANDLER(Soft386OpcodePushCs
)
2737 /* Call the internal API */
2738 return Soft386StackPush(State
, State
->SegmentRegs
[SOFT386_REG_CS
].Selector
);
2741 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcByteModrm
)
2743 UCHAR FirstValue
, SecondValue
, Result
;
2744 SOFT386_MOD_REG_RM ModRegRm
;
2745 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2747 /* Make sure this is the right instruction */
2748 ASSERT((Opcode
& 0xFD) == 0x10);
2750 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2752 /* The ADSIZE prefix toggles the size */
2753 AddressSize
= !AddressSize
;
2755 else if (State
->PrefixFlags
2756 & ~(SOFT386_PREFIX_ADSIZE
2757 | SOFT386_PREFIX_SEG
2758 | SOFT386_PREFIX_LOCK
))
2760 /* Invalid prefix */
2761 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2765 /* Get the operands */
2766 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2768 /* Exception occurred */
2772 if (!Soft386ReadModrmByteOperands(State
,
2777 /* Exception occurred */
2781 /* Calculate the result */
2782 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2784 /* Special exception for CF */
2785 State
->Flags
.Cf
= State
->Flags
.Cf
2786 && ((FirstValue
== 0xFF) || (SecondValue
== 0xFF));
2788 /* Update the flags */
2789 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2790 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
2791 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
2792 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
2793 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2794 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2795 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2797 /* Write back the result */
2798 return Soft386WriteModrmByteOperands(State
,
2800 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2804 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcModrm
)
2806 SOFT386_MOD_REG_RM ModRegRm
;
2807 BOOLEAN OperandSize
, AddressSize
;
2809 /* Make sure this is the right instruction */
2810 ASSERT((Opcode
& 0xFD) == 0x11);
2812 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2814 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2816 /* The ADSIZE prefix toggles the address size */
2817 AddressSize
= !AddressSize
;
2820 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2822 /* The OPSIZE prefix toggles the operand size */
2823 OperandSize
= !OperandSize
;
2826 if (State
->PrefixFlags
2827 & ~(SOFT386_PREFIX_ADSIZE
2828 | SOFT386_PREFIX_OPSIZE
2829 | SOFT386_PREFIX_SEG
2830 | SOFT386_PREFIX_LOCK
))
2832 /* Invalid prefix */
2833 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2837 /* Get the operands */
2838 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2840 /* Exception occurred */
2844 /* Check the operand size */
2847 ULONG FirstValue
, SecondValue
, Result
;
2849 if (!Soft386ReadModrmDwordOperands(State
,
2854 /* Exception occurred */
2858 /* Calculate the result */
2859 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2861 /* Special exception for CF */
2862 State
->Flags
.Cf
= State
->Flags
.Cf
2863 && ((FirstValue
== 0xFFFFFFFF) || (SecondValue
== 0xFFFFFFFF));
2865 /* Update the flags */
2866 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2867 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
2868 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
2869 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
2870 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2871 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2872 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2874 /* Write back the result */
2875 return Soft386WriteModrmDwordOperands(State
,
2877 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2882 USHORT FirstValue
, SecondValue
, Result
;
2884 if (!Soft386ReadModrmWordOperands(State
,
2889 /* Exception occurred */
2893 /* Calculate the result */
2894 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2896 /* Special exception for CF */
2897 State
->Flags
.Cf
= State
->Flags
.Cf
2898 && ((FirstValue
== 0xFFFF) || (SecondValue
== 0xFFFF));
2900 /* Update the flags */
2901 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2902 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
2903 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
2904 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
2905 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2906 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
2907 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2909 /* Write back the result */
2910 return Soft386WriteModrmWordOperands(State
,
2912 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2918 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcAl
)
2920 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
2921 UCHAR SecondValue
, Result
;
2923 /* Make sure this is the right instruction */
2924 ASSERT(Opcode
== 0x14);
2926 if (State
->PrefixFlags
)
2928 /* This opcode doesn't take any prefixes */
2929 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2933 if (!Soft386FetchByte(State
, &SecondValue
))
2935 /* Exception occurred */
2939 /* Calculate the result */
2940 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2942 /* Special exception for CF */
2943 State
->Flags
.Cf
= State
->Flags
.Cf
&&
2944 ((FirstValue
== 0xFF) || (SecondValue
== 0xFF));
2946 /* Update the flags */
2947 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2948 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
2949 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
2950 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
2951 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2952 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2953 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2955 /* Write back the result */
2956 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
2961 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcEax
)
2963 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2965 /* Make sure this is the right instruction */
2966 ASSERT(Opcode
== 0x15);
2968 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
2970 /* The OPSIZE prefix toggles the size */
2975 /* Invalid prefix */
2976 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2982 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
2983 ULONG SecondValue
, Result
;
2985 if (!Soft386FetchDword(State
, &SecondValue
))
2987 /* Exception occurred */
2991 /* Calculate the result */
2992 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2994 /* Special exception for CF */
2995 State
->Flags
.Cf
= State
->Flags
.Cf
&&
2996 ((FirstValue
== 0xFFFFFFFF) || (SecondValue
== 0xFFFFFFFF));
2998 /* Update the flags */
2999 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
3000 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
3001 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
3002 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
3003 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3004 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
3005 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3007 /* Write back the result */
3008 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
3012 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
3013 USHORT SecondValue
, Result
;
3015 if (!Soft386FetchWord(State
, &SecondValue
))
3017 /* Exception occurred */
3021 /* Calculate the result */
3022 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
3024 /* Special exception for CF */
3025 State
->Flags
.Cf
= State
->Flags
.Cf
&&
3026 ((FirstValue
== 0xFFFF) || (SecondValue
== 0xFFFF));
3028 /* Update the flags */
3029 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
3030 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
3031 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
3032 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
3033 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3034 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
3035 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3037 /* Write back the result */
3038 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
3044 SOFT386_OPCODE_HANDLER(Soft386OpcodePushSs
)
3046 /* Call the internal API */
3047 return Soft386StackPush(State
, State
->SegmentRegs
[SOFT386_REG_SS
].Selector
);
3050 SOFT386_OPCODE_HANDLER(Soft386OpcodePopSs
)
3054 if (!Soft386StackPop(State
, &NewSelector
))
3056 /* Exception occurred */
3060 /* Call the internal API */
3061 return Soft386LoadSegment(State
, SOFT386_REG_SS
, LOWORD(NewSelector
));
3064 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbByteModrm
)
3066 // TODO: NOT IMPLEMENTED
3072 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbModrm
)
3074 // TODO: NOT IMPLEMENTED
3080 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbAl
)
3082 // TODO: NOT IMPLEMENTED
3088 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbEax
)
3090 // TODO: NOT IMPLEMENTED
3096 SOFT386_OPCODE_HANDLER(Soft386OpcodePushDs
)
3098 /* Call the internal API */
3099 return Soft386StackPush(State
, State
->SegmentRegs
[SOFT386_REG_DS
].Selector
);
3102 SOFT386_OPCODE_HANDLER(Soft386OpcodePopDs
)
3106 if (!Soft386StackPop(State
, &NewSelector
))
3108 /* Exception occurred */
3112 /* Call the internal API */
3113 return Soft386LoadSegment(State
, SOFT386_REG_DS
, LOWORD(NewSelector
));
3116 SOFT386_OPCODE_HANDLER(Soft386OpcodeDaa
)
3118 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3119 BOOLEAN Carry
= State
->Flags
.Cf
;
3121 /* Clear the carry flag */
3122 State
->Flags
.Cf
= FALSE
;
3124 /* Check if the first BCD digit is invalid or there was a carry from it */
3125 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3128 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
+= 0x06;
3129 if (State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
< 0x06)
3131 /* A carry occurred */
3132 State
->Flags
.Cf
= TRUE
;
3135 /* Set the adjust flag */
3136 State
->Flags
.Af
= TRUE
;
3139 /* Check if the second BCD digit is invalid or there was a carry from it */
3140 if ((Value
> 0x99) || Carry
)
3143 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
+= 0x60;
3145 /* There was a carry */
3146 State
->Flags
.Cf
= TRUE
;
3152 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubByteModrm
)
3154 UCHAR FirstValue
, SecondValue
, Result
;
3155 SOFT386_MOD_REG_RM ModRegRm
;
3156 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3158 /* Make sure this is the right instruction */
3159 ASSERT((Opcode
& 0xED) == 0x28);
3161 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3163 /* The ADSIZE prefix toggles the size */
3164 AddressSize
= !AddressSize
;
3166 else if (State
->PrefixFlags
3167 & ~(SOFT386_PREFIX_ADSIZE
3168 | SOFT386_PREFIX_SEG
3169 | SOFT386_PREFIX_LOCK
))
3171 /* Invalid prefix */
3172 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3176 /* Get the operands */
3177 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3179 /* Exception occurred */
3183 if (!Soft386ReadModrmByteOperands(State
,
3188 /* Exception occurred */
3192 /* Check if this is the instruction that writes to R/M */
3193 if (!(Opcode
& SOFT386_OPCODE_WRITE_REG
))
3195 /* Swap the order */
3196 FirstValue
^= SecondValue
;
3197 SecondValue
^= FirstValue
;
3198 FirstValue
^= SecondValue
;
3201 /* Calculate the result */
3202 Result
= FirstValue
- SecondValue
;
3204 /* Update the flags */
3205 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3206 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) != (SecondValue
& SIGN_FLAG_BYTE
))
3207 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
3208 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3209 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3210 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
3211 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3213 /* Check if this is not a CMP */
3214 if (!(Opcode
& 0x10))
3216 /* Write back the result */
3217 return Soft386WriteModrmByteOperands(State
,
3219 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3224 /* Discard the result */
3229 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubModrm
)
3231 SOFT386_MOD_REG_RM ModRegRm
;
3232 BOOLEAN OperandSize
, AddressSize
;
3234 /* Make sure this is the right instruction */
3235 ASSERT((Opcode
& 0xED) == 0x29);
3237 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3239 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3241 /* The ADSIZE prefix toggles the address size */
3242 AddressSize
= !AddressSize
;
3245 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
3247 /* The OPSIZE prefix toggles the operand size */
3248 OperandSize
= !OperandSize
;
3251 if (State
->PrefixFlags
3252 & ~(SOFT386_PREFIX_ADSIZE
3253 | SOFT386_PREFIX_OPSIZE
3254 | SOFT386_PREFIX_SEG
3255 | SOFT386_PREFIX_LOCK
))
3257 /* Invalid prefix */
3258 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3262 /* Get the operands */
3263 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3265 /* Exception occurred */
3269 /* Check the operand size */
3272 ULONG FirstValue
, SecondValue
, Result
;
3274 if (!Soft386ReadModrmDwordOperands(State
,
3279 /* Exception occurred */
3283 /* Check if this is the instruction that writes to R/M */
3284 if (!(Opcode
& SOFT386_OPCODE_WRITE_REG
))
3286 /* Swap the order */
3287 FirstValue
^= SecondValue
;
3288 SecondValue
^= FirstValue
;
3289 FirstValue
^= SecondValue
;
3292 /* Calculate the result */
3293 Result
= FirstValue
- SecondValue
;
3295 /* Update the flags */
3296 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3297 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) != (SecondValue
& SIGN_FLAG_LONG
))
3298 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
3299 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3300 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3301 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
3302 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3304 /* Check if this is not a CMP */
3305 if (!(Opcode
& 0x10))
3307 /* Write back the result */
3308 return Soft386WriteModrmDwordOperands(State
,
3310 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3315 /* Discard the result */
3321 USHORT FirstValue
, SecondValue
, Result
;
3323 if (!Soft386ReadModrmWordOperands(State
,
3328 /* Exception occurred */
3332 /* Check if this is the instruction that writes to R/M */
3333 if (!(Opcode
& SOFT386_OPCODE_WRITE_REG
))
3335 /* Swap the order */
3336 FirstValue
^= SecondValue
;
3337 SecondValue
^= FirstValue
;
3338 FirstValue
^= SecondValue
;
3341 /* Calculate the result */
3342 Result
= FirstValue
- SecondValue
;
3344 /* Update the flags */
3345 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3346 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) != (SecondValue
& SIGN_FLAG_WORD
))
3347 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
3348 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3349 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3350 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
3351 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3353 /* Check if this is not a CMP */
3354 if (!(Opcode
& 0x10))
3356 /* Write back the result */
3357 return Soft386WriteModrmWordOperands(State
,
3359 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3364 /* Discard the result */
3371 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubAl
)
3373 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3374 UCHAR SecondValue
, Result
;
3376 /* Make sure this is the right instruction */
3377 ASSERT((Opcode
& 0xEF) == 0x2C);
3379 if (State
->PrefixFlags
)
3381 /* This opcode doesn't take any prefixes */
3382 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3386 if (!Soft386FetchByte(State
, &SecondValue
))
3388 /* Exception occurred */
3392 /* Calculate the result */
3393 Result
= FirstValue
- SecondValue
;
3395 /* Update the flags */
3396 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3397 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) != (SecondValue
& SIGN_FLAG_BYTE
))
3398 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
3399 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3400 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3401 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
3402 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3404 /* Check if this is not a CMP */
3405 if (!(Opcode
& 0x10))
3407 /* Write back the result */
3408 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
3414 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubEax
)
3416 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3418 /* Make sure this is the right instruction */
3419 ASSERT((Opcode
& 0xEF) == 0x2D);
3421 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
3423 /* The OPSIZE prefix toggles the size */
3428 /* Invalid prefix */
3429 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3435 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
3436 ULONG SecondValue
, Result
;
3438 if (!Soft386FetchDword(State
, &SecondValue
))
3440 /* Exception occurred */
3444 /* Calculate the result */
3445 Result
= FirstValue
- SecondValue
;
3447 /* Update the flags */
3448 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3449 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) != (SecondValue
& SIGN_FLAG_LONG
))
3450 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
3451 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3452 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3453 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
3454 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3456 /* Check if this is not a CMP */
3457 if (!(Opcode
& 0x10))
3459 /* Write back the result */
3460 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
3465 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
3466 USHORT SecondValue
, Result
;
3468 if (!Soft386FetchWord(State
, &SecondValue
))
3470 /* Exception occurred */
3474 /* Calculate the result */
3475 Result
= FirstValue
- SecondValue
;
3477 /* Update the flags */
3478 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3479 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) != (SecondValue
& SIGN_FLAG_WORD
))
3480 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
3481 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3482 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3483 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
3484 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3486 /* Write back the result */
3487 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
3493 SOFT386_OPCODE_HANDLER(Soft386OpcodeDas
)
3495 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3496 BOOLEAN Carry
= State
->Flags
.Cf
;
3498 /* Clear the carry flag */
3499 State
->Flags
.Cf
= FALSE
;
3501 /* Check if the first BCD digit is invalid or there was a borrow */
3502 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3505 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
-= 0x06;
3506 if (State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
> 0xFB)
3508 /* A borrow occurred */
3509 State
->Flags
.Cf
= TRUE
;
3512 /* Set the adjust flag */
3513 State
->Flags
.Af
= TRUE
;
3516 /* Check if the second BCD digit is invalid or there was a borrow */
3517 if ((Value
> 0x99) || Carry
)
3520 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
-= 0x60;
3522 /* There was a borrow */
3523 State
->Flags
.Cf
= TRUE
;
3529 SOFT386_OPCODE_HANDLER(Soft386OpcodeAaa
)
3531 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3534 * Check if the value in AL is not a valid BCD digit,
3535 * or there was a carry from the lowest 4 bits of AL
3537 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3540 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
+= 0x06;
3541 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
++;
3544 State
->Flags
.Cf
= State
->Flags
.Af
= TRUE
;
3548 /* Clear CF and AF */
3549 State
->Flags
.Cf
= State
->Flags
.Af
= FALSE
;
3552 /* Keep only the lowest 4 bits of AL */
3553 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
&= 0x0F;
3558 SOFT386_OPCODE_HANDLER(Soft386OpcodeAas
)
3560 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3563 * Check if the value in AL is not a valid BCD digit,
3564 * or there was a borrow from the lowest 4 bits of AL
3566 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3569 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
-= 0x06;
3570 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
--;
3573 State
->Flags
.Cf
= State
->Flags
.Af
= TRUE
;
3577 /* Clear CF and AF */
3578 State
->Flags
.Cf
= State
->Flags
.Af
= FALSE
;
3581 /* Keep only the lowest 4 bits of AL */
3582 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
&= 0x0F;
3587 SOFT386_OPCODE_HANDLER(Soft386OpcodePushAll
)
3590 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3591 SOFT386_REG SavedEsp
= State
->GeneralRegs
[SOFT386_REG_ESP
];
3593 /* Make sure this is the right instruction */
3594 ASSERT(Opcode
== 0x60);
3596 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
3598 /* The OPSIZE prefix toggles the size */
3603 /* Invalid prefix */
3604 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3608 /* Push all the registers in order */
3609 for (i
= 0; i
< SOFT386_NUM_GEN_REGS
; i
++)
3611 if (i
== SOFT386_REG_ESP
)
3613 /* Use the saved ESP instead */
3614 if (!Soft386StackPush(State
, Size
? SavedEsp
.Long
: SavedEsp
.LowWord
))
3616 /* Exception occurred */
3622 /* Push the register */
3623 if (!Soft386StackPush(State
, Size
? State
->GeneralRegs
[i
].Long
3624 : State
->GeneralRegs
[i
].LowWord
))
3626 /* Exception occurred */
3635 SOFT386_OPCODE_HANDLER(Soft386OpcodePopAll
)
3638 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3641 /* Make sure this is the right instruction */
3642 ASSERT(Opcode
== 0x61);
3644 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
3646 /* The OPSIZE prefix toggles the size */
3651 /* Invalid prefix */
3652 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3656 /* Pop all the registers in reverse order */
3657 for (i
= SOFT386_NUM_GEN_REGS
- 1; i
>= 0; i
--)
3660 if (!Soft386StackPop(State
, &Value
))
3662 /* Exception occurred */
3666 /* Don't modify ESP */
3667 if (i
!= SOFT386_REG_ESP
)
3669 if (Size
) State
->GeneralRegs
[i
].Long
= Value
;
3670 else State
->GeneralRegs
[i
].LowWord
= LOWORD(Value
);
3677 SOFT386_OPCODE_HANDLER(Soft386OpcodeBound
)
3679 // TODO: NOT IMPLEMENTED
3685 SOFT386_OPCODE_HANDLER(Soft386OpcodeArpl
)
3687 USHORT FirstValue
, SecondValue
;
3688 SOFT386_MOD_REG_RM ModRegRm
;
3689 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3691 if (!(State
->ControlRegisters
[SOFT386_REG_CR0
] & SOFT386_CR0_PE
)
3693 || (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
))
3695 /* Cannot be used in real mode or with a LOCK prefix */
3696 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3700 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3702 /* The ADSIZE prefix toggles the size */
3703 AddressSize
= !AddressSize
;
3706 /* Get the operands */
3707 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3709 /* Exception occurred */
3713 /* Read the operands */
3714 if (!Soft386ReadModrmWordOperands(State
,
3719 /* Exception occurred */
3723 /* Check if the RPL needs adjusting */
3724 if ((SecondValue
& 3) < (FirstValue
& 3))
3726 /* Adjust the RPL */
3728 SecondValue
|= FirstValue
& 3;
3731 State
->Flags
.Zf
= TRUE
;
3733 /* Write back the result */
3734 return Soft386WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, SecondValue
);
3739 State
->Flags
.Zf
= FALSE
;
3744 SOFT386_OPCODE_HANDLER(Soft386OpcodePushImm
)
3746 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3748 /* Make sure this is the right instruction */
3749 ASSERT(Opcode
== 0x68);
3751 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
3753 /* The OPSIZE prefix toggles the size */
3758 /* Invalid prefix */
3759 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3767 if (!Soft386FetchDword(State
, &Data
))
3769 /* Exception occurred */
3773 /* Call the internal API */
3774 return Soft386StackPush(State
, Data
);
3780 if (!Soft386FetchWord(State
, &Data
))
3782 /* Exception occurred */
3786 /* Call the internal API */
3787 return Soft386StackPush(State
, Data
);
3791 SOFT386_OPCODE_HANDLER(Soft386OpcodeImulModrmImm
)
3793 // TODO: NOT IMPLEMENTED
3799 SOFT386_OPCODE_HANDLER(Soft386OpcodePushByteImm
)
3803 /* Make sure this is the right instruction */
3804 ASSERT(Opcode
== 0x6A);
3806 if (!Soft386FetchByte(State
, &Data
))
3808 /* Exception occurred */
3812 /* Call the internal API */
3813 return Soft386StackPush(State
, Data
);
3816 SOFT386_OPCODE_HANDLER(Soft386OpcodeImulModrmByteImm
)
3818 // TODO: NOT IMPLEMENTED
3824 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovByteModrm
)
3826 UCHAR FirstValue
, SecondValue
, Result
;
3827 SOFT386_MOD_REG_RM ModRegRm
;
3828 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3830 /* Make sure this is the right instruction */
3831 ASSERT((Opcode
& 0xFD) == 0x88);
3833 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3835 /* The ADSIZE prefix toggles the size */
3836 AddressSize
= !AddressSize
;
3838 else if (State
->PrefixFlags
3839 & ~(SOFT386_PREFIX_ADSIZE
3840 | SOFT386_PREFIX_SEG
3841 | SOFT386_PREFIX_LOCK
))
3843 /* Invalid prefix */
3844 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3848 /* Get the operands */
3849 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3851 /* Exception occurred */
3855 if (!Soft386ReadModrmByteOperands(State
,
3860 /* Exception occurred */
3864 if (Opcode
& SOFT386_OPCODE_WRITE_REG
) Result
= SecondValue
;
3865 else Result
= FirstValue
;
3867 /* Write back the result */
3868 return Soft386WriteModrmByteOperands(State
,
3870 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3875 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovModrm
)
3877 SOFT386_MOD_REG_RM ModRegRm
;
3878 BOOLEAN OperandSize
, AddressSize
;
3880 /* Make sure this is the right instruction */
3881 ASSERT((Opcode
& 0xFD) == 0x89);
3883 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3885 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3887 /* The ADSIZE prefix toggles the address size */
3888 AddressSize
= !AddressSize
;
3891 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
3893 /* The OPSIZE prefix toggles the operand size */
3894 OperandSize
= !OperandSize
;
3897 if (State
->PrefixFlags
3898 & ~(SOFT386_PREFIX_ADSIZE
3899 | SOFT386_PREFIX_OPSIZE
3900 | SOFT386_PREFIX_SEG
3901 | SOFT386_PREFIX_LOCK
))
3903 /* Invalid prefix */
3904 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3908 /* Get the operands */
3909 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3911 /* Exception occurred */
3915 /* Check the operand size */
3918 ULONG FirstValue
, SecondValue
, Result
;
3920 if (!Soft386ReadModrmDwordOperands(State
,
3925 /* Exception occurred */
3929 if (Opcode
& SOFT386_OPCODE_WRITE_REG
) Result
= SecondValue
;
3930 else Result
= FirstValue
;
3932 /* Write back the result */
3933 return Soft386WriteModrmDwordOperands(State
,
3935 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3940 USHORT FirstValue
, SecondValue
, Result
;
3942 if (!Soft386ReadModrmWordOperands(State
,
3947 /* Exception occurred */
3951 if (Opcode
& SOFT386_OPCODE_WRITE_REG
) Result
= SecondValue
;
3952 else Result
= FirstValue
;
3954 /* Write back the result */
3955 return Soft386WriteModrmWordOperands(State
,
3957 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3962 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovStoreSeg
)
3964 // TODO: NOT IMPLEMENTED
3970 SOFT386_OPCODE_HANDLER(Soft386OpcodeLea
)
3972 SOFT386_MOD_REG_RM ModRegRm
;
3973 BOOLEAN OperandSize
, AddressSize
;
3975 /* Make sure this is the right instruction */
3976 ASSERT(Opcode
== 0x8D);
3978 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3980 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3982 /* The ADSIZE prefix toggles the address size */
3983 AddressSize
= !AddressSize
;
3986 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
3988 /* The OPSIZE prefix toggles the operand size */
3989 OperandSize
= !OperandSize
;
3992 /* Get the operands */
3993 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3995 /* Exception occurred */
3999 /* The second operand must be memory */
4000 if (!ModRegRm
.Memory
)
4003 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4007 /* Write the address to the register */
4010 return Soft386WriteModrmDwordOperands(State
,
4013 ModRegRm
.MemoryAddress
);
4017 return Soft386WriteModrmWordOperands(State
,
4020 ModRegRm
.MemoryAddress
);
4025 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovLoadSeg
)
4027 // TODO: NOT IMPLEMENTED
4033 SOFT386_OPCODE_HANDLER(Soft386OpcodeCwde
)
4035 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4037 /* Make sure this is the right instruction */
4038 ASSERT(Opcode
== 0x98);
4040 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
4042 /* The OPSIZE prefix toggles the size */
4045 else if (State
->PrefixFlags
!= 0)
4047 /* Invalid prefix */
4048 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4054 /* Sign extend AX to EAX */
4055 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= MAKELONG
4057 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
,
4058 (State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
& SIGN_FLAG_WORD
)
4064 /* Sign extend AL to AX */
4065 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
=
4066 (State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
& SIGN_FLAG_BYTE
)
4073 SOFT386_OPCODE_HANDLER(Soft386OpcodeCdq
)
4075 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4077 /* Make sure this is the right instruction */
4078 ASSERT(Opcode
== 0x99);
4080 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
4082 /* The OPSIZE prefix toggles the size */
4085 else if (State
->PrefixFlags
!= 0)
4087 /* Invalid prefix */
4088 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4094 /* Sign extend EAX to EDX:EAX */
4095 State
->GeneralRegs
[SOFT386_REG_EDX
].Long
=
4096 (State
->GeneralRegs
[SOFT386_REG_EAX
].Long
& SIGN_FLAG_LONG
)
4097 ? 0xFFFFFFFF : 0x00000000;
4101 /* Sign extend AX to DX:AX */
4102 State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
=
4103 (State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
& SIGN_FLAG_WORD
)
4110 SOFT386_OPCODE_HANDLER(Soft386OpcodeCallAbs
)
4112 // TODO: NOT IMPLEMENTED
4118 SOFT386_OPCODE_HANDLER(Soft386OpcodeWait
)
4120 // TODO: NOT IMPLEMENTED
4126 SOFT386_OPCODE_HANDLER(Soft386OpcodePushFlags
)
4128 // TODO: NOT IMPLEMENTED
4134 SOFT386_OPCODE_HANDLER(Soft386OpcodePopFlags
)
4136 // TODO: NOT IMPLEMENTED
4142 SOFT386_OPCODE_HANDLER(Soft386OpcodeSahf
)
4144 /* Make sure this is the right instruction */
4145 ASSERT(Opcode
== 0x9E);
4147 /* Set the low-order byte of FLAGS to AH */
4148 State
->Flags
.Long
&= 0xFFFFFF00;
4149 State
->Flags
.Long
|= State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
;
4151 /* Restore the reserved bits of FLAGS */
4152 State
->Flags
.AlwaysSet
= TRUE
;
4153 State
->Flags
.Reserved0
= State
->Flags
.Reserved1
= FALSE
;
4158 SOFT386_OPCODE_HANDLER(Soft386OpcodeLahf
)
4160 /* Make sure this is the right instruction */
4161 ASSERT(Opcode
== 0x9F);
4163 /* Set AH to the low-order byte of FLAGS */
4164 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
= LOBYTE(State
->Flags
.Long
);
4169 SOFT386_OPCODE_HANDLER(Soft386OpcodeRet
)
4171 ULONG ReturnAddress
;
4172 USHORT BytesToPop
= 0;
4173 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4175 /* Make sure this is the right instruction */
4176 ASSERT((Opcode
& 0xFE) == 0xC2);
4178 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4180 /* Invalid prefix */
4181 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4185 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
4187 /* The OPSIZE prefix toggles the size */
4193 /* Fetch the number of bytes to pop after the return */
4194 if (!Soft386FetchWord(State
, &BytesToPop
)) return FALSE
;
4197 /* Pop the return address */
4198 if (!Soft386StackPop(State
, &ReturnAddress
)) return FALSE
;
4200 /* Return to the calling procedure, and if necessary, pop the parameters */
4203 State
->InstPtr
.Long
= ReturnAddress
;
4204 State
->GeneralRegs
[SOFT386_REG_ESP
].Long
+= BytesToPop
;
4208 State
->InstPtr
.LowWord
= LOWORD(ReturnAddress
);
4209 State
->GeneralRegs
[SOFT386_REG_ESP
].LowWord
+= BytesToPop
;
4215 SOFT386_OPCODE_HANDLER(Soft386OpcodeLes
)
4217 // TODO: NOT IMPLEMENTED
4223 SOFT386_OPCODE_HANDLER(Soft386OpcodeLds
)
4225 // TODO: NOT IMPLEMENTED
4231 SOFT386_OPCODE_HANDLER(Soft386OpcodeEnter
)
4233 // TODO: NOT IMPLEMENTED
4239 SOFT386_OPCODE_HANDLER(Soft386OpcodeLeave
)
4241 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4243 /* Make sure this is the right instruction */
4244 ASSERT(Opcode
== 0xC9);
4246 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4248 /* Invalid prefix */
4249 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4253 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
4255 /* The OPSIZE prefix toggles the size */
4261 /* Set the stack pointer (ESP) to the base pointer (EBP) */
4262 State
->GeneralRegs
[SOFT386_REG_ESP
].Long
= State
->GeneralRegs
[SOFT386_REG_EBP
].Long
;
4264 /* Pop the saved base pointer from the stack */
4265 return Soft386StackPop(State
, &State
->GeneralRegs
[SOFT386_REG_EBP
].Long
);
4271 /* Set the stack pointer (SP) to the base pointer (BP) */
4272 State
->GeneralRegs
[SOFT386_REG_ESP
].LowWord
= State
->GeneralRegs
[SOFT386_REG_EBP
].LowWord
;
4274 /* Pop the saved base pointer from the stack */
4275 if (Soft386StackPop(State
, &Value
))
4277 State
->GeneralRegs
[SOFT386_REG_EBP
].LowWord
= LOWORD(Value
);
4284 SOFT386_OPCODE_HANDLER(Soft386OpcodeRetFarImm
)
4286 // TODO: NOT IMPLEMENTED
4292 SOFT386_OPCODE_HANDLER(Soft386OpcodeRetFar
)
4294 // TODO: NOT IMPLEMENTED
4300 SOFT386_OPCODE_HANDLER(Soft386OpcodeInt3
)
4302 // TODO: NOT IMPLEMENTED
4308 SOFT386_OPCODE_HANDLER(Soft386OpcodeInt
)
4310 // TODO: NOT IMPLEMENTED
4316 SOFT386_OPCODE_HANDLER(Soft386OpcodeIntOverflow
)
4318 // TODO: NOT IMPLEMENTED
4324 SOFT386_OPCODE_HANDLER(Soft386OpcodeIret
)
4326 // TODO: NOT IMPLEMENTED
4332 SOFT386_OPCODE_HANDLER(Soft386OpcodeAam
)
4334 // TODO: NOT IMPLEMENTED
4340 SOFT386_OPCODE_HANDLER(Soft386OpcodeAad
)
4342 // TODO: NOT IMPLEMENTED
4348 SOFT386_OPCODE_HANDLER(Soft386OpcodeXlat
)
4350 // TODO: NOT IMPLEMENTED
4356 SOFT386_OPCODE_HANDLER(Soft386OpcodeLoop
)
4359 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4362 /* Make sure this is the right instruction */
4363 ASSERT((Opcode
>= 0xE0) && (Opcode
<= 0xE2));
4365 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4367 /* Invalid prefix */
4368 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4372 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
4374 /* The OPSIZE prefix toggles the size */
4378 if (Size
) Condition
= ((--State
->GeneralRegs
[SOFT386_REG_ECX
].Long
) == 0);
4379 else Condition
= ((--State
->GeneralRegs
[SOFT386_REG_ECX
].LowWord
) == 0);
4383 /* Additional rule for LOOPNZ */
4384 if (State
->Flags
.Zf
) Condition
= FALSE
;
4389 /* Additional rule for LOOPZ */
4390 if (!State
->Flags
.Zf
) Condition
= FALSE
;
4393 /* Fetch the offset */
4394 if (!Soft386FetchByte(State
, (PUCHAR
)&Offset
))
4396 /* An exception occurred */
4402 /* Move the instruction pointer */
4403 State
->InstPtr
.Long
+= Offset
;
4409 SOFT386_OPCODE_HANDLER(Soft386OpcodeJecxz
)
4412 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4415 /* Make sure this is the right instruction */
4416 ASSERT(Opcode
== 0xE3);
4418 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4420 /* Invalid prefix */
4421 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4425 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
4427 /* The OPSIZE prefix toggles the size */
4431 if (Size
) Condition
= (State
->GeneralRegs
[SOFT386_REG_ECX
].Long
== 0);
4432 else Condition
= (State
->GeneralRegs
[SOFT386_REG_ECX
].LowWord
== 0);
4434 /* Fetch the offset */
4435 if (!Soft386FetchByte(State
, (PUCHAR
)&Offset
))
4437 /* An exception occurred */
4443 /* Move the instruction pointer */
4444 State
->InstPtr
.Long
+= Offset
;
4450 SOFT386_OPCODE_HANDLER(Soft386OpcodeCall
)
4452 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4454 /* Make sure this is the right instruction */
4455 ASSERT(Opcode
== 0xE8);
4457 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
4459 /* The OPSIZE prefix toggles the size */
4462 else if (State
->PrefixFlags
!= 0)
4464 /* Invalid prefix */
4465 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4469 /* Push the current value of the instruction pointer */
4470 if (!Soft386StackPush(State
, State
->InstPtr
.Long
))
4472 /* Exception occurred */
4480 /* Fetch the offset */
4481 if (!Soft386FetchDword(State
, (PULONG
)&Offset
))
4483 /* An exception occurred */
4487 /* Move the instruction pointer */
4488 State
->InstPtr
.Long
+= Offset
;
4494 /* Fetch the offset */
4495 if (!Soft386FetchWord(State
, (PUSHORT
)&Offset
))
4497 /* An exception occurred */
4501 /* Move the instruction pointer */
4502 State
->InstPtr
.LowWord
+= Offset
;
4508 SOFT386_OPCODE_HANDLER(Soft386OpcodeJmp
)
4510 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4512 /* Make sure this is the right instruction */
4513 ASSERT(Opcode
== 0xE9);
4515 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
4517 /* The OPSIZE prefix toggles the size */
4520 else if (State
->PrefixFlags
!= 0)
4522 /* Invalid prefix */
4523 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4531 /* Fetch the offset */
4532 if (!Soft386FetchDword(State
, (PULONG
)&Offset
))
4534 /* An exception occurred */
4538 /* Move the instruction pointer */
4539 State
->InstPtr
.Long
+= Offset
;
4545 /* Fetch the offset */
4546 if (!Soft386FetchWord(State
, (PUSHORT
)&Offset
))
4548 /* An exception occurred */
4552 /* Move the instruction pointer */
4553 State
->InstPtr
.LowWord
+= Offset
;
4559 SOFT386_OPCODE_HANDLER(Soft386OpcodeJmpAbs
)
4561 // TODO: NOT IMPLEMENTED