2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: 386/486 CPU Emulation Library
5 * PURPOSE: Opcode handlers.
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
9 /* INCLUDES *******************************************************************/
11 // #define WIN32_NO_STATUS
12 // #define _INC_WINDOWS
22 /* PUBLIC VARIABLES ***********************************************************/
24 SOFT386_OPCODE_HANDLER_PROC
25 Soft386OpcodeHandlers
[SOFT386_NUM_OPCODE_HANDLERS
] =
27 NULL
, // TODO: OPCODE 0x00 NOT SUPPORTED
28 NULL
, // TODO: OPCODE 0x01 NOT SUPPORTED
29 NULL
, // TODO: OPCODE 0x02 NOT SUPPORTED
30 NULL
, // TODO: OPCODE 0x03 NOT SUPPORTED
31 NULL
, // TODO: OPCODE 0x04 NOT SUPPORTED
32 NULL
, // TODO: OPCODE 0x05 NOT SUPPORTED
33 NULL
, // TODO: OPCODE 0x06 NOT SUPPORTED
34 NULL
, // TODO: OPCODE 0x07 NOT SUPPORTED
35 NULL
, // TODO: OPCODE 0x08 NOT SUPPORTED
36 NULL
, // TODO: OPCODE 0x09 NOT SUPPORTED
37 NULL
, // TODO: OPCODE 0x0A NOT SUPPORTED
38 NULL
, // TODO: OPCODE 0x0B NOT SUPPORTED
39 NULL
, // TODO: OPCODE 0x0C NOT SUPPORTED
40 NULL
, // TODO: OPCODE 0x0D NOT SUPPORTED
41 NULL
, // TODO: OPCODE 0x0E NOT SUPPORTED
42 NULL
, // TODO: OPCODE 0x0F NOT SUPPORTED
43 NULL
, // TODO: OPCODE 0x10 NOT SUPPORTED
44 NULL
, // TODO: OPCODE 0x11 NOT SUPPORTED
45 NULL
, // TODO: OPCODE 0x12 NOT SUPPORTED
46 NULL
, // TODO: OPCODE 0x13 NOT SUPPORTED
47 NULL
, // TODO: OPCODE 0x14 NOT SUPPORTED
48 NULL
, // TODO: OPCODE 0x15 NOT SUPPORTED
49 NULL
, // TODO: OPCODE 0x16 NOT SUPPORTED
50 NULL
, // TODO: OPCODE 0x17 NOT SUPPORTED
51 NULL
, // TODO: OPCODE 0x18 NOT SUPPORTED
52 NULL
, // TODO: OPCODE 0x19 NOT SUPPORTED
53 NULL
, // TODO: OPCODE 0x1A NOT SUPPORTED
54 NULL
, // TODO: OPCODE 0x1B NOT SUPPORTED
55 NULL
, // TODO: OPCODE 0x1C NOT SUPPORTED
56 NULL
, // TODO: OPCODE 0x1D NOT SUPPORTED
57 NULL
, // TODO: OPCODE 0x1E NOT SUPPORTED
58 NULL
, // TODO: OPCODE 0x1F NOT SUPPORTED
59 NULL
, // TODO: OPCODE 0x20 NOT SUPPORTED
60 NULL
, // TODO: OPCODE 0x21 NOT SUPPORTED
61 NULL
, // TODO: OPCODE 0x22 NOT SUPPORTED
62 NULL
, // TODO: OPCODE 0x23 NOT SUPPORTED
63 NULL
, // TODO: OPCODE 0x24 NOT SUPPORTED
64 NULL
, // TODO: OPCODE 0x25 NOT SUPPORTED
66 NULL
, // TODO: OPCODE 0x27 NOT SUPPORTED
67 NULL
, // TODO: OPCODE 0x28 NOT SUPPORTED
68 NULL
, // TODO: OPCODE 0x29 NOT SUPPORTED
69 NULL
, // TODO: OPCODE 0x2A NOT SUPPORTED
70 NULL
, // TODO: OPCODE 0x2B NOT SUPPORTED
71 NULL
, // TODO: OPCODE 0x2C NOT SUPPORTED
72 NULL
, // TODO: OPCODE 0x2D NOT SUPPORTED
74 NULL
, // TODO: OPCODE 0x2F NOT SUPPORTED
75 NULL
, // TODO: OPCODE 0x30 NOT SUPPORTED
76 NULL
, // TODO: OPCODE 0x31 NOT SUPPORTED
77 NULL
, // TODO: OPCODE 0x32 NOT SUPPORTED
78 NULL
, // TODO: OPCODE 0x33 NOT SUPPORTED
79 NULL
, // TODO: OPCODE 0x34 NOT SUPPORTED
80 NULL
, // TODO: OPCODE 0x35 NOT SUPPORTED
82 NULL
, // TODO: OPCODE 0x37 NOT SUPPORTED
83 NULL
, // TODO: OPCODE 0x38 NOT SUPPORTED
84 NULL
, // TODO: OPCODE 0x39 NOT SUPPORTED
85 NULL
, // TODO: OPCODE 0x3A NOT SUPPORTED
86 NULL
, // TODO: OPCODE 0x3B NOT SUPPORTED
87 NULL
, // TODO: OPCODE 0x3C NOT SUPPORTED
88 NULL
, // TODO: OPCODE 0x3D NOT SUPPORTED
90 NULL
, // TODO: OPCODE 0x3F NOT SUPPORTED
91 Soft386OpcodeIncrement
,
92 Soft386OpcodeIncrement
,
93 Soft386OpcodeIncrement
,
94 Soft386OpcodeIncrement
,
95 Soft386OpcodeIncrement
,
96 Soft386OpcodeIncrement
,
97 Soft386OpcodeIncrement
,
98 Soft386OpcodeIncrement
,
99 Soft386OpcodeDecrement
,
100 Soft386OpcodeDecrement
,
101 Soft386OpcodeDecrement
,
102 Soft386OpcodeDecrement
,
103 Soft386OpcodeDecrement
,
104 Soft386OpcodeDecrement
,
105 Soft386OpcodeDecrement
,
106 Soft386OpcodeDecrement
,
107 Soft386OpcodePushReg
,
108 Soft386OpcodePushReg
,
109 Soft386OpcodePushReg
,
110 Soft386OpcodePushReg
,
111 Soft386OpcodePushReg
,
112 Soft386OpcodePushReg
,
113 Soft386OpcodePushReg
,
114 Soft386OpcodePushReg
,
123 NULL
, // TODO: OPCODE 0x60 NOT SUPPORTED
124 NULL
, // TODO: OPCODE 0x61 NOT SUPPORTED
125 NULL
, // TODO: OPCODE 0x62 NOT SUPPORTED
126 NULL
, // TODO: OPCODE 0x63 NOT SUPPORTED
131 NULL
, // TODO: OPCODE 0x68 NOT SUPPORTED
132 NULL
, // TODO: OPCODE 0x69 NOT SUPPORTED
133 NULL
, // TODO: OPCODE 0x6A NOT SUPPORTED
134 NULL
, // TODO: OPCODE 0x6B NOT SUPPORTED
135 NULL
, // TODO: OPCODE 0x6C NOT SUPPORTED
136 NULL
, // TODO: OPCODE 0x6D NOT SUPPORTED
137 NULL
, // TODO: OPCODE 0x6E NOT SUPPORTED
138 NULL
, // TODO: OPCODE 0x6F NOT SUPPORTED
139 Soft386OpcodeShortConditionalJmp
,
140 Soft386OpcodeShortConditionalJmp
,
141 Soft386OpcodeShortConditionalJmp
,
142 Soft386OpcodeShortConditionalJmp
,
143 Soft386OpcodeShortConditionalJmp
,
144 Soft386OpcodeShortConditionalJmp
,
145 Soft386OpcodeShortConditionalJmp
,
146 Soft386OpcodeShortConditionalJmp
,
147 Soft386OpcodeShortConditionalJmp
,
148 Soft386OpcodeShortConditionalJmp
,
149 Soft386OpcodeShortConditionalJmp
,
150 Soft386OpcodeShortConditionalJmp
,
151 Soft386OpcodeShortConditionalJmp
,
152 Soft386OpcodeShortConditionalJmp
,
153 Soft386OpcodeShortConditionalJmp
,
154 Soft386OpcodeShortConditionalJmp
,
155 NULL
, // TODO: OPCODE 0x80 NOT SUPPORTED
156 NULL
, // TODO: OPCODE 0x81 NOT SUPPORTED
157 NULL
, // TODO: OPCODE 0x82 NOT SUPPORTED
158 NULL
, // TODO: OPCODE 0x83 NOT SUPPORTED
159 NULL
, // TODO: OPCODE 0x84 NOT SUPPORTED
160 NULL
, // TODO: OPCODE 0x85 NOT SUPPORTED
161 NULL
, // TODO: OPCODE 0x86 NOT SUPPORTED
162 NULL
, // TODO: OPCODE 0x87 NOT SUPPORTED
163 NULL
, // TODO: OPCODE 0x88 NOT SUPPORTED
164 NULL
, // TODO: OPCODE 0x89 NOT SUPPORTED
165 NULL
, // TODO: OPCODE 0x8A NOT SUPPORTED
166 NULL
, // TODO: OPCODE 0x8B NOT SUPPORTED
167 NULL
, // TODO: OPCODE 0x8C NOT SUPPORTED
168 NULL
, // TODO: OPCODE 0x8D NOT SUPPORTED
169 NULL
, // TODO: OPCODE 0x8E NOT SUPPORTED
170 NULL
, // TODO: OPCODE 0x8F NOT SUPPORTED
172 Soft386OpcodeExchangeEax
,
173 Soft386OpcodeExchangeEax
,
174 Soft386OpcodeExchangeEax
,
175 Soft386OpcodeExchangeEax
,
176 Soft386OpcodeExchangeEax
,
177 Soft386OpcodeExchangeEax
,
178 Soft386OpcodeExchangeEax
,
179 NULL
, // TODO: OPCODE 0x98 NOT SUPPORTED
180 NULL
, // TODO: OPCODE 0x99 NOT SUPPORTED
181 NULL
, // TODO: OPCODE 0x9A NOT SUPPORTED
182 NULL
, // TODO: OPCODE 0x9B NOT SUPPORTED
183 NULL
, // TODO: OPCODE 0x9C NOT SUPPORTED
184 NULL
, // TODO: OPCODE 0x9D NOT SUPPORTED
185 NULL
, // TODO: OPCODE 0x9E NOT SUPPORTED
186 NULL
, // TODO: OPCODE 0x9F NOT SUPPORTED
187 NULL
, // TODO: OPCODE 0xA0 NOT SUPPORTED
188 NULL
, // TODO: OPCODE 0xA1 NOT SUPPORTED
189 NULL
, // TODO: OPCODE 0xA2 NOT SUPPORTED
190 NULL
, // TODO: OPCODE 0xA3 NOT SUPPORTED
191 NULL
, // TODO: OPCODE 0xA4 NOT SUPPORTED
192 NULL
, // TODO: OPCODE 0xA5 NOT SUPPORTED
193 NULL
, // TODO: OPCODE 0xA6 NOT SUPPORTED
194 NULL
, // TODO: OPCODE 0xA7 NOT SUPPORTED
195 NULL
, // TODO: OPCODE 0xA8 NOT SUPPORTED
196 NULL
, // TODO: OPCODE 0xA9 NOT SUPPORTED
197 NULL
, // TODO: OPCODE 0xAA NOT SUPPORTED
198 NULL
, // TODO: OPCODE 0xAB NOT SUPPORTED
199 NULL
, // TODO: OPCODE 0xAC NOT SUPPORTED
200 NULL
, // TODO: OPCODE 0xAD NOT SUPPORTED
201 NULL
, // TODO: OPCODE 0xAE NOT SUPPORTED
202 NULL
, // TODO: OPCODE 0xAF NOT SUPPORTED
203 NULL
, // TODO: OPCODE 0xB0 NOT SUPPORTED
204 NULL
, // TODO: OPCODE 0xB1 NOT SUPPORTED
205 NULL
, // TODO: OPCODE 0xB2 NOT SUPPORTED
206 NULL
, // TODO: OPCODE 0xB3 NOT SUPPORTED
207 NULL
, // TODO: OPCODE 0xB4 NOT SUPPORTED
208 NULL
, // TODO: OPCODE 0xB5 NOT SUPPORTED
209 NULL
, // TODO: OPCODE 0xB6 NOT SUPPORTED
210 NULL
, // TODO: OPCODE 0xB7 NOT SUPPORTED
211 NULL
, // TODO: OPCODE 0xB8 NOT SUPPORTED
212 NULL
, // TODO: OPCODE 0xB9 NOT SUPPORTED
213 NULL
, // TODO: OPCODE 0xBA NOT SUPPORTED
214 NULL
, // TODO: OPCODE 0xBB NOT SUPPORTED
215 NULL
, // TODO: OPCODE 0xBC NOT SUPPORTED
216 NULL
, // TODO: OPCODE 0xBD NOT SUPPORTED
217 NULL
, // TODO: OPCODE 0xBE NOT SUPPORTED
218 NULL
, // TODO: OPCODE 0xBF NOT SUPPORTED
219 NULL
, // TODO: OPCODE 0xC0 NOT SUPPORTED
220 NULL
, // TODO: OPCODE 0xC1 NOT SUPPORTED
221 NULL
, // TODO: OPCODE 0xC2 NOT SUPPORTED
222 NULL
, // TODO: OPCODE 0xC3 NOT SUPPORTED
223 NULL
, // TODO: OPCODE 0xC4 NOT SUPPORTED
224 NULL
, // TODO: OPCODE 0xC5 NOT SUPPORTED
225 NULL
, // TODO: OPCODE 0xC6 NOT SUPPORTED
226 NULL
, // TODO: OPCODE 0xC7 NOT SUPPORTED
227 NULL
, // TODO: OPCODE 0xC8 NOT SUPPORTED
228 NULL
, // TODO: OPCODE 0xC9 NOT SUPPORTED
229 NULL
, // TODO: OPCODE 0xCA NOT SUPPORTED
230 NULL
, // TODO: OPCODE 0xCB NOT SUPPORTED
231 NULL
, // TODO: OPCODE 0xCC NOT SUPPORTED
232 NULL
, // TODO: OPCODE 0xCD NOT SUPPORTED
233 NULL
, // TODO: OPCODE 0xCE NOT SUPPORTED
234 NULL
, // TODO: OPCODE 0xCF NOT SUPPORTED
235 NULL
, // TODO: OPCODE 0xD0 NOT SUPPORTED
236 NULL
, // TODO: OPCODE 0xD1 NOT SUPPORTED
237 NULL
, // TODO: OPCODE 0xD2 NOT SUPPORTED
238 NULL
, // TODO: OPCODE 0xD3 NOT SUPPORTED
239 NULL
, // TODO: OPCODE 0xD4 NOT SUPPORTED
240 NULL
, // TODO: OPCODE 0xD5 NOT SUPPORTED
241 NULL
, // TODO: OPCODE 0xD6 NOT SUPPORTED
242 NULL
, // TODO: OPCODE 0xD7 NOT SUPPORTED
243 NULL
, // TODO: OPCODE 0xD8 NOT SUPPORTED
244 NULL
, // TODO: OPCODE 0xD9 NOT SUPPORTED
245 NULL
, // TODO: OPCODE 0xDA NOT SUPPORTED
246 NULL
, // TODO: OPCODE 0xDB NOT SUPPORTED
247 NULL
, // TODO: OPCODE 0xDC NOT SUPPORTED
248 NULL
, // TODO: OPCODE 0xDD NOT SUPPORTED
249 NULL
, // TODO: OPCODE 0xDE NOT SUPPORTED
250 NULL
, // TODO: OPCODE 0xDF NOT SUPPORTED
251 NULL
, // TODO: OPCODE 0xE0 NOT SUPPORTED
252 NULL
, // TODO: OPCODE 0xE1 NOT SUPPORTED
253 NULL
, // TODO: OPCODE 0xE2 NOT SUPPORTED
254 NULL
, // TODO: OPCODE 0xE3 NOT SUPPORTED
257 Soft386OpcodeOutByte
,
259 NULL
, // TODO: OPCODE 0xE8 NOT SUPPORTED
260 NULL
, // TODO: OPCODE 0xE9 NOT SUPPORTED
261 NULL
, // TODO: OPCODE 0xEA NOT SUPPORTED
262 NULL
, // TODO: OPCODE 0xEB NOT SUPPORTED
265 Soft386OpcodeOutByte
,
272 Soft386OpcodeComplCarry
,
273 NULL
, // TODO: OPCODE 0xF6 NOT SUPPORTED
274 NULL
, // TODO: OPCODE 0xF7 NOT SUPPORTED
275 Soft386OpcodeClearCarry
,
276 Soft386OpcodeSetCarry
,
277 Soft386OpcodeClearInt
,
279 Soft386OpcodeClearDir
,
281 NULL
, // TODO: OPCODE 0xFE NOT SUPPORTED
282 NULL
, // TODO: OPCODE 0xFF NOT SUPPORTED
287 Soft386OpcodePrefix(PSOFT386_STATE State
, UCHAR Opcode
)
289 BOOLEAN Valid
= FALSE
;
296 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
298 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
299 State
->SegmentOverride
= SOFT386_REG_ES
;
309 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
311 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
312 State
->SegmentOverride
= SOFT386_REG_CS
;
322 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
324 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
325 State
->SegmentOverride
= SOFT386_REG_SS
;
335 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
337 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
338 State
->SegmentOverride
= SOFT386_REG_DS
;
348 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
350 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
351 State
->SegmentOverride
= SOFT386_REG_FS
;
361 if (!(State
->PrefixFlags
& SOFT386_PREFIX_SEG
))
363 State
->PrefixFlags
|= SOFT386_PREFIX_SEG
;
364 State
->SegmentOverride
= SOFT386_REG_GS
;
374 if (!(State
->PrefixFlags
& SOFT386_PREFIX_OPSIZE
))
376 State
->PrefixFlags
|= SOFT386_PREFIX_OPSIZE
;
386 if (!(State
->PrefixFlags
& SOFT386_PREFIX_ADSIZE
))
388 State
->PrefixFlags
|= SOFT386_PREFIX_ADSIZE
;
397 if (!(State
->PrefixFlags
& SOFT386_PREFIX_LOCK
))
399 State
->PrefixFlags
|= SOFT386_PREFIX_LOCK
;
409 /* Mutually exclusive with REP */
410 if (!(State
->PrefixFlags
411 & (SOFT386_PREFIX_REPNZ
| SOFT386_PREFIX_REP
)))
413 State
->PrefixFlags
|= SOFT386_PREFIX_REPNZ
;
423 /* Mutually exclusive with REPNZ */
424 if (!(State
->PrefixFlags
425 & (SOFT386_PREFIX_REPNZ
| SOFT386_PREFIX_REP
)))
427 State
->PrefixFlags
|= SOFT386_PREFIX_REP
;
437 /* Clear all prefixes */
438 State
->PrefixFlags
= 0;
440 /* Throw an exception */
441 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
450 Soft386OpcodeIncrement(PSOFT386_STATE State
, UCHAR Opcode
)
453 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
455 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
457 /* The OPSIZE prefix toggles the size */
460 else if (State
->PrefixFlags
!= 0)
463 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
467 /* Make sure this is the right instruction */
468 ASSERT((Opcode
& 0xF8) == 0x40);
472 Value
= ++State
->GeneralRegs
[Opcode
& 0x07].Long
;
474 State
->Flags
.Of
= (Value
== SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
475 State
->Flags
.Sf
= (Value
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
479 Value
= ++State
->GeneralRegs
[Opcode
& 0x07].LowWord
;
481 State
->Flags
.Of
= (Value
== SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
482 State
->Flags
.Sf
= (Value
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
485 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
486 State
->Flags
.Af
= ((Value
& 0x0F) == 0) ? TRUE
: FALSE
;
487 State
->Flags
.Pf
= Soft386CalculateParity(LOBYTE(Value
));
495 Soft386OpcodeDecrement(PSOFT386_STATE State
, UCHAR Opcode
)
498 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
500 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
502 /* The OPSIZE prefix toggles the size */
505 else if (State
->PrefixFlags
!= 0)
508 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
512 /* Make sure this is the right instruction */
513 ASSERT((Opcode
& 0xF8) == 0x48);
517 Value
= --State
->GeneralRegs
[Opcode
& 0x07].Long
;
519 State
->Flags
.Of
= (Value
== (SIGN_FLAG_LONG
- 1)) ? TRUE
: FALSE
;
520 State
->Flags
.Sf
= (Value
& SIGN_FLAG_LONG
) ? TRUE
: FALSE
;
524 Value
= --State
->GeneralRegs
[Opcode
& 0x07].LowWord
;
526 State
->Flags
.Of
= (Value
== (SIGN_FLAG_WORD
- 1)) ? TRUE
: FALSE
;
527 State
->Flags
.Sf
= (Value
& SIGN_FLAG_WORD
) ? TRUE
: FALSE
;
530 State
->Flags
.Zf
= (Value
== 0) ? TRUE
: FALSE
;
531 State
->Flags
.Af
= ((Value
& 0x0F) == 0x0F) ? TRUE
: FALSE
;
532 State
->Flags
.Pf
= Soft386CalculateParity(LOBYTE(Value
));
540 Soft386OpcodePushReg(PSOFT386_STATE State
, UCHAR Opcode
)
542 if ((State
->PrefixFlags
!= SOFT386_PREFIX_OPSIZE
)
543 && (State
->PrefixFlags
!= 0))
546 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
550 /* Make sure this is the right instruction */
551 ASSERT((Opcode
& 0xF8) == 0x50);
553 /* Call the internal function */
554 return Soft386StackPush(State
, State
->GeneralRegs
[Opcode
& 0x07].Long
);
559 Soft386OpcodePopReg(PSOFT386_STATE State
, UCHAR Opcode
)
562 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_SS
].Size
;
564 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
566 /* The OPSIZE prefix toggles the size */
569 else if (State
->PrefixFlags
!= 0)
572 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
576 /* Make sure this is the right instruction */
577 ASSERT((Opcode
& 0xF8) == 0x58);
579 /* Call the internal function */
580 if (!Soft386StackPop(State
, &Value
)) return FALSE
;
582 /* Store the value */
583 if (Size
) State
->GeneralRegs
[Opcode
& 0x07].Long
= Value
;
584 else State
->GeneralRegs
[Opcode
& 0x07].LowWord
= Value
;
592 Soft386OpcodeNop(PSOFT386_STATE State
, UCHAR Opcode
)
594 if (State
->PrefixFlags
& ~(SOFT386_PREFIX_OPSIZE
| SOFT386_PREFIX_REP
))
596 /* Allowed prefixes are REP and OPSIZE */
597 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
601 if (State
->PrefixFlags
& SOFT386_PREFIX_REP
)
604 State
->IdleCallback(State
);
612 Soft386OpcodeExchangeEax(PSOFT386_STATE State
, UCHAR Opcode
)
614 INT Reg
= Opcode
& 0x07;
615 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
617 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
619 /* The OPSIZE prefix toggles the size */
622 else if (State
->PrefixFlags
!= 0)
625 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
629 /* Make sure this is the right instruction */
630 ASSERT((Opcode
& 0xF8) == 0x90);
632 /* Exchange the values */
637 Value
= State
->GeneralRegs
[Reg
].Long
;
638 State
->GeneralRegs
[Reg
].Long
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
639 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Value
;
645 Value
= State
->GeneralRegs
[Reg
].LowWord
;
646 State
->GeneralRegs
[Reg
].LowWord
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
647 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Value
;
655 Soft386OpcodeShortConditionalJmp(PSOFT386_STATE State
, UCHAR Opcode
)
657 BOOLEAN Jump
= FALSE
;
660 /* Make sure this is the right instruction */
661 ASSERT((Opcode
& 0xF0) == 0x70);
663 /* Fetch the offset */
664 if (!Soft386FetchByte(State
, (PUCHAR
)&Offset
))
666 /* An exception occurred */
670 switch ((Opcode
& 0x0F) >> 1)
675 Jump
= State
->Flags
.Of
;
682 Jump
= State
->Flags
.Cf
;
689 Jump
= State
->Flags
.Zf
;
696 Jump
= State
->Flags
.Cf
|| State
->Flags
.Zf
;
703 Jump
= State
->Flags
.Sf
;
710 Jump
= State
->Flags
.Pf
;
717 Jump
= State
->Flags
.Sf
!= State
->Flags
.Of
;
724 Jump
= (State
->Flags
.Sf
!= State
->Flags
.Of
) || State
->Flags
.Zf
;
729 if ((Opcode
& 0xF0) & 1)
731 /* Invert the result */
737 /* Move the instruction pointer */
738 State
->InstPtr
.Long
+= Offset
;
747 Soft386OpcodeClearCarry(PSOFT386_STATE State
, UCHAR Opcode
)
749 /* Make sure this is the right instruction */
750 ASSERT(Opcode
== 0xF8);
752 /* No prefixes allowed */
753 if (State
->PrefixFlags
)
755 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
759 /* Clear CF and return success */
760 State
->Flags
.Cf
= FALSE
;
766 Soft386OpcodeSetCarry(PSOFT386_STATE State
, UCHAR Opcode
)
768 /* Make sure this is the right instruction */
769 ASSERT(Opcode
== 0xF9);
771 /* No prefixes allowed */
772 if (State
->PrefixFlags
)
774 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
778 /* Set CF and return success*/
779 State
->Flags
.Cf
= TRUE
;
785 Soft386OpcodeComplCarry(PSOFT386_STATE State
, UCHAR Opcode
)
787 /* Make sure this is the right instruction */
788 ASSERT(Opcode
== 0xF5);
790 /* No prefixes allowed */
791 if (State
->PrefixFlags
)
793 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
797 /* Toggle CF and return success */
798 State
->Flags
.Cf
= !State
->Flags
.Cf
;
804 Soft386OpcodeClearInt(PSOFT386_STATE State
, UCHAR Opcode
)
806 /* Make sure this is the right instruction */
807 ASSERT(Opcode
== 0xFA);
809 /* No prefixes allowed */
810 if (State
->PrefixFlags
)
812 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
816 /* Check for protected mode */
817 if (State
->ControlRegisters
[SOFT386_REG_CR0
] & SOFT386_CR0_PE
)
820 if (State
->Flags
.Iopl
>= State
->SegmentRegs
[SOFT386_REG_CS
].Dpl
)
822 /* Clear the interrupt flag */
823 State
->Flags
.If
= FALSE
;
827 /* General Protection Fault */
828 Soft386Exception(State
, SOFT386_EXCEPTION_GP
);
834 /* Just clear the interrupt flag */
835 State
->Flags
.If
= FALSE
;
844 Soft386OpcodeSetInt(PSOFT386_STATE State
, UCHAR Opcode
)
846 /* Make sure this is the right instruction */
847 ASSERT(Opcode
== 0xFB);
849 /* No prefixes allowed */
850 if (State
->PrefixFlags
)
852 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
856 /* Check for protected mode */
857 if (State
->ControlRegisters
[SOFT386_REG_CR0
] & SOFT386_CR0_PE
)
860 if (State
->Flags
.Iopl
>= State
->SegmentRegs
[SOFT386_REG_CS
].Dpl
)
862 /* Set the interrupt flag */
863 State
->Flags
.If
= TRUE
;
867 /* General Protection Fault */
868 Soft386Exception(State
, SOFT386_EXCEPTION_GP
);
874 /* Just set the interrupt flag */
875 State
->Flags
.If
= TRUE
;
884 Soft386OpcodeClearDir(PSOFT386_STATE State
, UCHAR Opcode
)
886 /* Make sure this is the right instruction */
887 ASSERT(Opcode
== 0xFC);
889 /* No prefixes allowed */
890 if (State
->PrefixFlags
)
892 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
896 /* Clear DF and return success */
897 State
->Flags
.Df
= FALSE
;
903 Soft386OpcodeSetDir(PSOFT386_STATE State
, UCHAR Opcode
)
905 /* Make sure this is the right instruction */
906 ASSERT(Opcode
== 0xFD);
908 /* No prefixes allowed */
909 if (State
->PrefixFlags
)
911 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
915 /* Set DF and return success*/
916 State
->Flags
.Df
= TRUE
;
922 Soft386OpcodeHalt(PSOFT386_STATE State
, UCHAR Opcode
)
924 /* Make sure this is the right instruction */
925 ASSERT(Opcode
== 0xF4);
927 /* No prefixes allowed */
928 if (State
->PrefixFlags
)
930 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
934 /* Privileged instructions can only be executed under CPL = 0 */
935 if (State
->SegmentRegs
[SOFT386_REG_CS
].Dpl
!= 0)
937 Soft386Exception(State
, SOFT386_EXCEPTION_GP
);
942 while (!State
->HardwareInt
) State
->IdleCallback(State
);
950 Soft386OpcodeInByte(PSOFT386_STATE State
, UCHAR Opcode
)
955 /* Make sure this is the right instruction */
956 ASSERT((Opcode
& 0xF7) == 0xE4);
960 /* Fetch the parameter */
961 if (!Soft386FetchByte(State
, &Data
))
963 /* Exception occurred */
967 /* Set the port number to the parameter */
972 /* The port number is in DX */
973 Port
= State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
;
976 /* Read a byte from the I/O port */
977 State
->IoReadCallback(State
, Port
, &Data
, sizeof(UCHAR
));
979 /* Store the result in AL */
980 State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
= Data
;
987 Soft386OpcodeIn(PSOFT386_STATE State
, UCHAR Opcode
)
990 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
992 /* Make sure this is the right instruction */
993 ASSERT((Opcode
& 0xF7) == 0xE5);
995 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
997 /* The OPSIZE prefix toggles the size */
1000 else if (State
->PrefixFlags
!= 0)
1002 /* Invalid prefix */
1003 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1011 /* Fetch the parameter */
1012 if (!Soft386FetchByte(State
, &Data
))
1014 /* Exception occurred */
1018 /* Set the port number to the parameter */
1023 /* The port number is in DX */
1024 Port
= State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
;
1031 /* Read a dword from the I/O port */
1032 State
->IoReadCallback(State
, Port
, &Data
, sizeof(ULONG
));
1034 /* Store the value in EAX */
1035 State
->GeneralRegs
[SOFT386_REG_EAX
].Long
= Data
;
1041 /* Read a word from the I/O port */
1042 State
->IoReadCallback(State
, Port
, &Data
, sizeof(USHORT
));
1044 /* Store the value in AX */
1045 State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
= Data
;
1053 Soft386OpcodeOutByte(PSOFT386_STATE State
, UCHAR Opcode
)
1058 /* Make sure this is the right instruction */
1059 ASSERT((Opcode
& 0xF7) == 0xE6);
1063 /* Fetch the parameter */
1064 if (!Soft386FetchByte(State
, &Data
))
1066 /* Exception occurred */
1070 /* Set the port number to the parameter */
1075 /* The port number is in DX */
1076 Port
= State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
;
1079 /* Read the value from AL */
1080 Data
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowByte
;
1082 /* Write the byte to the I/O port */
1083 State
->IoWriteCallback(State
, Port
, &Data
, sizeof(UCHAR
));
1090 Soft386OpcodeOut(PSOFT386_STATE State
, UCHAR Opcode
)
1093 BOOLEAN Size
= State
->SegmentRegs
[SOFT386_REG_CS
].Size
;
1095 /* Make sure this is the right instruction */
1096 ASSERT((Opcode
& 0xF7) == 0xE7);
1098 if (State
->PrefixFlags
== SOFT386_PREFIX_OPSIZE
)
1100 /* The OPSIZE prefix toggles the size */
1103 else if (State
->PrefixFlags
!= 0)
1105 /* Invalid prefix */
1106 Soft386Exception(State
, SOFT386_EXCEPTION_UD
);
1114 /* Fetch the parameter */
1115 if (!Soft386FetchByte(State
, &Data
))
1117 /* Exception occurred */
1121 /* Set the port number to the parameter */
1126 /* The port number is in DX */
1127 Port
= State
->GeneralRegs
[SOFT386_REG_EDX
].LowWord
;
1132 /* Get the value from EAX */
1133 ULONG Data
= State
->GeneralRegs
[SOFT386_REG_EAX
].Long
;
1135 /* Write a dword to the I/O port */
1136 State
->IoReadCallback(State
, Port
, &Data
, sizeof(ULONG
));
1140 /* Get the value from AX */
1141 USHORT Data
= State
->GeneralRegs
[SOFT386_REG_EAX
].LowWord
;
1143 /* Write a word to the I/O port */
1144 State
->IoWriteCallback(State
, Port
, &Data
, sizeof(USHORT
));