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
23 /* PUBLIC VARIABLES ***********************************************************/
25 SOFT386_OPCODE_HANDLER_PROC
26 Soft386OpcodeHandlers
[SOFT386_NUM_OPCODE_HANDLERS
] =
28 Soft386OpcodeAddByteModrm
,
29 Soft386OpcodeAddModrm
,
30 Soft386OpcodeAddByteModrm
,
31 Soft386OpcodeAddModrm
,
36 Soft386OpcodeOrByteModrm
,
38 Soft386OpcodeOrByteModrm
,
43 NULL
, // TODO: OPCODE 0x0F NOT SUPPORTED
44 Soft386OpcodeAdcByteModrm
,
45 Soft386OpcodeAdcModrm
,
46 Soft386OpcodeAdcByteModrm
,
47 Soft386OpcodeAdcModrm
,
52 Soft386OpcodeSbbByteModrm
,
53 Soft386OpcodeSbbModrm
,
54 Soft386OpcodeSbbByteModrm
,
55 Soft386OpcodeSbbModrm
,
60 Soft386OpcodeAndByteModrm
,
61 Soft386OpcodeAndModrm
,
62 Soft386OpcodeAndByteModrm
,
63 Soft386OpcodeAndModrm
,
68 Soft386OpcodeCmpSubByteModrm
,
69 Soft386OpcodeCmpSubModrm
,
70 Soft386OpcodeCmpSubByteModrm
,
71 Soft386OpcodeCmpSubModrm
,
72 Soft386OpcodeCmpSubAl
,
73 Soft386OpcodeCmpSubEax
,
76 Soft386OpcodeXorByteModrm
,
77 Soft386OpcodeXorModrm
,
78 Soft386OpcodeXorByteModrm
,
79 Soft386OpcodeXorModrm
,
84 Soft386OpcodeCmpSubByteModrm
,
85 Soft386OpcodeCmpSubModrm
,
86 Soft386OpcodeCmpSubByteModrm
,
87 Soft386OpcodeCmpSubModrm
,
88 Soft386OpcodeCmpSubAl
,
89 Soft386OpcodeCmpSubEax
,
92 Soft386OpcodeIncrement
,
93 Soft386OpcodeIncrement
,
94 Soft386OpcodeIncrement
,
95 Soft386OpcodeIncrement
,
96 Soft386OpcodeIncrement
,
97 Soft386OpcodeIncrement
,
98 Soft386OpcodeIncrement
,
99 Soft386OpcodeIncrement
,
100 Soft386OpcodeDecrement
,
101 Soft386OpcodeDecrement
,
102 Soft386OpcodeDecrement
,
103 Soft386OpcodeDecrement
,
104 Soft386OpcodeDecrement
,
105 Soft386OpcodeDecrement
,
106 Soft386OpcodeDecrement
,
107 Soft386OpcodeDecrement
,
108 Soft386OpcodePushReg
,
109 Soft386OpcodePushReg
,
110 Soft386OpcodePushReg
,
111 Soft386OpcodePushReg
,
112 Soft386OpcodePushReg
,
113 Soft386OpcodePushReg
,
114 Soft386OpcodePushReg
,
115 Soft386OpcodePushReg
,
124 Soft386OpcodePushAll
,
132 Soft386OpcodePushImm
,
133 Soft386OpcodeImulModrmImm
,
134 Soft386OpcodePushByteImm
,
135 Soft386OpcodeImulModrmImm
,
136 NULL
, // TODO: OPCODE 0x6C NOT SUPPORTED
137 NULL
, // TODO: OPCODE 0x6D NOT SUPPORTED
138 NULL
, // TODO: OPCODE 0x6E NOT SUPPORTED
139 NULL
, // TODO: OPCODE 0x6F NOT SUPPORTED
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 Soft386OpcodeShortConditionalJmp
,
156 NULL
, // TODO: OPCODE 0x80 NOT SUPPORTED
157 NULL
, // TODO: OPCODE 0x81 NOT SUPPORTED
158 NULL
, // TODO: OPCODE 0x82 NOT SUPPORTED
159 NULL
, // TODO: OPCODE 0x83 NOT SUPPORTED
160 Soft386OpcodeTestByteModrm
,
161 Soft386OpcodeTestModrm
,
162 Soft386OpcodeXchgByteModrm
,
163 Soft386OpcodeXchgModrm
,
164 Soft386OpcodeMovByteModrm
,
165 Soft386OpcodeMovModrm
,
166 Soft386OpcodeMovByteModrm
,
167 Soft386OpcodeMovModrm
,
168 Soft386OpcodeMovStoreSeg
,
170 Soft386OpcodeMovLoadSeg
,
171 NULL
, // TODO: OPCODE 0x8F NOT SUPPORTED
173 Soft386OpcodeExchangeEax
,
174 Soft386OpcodeExchangeEax
,
175 Soft386OpcodeExchangeEax
,
176 Soft386OpcodeExchangeEax
,
177 Soft386OpcodeExchangeEax
,
178 Soft386OpcodeExchangeEax
,
179 Soft386OpcodeExchangeEax
,
182 Soft386OpcodeCallAbs
,
184 Soft386OpcodePushFlags
,
185 Soft386OpcodePopFlags
,
188 Soft386OpcodeMovAlOffset
,
189 Soft386OpcodeMovEaxOffset
,
190 Soft386OpcodeMovOffsetAl
,
191 Soft386OpcodeMovOffsetEax
,
192 NULL
, // TODO: OPCODE 0xA4 NOT SUPPORTED
193 NULL
, // TODO: OPCODE 0xA5 NOT SUPPORTED
194 NULL
, // TODO: OPCODE 0xA6 NOT SUPPORTED
195 NULL
, // TODO: OPCODE 0xA7 NOT SUPPORTED
197 Soft386OpcodeTestEax
,
198 NULL
, // TODO: OPCODE 0xAA NOT SUPPORTED
199 NULL
, // TODO: OPCODE 0xAB NOT SUPPORTED
200 NULL
, // TODO: OPCODE 0xAC NOT SUPPORTED
201 NULL
, // TODO: OPCODE 0xAD NOT SUPPORTED
202 NULL
, // TODO: OPCODE 0xAE NOT SUPPORTED
203 NULL
, // TODO: OPCODE 0xAF NOT SUPPORTED
204 Soft386OpcodeMovByteRegImm
,
205 Soft386OpcodeMovByteRegImm
,
206 Soft386OpcodeMovByteRegImm
,
207 Soft386OpcodeMovByteRegImm
,
208 Soft386OpcodeMovByteRegImm
,
209 Soft386OpcodeMovByteRegImm
,
210 Soft386OpcodeMovByteRegImm
,
211 Soft386OpcodeMovByteRegImm
,
212 Soft386OpcodeMovRegImm
,
213 Soft386OpcodeMovRegImm
,
214 Soft386OpcodeMovRegImm
,
215 Soft386OpcodeMovRegImm
,
216 Soft386OpcodeMovRegImm
,
217 Soft386OpcodeMovRegImm
,
218 Soft386OpcodeMovRegImm
,
219 Soft386OpcodeMovRegImm
,
220 NULL
, // TODO: OPCODE 0xC0 NOT SUPPORTED
221 NULL
, // TODO: OPCODE 0xC1 NOT SUPPORTED
226 NULL
, // TODO: OPCODE 0xC6 NOT SUPPORTED
227 NULL
, // TODO: OPCODE 0xC7 NOT SUPPORTED
230 Soft386OpcodeRetFarImm
,
236 NULL
, // TODO: OPCODE 0xD0 NOT SUPPORTED
237 NULL
, // TODO: OPCODE 0xD1 NOT SUPPORTED
238 NULL
, // TODO: OPCODE 0xD2 NOT SUPPORTED
239 NULL
, // TODO: OPCODE 0xD3 NOT SUPPORTED
242 NULL
, // TODO: OPCODE 0xD6 NOT SUPPORTED
244 NULL
, // TODO: OPCODE 0xD8 NOT SUPPORTED
245 NULL
, // TODO: OPCODE 0xD9 NOT SUPPORTED
246 NULL
, // TODO: OPCODE 0xDA NOT SUPPORTED
247 NULL
, // TODO: OPCODE 0xDB NOT SUPPORTED
248 NULL
, // TODO: OPCODE 0xDC NOT SUPPORTED
249 NULL
, // TODO: OPCODE 0xDD NOT SUPPORTED
250 NULL
, // TODO: OPCODE 0xDE NOT SUPPORTED
251 NULL
, // TODO: OPCODE 0xDF NOT SUPPORTED
258 Soft386OpcodeOutByte
,
263 Soft386OpcodeShortJump
,
266 Soft386OpcodeOutByte
,
273 Soft386OpcodeComplCarry
,
274 NULL
, // TODO: OPCODE 0xF6 NOT SUPPORTED
275 NULL
, // TODO: OPCODE 0xF7 NOT SUPPORTED
276 Soft386OpcodeClearCarry
,
277 Soft386OpcodeSetCarry
,
278 Soft386OpcodeClearInt
,
280 Soft386OpcodeClearDir
,
282 NULL
, // TODO: OPCODE 0xFE NOT SUPPORTED
283 NULL
, // TODO: OPCODE 0xFF NOT SUPPORTED
286 /* PUBLIC FUNCTIONS ***********************************************************/
288 SOFT386_OPCODE_HANDLER(Soft386OpcodePrefix
)
290 BOOLEAN Valid
= FALSE
;
297 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
299 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
300 State
->SegmentOverride
= SOFT386_REG_ES
;
310 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
312 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
313 State
->SegmentOverride
= SOFT386_REG_CS
;
323 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
325 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
326 State
->SegmentOverride
= SOFT386_REG_SS
;
336 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
338 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
339 State
->SegmentOverride
= SOFT386_REG_DS
;
349 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
351 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
352 State
->SegmentOverride
= SOFT386_REG_FS
;
362 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
364 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
365 State
->SegmentOverride
= SOFT386_REG_GS
;
375 if (!(State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
))
377 State
->PrefixFlags
|= SOFT386_PREFIX_OPSIZE
;
387 if (!(State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
))
389 State
->PrefixFlags
|= SOFT386_PREFIX_ADSIZE
;
398 if (!(State
->PrefixFlags
& SOFT386_PREFIX_LOCK
))
400 State
->PrefixFlags
|= SOFT386_PREFIX_LOCK
;
410 /* Mutually exclusive with REP */
411 if (!(State
->PrefixFlags
412 & (SOFT386_PREFIX_REPNZ
| SOFT386_PREFIX_REP
)))
414 State
->PrefixFlags
|= SOFT386_PREFIX_REPNZ
;
424 /* Mutually exclusive with REPNZ */
425 if (!(State
->PrefixFlags
426 & (SOFT386_PREFIX_REPNZ
| SOFT386_PREFIX_REP
)))
428 State
->PrefixFlags
|= SOFT386_PREFIX_REP
;
438 /* Clear all prefixes */
439 State
->PrefixFlags
= 0;
441 /* Throw an exception */
442 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
449 SOFT386_OPCODE_HANDLER(Soft386OpcodeIncrement
)
452 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
454 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
456 /* The OPSIZE prefix toggles the size */
459 else if (State
->PrefixFlags
!= 0)
462 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
466 /* Make sure this is the right instruction */
467 ASSERT((Opcode
& 0xF8) == 0x40);
471 Value
= ++State
->GeneralRegs
[Opcode
& 0x07].Long
;
473 State
->Flags
.Of
= (Value
== SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
474 State
->Flags
.Sf
= (Value
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
478 Value
= ++State
->GeneralRegs
[Opcode
& 0x07].LowWord
;
480 State
->Flags
.Of
= (Value
== SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
481 State
->Flags
.Sf
= (Value
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
484 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
485 State
->Flags
.Af
= ((Value
& 0x0F) == 0) ? TRUE
: FALSE
;
486 State
->Flags
.Pf
= Soft386CalculateParity(LOBYTE(Value
));
492 SOFT386_OPCODE_HANDLER(Soft386OpcodeDecrement
)
495 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
497 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
499 /* The OPSIZE prefix toggles the size */
502 else if (State
->PrefixFlags
!= 0)
505 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
509 /* Make sure this is the right instruction */
510 ASSERT((Opcode
& 0xF8) == 0x48);
514 Value
= --State
->GeneralRegs
[Opcode
& 0x07].Long
;
516 State
->Flags
.Of
= (Value
== (SIGN_FLAG_LONG
- 1)) ? TRUE
: FALSE
;
517 State
->Flags
.Sf
= (Value
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
521 Value
= --State
->GeneralRegs
[Opcode
& 0x07].LowWord
;
523 State
->Flags
.Of
= (Value
== (SIGN_FLAG_WORD
- 1)) ? TRUE
: FALSE
;
524 State
->Flags
.Sf
= (Value
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
527 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
528 State
->Flags
.Af
= ((Value
& 0x0F) == 0x0F) ? TRUE
: FALSE
;
529 State
->Flags
.Pf
= Soft386CalculateParity(LOBYTE(Value
));
535 SOFT386_OPCODE_HANDLER(Soft386OpcodePushReg
)
537 if ((State
->PrefixFlags
!= SOFT386_PREFIX_OPSIZE
)
538 && (State
->PrefixFlags
!= 0))
541 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
545 /* Make sure this is the right instruction */
546 ASSERT((Opcode
& 0xF8) == 0x50);
548 /* Call the internal function */
549 return Soft386StackPush(State
, State
->GeneralRegs
[Opcode
& 0x07].Long
);
552 SOFT386_OPCODE_HANDLER(Soft386OpcodePopReg
)
555 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_SS
].Size
;
557 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
559 /* The OPSIZE prefix toggles the size */
562 else if (State
->PrefixFlags
!= 0)
565 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
569 /* Make sure this is the right instruction */
570 ASSERT((Opcode
& 0xF8) == 0x58);
572 /* Call the internal function */
573 if (!Soft386StackPop(State
, &Value
)) return FALSE
;
575 /* Store the value */
576 if (Size
) State
->GeneralRegs
[Opcode
& 0x07].Long
= Value
;
577 else State
->GeneralRegs
[Opcode
& 0x07].LowWord
= Value
;
583 SOFT386_OPCODE_HANDLER(Soft386OpcodeNop
)
585 if (State
->PrefixFlags
& ~(SOFT386_PREFIX_OPSIZE
| SOFT386_PREFIX_REP
))
587 /* Allowed prefixes are REP and OPSIZE */
588 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
592 if (State
->PrefixFlags
& SOFT386_PREFIX_REP
)
595 State
->IdleCallback(State
);
601 SOFT386_OPCODE_HANDLER(Soft386OpcodeExchangeEax
)
603 INT Reg
= Opcode
& 0x07;
604 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
606 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
608 /* The OPSIZE prefix toggles the size */
611 else if (State
->PrefixFlags
!= 0)
614 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
618 /* Make sure this is the right instruction */
619 ASSERT((Opcode
& 0xF8) == 0x90);
621 /* Exchange the values */
626 Value
= State
->GeneralRegs
[Reg
].Long
;
627 State
->GeneralRegs
[Reg
].Long
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
628 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Value
;
634 Value
= State
->GeneralRegs
[Reg
].LowWord
;
635 State
->GeneralRegs
[Reg
].LowWord
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
636 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Value
;
642 SOFT386_OPCODE_HANDLER(Soft386OpcodeShortConditionalJmp
)
644 BOOLEAN Jump
= FALSE
;
647 /* Make sure this is the right instruction */
648 ASSERT((Opcode
& 0xF0) == 0x70);
650 /* Fetch the offset */
651 if (!Soft386FetchByte(State
, (PUCHAR
)&Offset
))
653 /* An exception occurred */
657 switch ((Opcode
& 0x0F) >> 1)
662 Jump
= State
->Flags
.Of
;
669 Jump
= State
->Flags
.Cf
;
676 Jump
= State
->Flags
.Zf
;
683 Jump
= State
->Flags
.Cf
|| State
->Flags
.Zf
;
690 Jump
= State
->Flags
.Sf
;
697 Jump
= State
->Flags
.Pf
;
704 Jump
= State
->Flags
.Sf
!= State
->Flags
.Of
;
711 Jump
= (State
->Flags
.Sf
!= State
->Flags
.Of
) || State
->Flags
.Zf
;
718 /* Invert the result */
724 /* Move the instruction pointer */
725 State
->InstPtr
.Long
+= Offset
;
732 SOFT386_OPCODE_HANDLER(Soft386OpcodeClearCarry
)
734 /* Make sure this is the right instruction */
735 ASSERT(Opcode
== 0xF8);
737 /* No prefixes allowed */
738 if (State
->PrefixFlags
)
740 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
744 /* Clear CF and return success */
745 State
->Flags
.Cf
= FALSE
;
749 SOFT386_OPCODE_HANDLER(Soft386OpcodeSetCarry
)
751 /* Make sure this is the right instruction */
752 ASSERT(Opcode
== 0xF9);
754 /* No prefixes allowed */
755 if (State
->PrefixFlags
)
757 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
761 /* Set CF and return success*/
762 State
->Flags
.Cf
= TRUE
;
766 SOFT386_OPCODE_HANDLER(Soft386OpcodeComplCarry
)
768 /* Make sure this is the right instruction */
769 ASSERT(Opcode
== 0xF5);
771 /* No prefixes allowed */
772 if (State
->PrefixFlags
)
774 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
778 /* Toggle CF and return success */
779 State
->Flags
.Cf
= !State
->Flags
.Cf
;
783 SOFT386_OPCODE_HANDLER(Soft386OpcodeClearInt
)
785 /* Make sure this is the right instruction */
786 ASSERT(Opcode
== 0xFA);
788 /* No prefixes allowed */
789 if (State
->PrefixFlags
)
791 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
795 /* Check for protected mode */
796 if (State
->ControlRegisters
[SOFT386_REG_CR0
] & SOFT386_CR0_PE
)
799 if (State
->Flags
.Iopl
>= State
->SegmentRegs
[SOFT386_REG_CS
].Dpl
)
801 /* Clear the interrupt flag */
802 State
->Flags
.If
= FALSE
;
806 /* General Protection Fault */
807 Soft386Exception(State
, SOFT386_EXCEPTION_GP
);
813 /* Just clear the interrupt flag */
814 State
->Flags
.If
= FALSE
;
821 SOFT386_OPCODE_HANDLER(Soft386OpcodeSetInt
)
823 /* Make sure this is the right instruction */
824 ASSERT(Opcode
== 0xFB);
826 /* No prefixes allowed */
827 if (State
->PrefixFlags
)
829 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
833 /* Check for protected mode */
834 if (State
->ControlRegisters
[SOFT386_REG_CR0
] & SOFT386_CR0_PE
)
837 if (State
->Flags
.Iopl
>= State
->SegmentRegs
[SOFT386_REG_CS
].Dpl
)
839 /* Set the interrupt flag */
840 State
->Flags
.If
= TRUE
;
844 /* General Protection Fault */
845 Soft386Exception(State
, SOFT386_EXCEPTION_GP
);
851 /* Just set the interrupt flag */
852 State
->Flags
.If
= TRUE
;
859 SOFT386_OPCODE_HANDLER(Soft386OpcodeClearDir
)
861 /* Make sure this is the right instruction */
862 ASSERT(Opcode
== 0xFC);
864 /* No prefixes allowed */
865 if (State
->PrefixFlags
)
867 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
871 /* Clear DF and return success */
872 State
->Flags
.Df
= FALSE
;
876 SOFT386_OPCODE_HANDLER(Soft386OpcodeSetDir
)
878 /* Make sure this is the right instruction */
879 ASSERT(Opcode
== 0xFD);
881 /* No prefixes allowed */
882 if (State
->PrefixFlags
)
884 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
888 /* Set DF and return success*/
889 State
->Flags
.Df
= TRUE
;
893 SOFT386_OPCODE_HANDLER(Soft386OpcodeHalt
)
895 /* Make sure this is the right instruction */
896 ASSERT(Opcode
== 0xF4);
898 /* No prefixes allowed */
899 if (State
->PrefixFlags
)
901 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
905 /* Privileged instructions can only be executed under CPL = 0 */
906 if (State
->SegmentRegs
[SOFT386_REG_CS
].Dpl
!= 0)
908 Soft386Exception(State
, SOFT386_EXCEPTION_GP
);
913 while (!State
->HardwareInt
) State
->IdleCallback(State
);
919 SOFT386_OPCODE_HANDLER(Soft386OpcodeInByte
)
924 /* Make sure this is the right instruction */
925 ASSERT((Opcode
& 0xF7) == 0xE4);
929 /* Fetch the parameter */
930 if (!Soft386FetchByte(State
, &Data
))
932 /* Exception occurred */
936 /* Set the port number to the parameter */
941 /* The port number is in DX */
942 Port
= State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
;
945 /* Read a byte from the I/O port */
946 State
->IoReadCallback(State
, Port
, &Data
, sizeof(UCHAR
));
948 /* Store the result in AL */
949 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Data
;
954 SOFT386_OPCODE_HANDLER(Soft386OpcodeIn
)
957 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
959 /* Make sure this is the right instruction */
960 ASSERT((Opcode
& 0xF7) == 0xE5);
962 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
964 /* The OPSIZE prefix toggles the size */
967 else if (State
->PrefixFlags
!= 0)
970 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
978 /* Fetch the parameter */
979 if (!Soft386FetchByte(State
, &Data
))
981 /* Exception occurred */
985 /* Set the port number to the parameter */
990 /* The port number is in DX */
991 Port
= State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
;
998 /* Read a dword from the I/O port */
999 State
->IoReadCallback(State
, Port
, &Data
, sizeof(ULONG
));
1001 /* Store the value in EAX */
1002 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Data
;
1008 /* Read a word from the I/O port */
1009 State
->IoReadCallback(State
, Port
, &Data
, sizeof(USHORT
));
1011 /* Store the value in AX */
1012 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Data
;
1018 SOFT386_OPCODE_HANDLER(Soft386OpcodeOutByte
)
1023 /* Make sure this is the right instruction */
1024 ASSERT((Opcode
& 0xF7) == 0xE6);
1028 /* Fetch the parameter */
1029 if (!Soft386FetchByte(State
, &Data
))
1031 /* Exception occurred */
1035 /* Set the port number to the parameter */
1040 /* The port number is in DX */
1041 Port
= State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
;
1044 /* Read the value from AL */
1045 Data
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
1047 /* Write the byte to the I/O port */
1048 State
->IoWriteCallback(State
, Port
, &Data
, sizeof(UCHAR
));
1053 SOFT386_OPCODE_HANDLER(Soft386OpcodeOut
)
1056 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1058 /* Make sure this is the right instruction */
1059 ASSERT((Opcode
& 0xF7) == 0xE7);
1061 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
1063 /* The OPSIZE prefix toggles the size */
1066 else if (State
->PrefixFlags
!= 0)
1068 /* Invalid prefix */
1069 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1077 /* Fetch the parameter */
1078 if (!Soft386FetchByte(State
, &Data
))
1080 /* Exception occurred */
1084 /* Set the port number to the parameter */
1089 /* The port number is in DX */
1090 Port
= State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
;
1095 /* Get the value from EAX */
1096 ULONG Data
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
1098 /* Write a dword to the I/O port */
1099 State
->IoReadCallback(State
, Port
, &Data
, sizeof(ULONG
));
1103 /* Get the value from AX */
1104 USHORT Data
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
1106 /* Write a word to the I/O port */
1107 State
->IoWriteCallback(State
, Port
, &Data
, sizeof(USHORT
));
1113 SOFT386_OPCODE_HANDLER(Soft386OpcodeShortJump
)
1117 /* Make sure this is the right instruction */
1118 ASSERT(Opcode
== 0xEB);
1120 /* Fetch the offset */
1121 if (!Soft386FetchByte(State
, (PUCHAR
)&Offset
))
1123 /* An exception occurred */
1127 /* Move the instruction pointer */
1128 State
->InstPtr
.Long
+= Offset
;
1133 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovRegImm
)
1135 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1137 /* Make sure this is the right instruction */
1138 ASSERT((Opcode
& 0xF8) == 0xB8);
1140 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
1142 /* The OPSIZE prefix toggles the size */
1145 else if (State
->PrefixFlags
!= 0)
1147 /* Invalid prefix */
1148 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1156 /* Fetch the dword */
1157 if (!Soft386FetchDword(State
, &Value
))
1159 /* Exception occurred */
1163 /* Store the value in the register */
1164 State
->GeneralRegs
[Opcode
& 0x07].Long
= Value
;
1170 /* Fetch the word */
1171 if (!Soft386FetchWord(State
, &Value
))
1173 /* Exception occurred */
1177 /* Store the value in the register */
1178 State
->GeneralRegs
[Opcode
& 0x07].LowWord
= Value
;
1184 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovByteRegImm
)
1188 /* Make sure this is the right instruction */
1189 ASSERT((Opcode
& 0xF8) == 0xB0);
1191 if (State
->PrefixFlags
!= 0)
1193 /* Invalid prefix */
1194 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1198 /* Fetch the byte */
1199 if (!Soft386FetchByte(State
, &Value
))
1201 /* Exception occurred */
1207 /* AH, CH, DH or BH */
1208 State
->GeneralRegs
[Opcode
& 0x03].HighByte
= Value
;
1212 /* AL, CL, DL or BL */
1213 State
->GeneralRegs
[Opcode
& 0x03].LowByte
= Value
;
1219 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddByteModrm
)
1221 UCHAR FirstValue
, SecondValue
, Result
;
1222 SOFT386_MOD_REG_RM ModRegRm
;
1223 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1225 /* Make sure this is the right instruction */
1226 ASSERT((Opcode
& 0xFD) == 0x00);
1228 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1230 /* The ADSIZE prefix toggles the size */
1231 AddressSize
= !AddressSize
;
1233 else if (State
->PrefixFlags
1234 & ~(SOFT386_PREFIX_ADSIZE
1235 | SOFT386_PREFIX_SEG
1236 | SOFT386_PREFIX_LOCK
))
1238 /* Invalid prefix */
1239 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1243 /* Get the operands */
1244 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1246 /* Exception occurred */
1250 if (!Soft386ReadModrmByteOperands(State
,
1255 /* Exception occurred */
1259 /* Calculate the result */
1260 Result
= FirstValue
+ SecondValue
;
1262 /* Update the flags */
1263 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1264 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
1265 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
1266 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
1267 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1268 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1269 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1271 /* Write back the result */
1272 return Soft386WriteModrmByteOperands(State
,
1274 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1278 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddModrm
)
1280 SOFT386_MOD_REG_RM ModRegRm
;
1281 BOOLEAN OperandSize
, AddressSize
;
1283 /* Make sure this is the right instruction */
1284 ASSERT((Opcode
& 0xFD) == 0x01);
1286 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1288 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1290 /* The ADSIZE prefix toggles the address size */
1291 AddressSize
= !AddressSize
;
1294 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1296 /* The OPSIZE prefix toggles the operand size */
1297 OperandSize
= !OperandSize
;
1300 if (State
->PrefixFlags
1301 & ~(SOFT386_PREFIX_ADSIZE
1302 | SOFT386_PREFIX_OPSIZE
1303 | SOFT386_PREFIX_SEG
1304 | SOFT386_PREFIX_LOCK
))
1306 /* Invalid prefix */
1307 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1311 /* Get the operands */
1312 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1314 /* Exception occurred */
1318 /* Check the operand size */
1321 ULONG FirstValue
, SecondValue
, Result
;
1323 if (!Soft386ReadModrmDwordOperands(State
,
1328 /* Exception occurred */
1332 /* Calculate the result */
1333 Result
= FirstValue
+ SecondValue
;
1335 /* Update the flags */
1336 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1337 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
1338 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
1339 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
1340 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1341 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1342 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1344 /* Write back the result */
1345 return Soft386WriteModrmDwordOperands(State
,
1347 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1352 USHORT FirstValue
, SecondValue
, Result
;
1354 if (!Soft386ReadModrmWordOperands(State
,
1359 /* Exception occurred */
1363 /* Calculate the result */
1364 Result
= FirstValue
+ SecondValue
;
1366 /* Update the flags */
1367 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1368 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
1369 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
1370 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
1371 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1372 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
1373 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1375 /* Write back the result */
1376 return Soft386WriteModrmWordOperands(State
,
1378 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1383 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddAl
)
1385 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
1386 UCHAR SecondValue
, Result
;
1388 /* Make sure this is the right instruction */
1389 ASSERT(Opcode
== 0x04);
1391 if (State
->PrefixFlags
)
1393 /* This opcode doesn't take any prefixes */
1394 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1398 if (!Soft386FetchByte(State
, &SecondValue
))
1400 /* Exception occurred */
1404 /* Calculate the result */
1405 Result
= FirstValue
+ SecondValue
;
1407 /* Update the flags */
1408 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1409 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
1410 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
1411 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
1412 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1413 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1414 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1416 /* Write back the result */
1417 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
1422 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddEax
)
1424 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1426 /* Make sure this is the right instruction */
1427 ASSERT(Opcode
== 0x05);
1429 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
1431 /* Invalid prefix */
1432 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1436 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1438 /* The OPSIZE prefix toggles the size */
1444 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
1445 ULONG SecondValue
, Result
;
1447 if (!Soft386FetchDword(State
, &SecondValue
))
1449 /* Exception occurred */
1453 /* Calculate the result */
1454 Result
= FirstValue
+ SecondValue
;
1456 /* Update the flags */
1457 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1458 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
1459 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
1460 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
1461 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1462 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1463 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1465 /* Write back the result */
1466 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
1470 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
1471 USHORT SecondValue
, Result
;
1473 if (!Soft386FetchWord(State
, &SecondValue
))
1475 /* Exception occurred */
1479 /* Calculate the result */
1480 Result
= FirstValue
+ SecondValue
;
1482 /* Update the flags */
1483 State
->Flags
.Cf
= (Result
< FirstValue
) && (Result
< SecondValue
);
1484 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
1485 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
1486 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
1487 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1488 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
1489 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1491 /* Write back the result */
1492 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
1498 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrByteModrm
)
1500 UCHAR FirstValue
, SecondValue
, Result
;
1501 SOFT386_MOD_REG_RM ModRegRm
;
1502 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1504 /* Make sure this is the right instruction */
1505 ASSERT((Opcode
& 0xFD) == 0x08);
1507 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1509 /* The ADSIZE prefix toggles the size */
1510 AddressSize
= !AddressSize
;
1512 else if (State
->PrefixFlags
1513 & ~(SOFT386_PREFIX_ADSIZE
1514 | SOFT386_PREFIX_SEG
1515 | SOFT386_PREFIX_LOCK
))
1517 /* Invalid prefix */
1518 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1522 /* Get the operands */
1523 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1525 /* Exception occurred */
1529 if (!Soft386ReadModrmByteOperands(State
,
1534 /* Exception occurred */
1538 /* Calculate the result */
1539 Result
= FirstValue
| SecondValue
;
1541 /* Update the flags */
1542 State
->Flags
.Cf
= FALSE
;
1543 State
->Flags
.Of
= FALSE
;
1544 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1545 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1546 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1548 /* Write back the result */
1549 return Soft386WriteModrmByteOperands(State
,
1551 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1555 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrModrm
)
1557 SOFT386_MOD_REG_RM ModRegRm
;
1558 BOOLEAN OperandSize
, AddressSize
;
1560 /* Make sure this is the right instruction */
1561 ASSERT((Opcode
& 0xFD) == 0x09);
1563 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1565 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1567 /* The ADSIZE prefix toggles the address size */
1568 AddressSize
= !AddressSize
;
1571 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1573 /* The OPSIZE prefix toggles the operand size */
1574 OperandSize
= !OperandSize
;
1577 if (State
->PrefixFlags
1578 & ~(SOFT386_PREFIX_ADSIZE
1579 | SOFT386_PREFIX_OPSIZE
1580 | SOFT386_PREFIX_SEG
1581 | SOFT386_PREFIX_LOCK
))
1583 /* Invalid prefix */
1584 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1588 /* Get the operands */
1589 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1591 /* Exception occurred */
1595 /* Check the operand size */
1598 ULONG FirstValue
, SecondValue
, Result
;
1600 if (!Soft386ReadModrmDwordOperands(State
,
1605 /* Exception occurred */
1609 /* Calculate the result */
1610 Result
= FirstValue
| SecondValue
;
1612 /* Update the flags */
1613 State
->Flags
.Cf
= FALSE
;
1614 State
->Flags
.Of
= FALSE
;
1615 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1616 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1617 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1619 /* Write back the result */
1620 return Soft386WriteModrmDwordOperands(State
,
1622 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1627 USHORT FirstValue
, SecondValue
, Result
;
1629 if (!Soft386ReadModrmWordOperands(State
,
1634 /* Exception occurred */
1638 /* Calculate the result */
1639 Result
= FirstValue
| SecondValue
;
1641 /* Update the flags */
1642 State
->Flags
.Cf
= FALSE
;
1643 State
->Flags
.Of
= FALSE
;
1644 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1645 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1646 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1648 /* Write back the result */
1649 return Soft386WriteModrmWordOperands(State
,
1651 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1656 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrAl
)
1658 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
1659 UCHAR SecondValue
, Result
;
1661 /* Make sure this is the right instruction */
1662 ASSERT(Opcode
== 0x0C);
1664 if (State
->PrefixFlags
)
1666 /* This opcode doesn't take any prefixes */
1667 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1671 if (!Soft386FetchByte(State
, &SecondValue
))
1673 /* Exception occurred */
1677 /* Calculate the result */
1678 Result
= FirstValue
| SecondValue
;
1680 /* Update the flags */
1681 State
->Flags
.Cf
= FALSE
;
1682 State
->Flags
.Of
= FALSE
;
1683 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1684 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1685 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1687 /* Write back the result */
1688 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
1693 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrEax
)
1695 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1697 /* Make sure this is the right instruction */
1698 ASSERT(Opcode
== 0x0D);
1700 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
1702 /* Invalid prefix */
1703 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1707 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1709 /* The OPSIZE prefix toggles the size */
1715 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
1716 ULONG SecondValue
, Result
;
1718 if (!Soft386FetchDword(State
, &SecondValue
))
1720 /* Exception occurred */
1724 /* Calculate the result */
1725 Result
= FirstValue
| SecondValue
;
1727 /* Update the flags */
1728 State
->Flags
.Cf
= FALSE
;
1729 State
->Flags
.Of
= FALSE
;
1730 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1731 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1732 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1734 /* Write back the result */
1735 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
1739 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
1740 USHORT SecondValue
, Result
;
1742 if (!Soft386FetchWord(State
, &SecondValue
))
1744 /* Exception occurred */
1748 /* Calculate the result */
1749 Result
= FirstValue
| SecondValue
;
1751 /* Update the flags */
1752 State
->Flags
.Cf
= FALSE
;
1753 State
->Flags
.Of
= FALSE
;
1754 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1755 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
1756 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1758 /* Write back the result */
1759 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
1765 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndByteModrm
)
1767 UCHAR FirstValue
, SecondValue
, Result
;
1768 SOFT386_MOD_REG_RM ModRegRm
;
1769 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1771 /* Make sure this is the right instruction */
1772 ASSERT((Opcode
& 0xFD) == 0x20);
1774 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1776 /* The ADSIZE prefix toggles the size */
1777 AddressSize
= !AddressSize
;
1779 else if (State
->PrefixFlags
1780 & ~(SOFT386_PREFIX_ADSIZE
1781 | SOFT386_PREFIX_SEG
1782 | SOFT386_PREFIX_LOCK
))
1784 /* Invalid prefix */
1785 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1789 /* Get the operands */
1790 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1792 /* Exception occurred */
1796 if (!Soft386ReadModrmByteOperands(State
,
1801 /* Exception occurred */
1805 /* Calculate the result */
1806 Result
= FirstValue
& SecondValue
;
1808 /* Update the flags */
1809 State
->Flags
.Cf
= FALSE
;
1810 State
->Flags
.Of
= FALSE
;
1811 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1812 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1813 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1815 /* Write back the result */
1816 return Soft386WriteModrmByteOperands(State
,
1818 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1822 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndModrm
)
1824 SOFT386_MOD_REG_RM ModRegRm
;
1825 BOOLEAN OperandSize
, AddressSize
;
1827 /* Make sure this is the right instruction */
1828 ASSERT((Opcode
& 0xFD) == 0x21);
1830 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1832 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
1834 /* The ADSIZE prefix toggles the address size */
1835 AddressSize
= !AddressSize
;
1838 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1840 /* The OPSIZE prefix toggles the operand size */
1841 OperandSize
= !OperandSize
;
1844 if (State
->PrefixFlags
1845 & ~(SOFT386_PREFIX_ADSIZE
1846 | SOFT386_PREFIX_OPSIZE
1847 | SOFT386_PREFIX_SEG
1848 | SOFT386_PREFIX_LOCK
))
1850 /* Invalid prefix */
1851 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1855 /* Get the operands */
1856 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
1858 /* Exception occurred */
1862 /* Check the operand size */
1865 ULONG FirstValue
, SecondValue
, Result
;
1867 if (!Soft386ReadModrmDwordOperands(State
,
1872 /* Exception occurred */
1876 /* Calculate the result */
1877 Result
= FirstValue
& SecondValue
;
1879 /* Update the flags */
1880 State
->Flags
.Cf
= FALSE
;
1881 State
->Flags
.Of
= FALSE
;
1882 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1883 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1884 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1886 /* Write back the result */
1887 return Soft386WriteModrmDwordOperands(State
,
1889 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1894 USHORT FirstValue
, SecondValue
, Result
;
1896 if (!Soft386ReadModrmWordOperands(State
,
1901 /* Exception occurred */
1905 /* Calculate the result */
1906 Result
= FirstValue
& SecondValue
;
1908 /* Update the flags */
1909 State
->Flags
.Cf
= FALSE
;
1910 State
->Flags
.Of
= FALSE
;
1911 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1912 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1913 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1915 /* Write back the result */
1916 return Soft386WriteModrmWordOperands(State
,
1918 Opcode
& SOFT386_OPCODE_WRITE_REG
,
1923 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndAl
)
1925 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
1926 UCHAR SecondValue
, Result
;
1928 /* Make sure this is the right instruction */
1929 ASSERT(Opcode
== 0x24);
1931 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
1933 /* Invalid prefix */
1934 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1938 if (!Soft386FetchByte(State
, &SecondValue
))
1940 /* Exception occurred */
1944 /* Calculate the result */
1945 Result
= FirstValue
& SecondValue
;
1947 /* Update the flags */
1948 State
->Flags
.Cf
= FALSE
;
1949 State
->Flags
.Of
= FALSE
;
1950 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1951 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
1952 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
1954 /* Write back the result */
1955 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
1960 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndEax
)
1962 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1964 /* Make sure this is the right instruction */
1965 ASSERT(Opcode
== 0x25);
1967 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
1969 /* Invalid prefix */
1970 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1974 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
1976 /* The OPSIZE prefix toggles the size */
1982 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
1983 ULONG SecondValue
, Result
;
1985 if (!Soft386FetchDword(State
, &SecondValue
))
1987 /* Exception occurred */
1991 /* Calculate the result */
1992 Result
= FirstValue
& SecondValue
;
1994 /* Update the flags */
1995 State
->Flags
.Cf
= FALSE
;
1996 State
->Flags
.Of
= FALSE
;
1997 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
1998 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
1999 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2001 /* Write back the result */
2002 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
2006 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
2007 USHORT SecondValue
, Result
;
2009 if (!Soft386FetchWord(State
, &SecondValue
))
2011 /* Exception occurred */
2015 /* Calculate the result */
2016 Result
= FirstValue
& SecondValue
;
2018 /* Update the flags */
2019 State
->Flags
.Cf
= FALSE
;
2020 State
->Flags
.Of
= FALSE
;
2021 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2022 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
2023 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2025 /* Write back the result */
2026 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
2032 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorByteModrm
)
2034 UCHAR FirstValue
, SecondValue
, Result
;
2035 SOFT386_MOD_REG_RM ModRegRm
;
2036 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2038 /* Make sure this is the right instruction */
2039 ASSERT((Opcode
& 0xFD) == 0x30);
2041 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2043 /* The ADSIZE prefix toggles the size */
2044 AddressSize
= !AddressSize
;
2046 else if (State
->PrefixFlags
2047 & ~(SOFT386_PREFIX_ADSIZE
2048 | SOFT386_PREFIX_SEG
2049 | SOFT386_PREFIX_LOCK
))
2051 /* Invalid prefix */
2052 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2056 /* Get the operands */
2057 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2059 /* Exception occurred */
2063 if (!Soft386ReadModrmByteOperands(State
,
2068 /* Exception occurred */
2072 /* Calculate the result */
2073 Result
= FirstValue
^ SecondValue
;
2075 /* Update the flags */
2076 State
->Flags
.Cf
= FALSE
;
2077 State
->Flags
.Of
= FALSE
;
2078 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2079 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2080 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2082 /* Write back the result */
2083 return Soft386WriteModrmByteOperands(State
,
2085 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2089 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorModrm
)
2091 SOFT386_MOD_REG_RM ModRegRm
;
2092 BOOLEAN OperandSize
, AddressSize
;
2094 /* Make sure this is the right instruction */
2095 ASSERT((Opcode
& 0xFD) == 0x31);
2097 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2099 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2101 /* The ADSIZE prefix toggles the address size */
2102 AddressSize
= !AddressSize
;
2105 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2107 /* The OPSIZE prefix toggles the operand size */
2108 OperandSize
= !OperandSize
;
2111 if (State
->PrefixFlags
2112 & ~(SOFT386_PREFIX_ADSIZE
2113 | SOFT386_PREFIX_OPSIZE
2114 | SOFT386_PREFIX_SEG
2115 | SOFT386_PREFIX_LOCK
))
2117 /* Invalid prefix */
2118 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2122 /* Get the operands */
2123 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2125 /* Exception occurred */
2129 /* Check the operand size */
2132 ULONG FirstValue
, SecondValue
, Result
;
2134 if (!Soft386ReadModrmDwordOperands(State
,
2139 /* Exception occurred */
2143 /* Calculate the result */
2144 Result
= FirstValue
^ SecondValue
;
2146 /* Update the flags */
2147 State
->Flags
.Cf
= FALSE
;
2148 State
->Flags
.Of
= FALSE
;
2149 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2150 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2151 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2153 /* Write back the result */
2154 return Soft386WriteModrmDwordOperands(State
,
2156 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2161 USHORT FirstValue
, SecondValue
, Result
;
2163 if (!Soft386ReadModrmWordOperands(State
,
2168 /* Exception occurred */
2172 /* Calculate the result */
2173 Result
= FirstValue
^ SecondValue
;
2175 /* Update the flags */
2176 State
->Flags
.Cf
= FALSE
;
2177 State
->Flags
.Of
= FALSE
;
2178 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2179 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2180 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2182 /* Write back the result */
2183 return Soft386WriteModrmWordOperands(State
,
2185 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2190 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorAl
)
2192 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
2193 UCHAR SecondValue
, Result
;
2195 /* Make sure this is the right instruction */
2196 ASSERT(Opcode
== 0x34);
2198 if (State
->PrefixFlags
)
2200 /* This opcode doesn't take any prefixes */
2201 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2205 if (!Soft386FetchByte(State
, &SecondValue
))
2207 /* Exception occurred */
2211 /* Calculate the result */
2212 Result
= FirstValue
^ SecondValue
;
2214 /* Update the flags */
2215 State
->Flags
.Cf
= FALSE
;
2216 State
->Flags
.Of
= FALSE
;
2217 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2218 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2219 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2221 /* Write back the result */
2222 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
2227 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorEax
)
2229 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2231 /* Make sure this is the right instruction */
2232 ASSERT(Opcode
== 0x35);
2234 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
2236 /* Invalid prefix */
2237 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2241 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2243 /* The OPSIZE prefix toggles the size */
2249 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
2250 ULONG SecondValue
, Result
;
2252 if (!Soft386FetchDword(State
, &SecondValue
))
2254 /* Exception occurred */
2258 /* Calculate the result */
2259 Result
= FirstValue
^ SecondValue
;
2261 /* Update the flags */
2262 State
->Flags
.Cf
= FALSE
;
2263 State
->Flags
.Of
= FALSE
;
2264 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2265 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2266 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2268 /* Write back the result */
2269 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
2273 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
2274 USHORT SecondValue
, Result
;
2276 if (!Soft386FetchWord(State
, &SecondValue
))
2278 /* Exception occurred */
2282 /* Calculate the result */
2283 Result
= FirstValue
^ SecondValue
;
2285 /* Update the flags */
2286 State
->Flags
.Cf
= FALSE
;
2287 State
->Flags
.Of
= FALSE
;
2288 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2289 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
2290 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2292 /* Write back the result */
2293 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
2299 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestByteModrm
)
2301 UCHAR FirstValue
, SecondValue
, Result
;
2302 SOFT386_MOD_REG_RM ModRegRm
;
2303 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2305 /* Make sure this is the right instruction */
2306 ASSERT(Opcode
== 0x84);
2308 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2310 /* The ADSIZE prefix toggles the size */
2311 AddressSize
= !AddressSize
;
2313 else if (State
->PrefixFlags
2314 & ~(SOFT386_PREFIX_ADSIZE
2315 | SOFT386_PREFIX_SEG
2316 | SOFT386_PREFIX_LOCK
))
2318 /* Invalid prefix */
2319 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2323 /* Get the operands */
2324 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2326 /* Exception occurred */
2330 if (!Soft386ReadModrmByteOperands(State
,
2335 /* Exception occurred */
2338 /* Calculate the result */
2339 Result
= FirstValue
& SecondValue
;
2341 /* Update the flags */
2342 State
->Flags
.Cf
= FALSE
;
2343 State
->Flags
.Of
= FALSE
;
2344 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2345 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2346 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2348 /* The result is discarded */
2352 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestModrm
)
2354 SOFT386_MOD_REG_RM ModRegRm
;
2355 BOOLEAN OperandSize
, AddressSize
;
2357 /* Make sure this is the right instruction */
2358 ASSERT(Opcode
== 0x85);
2360 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2362 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2364 /* The ADSIZE prefix toggles the address size */
2365 AddressSize
= !AddressSize
;
2368 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2370 /* The OPSIZE prefix toggles the operand size */
2371 OperandSize
= !OperandSize
;
2374 if (State
->PrefixFlags
2375 & ~(SOFT386_PREFIX_ADSIZE
2376 | SOFT386_PREFIX_OPSIZE
2377 | SOFT386_PREFIX_SEG
2378 | SOFT386_PREFIX_LOCK
))
2380 /* Invalid prefix */
2381 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2385 /* Get the operands */
2386 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2388 /* Exception occurred */
2392 /* Check the operand size */
2395 ULONG FirstValue
, SecondValue
, Result
;
2397 if (!Soft386ReadModrmDwordOperands(State
,
2402 /* Exception occurred */
2406 /* Calculate the result */
2407 Result
= FirstValue
& SecondValue
;
2409 /* Update the flags */
2410 State
->Flags
.Cf
= FALSE
;
2411 State
->Flags
.Of
= FALSE
;
2412 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2413 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2414 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2418 USHORT FirstValue
, SecondValue
, Result
;
2420 if (!Soft386ReadModrmWordOperands(State
,
2425 /* Exception occurred */
2429 /* Calculate the result */
2430 Result
= FirstValue
& SecondValue
;
2432 /* Update the flags */
2433 State
->Flags
.Cf
= FALSE
;
2434 State
->Flags
.Of
= FALSE
;
2435 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2436 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2437 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2440 /* The result is discarded */
2444 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestAl
)
2446 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
2447 UCHAR SecondValue
, Result
;
2449 /* Make sure this is the right instruction */
2450 ASSERT(Opcode
== 0xA8);
2452 if (State
->PrefixFlags
)
2454 /* This opcode doesn't take any prefixes */
2455 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2459 if (!Soft386FetchByte(State
, &SecondValue
))
2461 /* Exception occurred */
2465 /* Calculate the result */
2466 Result
= FirstValue
& SecondValue
;
2468 /* Update the flags */
2469 State
->Flags
.Cf
= FALSE
;
2470 State
->Flags
.Of
= FALSE
;
2471 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2472 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2473 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2475 /* The result is discarded */
2479 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestEax
)
2481 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2483 /* Make sure this is the right instruction */
2484 ASSERT(Opcode
== 0xA9);
2486 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
2488 /* Invalid prefix */
2489 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2493 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2495 /* The OPSIZE prefix toggles the size */
2501 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
2502 ULONG SecondValue
, Result
;
2504 if (!Soft386FetchDword(State
, &SecondValue
))
2506 /* Exception occurred */
2510 /* Calculate the result */
2511 Result
= FirstValue
& SecondValue
;
2513 /* Update the flags */
2514 State
->Flags
.Cf
= FALSE
;
2515 State
->Flags
.Of
= FALSE
;
2516 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2517 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2518 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2522 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
2523 USHORT SecondValue
, Result
;
2525 if (!Soft386FetchWord(State
, &SecondValue
))
2527 /* Exception occurred */
2531 /* Calculate the result */
2532 Result
= FirstValue
& SecondValue
;
2534 /* Update the flags */
2535 State
->Flags
.Cf
= FALSE
;
2536 State
->Flags
.Of
= FALSE
;
2537 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2538 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
2539 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2542 /* The result is discarded */
2546 SOFT386_OPCODE_HANDLER(Soft386OpcodeXchgByteModrm
)
2548 UCHAR FirstValue
, SecondValue
;
2549 SOFT386_MOD_REG_RM ModRegRm
;
2550 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2552 /* Make sure this is the right instruction */
2553 ASSERT(Opcode
== 0x86);
2555 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2557 /* The ADSIZE prefix toggles the size */
2558 AddressSize
= !AddressSize
;
2560 else if (State
->PrefixFlags
2561 & ~(SOFT386_PREFIX_ADSIZE
2562 | SOFT386_PREFIX_SEG
2563 | SOFT386_PREFIX_LOCK
))
2565 /* Invalid prefix */
2566 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2570 /* Get the operands */
2571 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2573 /* Exception occurred */
2577 if (!Soft386ReadModrmByteOperands(State
,
2582 /* Exception occurred */
2586 /* Write the value from the register to the R/M */
2587 if (!Soft386WriteModrmByteOperands(State
,
2592 /* Exception occurred */
2596 /* Write the value from the R/M to the register */
2597 if (!Soft386WriteModrmByteOperands(State
,
2602 /* Exception occurred */
2609 SOFT386_OPCODE_HANDLER(Soft386OpcodeXchgModrm
)
2611 SOFT386_MOD_REG_RM ModRegRm
;
2612 BOOLEAN OperandSize
, AddressSize
;
2614 /* Make sure this is the right instruction */
2615 ASSERT(Opcode
== 0x87);
2617 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2619 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2621 /* The ADSIZE prefix toggles the address size */
2622 AddressSize
= !AddressSize
;
2625 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2627 /* The OPSIZE prefix toggles the operand size */
2628 OperandSize
= !OperandSize
;
2631 if (State
->PrefixFlags
2632 & ~(SOFT386_PREFIX_ADSIZE
2633 | SOFT386_PREFIX_OPSIZE
2634 | SOFT386_PREFIX_SEG
2635 | SOFT386_PREFIX_LOCK
))
2637 /* Invalid prefix */
2638 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2642 /* Get the operands */
2643 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2645 /* Exception occurred */
2649 /* Check the operand size */
2652 ULONG FirstValue
, SecondValue
;
2654 if (!Soft386ReadModrmDwordOperands(State
,
2659 /* Exception occurred */
2663 /* Write the value from the register to the R/M */
2664 if (!Soft386WriteModrmDwordOperands(State
,
2669 /* Exception occurred */
2673 /* Write the value from the R/M to the register */
2674 if (!Soft386WriteModrmDwordOperands(State
,
2679 /* Exception occurred */
2685 USHORT FirstValue
, SecondValue
;
2687 if (!Soft386ReadModrmWordOperands(State
,
2692 /* Exception occurred */
2696 /* Write the value from the register to the R/M */
2697 if (!Soft386WriteModrmWordOperands(State
,
2702 /* Exception occurred */
2706 /* Write the value from the R/M to the register */
2707 if (!Soft386WriteModrmWordOperands(State
,
2712 /* Exception occurred */
2717 /* The result is discarded */
2721 SOFT386_OPCODE_HANDLER(Soft386OpcodePushEs
)
2723 /* Call the internal API */
2724 return Soft386StackPush(State
, State
->SegmentRegs
[SOFT386_REG_ES
].Selector
);
2727 SOFT386_OPCODE_HANDLER(Soft386OpcodePopEs
)
2731 if (!Soft386StackPop(State
, &NewSelector
))
2733 /* Exception occurred */
2737 /* Call the internal API */
2738 return Soft386LoadSegment(State
, SOFT386_REG_ES
, LOWORD(NewSelector
));
2741 SOFT386_OPCODE_HANDLER(Soft386OpcodePushCs
)
2743 /* Call the internal API */
2744 return Soft386StackPush(State
, State
->SegmentRegs
[SOFT386_REG_CS
].Selector
);
2747 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcByteModrm
)
2749 UCHAR FirstValue
, SecondValue
, Result
;
2750 SOFT386_MOD_REG_RM ModRegRm
;
2751 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2753 /* Make sure this is the right instruction */
2754 ASSERT((Opcode
& 0xFD) == 0x10);
2756 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2758 /* The ADSIZE prefix toggles the size */
2759 AddressSize
= !AddressSize
;
2761 else if (State
->PrefixFlags
2762 & ~(SOFT386_PREFIX_ADSIZE
2763 | SOFT386_PREFIX_SEG
2764 | SOFT386_PREFIX_LOCK
))
2766 /* Invalid prefix */
2767 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2771 /* Get the operands */
2772 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2774 /* Exception occurred */
2778 if (!Soft386ReadModrmByteOperands(State
,
2783 /* Exception occurred */
2787 /* Calculate the result */
2788 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2790 /* Special exception for CF */
2791 State
->Flags
.Cf
= State
->Flags
.Cf
2792 && ((FirstValue
== 0xFF) || (SecondValue
== 0xFF));
2794 /* Update the flags */
2795 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2796 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
2797 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
2798 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
2799 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2800 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2801 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2803 /* Write back the result */
2804 return Soft386WriteModrmByteOperands(State
,
2806 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2810 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcModrm
)
2812 SOFT386_MOD_REG_RM ModRegRm
;
2813 BOOLEAN OperandSize
, AddressSize
;
2815 /* Make sure this is the right instruction */
2816 ASSERT((Opcode
& 0xFD) == 0x11);
2818 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2820 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
2822 /* The ADSIZE prefix toggles the address size */
2823 AddressSize
= !AddressSize
;
2826 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2828 /* The OPSIZE prefix toggles the operand size */
2829 OperandSize
= !OperandSize
;
2832 if (State
->PrefixFlags
2833 & ~(SOFT386_PREFIX_ADSIZE
2834 | SOFT386_PREFIX_OPSIZE
2835 | SOFT386_PREFIX_SEG
2836 | SOFT386_PREFIX_LOCK
))
2838 /* Invalid prefix */
2839 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2843 /* Get the operands */
2844 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
2846 /* Exception occurred */
2850 /* Check the operand size */
2853 ULONG FirstValue
, SecondValue
, Result
;
2855 if (!Soft386ReadModrmDwordOperands(State
,
2860 /* Exception occurred */
2864 /* Calculate the result */
2865 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2867 /* Special exception for CF */
2868 State
->Flags
.Cf
= State
->Flags
.Cf
2869 && ((FirstValue
== 0xFFFFFFFF) || (SecondValue
== 0xFFFFFFFF));
2871 /* Update the flags */
2872 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2873 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
2874 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
2875 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
2876 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2877 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
2878 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2880 /* Write back the result */
2881 return Soft386WriteModrmDwordOperands(State
,
2883 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2888 USHORT FirstValue
, SecondValue
, Result
;
2890 if (!Soft386ReadModrmWordOperands(State
,
2895 /* Exception occurred */
2899 /* Calculate the result */
2900 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2902 /* Special exception for CF */
2903 State
->Flags
.Cf
= State
->Flags
.Cf
2904 && ((FirstValue
== 0xFFFF) || (SecondValue
== 0xFFFF));
2906 /* Update the flags */
2907 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2908 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
2909 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
2910 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
2911 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2912 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
2913 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2915 /* Write back the result */
2916 return Soft386WriteModrmWordOperands(State
,
2918 Opcode
& SOFT386_OPCODE_WRITE_REG
,
2924 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcAl
)
2926 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
2927 UCHAR SecondValue
, Result
;
2929 /* Make sure this is the right instruction */
2930 ASSERT(Opcode
== 0x14);
2932 if (State
->PrefixFlags
)
2934 /* This opcode doesn't take any prefixes */
2935 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2939 if (!Soft386FetchByte(State
, &SecondValue
))
2941 /* Exception occurred */
2945 /* Calculate the result */
2946 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
2948 /* Special exception for CF */
2949 State
->Flags
.Cf
= State
->Flags
.Cf
&&
2950 ((FirstValue
== 0xFF) || (SecondValue
== 0xFF));
2952 /* Update the flags */
2953 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
2954 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) == (SecondValue
& SIGN_FLAG_BYTE
))
2955 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
2956 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
2957 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
2958 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
2959 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
2961 /* Write back the result */
2962 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
2967 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcEax
)
2969 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
2971 /* Make sure this is the right instruction */
2972 ASSERT(Opcode
== 0x15);
2974 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
2976 /* Invalid prefix */
2977 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
2981 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
2983 /* The OPSIZE prefix toggles the size */
2989 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
2990 ULONG SecondValue
, Result
;
2992 if (!Soft386FetchDword(State
, &SecondValue
))
2994 /* Exception occurred */
2998 /* Calculate the result */
2999 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
3001 /* Special exception for CF */
3002 State
->Flags
.Cf
= State
->Flags
.Cf
&&
3003 ((FirstValue
== 0xFFFFFFFF) || (SecondValue
== 0xFFFFFFFF));
3005 /* Update the flags */
3006 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
3007 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) == (SecondValue
& SIGN_FLAG_LONG
))
3008 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
3009 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
3010 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3011 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
3012 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3014 /* Write back the result */
3015 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
3019 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
3020 USHORT SecondValue
, Result
;
3022 if (!Soft386FetchWord(State
, &SecondValue
))
3024 /* Exception occurred */
3028 /* Calculate the result */
3029 Result
= FirstValue
+ SecondValue
+ State
->Flags
.Cf
;
3031 /* Special exception for CF */
3032 State
->Flags
.Cf
= State
->Flags
.Cf
&&
3033 ((FirstValue
== 0xFFFF) || (SecondValue
== 0xFFFF));
3035 /* Update the flags */
3036 State
->Flags
.Cf
= State
->Flags
.Cf
|| ((Result
< FirstValue
) && (Result
< SecondValue
));
3037 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) == (SecondValue
& SIGN_FLAG_WORD
))
3038 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
3039 State
->Flags
.Af
= (((FirstValue
& 0x0F) + (SecondValue
& 0x0F)) & 0x10) ? TRUE
: FALSE
;
3040 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3041 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
3042 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3044 /* Write back the result */
3045 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
3051 SOFT386_OPCODE_HANDLER(Soft386OpcodePushSs
)
3053 /* Call the internal API */
3054 return Soft386StackPush(State
, State
->SegmentRegs
[SOFT386_REG_SS
].Selector
);
3057 SOFT386_OPCODE_HANDLER(Soft386OpcodePopSs
)
3061 if (!Soft386StackPop(State
, &NewSelector
))
3063 /* Exception occurred */
3067 /* Call the internal API */
3068 return Soft386LoadSegment(State
, SOFT386_REG_SS
, LOWORD(NewSelector
));
3071 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbByteModrm
)
3073 // TODO: NOT IMPLEMENTED
3079 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbModrm
)
3081 // TODO: NOT IMPLEMENTED
3087 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbAl
)
3089 // TODO: NOT IMPLEMENTED
3095 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbEax
)
3097 // TODO: NOT IMPLEMENTED
3103 SOFT386_OPCODE_HANDLER(Soft386OpcodePushDs
)
3105 /* Call the internal API */
3106 return Soft386StackPush(State
, State
->SegmentRegs
[SOFT386_REG_DS
].Selector
);
3109 SOFT386_OPCODE_HANDLER(Soft386OpcodePopDs
)
3113 if (!Soft386StackPop(State
, &NewSelector
))
3115 /* Exception occurred */
3119 /* Call the internal API */
3120 return Soft386LoadSegment(State
, SOFT386_REG_DS
, LOWORD(NewSelector
));
3123 SOFT386_OPCODE_HANDLER(Soft386OpcodeDaa
)
3125 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3126 BOOLEAN Carry
= State
->Flags
.Cf
;
3128 /* Clear the carry flag */
3129 State
->Flags
.Cf
= FALSE
;
3131 /* Check if the first BCD digit is invalid or there was a carry from it */
3132 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3135 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
+= 0x06;
3136 if (State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
< 0x06)
3138 /* A carry occurred */
3139 State
->Flags
.Cf
= TRUE
;
3142 /* Set the adjust flag */
3143 State
->Flags
.Af
= TRUE
;
3146 /* Check if the second BCD digit is invalid or there was a carry from it */
3147 if ((Value
> 0x99) || Carry
)
3150 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
+= 0x60;
3152 /* There was a carry */
3153 State
->Flags
.Cf
= TRUE
;
3159 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubByteModrm
)
3161 UCHAR FirstValue
, SecondValue
, Result
;
3162 SOFT386_MOD_REG_RM ModRegRm
;
3163 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3165 /* Make sure this is the right instruction */
3166 ASSERT((Opcode
& 0xED) == 0x28);
3168 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3170 /* The ADSIZE prefix toggles the size */
3171 AddressSize
= !AddressSize
;
3173 else if (State
->PrefixFlags
3174 & ~(SOFT386_PREFIX_ADSIZE
3175 | SOFT386_PREFIX_SEG
3176 | SOFT386_PREFIX_LOCK
))
3178 /* Invalid prefix */
3179 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3183 /* Get the operands */
3184 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3186 /* Exception occurred */
3190 if (!Soft386ReadModrmByteOperands(State
,
3195 /* Exception occurred */
3199 /* Check if this is the instruction that writes to R/M */
3200 if (!(Opcode
& SOFT386_OPCODE_WRITE_REG
))
3202 /* Swap the order */
3203 FirstValue
^= SecondValue
;
3204 SecondValue
^= FirstValue
;
3205 FirstValue
^= SecondValue
;
3208 /* Calculate the result */
3209 Result
= FirstValue
- SecondValue
;
3211 /* Update the flags */
3212 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3213 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) != (SecondValue
& SIGN_FLAG_BYTE
))
3214 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
3215 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3216 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3217 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
3218 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3220 /* Check if this is not a CMP */
3221 if (!(Opcode
& 0x10))
3223 /* Write back the result */
3224 return Soft386WriteModrmByteOperands(State
,
3226 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3231 /* Discard the result */
3236 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubModrm
)
3238 SOFT386_MOD_REG_RM ModRegRm
;
3239 BOOLEAN OperandSize
, AddressSize
;
3241 /* Make sure this is the right instruction */
3242 ASSERT((Opcode
& 0xED) == 0x29);
3244 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3246 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3248 /* The ADSIZE prefix toggles the address size */
3249 AddressSize
= !AddressSize
;
3252 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
3254 /* The OPSIZE prefix toggles the operand size */
3255 OperandSize
= !OperandSize
;
3258 if (State
->PrefixFlags
3259 & ~(SOFT386_PREFIX_ADSIZE
3260 | SOFT386_PREFIX_OPSIZE
3261 | SOFT386_PREFIX_SEG
3262 | SOFT386_PREFIX_LOCK
))
3264 /* Invalid prefix */
3265 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3269 /* Get the operands */
3270 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3272 /* Exception occurred */
3276 /* Check the operand size */
3279 ULONG FirstValue
, SecondValue
, Result
;
3281 if (!Soft386ReadModrmDwordOperands(State
,
3286 /* Exception occurred */
3290 /* Check if this is the instruction that writes to R/M */
3291 if (!(Opcode
& SOFT386_OPCODE_WRITE_REG
))
3293 /* Swap the order */
3294 FirstValue
^= SecondValue
;
3295 SecondValue
^= FirstValue
;
3296 FirstValue
^= SecondValue
;
3299 /* Calculate the result */
3300 Result
= FirstValue
- SecondValue
;
3302 /* Update the flags */
3303 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3304 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) != (SecondValue
& SIGN_FLAG_LONG
))
3305 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
3306 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3307 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3308 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
3309 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3311 /* Check if this is not a CMP */
3312 if (!(Opcode
& 0x10))
3314 /* Write back the result */
3315 return Soft386WriteModrmDwordOperands(State
,
3317 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3322 /* Discard the result */
3328 USHORT FirstValue
, SecondValue
, Result
;
3330 if (!Soft386ReadModrmWordOperands(State
,
3335 /* Exception occurred */
3339 /* Check if this is the instruction that writes to R/M */
3340 if (!(Opcode
& SOFT386_OPCODE_WRITE_REG
))
3342 /* Swap the order */
3343 FirstValue
^= SecondValue
;
3344 SecondValue
^= FirstValue
;
3345 FirstValue
^= SecondValue
;
3348 /* Calculate the result */
3349 Result
= FirstValue
- SecondValue
;
3351 /* Update the flags */
3352 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3353 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) != (SecondValue
& SIGN_FLAG_WORD
))
3354 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
3355 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3356 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3357 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
3358 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3360 /* Check if this is not a CMP */
3361 if (!(Opcode
& 0x10))
3363 /* Write back the result */
3364 return Soft386WriteModrmWordOperands(State
,
3366 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3371 /* Discard the result */
3378 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubAl
)
3380 UCHAR FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3381 UCHAR SecondValue
, Result
;
3383 /* Make sure this is the right instruction */
3384 ASSERT((Opcode
& 0xEF) == 0x2C);
3386 if (State
->PrefixFlags
)
3388 /* This opcode doesn't take any prefixes */
3389 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3393 if (!Soft386FetchByte(State
, &SecondValue
))
3395 /* Exception occurred */
3399 /* Calculate the result */
3400 Result
= FirstValue
- SecondValue
;
3402 /* Update the flags */
3403 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3404 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_BYTE
) != (SecondValue
& SIGN_FLAG_BYTE
))
3405 && ((FirstValue
& SIGN_FLAG_BYTE
) != (Result
& SIGN_FLAG_BYTE
));
3406 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3407 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3408 State
->Flags
.Sf
= (Result
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
3409 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3411 /* Check if this is not a CMP */
3412 if (!(Opcode
& 0x10))
3414 /* Write back the result */
3415 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Result
;
3421 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubEax
)
3423 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3425 /* Make sure this is the right instruction */
3426 ASSERT((Opcode
& 0xEF) == 0x2D);
3428 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
3430 /* Invalid prefix */
3431 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3435 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
3437 /* The OPSIZE prefix toggles the size */
3443 ULONG FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
3444 ULONG SecondValue
, Result
;
3446 if (!Soft386FetchDword(State
, &SecondValue
))
3448 /* Exception occurred */
3452 /* Calculate the result */
3453 Result
= FirstValue
- SecondValue
;
3455 /* Update the flags */
3456 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3457 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_LONG
) != (SecondValue
& SIGN_FLAG_LONG
))
3458 && ((FirstValue
& SIGN_FLAG_LONG
) != (Result
& SIGN_FLAG_LONG
));
3459 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3460 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3461 State
->Flags
.Sf
= (Result
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
3462 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3464 /* Check if this is not a CMP */
3465 if (!(Opcode
& 0x10))
3467 /* Write back the result */
3468 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Result
;
3473 USHORT FirstValue
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
3474 USHORT SecondValue
, Result
;
3476 if (!Soft386FetchWord(State
, &SecondValue
))
3478 /* Exception occurred */
3482 /* Calculate the result */
3483 Result
= FirstValue
- SecondValue
;
3485 /* Update the flags */
3486 State
->Flags
.Cf
= FirstValue
< SecondValue
;
3487 State
->Flags
.Of
= ((FirstValue
& SIGN_FLAG_WORD
) != (SecondValue
& SIGN_FLAG_WORD
))
3488 && ((FirstValue
& SIGN_FLAG_WORD
) != (Result
& SIGN_FLAG_WORD
));
3489 State
->Flags
.Af
= (FirstValue
& 0x0F) < (SecondValue
& 0x0F);
3490 State
->Flags
.Zf
= (Result
== 0) ? TRUE
: FALSE
;
3491 State
->Flags
.Sf
= (Result
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
3492 State
->Flags
.Pf
= Soft386CalculateParity(Result
);
3494 /* Write back the result */
3495 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Result
;
3501 SOFT386_OPCODE_HANDLER(Soft386OpcodeDas
)
3503 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3504 BOOLEAN Carry
= State
->Flags
.Cf
;
3506 /* Clear the carry flag */
3507 State
->Flags
.Cf
= FALSE
;
3509 /* Check if the first BCD digit is invalid or there was a borrow */
3510 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3513 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
-= 0x06;
3514 if (State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
> 0xFB)
3516 /* A borrow occurred */
3517 State
->Flags
.Cf
= TRUE
;
3520 /* Set the adjust flag */
3521 State
->Flags
.Af
= TRUE
;
3524 /* Check if the second BCD digit is invalid or there was a borrow */
3525 if ((Value
> 0x99) || Carry
)
3528 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
-= 0x60;
3530 /* There was a borrow */
3531 State
->Flags
.Cf
= TRUE
;
3537 SOFT386_OPCODE_HANDLER(Soft386OpcodeAaa
)
3539 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3542 * Check if the value in AL is not a valid BCD digit,
3543 * or there was a carry from the lowest 4 bits of AL
3545 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3548 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
+= 0x06;
3549 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
++;
3552 State
->Flags
.Cf
= State
->Flags
.Af
= TRUE
;
3556 /* Clear CF and AF */
3557 State
->Flags
.Cf
= State
->Flags
.Af
= FALSE
;
3560 /* Keep only the lowest 4 bits of AL */
3561 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
&= 0x0F;
3566 SOFT386_OPCODE_HANDLER(Soft386OpcodeAas
)
3568 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
3571 * Check if the value in AL is not a valid BCD digit,
3572 * or there was a borrow from the lowest 4 bits of AL
3574 if (((Value
& 0x0F) > 9) || State
->Flags
.Af
)
3577 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
-= 0x06;
3578 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
--;
3581 State
->Flags
.Cf
= State
->Flags
.Af
= TRUE
;
3585 /* Clear CF and AF */
3586 State
->Flags
.Cf
= State
->Flags
.Af
= FALSE
;
3589 /* Keep only the lowest 4 bits of AL */
3590 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
&= 0x0F;
3595 SOFT386_OPCODE_HANDLER(Soft386OpcodePushAll
)
3598 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3599 SOFT386_REG SavedEsp
= State
->GeneralRegs
[SOFT386_REG_ESP
];
3601 /* Make sure this is the right instruction */
3602 ASSERT(Opcode
== 0x60);
3604 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
3606 /* The OPSIZE prefix toggles the size */
3611 /* Invalid prefix */
3612 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3616 /* Push all the registers in order */
3617 for (i
= 0; i
< SOFT386_NUM_GEN_REGS
; i
++)
3619 if (i
== SOFT386_REG_ESP
)
3621 /* Use the saved ESP instead */
3622 if (!Soft386StackPush(State
, Size
? SavedEsp
.Long
: SavedEsp
.LowWord
))
3624 /* Exception occurred */
3630 /* Push the register */
3631 if (!Soft386StackPush(State
, Size
? State
->GeneralRegs
[i
].Long
3632 : State
->GeneralRegs
[i
].LowWord
))
3634 /* Exception occurred */
3643 SOFT386_OPCODE_HANDLER(Soft386OpcodePopAll
)
3646 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3649 /* Make sure this is the right instruction */
3650 ASSERT(Opcode
== 0x61);
3652 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
3654 /* The OPSIZE prefix toggles the size */
3659 /* Invalid prefix */
3660 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3664 /* Pop all the registers in reverse order */
3665 for (i
= SOFT386_NUM_GEN_REGS
- 1; i
>= 0; i
--)
3668 if (!Soft386StackPop(State
, &Value
))
3670 /* Exception occurred */
3674 /* Don't modify ESP */
3675 if (i
!= SOFT386_REG_ESP
)
3677 if (Size
) State
->GeneralRegs
[i
].Long
= Value
;
3678 else State
->GeneralRegs
[i
].LowWord
= LOWORD(Value
);
3685 SOFT386_OPCODE_HANDLER(Soft386OpcodeBound
)
3687 // TODO: NOT IMPLEMENTED
3693 SOFT386_OPCODE_HANDLER(Soft386OpcodeArpl
)
3695 USHORT FirstValue
, SecondValue
;
3696 SOFT386_MOD_REG_RM ModRegRm
;
3697 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3699 if (!(State
->ControlRegisters
[SOFT386_REG_CR0
] & SOFT386_CR0_PE
)
3701 || (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
))
3703 /* Cannot be used in real mode or with a LOCK prefix */
3704 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3708 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3710 /* The ADSIZE prefix toggles the size */
3711 AddressSize
= !AddressSize
;
3714 /* Get the operands */
3715 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3717 /* Exception occurred */
3721 /* Read the operands */
3722 if (!Soft386ReadModrmWordOperands(State
,
3727 /* Exception occurred */
3731 /* Check if the RPL needs adjusting */
3732 if ((SecondValue
& 3) < (FirstValue
& 3))
3734 /* Adjust the RPL */
3736 SecondValue
|= FirstValue
& 3;
3739 State
->Flags
.Zf
= TRUE
;
3741 /* Write back the result */
3742 return Soft386WriteModrmWordOperands(State
, &ModRegRm
, FALSE
, SecondValue
);
3747 State
->Flags
.Zf
= FALSE
;
3752 SOFT386_OPCODE_HANDLER(Soft386OpcodePushImm
)
3754 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3756 /* Make sure this is the right instruction */
3757 ASSERT(Opcode
== 0x68);
3759 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
3761 /* The OPSIZE prefix toggles the size */
3766 /* Invalid prefix */
3767 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3775 if (!Soft386FetchDword(State
, &Data
))
3777 /* Exception occurred */
3781 /* Call the internal API */
3782 return Soft386StackPush(State
, Data
);
3788 if (!Soft386FetchWord(State
, &Data
))
3790 /* Exception occurred */
3794 /* Call the internal API */
3795 return Soft386StackPush(State
, Data
);
3799 SOFT386_OPCODE_HANDLER(Soft386OpcodeImulModrmImm
)
3801 BOOLEAN OperandSize
, AddressSize
;
3802 SOFT386_MOD_REG_RM ModRegRm
;
3806 /* Make sure this is the right instruction */
3807 ASSERT((Opcode
& 0xFD) == 0x69);
3809 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3811 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3813 /* The ADSIZE prefix toggles the address size */
3814 AddressSize
= !AddressSize
;
3817 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
3819 /* The OPSIZE prefix toggles the operand size */
3820 OperandSize
= !OperandSize
;
3823 /* Fetch the parameters */
3824 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3826 /* Exception occurred */
3834 /* Fetch the immediate operand */
3835 if (!Soft386FetchByte(State
, (PUCHAR
)&Byte
))
3837 /* Exception occurred */
3841 Multiplier
= (LONG
)Byte
;
3849 /* Fetch the immediate operand */
3850 if (!Soft386FetchDword(State
, (PULONG
)&Dword
))
3852 /* Exception occurred */
3862 /* Fetch the immediate operand */
3863 if (!Soft386FetchWord(State
, (PUSHORT
)&Word
))
3865 /* Exception occurred */
3869 Multiplier
= (LONG
)Word
;
3875 LONG RegValue
, Multiplicand
;
3877 /* Read the operands */
3878 if (!Soft386ReadModrmDwordOperands(State
,
3881 (PULONG
)&Multiplicand
))
3883 /* Exception occurred */
3888 Product
= (LONGLONG
)Multiplicand
* (LONGLONG
)Multiplier
;
3892 SHORT RegValue
, Multiplicand
;
3894 /* Read the operands */
3895 if (!Soft386ReadModrmWordOperands(State
,
3898 (PUSHORT
)&Multiplicand
))
3900 /* Exception occurred */
3905 Product
= (LONGLONG
)Multiplicand
* (LONGLONG
)Multiplier
;
3908 /* Check for carry/overflow */
3909 if ((Product
< LONG_MIN
) || (Product
> LONG_MAX
))
3911 State
->Flags
.Cf
= State
->Flags
.Of
= TRUE
;
3913 else State
->Flags
.Cf
= State
->Flags
.Of
= FALSE
;
3915 /* Write-back the result */
3916 return Soft386WriteModrmDwordOperands(State
,
3919 (ULONG
)((LONG
)Product
));
3922 SOFT386_OPCODE_HANDLER(Soft386OpcodePushByteImm
)
3926 /* Make sure this is the right instruction */
3927 ASSERT(Opcode
== 0x6A);
3929 if (!Soft386FetchByte(State
, &Data
))
3931 /* Exception occurred */
3935 /* Call the internal API */
3936 return Soft386StackPush(State
, Data
);
3939 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovByteModrm
)
3941 UCHAR FirstValue
, SecondValue
, Result
;
3942 SOFT386_MOD_REG_RM ModRegRm
;
3943 BOOLEAN AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
3945 /* Make sure this is the right instruction */
3946 ASSERT((Opcode
& 0xFD) == 0x88);
3948 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
3950 /* The ADSIZE prefix toggles the size */
3951 AddressSize
= !AddressSize
;
3953 else if (State
->PrefixFlags
3954 & ~(SOFT386_PREFIX_ADSIZE
3955 | SOFT386_PREFIX_SEG
3956 | SOFT386_PREFIX_LOCK
))
3958 /* Invalid prefix */
3959 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
3963 /* Get the operands */
3964 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
3966 /* Exception occurred */
3970 if (!Soft386ReadModrmByteOperands(State
,
3975 /* Exception occurred */
3979 if (Opcode
& SOFT386_OPCODE_WRITE_REG
) Result
= SecondValue
;
3980 else Result
= FirstValue
;
3982 /* Write back the result */
3983 return Soft386WriteModrmByteOperands(State
,
3985 Opcode
& SOFT386_OPCODE_WRITE_REG
,
3990 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovModrm
)
3992 SOFT386_MOD_REG_RM ModRegRm
;
3993 BOOLEAN OperandSize
, AddressSize
;
3995 /* Make sure this is the right instruction */
3996 ASSERT((Opcode
& 0xFD) == 0x89);
3998 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4000 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
4002 /* The ADSIZE prefix toggles the address size */
4003 AddressSize
= !AddressSize
;
4006 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
4008 /* The OPSIZE prefix toggles the operand size */
4009 OperandSize
= !OperandSize
;
4012 if (State
->PrefixFlags
4013 & ~(SOFT386_PREFIX_ADSIZE
4014 | SOFT386_PREFIX_OPSIZE
4015 | SOFT386_PREFIX_SEG
4016 | SOFT386_PREFIX_LOCK
))
4018 /* Invalid prefix */
4019 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4023 /* Get the operands */
4024 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
4026 /* Exception occurred */
4030 /* Check the operand size */
4033 ULONG FirstValue
, SecondValue
, Result
;
4035 if (!Soft386ReadModrmDwordOperands(State
,
4040 /* Exception occurred */
4044 if (Opcode
& SOFT386_OPCODE_WRITE_REG
) Result
= SecondValue
;
4045 else Result
= FirstValue
;
4047 /* Write back the result */
4048 return Soft386WriteModrmDwordOperands(State
,
4050 Opcode
& SOFT386_OPCODE_WRITE_REG
,
4055 USHORT FirstValue
, SecondValue
, Result
;
4057 if (!Soft386ReadModrmWordOperands(State
,
4062 /* Exception occurred */
4066 if (Opcode
& SOFT386_OPCODE_WRITE_REG
) Result
= SecondValue
;
4067 else Result
= FirstValue
;
4069 /* Write back the result */
4070 return Soft386WriteModrmWordOperands(State
,
4072 Opcode
& SOFT386_OPCODE_WRITE_REG
,
4077 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovStoreSeg
)
4079 // TODO: NOT IMPLEMENTED
4085 SOFT386_OPCODE_HANDLER(Soft386OpcodeLea
)
4087 SOFT386_MOD_REG_RM ModRegRm
;
4088 BOOLEAN OperandSize
, AddressSize
;
4090 /* Make sure this is the right instruction */
4091 ASSERT(Opcode
== 0x8D);
4093 OperandSize
= AddressSize
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4095 if (State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
)
4097 /* The ADSIZE prefix toggles the address size */
4098 AddressSize
= !AddressSize
;
4101 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
4103 /* The OPSIZE prefix toggles the operand size */
4104 OperandSize
= !OperandSize
;
4107 /* Get the operands */
4108 if (!Soft386ParseModRegRm(State
, AddressSize
, &ModRegRm
))
4110 /* Exception occurred */
4114 /* The second operand must be memory */
4115 if (!ModRegRm
.Memory
)
4118 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4122 /* Write the address to the register */
4125 return Soft386WriteModrmDwordOperands(State
,
4128 ModRegRm
.MemoryAddress
);
4132 return Soft386WriteModrmWordOperands(State
,
4135 ModRegRm
.MemoryAddress
);
4140 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovLoadSeg
)
4142 // TODO: NOT IMPLEMENTED
4148 SOFT386_OPCODE_HANDLER(Soft386OpcodeCwde
)
4150 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4152 /* Make sure this is the right instruction */
4153 ASSERT(Opcode
== 0x98);
4155 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
4157 /* The OPSIZE prefix toggles the size */
4160 else if (State
->PrefixFlags
!= 0)
4162 /* Invalid prefix */
4163 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4169 /* Sign extend AX to EAX */
4170 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= MAKELONG
4172 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
,
4173 (State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
& SIGN_FLAG_WORD
)
4179 /* Sign extend AL to AX */
4180 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
=
4181 (State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
& SIGN_FLAG_BYTE
)
4188 SOFT386_OPCODE_HANDLER(Soft386OpcodeCdq
)
4190 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4192 /* Make sure this is the right instruction */
4193 ASSERT(Opcode
== 0x99);
4195 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
4197 /* The OPSIZE prefix toggles the size */
4200 else if (State
->PrefixFlags
!= 0)
4202 /* Invalid prefix */
4203 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4209 /* Sign extend EAX to EDX:EAX */
4210 State
->GeneralRegs
[SOFT386_REG_EDX
].Long
=
4211 (State
->GeneralRegs
[SOFT386_REG_EAX
].Long
& SIGN_FLAG_LONG
)
4212 ? 0xFFFFFFFF : 0x00000000;
4216 /* Sign extend AX to DX:AX */
4217 State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
=
4218 (State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
& SIGN_FLAG_WORD
)
4225 SOFT386_OPCODE_HANDLER(Soft386OpcodeCallAbs
)
4227 // TODO: NOT IMPLEMENTED
4233 SOFT386_OPCODE_HANDLER(Soft386OpcodeWait
)
4235 // TODO: NOT IMPLEMENTED
4241 SOFT386_OPCODE_HANDLER(Soft386OpcodePushFlags
)
4243 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4245 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4247 /* Invalid prefix */
4248 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4252 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
4254 /* This OPSIZE prefix toggles the size */
4258 /* Check for VM86 mode when IOPL is not 3 */
4259 if (State
->Flags
.Vm
&& (State
->Flags
.Iopl
!= 3))
4261 /* Call the VM86 monitor */
4262 Soft386ExceptionWithErrorCode(State
, SOFT386_EXCEPTION_GP
, 0);
4266 /* Push the flags */
4267 if (Size
) return Soft386StackPush(State
, State
->Flags
.Long
);
4268 else return Soft386StackPush(State
, LOWORD(State
->Flags
.Long
));
4271 SOFT386_OPCODE_HANDLER(Soft386OpcodePopFlags
)
4273 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4274 INT Cpl
= Soft386GetCurrentPrivLevel(State
);
4277 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4279 /* Invalid prefix */
4280 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4284 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
4286 /* This OPSIZE prefix toggles the size */
4290 /* Pop the new flags */
4291 if (!Soft386StackPop(State
, &NewFlags
))
4293 /* Exception occurred */
4297 if (!State
->Flags
.Vm
)
4299 /* Check the current privilege level */
4307 /* Memorize the old state of RF */
4308 BOOLEAN OldRf
= State
->Flags
.Rf
;
4310 State
->Flags
.Long
= NewFlags
;
4312 /* Restore VM and RF */
4313 State
->Flags
.Vm
= FALSE
;
4314 State
->Flags
.Rf
= OldRf
;
4316 /* Clear VIF and VIP */
4317 State
->Flags
.Vif
= State
->Flags
.Vip
= FALSE
;
4319 else State
->Flags
.LowWord
= LOWORD(NewFlags
);
4321 /* Restore the reserved bits */
4322 State
->Flags
.AlwaysSet
= TRUE
;
4323 State
->Flags
.Reserved0
= FALSE
;
4324 State
->Flags
.Reserved1
= FALSE
;
4330 /* Memorize the old state of IF and IOPL */
4331 BOOLEAN OldIf
= State
->Flags
.If
;
4332 UINT OldIopl
= State
->Flags
.Iopl
;
4337 /* Memorize the old state of RF */
4338 BOOLEAN OldRf
= State
->Flags
.Rf
;
4340 State
->Flags
.Long
= NewFlags
;
4342 /* Restore VM and RF */
4343 State
->Flags
.Vm
= FALSE
;
4344 State
->Flags
.Rf
= OldRf
;
4346 /* Clear VIF and VIP */
4347 State
->Flags
.Vif
= State
->Flags
.Vip
= FALSE
;
4349 else State
->Flags
.LowWord
= LOWORD(NewFlags
);
4351 /* Restore the reserved bits and IOPL */
4352 State
->Flags
.AlwaysSet
= TRUE
;
4353 State
->Flags
.Reserved0
= FALSE
;
4354 State
->Flags
.Reserved1
= FALSE
;
4355 State
->Flags
.Iopl
= OldIopl
;
4357 /* Check if the user doesn't have the privilege to change IF */
4358 if (Cpl
> State
->Flags
.Iopl
)
4361 State
->Flags
.If
= OldIf
;
4367 /* Check the IOPL */
4368 if (State
->Flags
.Iopl
== 3)
4372 /* Memorize the old state of RF, VIF and VIP */
4373 BOOLEAN OldRf
= State
->Flags
.Rf
;
4374 BOOLEAN OldVif
= State
->Flags
.Vif
;
4375 BOOLEAN OldVip
= State
->Flags
.Vip
;
4377 State
->Flags
.Long
= NewFlags
;
4379 /* Restore VM, RF, VIF and VIP */
4380 State
->Flags
.Vm
= TRUE
;
4381 State
->Flags
.Rf
= OldRf
;
4382 State
->Flags
.Vif
= OldVif
;
4383 State
->Flags
.Vip
= OldVip
;
4385 else State
->Flags
.LowWord
= LOWORD(NewFlags
);
4387 /* Restore the reserved bits and IOPL */
4388 State
->Flags
.AlwaysSet
= TRUE
;
4389 State
->Flags
.Reserved0
= FALSE
;
4390 State
->Flags
.Reserved1
= FALSE
;
4391 State
->Flags
.Iopl
= 3;
4395 /* Call the VM86 monitor */
4396 Soft386ExceptionWithErrorCode(State
, SOFT386_EXCEPTION_GP
, 0);
4404 SOFT386_OPCODE_HANDLER(Soft386OpcodeSahf
)
4406 /* Make sure this is the right instruction */
4407 ASSERT(Opcode
== 0x9E);
4409 /* Set the low-order byte of FLAGS to AH */
4410 State
->Flags
.Long
&= 0xFFFFFF00;
4411 State
->Flags
.Long
|= State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
;
4413 /* Restore the reserved bits of FLAGS */
4414 State
->Flags
.AlwaysSet
= TRUE
;
4415 State
->Flags
.Reserved0
= State
->Flags
.Reserved1
= FALSE
;
4420 SOFT386_OPCODE_HANDLER(Soft386OpcodeLahf
)
4422 /* Make sure this is the right instruction */
4423 ASSERT(Opcode
== 0x9F);
4425 /* Set AH to the low-order byte of FLAGS */
4426 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
= LOBYTE(State
->Flags
.Long
);
4431 SOFT386_OPCODE_HANDLER(Soft386OpcodeRet
)
4433 ULONG ReturnAddress
;
4434 USHORT BytesToPop
= 0;
4435 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4437 /* Make sure this is the right instruction */
4438 ASSERT((Opcode
& 0xFE) == 0xC2);
4440 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4442 /* Invalid prefix */
4443 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4447 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
4449 /* The OPSIZE prefix toggles the size */
4455 /* Fetch the number of bytes to pop after the return */
4456 if (!Soft386FetchWord(State
, &BytesToPop
)) return FALSE
;
4459 /* Pop the return address */
4460 if (!Soft386StackPop(State
, &ReturnAddress
)) return FALSE
;
4462 /* Return to the calling procedure, and if necessary, pop the parameters */
4465 State
->InstPtr
.Long
= ReturnAddress
;
4466 State
->GeneralRegs
[SOFT386_REG_ESP
].Long
+= BytesToPop
;
4470 State
->InstPtr
.LowWord
= LOWORD(ReturnAddress
);
4471 State
->GeneralRegs
[SOFT386_REG_ESP
].LowWord
+= BytesToPop
;
4477 SOFT386_OPCODE_HANDLER(Soft386OpcodeLes
)
4479 // TODO: NOT IMPLEMENTED
4485 SOFT386_OPCODE_HANDLER(Soft386OpcodeLds
)
4487 // TODO: NOT IMPLEMENTED
4493 SOFT386_OPCODE_HANDLER(Soft386OpcodeEnter
)
4496 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4499 SOFT386_REG FramePointer
;
4501 /* Make sure this is the right instruction */
4502 ASSERT(Opcode
== 0xC8);
4504 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4506 /* Invalid prefix */
4507 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4511 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
4513 /* The OPSIZE prefix toggles the size */
4517 if (!Soft386FetchWord(State
, &FrameSize
))
4519 /* Exception occurred */
4523 if (!Soft386FetchByte(State
, &NestingLevel
))
4525 /* Exception occurred */
4530 if (!Soft386StackPush(State
, State
->GeneralRegs
[SOFT386_REG_EBP
].Long
))
4532 /* Exception occurred */
4537 FramePointer
= State
->GeneralRegs
[SOFT386_REG_ESP
];
4539 /* Set up the nested procedure stacks */
4540 for (i
= 1; i
< NestingLevel
; i
++)
4544 State
->GeneralRegs
[SOFT386_REG_EBP
].Long
-= 4;
4545 Soft386StackPush(State
, State
->GeneralRegs
[SOFT386_REG_EBP
].Long
);
4549 State
->GeneralRegs
[SOFT386_REG_EBP
].LowWord
-= 2;
4550 Soft386StackPush(State
, State
->GeneralRegs
[SOFT386_REG_EBP
].LowWord
);
4554 if (NestingLevel
> 0) Soft386StackPush(State
, FramePointer
.Long
);
4556 /* Set EBP to the frame pointer */
4557 State
->GeneralRegs
[SOFT386_REG_EBP
] = FramePointer
;
4559 /* Reserve space for the frame */
4560 if (Size
) State
->GeneralRegs
[SOFT386_REG_ESP
].Long
-= (ULONG
)FrameSize
;
4561 else State
->GeneralRegs
[SOFT386_REG_ESP
].LowWord
-= FrameSize
;
4566 SOFT386_OPCODE_HANDLER(Soft386OpcodeLeave
)
4568 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4570 /* Make sure this is the right instruction */
4571 ASSERT(Opcode
== 0xC9);
4573 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4575 /* Invalid prefix */
4576 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4580 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
4582 /* The OPSIZE prefix toggles the size */
4588 /* Set the stack pointer (ESP) to the base pointer (EBP) */
4589 State
->GeneralRegs
[SOFT386_REG_ESP
].Long
= State
->GeneralRegs
[SOFT386_REG_EBP
].Long
;
4591 /* Pop the saved base pointer from the stack */
4592 return Soft386StackPop(State
, &State
->GeneralRegs
[SOFT386_REG_EBP
].Long
);
4598 /* Set the stack pointer (SP) to the base pointer (BP) */
4599 State
->GeneralRegs
[SOFT386_REG_ESP
].LowWord
= State
->GeneralRegs
[SOFT386_REG_EBP
].LowWord
;
4601 /* Pop the saved base pointer from the stack */
4602 if (Soft386StackPop(State
, &Value
))
4604 State
->GeneralRegs
[SOFT386_REG_EBP
].LowWord
= LOWORD(Value
);
4611 SOFT386_OPCODE_HANDLER(Soft386OpcodeRetFarImm
)
4613 // TODO: NOT IMPLEMENTED
4619 SOFT386_OPCODE_HANDLER(Soft386OpcodeRetFar
)
4621 // TODO: NOT IMPLEMENTED
4627 SOFT386_OPCODE_HANDLER(Soft386OpcodeInt
)
4630 SOFT386_IDT_ENTRY IdtEntry
;
4636 /* This is the INT3 instruction */
4643 /* Fetch the interrupt number */
4644 if (!Soft386FetchByte(State
, &IntNum
))
4646 /* Exception occurred */
4655 /* Don't do anything if OF is cleared */
4656 if (!State
->Flags
.Of
) return TRUE
;
4659 IntNum
= SOFT386_EXCEPTION_OF
;
4666 /* Should not happen */
4671 /* Get the interrupt vector */
4672 if (!Soft386GetIntVector(State
, IntNum
, &IdtEntry
))
4674 /* Exception occurred */
4678 /* Perform the interrupt */
4679 if (!Soft386InterruptInternal(State
,
4681 MAKELONG(IdtEntry
.Offset
, IdtEntry
.OffsetHigh
),
4684 /* Exception occurred */
4691 SOFT386_OPCODE_HANDLER(Soft386OpcodeIret
)
4694 ULONG InstPtr
, CodeSel
, StackPtr
, StackSel
;
4695 SOFT386_FLAGS_REG NewFlags
;
4696 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4698 /* Make sure this is the right instruction */
4699 ASSERT(Opcode
== 0xCF);
4701 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4703 /* Invalid prefix */
4704 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4708 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
4710 /* The OPSIZE prefix toggles the size */
4715 if (!Soft386StackPop(State
, &InstPtr
))
4717 /* Exception occurred */
4722 if (!Soft386StackPop(State
, &CodeSel
))
4724 /* Exception occurred */
4729 if (!Soft386StackPop(State
, &NewFlags
.Long
))
4731 /* Exception occurred */
4735 /* Check for protected mode */
4736 if (State
->ControlRegisters
[SOFT386_REG_CR0
] & SOFT386_CR0_PE
)
4738 INT Cpl
= Soft386GetCurrentPrivLevel(State
);
4740 if (State
->Flags
.Vm
)
4742 /* Return from VM86 mode */
4744 /* Check the IOPL */
4745 if (State
->Flags
.Iopl
== 3)
4748 State
->InstPtr
.Long
= LOWORD(InstPtr
);
4751 if (!Soft386LoadSegment(State
, SOFT386_REG_CS
, CodeSel
))
4753 /* Exception occurred */
4757 /* Set the new flags */
4758 if (Size
) State
->Flags
.Long
= NewFlags
.Long
& REAL_MODE_FLAGS_MASK
;
4759 else State
->Flags
.LowWord
= NewFlags
.LowWord
& REAL_MODE_FLAGS_MASK
;
4760 State
->Flags
.AlwaysSet
= State
->Flags
.Vm
= TRUE
;
4761 State
->Flags
.Iopl
= 3;
4765 /* Call the VM86 monitor */
4766 Soft386ExceptionWithErrorCode(State
, SOFT386_EXCEPTION_GP
, 0);
4773 if (State
->Flags
.Nt
)
4775 /* Nested task return */
4783 /* Return to VM86 mode */
4784 ULONG Es
, Ds
, Fs
, Gs
;
4786 /* Pop ESP, SS, ES, FS, GS */
4787 if (!Soft386StackPop(State
, &StackPtr
)) return FALSE
;
4788 if (!Soft386StackPop(State
, &StackSel
)) return FALSE
;
4789 if (!Soft386StackPop(State
, &Es
)) return FALSE
;
4790 if (!Soft386StackPop(State
, &Ds
)) return FALSE
;
4791 if (!Soft386StackPop(State
, &Fs
)) return FALSE
;
4792 if (!Soft386StackPop(State
, &Gs
)) return FALSE
;
4794 /* Set the new IP */
4795 State
->InstPtr
.Long
= LOWORD(InstPtr
);
4797 /* Set the new flags */
4798 if (Size
) State
->Flags
.Long
= NewFlags
.Long
& REAL_MODE_FLAGS_MASK
;
4799 else State
->Flags
.LowWord
= NewFlags
.LowWord
& REAL_MODE_FLAGS_MASK
;
4800 State
->Flags
.AlwaysSet
= State
->Flags
.Vm
= TRUE
;
4802 /* Load the new segments */
4803 if (!Soft386LoadSegment(State
, SOFT386_REG_CS
, CodeSel
)) return FALSE
;
4804 if (!Soft386LoadSegment(State
, SOFT386_REG_SS
, StackSel
)) return FALSE
;
4805 if (!Soft386LoadSegment(State
, SOFT386_REG_ES
, Es
)) return FALSE
;
4806 if (!Soft386LoadSegment(State
, SOFT386_REG_DS
, Ds
)) return FALSE
;
4807 if (!Soft386LoadSegment(State
, SOFT386_REG_FS
, Fs
)) return FALSE
;
4808 if (!Soft386LoadSegment(State
, SOFT386_REG_GS
, Gs
)) return FALSE
;
4813 /* Load the new CS */
4814 if (!Soft386LoadSegment(State
, SOFT386_REG_CS
, CodeSel
))
4816 /* Exception occurred */
4821 if (Size
) State
->InstPtr
.Long
= InstPtr
;
4822 else State
->InstPtr
.LowWord
= LOWORD(InstPtr
);
4824 if (GET_SEGMENT_RPL(CodeSel
) > Cpl
)
4827 if (!Soft386StackPop(State
, &StackPtr
))
4834 if (!Soft386StackPop(State
, &StackSel
))
4841 if (!Soft386LoadSegment(State
, SOFT386_REG_SS
, StackSel
))
4848 if (Size
) State
->GeneralRegs
[SOFT386_REG_ESP
].Long
= StackPtr
;
4849 else State
->GeneralRegs
[SOFT386_REG_ESP
].LowWord
= LOWORD(StackPtr
);
4852 /* Set the new flags */
4853 if (Size
) State
->Flags
.Long
= NewFlags
.Long
& PROT_MODE_FLAGS_MASK
;
4854 else State
->Flags
.LowWord
= NewFlags
.LowWord
& PROT_MODE_FLAGS_MASK
;
4855 State
->Flags
.AlwaysSet
= TRUE
;
4857 /* Set additional flags */
4858 if (Cpl
<= State
->Flags
.Iopl
) State
->Flags
.If
= NewFlags
.If
;
4859 if (Cpl
== 0) State
->Flags
.Iopl
= NewFlags
.Iopl
;
4861 if (GET_SEGMENT_RPL(CodeSel
) > Cpl
)
4863 /* Update the CPL */
4864 Cpl
= Soft386GetCurrentPrivLevel(State
);
4866 /* Check segment security */
4867 for (i
= 0; i
<= SOFT386_NUM_SEG_REGS
; i
++)
4869 /* Don't check CS or SS */
4870 if ((i
== SOFT386_REG_CS
) || (i
== SOFT386_REG_SS
)) continue;
4872 if ((Cpl
> State
->SegmentRegs
[i
].Dpl
)
4873 && (!State
->SegmentRegs
[i
].Executable
4874 || !State
->SegmentRegs
[i
].DirConf
))
4876 /* Load the NULL descriptor in the segment */
4877 if (!Soft386LoadSegment(State
, i
, 0)) return FALSE
;
4884 if (Size
&& (InstPtr
& 0xFFFF0000))
4887 Soft386ExceptionWithErrorCode(State
, SOFT386_EXCEPTION_GP
, 0);
4892 State
->InstPtr
.Long
= InstPtr
;
4895 if (!Soft386LoadSegment(State
, SOFT386_REG_CS
, CodeSel
))
4897 /* Exception occurred */
4901 /* Set the new flags */
4902 if (Size
) State
->Flags
.Long
= NewFlags
.Long
& REAL_MODE_FLAGS_MASK
;
4903 else State
->Flags
.LowWord
= NewFlags
.LowWord
& REAL_MODE_FLAGS_MASK
;
4904 State
->Flags
.AlwaysSet
= TRUE
;
4910 SOFT386_OPCODE_HANDLER(Soft386OpcodeAam
)
4913 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
4915 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4917 /* Invalid prefix */
4918 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4922 /* Fetch the base */
4923 if (!Soft386FetchByte(State
, &Base
))
4925 /* Exception occurred */
4929 /* Check if the base is zero */
4933 Soft386Exception(State
, SOFT386_EXCEPTION_DE
);
4938 State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
= Value
/ Base
;
4939 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Value
%= Base
;
4942 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
4943 State
->Flags
.Sf
= (Value
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
4944 State
->Flags
.Pf
= Soft386CalculateParity(Value
);
4949 SOFT386_OPCODE_HANDLER(Soft386OpcodeAad
)
4952 UCHAR Value
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
4954 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4956 /* Invalid prefix */
4957 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
4961 /* Fetch the base */
4962 if (!Soft386FetchByte(State
, &Base
))
4964 /* Exception occurred */
4969 Value
+= State
->GeneralRegs
[SOFT386_REG_EAX
].HighByte
* Base
;
4970 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Value
;
4973 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
4974 State
->Flags
.Sf
= (Value
& SIGN_FLAG_BYTE
) ? TRUE
: FALSE
;
4975 State
->Flags
.Pf
= Soft386CalculateParity(Value
);
4980 SOFT386_OPCODE_HANDLER(Soft386OpcodeXlat
)
4982 // TODO: NOT IMPLEMENTED
4988 SOFT386_OPCODE_HANDLER(Soft386OpcodeLoop
)
4991 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
4994 /* Make sure this is the right instruction */
4995 ASSERT((Opcode
>= 0xE0) && (Opcode
<= 0xE2));
4997 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
4999 /* Invalid prefix */
5000 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
5004 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
5006 /* The OPSIZE prefix toggles the size */
5010 if (Size
) Condition
= ((--State
->GeneralRegs
[SOFT386_REG_ECX
].Long
) == 0);
5011 else Condition
= ((--State
->GeneralRegs
[SOFT386_REG_ECX
].LowWord
) == 0);
5015 /* Additional rule for LOOPNZ */
5016 if (State
->Flags
.Zf
) Condition
= FALSE
;
5021 /* Additional rule for LOOPZ */
5022 if (!State
->Flags
.Zf
) Condition
= FALSE
;
5025 /* Fetch the offset */
5026 if (!Soft386FetchByte(State
, (PUCHAR
)&Offset
))
5028 /* An exception occurred */
5034 /* Move the instruction pointer */
5035 State
->InstPtr
.Long
+= Offset
;
5041 SOFT386_OPCODE_HANDLER(Soft386OpcodeJecxz
)
5044 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
5047 /* Make sure this is the right instruction */
5048 ASSERT(Opcode
== 0xE3);
5050 if (State
->PrefixFlags
& SOFT386_PREFIX_LOCK
)
5052 /* Invalid prefix */
5053 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
5057 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
5059 /* The OPSIZE prefix toggles the size */
5063 if (Size
) Condition
= (State
->GeneralRegs
[SOFT386_REG_ECX
].Long
== 0);
5064 else Condition
= (State
->GeneralRegs
[SOFT386_REG_ECX
].LowWord
== 0);
5066 /* Fetch the offset */
5067 if (!Soft386FetchByte(State
, (PUCHAR
)&Offset
))
5069 /* An exception occurred */
5075 /* Move the instruction pointer */
5076 State
->InstPtr
.Long
+= Offset
;
5082 SOFT386_OPCODE_HANDLER(Soft386OpcodeCall
)
5084 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
5086 /* Make sure this is the right instruction */
5087 ASSERT(Opcode
== 0xE8);
5089 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
5091 /* The OPSIZE prefix toggles the size */
5094 else if (State
->PrefixFlags
!= 0)
5096 /* Invalid prefix */
5097 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
5105 /* Fetch the offset */
5106 if (!Soft386FetchDword(State
, (PULONG
)&Offset
))
5108 /* An exception occurred */
5112 /* Push the current value of the instruction pointer */
5113 if (!Soft386StackPush(State
, State
->InstPtr
.Long
))
5115 /* Exception occurred */
5119 /* Move the instruction pointer */
5120 State
->InstPtr
.Long
+= Offset
;
5126 /* Fetch the offset */
5127 if (!Soft386FetchWord(State
, (PUSHORT
)&Offset
))
5129 /* An exception occurred */
5133 /* Push the current value of the instruction pointer */
5134 if (!Soft386StackPush(State
, State
->InstPtr
.Long
))
5136 /* Exception occurred */
5140 /* Move the instruction pointer */
5141 State
->InstPtr
.LowWord
+= Offset
;
5147 SOFT386_OPCODE_HANDLER(Soft386OpcodeJmp
)
5149 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
5151 /* Make sure this is the right instruction */
5152 ASSERT(Opcode
== 0xE9);
5154 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
5156 /* The OPSIZE prefix toggles the size */
5159 else if (State
->PrefixFlags
!= 0)
5161 /* Invalid prefix */
5162 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
5170 /* Fetch the offset */
5171 if (!Soft386FetchDword(State
, (PULONG
)&Offset
))
5173 /* An exception occurred */
5177 /* Move the instruction pointer */
5178 State
->InstPtr
.Long
+= Offset
;
5184 /* Fetch the offset */
5185 if (!Soft386FetchWord(State
, (PUSHORT
)&Offset
))
5187 /* An exception occurred */
5191 /* Move the instruction pointer */
5192 State
->InstPtr
.LowWord
+= Offset
;
5198 SOFT386_OPCODE_HANDLER(Soft386OpcodeJmpAbs
)
5200 // TODO: NOT IMPLEMENTED
5206 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovAlOffset
)
5208 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
5211 /* Make sure this is the right instruction */
5212 ASSERT(Opcode
== 0xA0);
5214 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
5216 /* The OPSIZE prefix toggles the size */
5222 if (!Soft386FetchDword(State
, &Offset
))
5224 /* Exception occurred */
5232 if (!Soft386FetchWord(State
, &WordOffset
))
5234 /* Exception occurred */
5238 Offset
= (ULONG
)WordOffset
;
5241 /* Read from memory */
5242 return Soft386ReadMemory(State
,
5243 (State
->PrefixFlags
& SOFT386_PREFIX_SEG
) ?
5244 State
->SegmentOverride
: SOFT386_REG_DS
,
5247 &State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
,
5251 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovEaxOffset
)
5253 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
5255 /* Make sure this is the right instruction */
5256 ASSERT(Opcode
== 0xA1);
5258 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
5260 /* The OPSIZE prefix toggles the size */
5268 if (!Soft386FetchDword(State
, &Offset
))
5270 /* Exception occurred */
5274 /* Read from memory */
5275 return Soft386ReadMemory(State
,
5276 (State
->PrefixFlags
& SOFT386_PREFIX_SEG
) ?
5277 State
->SegmentOverride
: SOFT386_REG_DS
,
5280 &State
->GeneralRegs
[SOFT386_REG_EAX
].Long
,
5287 if (!Soft386FetchWord(State
, &Offset
))
5289 /* Exception occurred */
5293 /* Read from memory */
5294 return Soft386ReadMemory(State
,
5295 (State
->PrefixFlags
& SOFT386_PREFIX_SEG
) ?
5296 State
->SegmentOverride
: SOFT386_REG_DS
,
5299 &State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
,
5304 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovOffsetAl
)
5306 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
5309 /* Make sure this is the right instruction */
5310 ASSERT(Opcode
== 0xA2);
5312 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
5314 /* The OPSIZE prefix toggles the size */
5320 if (!Soft386FetchDword(State
, &Offset
))
5322 /* Exception occurred */
5330 if (!Soft386FetchWord(State
, &WordOffset
))
5332 /* Exception occurred */
5336 Offset
= (ULONG
)WordOffset
;
5339 /* Write to memory */
5340 return Soft386WriteMemory(State
,
5341 (State
->PrefixFlags
& SOFT386_PREFIX_SEG
) ?
5342 State
->SegmentOverride
: SOFT386_REG_DS
,
5344 &State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
,
5348 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovOffsetEax
)
5350 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
5352 /* Make sure this is the right instruction */
5353 ASSERT(Opcode
== 0xA3);
5355 if (State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
)
5357 /* The OPSIZE prefix toggles the size */
5365 if (!Soft386FetchDword(State
, &Offset
))
5367 /* Exception occurred */
5371 /* Write to memory */
5372 return Soft386WriteMemory(State
,
5373 (State
->PrefixFlags
& SOFT386_PREFIX_SEG
) ?
5374 State
->SegmentOverride
: SOFT386_REG_DS
,
5376 &State
->GeneralRegs
[SOFT386_REG_EAX
].Long
,
5383 if (!Soft386FetchWord(State
, &Offset
))
5385 /* Exception occurred */
5389 /* Write to memory */
5390 return Soft386WriteMemory(State
,
5391 (State
->PrefixFlags
& SOFT386_PREFIX_SEG
) ?
5392 State
->SegmentOverride
: SOFT386_REG_DS
,
5394 &State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
,