[SOFT386]
[reactos.git] / lib / soft386 / opcodes.c
1 /*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: 386/486 CPU Emulation Library
4 * FILE: opcodes.c
5 * PURPOSE: Opcode handlers.
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 // #define WIN32_NO_STATUS
12 // #define _INC_WINDOWS
13 #include <windef.h>
14 #include <limits.h>
15
16 // #define NDEBUG
17 #include <debug.h>
18
19 #include <soft386.h>
20 #include "opcodes.h"
21 #include "common.h"
22
23 /* PUBLIC VARIABLES ***********************************************************/
24
25 SOFT386_OPCODE_HANDLER_PROC
26 Soft386OpcodeHandlers[SOFT386_NUM_OPCODE_HANDLERS] =
27 {
28 Soft386OpcodeAddByteModrm,
29 Soft386OpcodeAddModrm,
30 Soft386OpcodeAddByteModrm,
31 Soft386OpcodeAddModrm,
32 Soft386OpcodeAddAl,
33 Soft386OpcodeAddEax,
34 Soft386OpcodePushEs,
35 Soft386OpcodePopEs,
36 Soft386OpcodeOrByteModrm,
37 Soft386OpcodeOrModrm,
38 Soft386OpcodeOrByteModrm,
39 Soft386OpcodeOrModrm,
40 Soft386OpcodeOrAl,
41 Soft386OpcodeOrEax,
42 Soft386OpcodePushCs,
43 NULL, // TODO: OPCODE 0x0F NOT SUPPORTED
44 Soft386OpcodeAdcByteModrm,
45 Soft386OpcodeAdcModrm,
46 Soft386OpcodeAdcByteModrm,
47 Soft386OpcodeAdcModrm,
48 Soft386OpcodeAdcAl,
49 Soft386OpcodeAdcEax,
50 Soft386OpcodePushSs,
51 Soft386OpcodePopSs,
52 Soft386OpcodeSbbByteModrm,
53 Soft386OpcodeSbbModrm,
54 Soft386OpcodeSbbByteModrm,
55 Soft386OpcodeSbbModrm,
56 Soft386OpcodeSbbAl,
57 Soft386OpcodeSbbEax,
58 Soft386OpcodePushDs,
59 Soft386OpcodePopDs,
60 Soft386OpcodeAndByteModrm,
61 Soft386OpcodeAndModrm,
62 Soft386OpcodeAndByteModrm,
63 Soft386OpcodeAndModrm,
64 Soft386OpcodeAndAl,
65 Soft386OpcodeAndEax,
66 Soft386OpcodePrefix,
67 Soft386OpcodeDaa,
68 Soft386OpcodeCmpSubByteModrm,
69 Soft386OpcodeCmpSubModrm,
70 Soft386OpcodeCmpSubByteModrm,
71 Soft386OpcodeCmpSubModrm,
72 Soft386OpcodeCmpSubAl,
73 Soft386OpcodeCmpSubEax,
74 Soft386OpcodePrefix,
75 Soft386OpcodeDas,
76 Soft386OpcodeXorByteModrm,
77 Soft386OpcodeXorModrm,
78 Soft386OpcodeXorByteModrm,
79 Soft386OpcodeXorModrm,
80 Soft386OpcodeXorAl,
81 Soft386OpcodeXorEax,
82 Soft386OpcodePrefix,
83 Soft386OpcodeAaa,
84 Soft386OpcodeCmpSubByteModrm,
85 Soft386OpcodeCmpSubModrm,
86 Soft386OpcodeCmpSubByteModrm,
87 Soft386OpcodeCmpSubModrm,
88 Soft386OpcodeCmpSubAl,
89 Soft386OpcodeCmpSubEax,
90 Soft386OpcodePrefix,
91 Soft386OpcodeAas,
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,
116 Soft386OpcodePopReg,
117 Soft386OpcodePopReg,
118 Soft386OpcodePopReg,
119 Soft386OpcodePopReg,
120 Soft386OpcodePopReg,
121 Soft386OpcodePopReg,
122 Soft386OpcodePopReg,
123 Soft386OpcodePopReg,
124 Soft386OpcodePushAll,
125 Soft386OpcodePopAll,
126 Soft386OpcodeBound,
127 Soft386OpcodeArpl,
128 Soft386OpcodePrefix,
129 Soft386OpcodePrefix,
130 Soft386OpcodePrefix,
131 Soft386OpcodePrefix,
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,
169 Soft386OpcodeLea,
170 Soft386OpcodeMovLoadSeg,
171 NULL, // TODO: OPCODE 0x8F NOT SUPPORTED
172 Soft386OpcodeNop,
173 Soft386OpcodeExchangeEax,
174 Soft386OpcodeExchangeEax,
175 Soft386OpcodeExchangeEax,
176 Soft386OpcodeExchangeEax,
177 Soft386OpcodeExchangeEax,
178 Soft386OpcodeExchangeEax,
179 Soft386OpcodeExchangeEax,
180 Soft386OpcodeCwde,
181 Soft386OpcodeCdq,
182 Soft386OpcodeCallAbs,
183 Soft386OpcodeWait,
184 Soft386OpcodePushFlags,
185 Soft386OpcodePopFlags,
186 Soft386OpcodeSahf,
187 Soft386OpcodeLahf,
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
196 Soft386OpcodeTestAl,
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
222 Soft386OpcodeRet,
223 Soft386OpcodeRet,
224 Soft386OpcodeLdsLes,
225 Soft386OpcodeLdsLes,
226 NULL, // TODO: OPCODE 0xC6 NOT SUPPORTED
227 NULL, // TODO: OPCODE 0xC7 NOT SUPPORTED
228 Soft386OpcodeEnter,
229 Soft386OpcodeLeave,
230 Soft386OpcodeRetFarImm,
231 Soft386OpcodeRetFar,
232 Soft386OpcodeInt,
233 Soft386OpcodeInt,
234 Soft386OpcodeInt,
235 Soft386OpcodeIret,
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
240 Soft386OpcodeAam,
241 Soft386OpcodeAad,
242 NULL, // TODO: OPCODE 0xD6 NOT SUPPORTED
243 Soft386OpcodeXlat,
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
252 Soft386OpcodeLoop,
253 Soft386OpcodeLoop,
254 Soft386OpcodeLoop,
255 Soft386OpcodeJecxz,
256 Soft386OpcodeInByte,
257 Soft386OpcodeIn,
258 Soft386OpcodeOutByte,
259 Soft386OpcodeOut,
260 Soft386OpcodeCall,
261 Soft386OpcodeJmp,
262 Soft386OpcodeJmpAbs,
263 Soft386OpcodeShortJump,
264 Soft386OpcodeInByte,
265 Soft386OpcodeIn,
266 Soft386OpcodeOutByte,
267 Soft386OpcodeOut,
268 Soft386OpcodePrefix,
269 NULL, // Invalid
270 Soft386OpcodePrefix,
271 Soft386OpcodePrefix,
272 Soft386OpcodeHalt,
273 Soft386OpcodeComplCarry,
274 NULL, // TODO: OPCODE 0xF6 NOT SUPPORTED
275 NULL, // TODO: OPCODE 0xF7 NOT SUPPORTED
276 Soft386OpcodeClearCarry,
277 Soft386OpcodeSetCarry,
278 Soft386OpcodeClearInt,
279 Soft386OpcodeSetInt,
280 Soft386OpcodeClearDir,
281 Soft386OpcodeSetDir,
282 NULL, // TODO: OPCODE 0xFE NOT SUPPORTED
283 NULL, // TODO: OPCODE 0xFF NOT SUPPORTED
284 };
285
286 /* PUBLIC FUNCTIONS ***********************************************************/
287
288 SOFT386_OPCODE_HANDLER(Soft386OpcodePrefix)
289 {
290 BOOLEAN Valid = FALSE;
291
292 switch (Opcode)
293 {
294 /* ES: */
295 case 0x26:
296 {
297 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
298 {
299 State->PrefixFlags |= SOFT386_PREFIX_SEG;
300 State->SegmentOverride = SOFT386_REG_ES;
301 Valid = TRUE;
302 }
303
304 break;
305 }
306
307 /* CS: */
308 case 0x2E:
309 {
310 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
311 {
312 State->PrefixFlags |= SOFT386_PREFIX_SEG;
313 State->SegmentOverride = SOFT386_REG_CS;
314 Valid = TRUE;
315 }
316
317 break;
318 }
319
320 /* SS: */
321 case 0x36:
322 {
323 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
324 {
325 State->PrefixFlags |= SOFT386_PREFIX_SEG;
326 State->SegmentOverride = SOFT386_REG_SS;
327 Valid = TRUE;
328 }
329
330 break;
331 }
332
333 /* DS: */
334 case 0x3E:
335 {
336 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
337 {
338 State->PrefixFlags |= SOFT386_PREFIX_SEG;
339 State->SegmentOverride = SOFT386_REG_DS;
340 Valid = TRUE;
341 }
342
343 break;
344 }
345
346 /* FS: */
347 case 0x64:
348 {
349 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
350 {
351 State->PrefixFlags |= SOFT386_PREFIX_SEG;
352 State->SegmentOverride = SOFT386_REG_FS;
353 Valid = TRUE;
354 }
355
356 break;
357 }
358
359 /* GS: */
360 case 0x65:
361 {
362 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
363 {
364 State->PrefixFlags |= SOFT386_PREFIX_SEG;
365 State->SegmentOverride = SOFT386_REG_GS;
366 Valid = TRUE;
367 }
368
369 break;
370 }
371
372 /* OPSIZE */
373 case 0x66:
374 {
375 if (!(State->PrefixFlags & SOFT386_PREFIX_OPSIZE))
376 {
377 State->PrefixFlags |= SOFT386_PREFIX_OPSIZE;
378 Valid = TRUE;
379 }
380
381 break;
382 }
383
384 /* ADSIZE */
385 case 0x67:
386 {
387 if (!(State->PrefixFlags & SOFT386_PREFIX_ADSIZE))
388 {
389 State->PrefixFlags |= SOFT386_PREFIX_ADSIZE;
390 Valid = TRUE;
391 }
392 break;
393 }
394
395 /* LOCK */
396 case 0xF0:
397 {
398 if (!(State->PrefixFlags & SOFT386_PREFIX_LOCK))
399 {
400 State->PrefixFlags |= SOFT386_PREFIX_LOCK;
401 Valid = TRUE;
402 }
403
404 break;
405 }
406
407 /* REPNZ */
408 case 0xF2:
409 {
410 /* Mutually exclusive with REP */
411 if (!(State->PrefixFlags
412 & (SOFT386_PREFIX_REPNZ | SOFT386_PREFIX_REP)))
413 {
414 State->PrefixFlags |= SOFT386_PREFIX_REPNZ;
415 Valid = TRUE;
416 }
417
418 break;
419 }
420
421 /* REP / REPZ */
422 case 0xF3:
423 {
424 /* Mutually exclusive with REPNZ */
425 if (!(State->PrefixFlags
426 & (SOFT386_PREFIX_REPNZ | SOFT386_PREFIX_REP)))
427 {
428 State->PrefixFlags |= SOFT386_PREFIX_REP;
429 Valid = TRUE;
430 }
431
432 break;
433 }
434 }
435
436 if (!Valid)
437 {
438 /* Clear all prefixes */
439 State->PrefixFlags = 0;
440
441 /* Throw an exception */
442 Soft386Exception(State, SOFT386_EXCEPTION_UD);
443 return FALSE;
444 }
445
446 return TRUE;
447 }
448
449 SOFT386_OPCODE_HANDLER(Soft386OpcodeIncrement)
450 {
451 ULONG Value;
452 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
453
454 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
455 {
456 /* The OPSIZE prefix toggles the size */
457 Size = !Size;
458 }
459 else if (State->PrefixFlags != 0)
460 {
461 /* Invalid prefix */
462 Soft386Exception(State, SOFT386_EXCEPTION_UD);
463 return FALSE;
464 }
465
466 /* Make sure this is the right instruction */
467 ASSERT((Opcode & 0xF8) == 0x40);
468
469 if (Size)
470 {
471 Value = ++State->GeneralRegs[Opcode & 0x07].Long;
472
473 State->Flags.Of = (Value == SIGN_FLAG_LONG) ? TRUE : FALSE;
474 State->Flags.Sf = (Value & SIGN_FLAG_LONG) ? TRUE : FALSE;
475 }
476 else
477 {
478 Value = ++State->GeneralRegs[Opcode & 0x07].LowWord;
479
480 State->Flags.Of = (Value == SIGN_FLAG_WORD) ? TRUE : FALSE;
481 State->Flags.Sf = (Value & SIGN_FLAG_WORD) ? TRUE : FALSE;
482 }
483
484 State->Flags.Zf = (Value == 0) ? TRUE : FALSE;
485 State->Flags.Af = ((Value & 0x0F) == 0) ? TRUE : FALSE;
486 State->Flags.Pf = Soft386CalculateParity(LOBYTE(Value));
487
488 /* Return success */
489 return TRUE;
490 }
491
492 SOFT386_OPCODE_HANDLER(Soft386OpcodeDecrement)
493 {
494 ULONG Value;
495 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
496
497 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
498 {
499 /* The OPSIZE prefix toggles the size */
500 Size = !Size;
501 }
502 else if (State->PrefixFlags != 0)
503 {
504 /* Invalid prefix */
505 Soft386Exception(State, SOFT386_EXCEPTION_UD);
506 return FALSE;
507 }
508
509 /* Make sure this is the right instruction */
510 ASSERT((Opcode & 0xF8) == 0x48);
511
512 if (Size)
513 {
514 Value = --State->GeneralRegs[Opcode & 0x07].Long;
515
516 State->Flags.Of = (Value == (SIGN_FLAG_LONG - 1)) ? TRUE : FALSE;
517 State->Flags.Sf = (Value & SIGN_FLAG_LONG) ? TRUE : FALSE;
518 }
519 else
520 {
521 Value = --State->GeneralRegs[Opcode & 0x07].LowWord;
522
523 State->Flags.Of = (Value == (SIGN_FLAG_WORD - 1)) ? TRUE : FALSE;
524 State->Flags.Sf = (Value & SIGN_FLAG_WORD) ? TRUE : FALSE;
525 }
526
527 State->Flags.Zf = (Value == 0) ? TRUE : FALSE;
528 State->Flags.Af = ((Value & 0x0F) == 0x0F) ? TRUE : FALSE;
529 State->Flags.Pf = Soft386CalculateParity(LOBYTE(Value));
530
531 /* Return success */
532 return TRUE;
533 }
534
535 SOFT386_OPCODE_HANDLER(Soft386OpcodePushReg)
536 {
537 if ((State->PrefixFlags != SOFT386_PREFIX_OPSIZE)
538 && (State->PrefixFlags != 0))
539 {
540 /* Invalid prefix */
541 Soft386Exception(State, SOFT386_EXCEPTION_UD);
542 return FALSE;
543 }
544
545 /* Make sure this is the right instruction */
546 ASSERT((Opcode & 0xF8) == 0x50);
547
548 /* Call the internal function */
549 return Soft386StackPush(State, State->GeneralRegs[Opcode & 0x07].Long);
550 }
551
552 SOFT386_OPCODE_HANDLER(Soft386OpcodePopReg)
553 {
554 ULONG Value;
555 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_SS].Size;
556
557 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
558 {
559 /* The OPSIZE prefix toggles the size */
560 Size = !Size;
561 }
562 else if (State->PrefixFlags != 0)
563 {
564 /* Invalid prefix */
565 Soft386Exception(State, SOFT386_EXCEPTION_UD);
566 return FALSE;
567 }
568
569 /* Make sure this is the right instruction */
570 ASSERT((Opcode & 0xF8) == 0x58);
571
572 /* Call the internal function */
573 if (!Soft386StackPop(State, &Value)) return FALSE;
574
575 /* Store the value */
576 if (Size) State->GeneralRegs[Opcode & 0x07].Long = Value;
577 else State->GeneralRegs[Opcode & 0x07].LowWord = Value;
578
579 /* Return success */
580 return TRUE;
581 }
582
583 SOFT386_OPCODE_HANDLER(Soft386OpcodeNop)
584 {
585 if (State->PrefixFlags & ~(SOFT386_PREFIX_OPSIZE | SOFT386_PREFIX_REP))
586 {
587 /* Allowed prefixes are REP and OPSIZE */
588 Soft386Exception(State, SOFT386_EXCEPTION_UD);
589 return FALSE;
590 }
591
592 if (State->PrefixFlags & SOFT386_PREFIX_REP)
593 {
594 /* Idle cycle */
595 State->IdleCallback(State);
596 }
597
598 return TRUE;
599 }
600
601 SOFT386_OPCODE_HANDLER(Soft386OpcodeExchangeEax)
602 {
603 INT Reg = Opcode & 0x07;
604 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
605
606 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
607 {
608 /* The OPSIZE prefix toggles the size */
609 Size = !Size;
610 }
611 else if (State->PrefixFlags != 0)
612 {
613 /* Invalid prefix */
614 Soft386Exception(State, SOFT386_EXCEPTION_UD);
615 return FALSE;
616 }
617
618 /* Make sure this is the right instruction */
619 ASSERT((Opcode & 0xF8) == 0x90);
620
621 /* Exchange the values */
622 if (Size)
623 {
624 ULONG Value;
625
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;
629 }
630 else
631 {
632 USHORT Value;
633
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;
637 }
638
639 return TRUE;
640 }
641
642 SOFT386_OPCODE_HANDLER(Soft386OpcodeShortConditionalJmp)
643 {
644 BOOLEAN Jump = FALSE;
645 CHAR Offset = 0;
646
647 /* Make sure this is the right instruction */
648 ASSERT((Opcode & 0xF0) == 0x70);
649
650 /* Fetch the offset */
651 if (!Soft386FetchByte(State, (PUCHAR)&Offset))
652 {
653 /* An exception occurred */
654 return FALSE;
655 }
656
657 switch ((Opcode & 0x0F) >> 1)
658 {
659 /* JO / JNO */
660 case 0:
661 {
662 Jump = State->Flags.Of;
663 break;
664 }
665
666 /* JC / JNC */
667 case 1:
668 {
669 Jump = State->Flags.Cf;
670 break;
671 }
672
673 /* JZ / JNZ */
674 case 2:
675 {
676 Jump = State->Flags.Zf;
677 break;
678 }
679
680 /* JBE / JNBE */
681 case 3:
682 {
683 Jump = State->Flags.Cf || State->Flags.Zf;
684 break;
685 }
686
687 /* JS / JNS */
688 case 4:
689 {
690 Jump = State->Flags.Sf;
691 break;
692 }
693
694 /* JP / JNP */
695 case 5:
696 {
697 Jump = State->Flags.Pf;
698 break;
699 }
700
701 /* JL / JNL */
702 case 6:
703 {
704 Jump = State->Flags.Sf != State->Flags.Of;
705 break;
706 }
707
708 /* JLE / JNLE */
709 case 7:
710 {
711 Jump = (State->Flags.Sf != State->Flags.Of) || State->Flags.Zf;
712 break;
713 }
714 }
715
716 if (Opcode & 1)
717 {
718 /* Invert the result */
719 Jump = !Jump;
720 }
721
722 if (Jump)
723 {
724 /* Move the instruction pointer */
725 State->InstPtr.Long += Offset;
726 }
727
728 /* Return success */
729 return TRUE;
730 }
731
732 SOFT386_OPCODE_HANDLER(Soft386OpcodeClearCarry)
733 {
734 /* Make sure this is the right instruction */
735 ASSERT(Opcode == 0xF8);
736
737 /* No prefixes allowed */
738 if (State->PrefixFlags)
739 {
740 Soft386Exception(State, SOFT386_EXCEPTION_UD);
741 return FALSE;
742 }
743
744 /* Clear CF and return success */
745 State->Flags.Cf = FALSE;
746 return TRUE;
747 }
748
749 SOFT386_OPCODE_HANDLER(Soft386OpcodeSetCarry)
750 {
751 /* Make sure this is the right instruction */
752 ASSERT(Opcode == 0xF9);
753
754 /* No prefixes allowed */
755 if (State->PrefixFlags)
756 {
757 Soft386Exception(State, SOFT386_EXCEPTION_UD);
758 return FALSE;
759 }
760
761 /* Set CF and return success*/
762 State->Flags.Cf = TRUE;
763 return TRUE;
764 }
765
766 SOFT386_OPCODE_HANDLER(Soft386OpcodeComplCarry)
767 {
768 /* Make sure this is the right instruction */
769 ASSERT(Opcode == 0xF5);
770
771 /* No prefixes allowed */
772 if (State->PrefixFlags)
773 {
774 Soft386Exception(State, SOFT386_EXCEPTION_UD);
775 return FALSE;
776 }
777
778 /* Toggle CF and return success */
779 State->Flags.Cf = !State->Flags.Cf;
780 return TRUE;
781 }
782
783 SOFT386_OPCODE_HANDLER(Soft386OpcodeClearInt)
784 {
785 /* Make sure this is the right instruction */
786 ASSERT(Opcode == 0xFA);
787
788 /* No prefixes allowed */
789 if (State->PrefixFlags)
790 {
791 Soft386Exception(State, SOFT386_EXCEPTION_UD);
792 return FALSE;
793 }
794
795 /* Check for protected mode */
796 if (State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE)
797 {
798 /* Check IOPL */
799 if (State->Flags.Iopl >= State->SegmentRegs[SOFT386_REG_CS].Dpl)
800 {
801 /* Clear the interrupt flag */
802 State->Flags.If = FALSE;
803 }
804 else
805 {
806 /* General Protection Fault */
807 Soft386Exception(State, SOFT386_EXCEPTION_GP);
808 return FALSE;
809 }
810 }
811 else
812 {
813 /* Just clear the interrupt flag */
814 State->Flags.If = FALSE;
815 }
816
817 /* Return success */
818 return TRUE;
819 }
820
821 SOFT386_OPCODE_HANDLER(Soft386OpcodeSetInt)
822 {
823 /* Make sure this is the right instruction */
824 ASSERT(Opcode == 0xFB);
825
826 /* No prefixes allowed */
827 if (State->PrefixFlags)
828 {
829 Soft386Exception(State, SOFT386_EXCEPTION_UD);
830 return FALSE;
831 }
832
833 /* Check for protected mode */
834 if (State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE)
835 {
836 /* Check IOPL */
837 if (State->Flags.Iopl >= State->SegmentRegs[SOFT386_REG_CS].Dpl)
838 {
839 /* Set the interrupt flag */
840 State->Flags.If = TRUE;
841 }
842 else
843 {
844 /* General Protection Fault */
845 Soft386Exception(State, SOFT386_EXCEPTION_GP);
846 return FALSE;
847 }
848 }
849 else
850 {
851 /* Just set the interrupt flag */
852 State->Flags.If = TRUE;
853 }
854
855 /* Return success */
856 return TRUE;
857 }
858
859 SOFT386_OPCODE_HANDLER(Soft386OpcodeClearDir)
860 {
861 /* Make sure this is the right instruction */
862 ASSERT(Opcode == 0xFC);
863
864 /* No prefixes allowed */
865 if (State->PrefixFlags)
866 {
867 Soft386Exception(State, SOFT386_EXCEPTION_UD);
868 return FALSE;
869 }
870
871 /* Clear DF and return success */
872 State->Flags.Df = FALSE;
873 return TRUE;
874 }
875
876 SOFT386_OPCODE_HANDLER(Soft386OpcodeSetDir)
877 {
878 /* Make sure this is the right instruction */
879 ASSERT(Opcode == 0xFD);
880
881 /* No prefixes allowed */
882 if (State->PrefixFlags)
883 {
884 Soft386Exception(State, SOFT386_EXCEPTION_UD);
885 return FALSE;
886 }
887
888 /* Set DF and return success*/
889 State->Flags.Df = TRUE;
890 return TRUE;
891 }
892
893 SOFT386_OPCODE_HANDLER(Soft386OpcodeHalt)
894 {
895 /* Make sure this is the right instruction */
896 ASSERT(Opcode == 0xF4);
897
898 /* No prefixes allowed */
899 if (State->PrefixFlags)
900 {
901 Soft386Exception(State, SOFT386_EXCEPTION_UD);
902 return FALSE;
903 }
904
905 /* Privileged instructions can only be executed under CPL = 0 */
906 if (State->SegmentRegs[SOFT386_REG_CS].Dpl != 0)
907 {
908 Soft386Exception(State, SOFT386_EXCEPTION_GP);
909 return FALSE;
910 }
911
912 /* Halt */
913 while (!State->HardwareInt) State->IdleCallback(State);
914
915 /* Return success */
916 return TRUE;
917 }
918
919 SOFT386_OPCODE_HANDLER(Soft386OpcodeInByte)
920 {
921 UCHAR Data;
922 ULONG Port;
923
924 /* Make sure this is the right instruction */
925 ASSERT((Opcode & 0xF7) == 0xE4);
926
927 if (Opcode == 0xE4)
928 {
929 /* Fetch the parameter */
930 if (!Soft386FetchByte(State, &Data))
931 {
932 /* Exception occurred */
933 return FALSE;
934 }
935
936 /* Set the port number to the parameter */
937 Port = Data;
938 }
939 else
940 {
941 /* The port number is in DX */
942 Port = State->GeneralRegs[SOFT386_REG_EDX].LowWord;
943 }
944
945 /* Read a byte from the I/O port */
946 State->IoReadCallback(State, Port, &Data, sizeof(UCHAR));
947
948 /* Store the result in AL */
949 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Data;
950
951 return TRUE;
952 }
953
954 SOFT386_OPCODE_HANDLER(Soft386OpcodeIn)
955 {
956 ULONG Port;
957 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
958
959 /* Make sure this is the right instruction */
960 ASSERT((Opcode & 0xF7) == 0xE5);
961
962 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
963 {
964 /* The OPSIZE prefix toggles the size */
965 Size = !Size;
966 }
967 else if (State->PrefixFlags != 0)
968 {
969 /* Invalid prefix */
970 Soft386Exception(State, SOFT386_EXCEPTION_UD);
971 return FALSE;
972 }
973
974 if (Opcode == 0xE5)
975 {
976 UCHAR Data;
977
978 /* Fetch the parameter */
979 if (!Soft386FetchByte(State, &Data))
980 {
981 /* Exception occurred */
982 return FALSE;
983 }
984
985 /* Set the port number to the parameter */
986 Port = Data;
987 }
988 else
989 {
990 /* The port number is in DX */
991 Port = State->GeneralRegs[SOFT386_REG_EDX].LowWord;
992 }
993
994 if (Size)
995 {
996 ULONG Data;
997
998 /* Read a dword from the I/O port */
999 State->IoReadCallback(State, Port, &Data, sizeof(ULONG));
1000
1001 /* Store the value in EAX */
1002 State->GeneralRegs[SOFT386_REG_EAX].Long = Data;
1003 }
1004 else
1005 {
1006 USHORT Data;
1007
1008 /* Read a word from the I/O port */
1009 State->IoReadCallback(State, Port, &Data, sizeof(USHORT));
1010
1011 /* Store the value in AX */
1012 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Data;
1013 }
1014
1015 return TRUE;
1016 }
1017
1018 SOFT386_OPCODE_HANDLER(Soft386OpcodeOutByte)
1019 {
1020 UCHAR Data;
1021 ULONG Port;
1022
1023 /* Make sure this is the right instruction */
1024 ASSERT((Opcode & 0xF7) == 0xE6);
1025
1026 if (Opcode == 0xE6)
1027 {
1028 /* Fetch the parameter */
1029 if (!Soft386FetchByte(State, &Data))
1030 {
1031 /* Exception occurred */
1032 return FALSE;
1033 }
1034
1035 /* Set the port number to the parameter */
1036 Port = Data;
1037 }
1038 else
1039 {
1040 /* The port number is in DX */
1041 Port = State->GeneralRegs[SOFT386_REG_EDX].LowWord;
1042 }
1043
1044 /* Read the value from AL */
1045 Data = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
1046
1047 /* Write the byte to the I/O port */
1048 State->IoWriteCallback(State, Port, &Data, sizeof(UCHAR));
1049
1050 return TRUE;
1051 }
1052
1053 SOFT386_OPCODE_HANDLER(Soft386OpcodeOut)
1054 {
1055 ULONG Port;
1056 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
1057
1058 /* Make sure this is the right instruction */
1059 ASSERT((Opcode & 0xF7) == 0xE7);
1060
1061 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
1062 {
1063 /* The OPSIZE prefix toggles the size */
1064 Size = !Size;
1065 }
1066 else if (State->PrefixFlags != 0)
1067 {
1068 /* Invalid prefix */
1069 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1070 return FALSE;
1071 }
1072
1073 if (Opcode == 0xE7)
1074 {
1075 UCHAR Data;
1076
1077 /* Fetch the parameter */
1078 if (!Soft386FetchByte(State, &Data))
1079 {
1080 /* Exception occurred */
1081 return FALSE;
1082 }
1083
1084 /* Set the port number to the parameter */
1085 Port = Data;
1086 }
1087 else
1088 {
1089 /* The port number is in DX */
1090 Port = State->GeneralRegs[SOFT386_REG_EDX].LowWord;
1091 }
1092
1093 if (Size)
1094 {
1095 /* Get the value from EAX */
1096 ULONG Data = State->GeneralRegs[SOFT386_REG_EAX].Long;
1097
1098 /* Write a dword to the I/O port */
1099 State->IoReadCallback(State, Port, &Data, sizeof(ULONG));
1100 }
1101 else
1102 {
1103 /* Get the value from AX */
1104 USHORT Data = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
1105
1106 /* Write a word to the I/O port */
1107 State->IoWriteCallback(State, Port, &Data, sizeof(USHORT));
1108 }
1109
1110 return TRUE;
1111 }
1112
1113 SOFT386_OPCODE_HANDLER(Soft386OpcodeShortJump)
1114 {
1115 CHAR Offset = 0;
1116
1117 /* Make sure this is the right instruction */
1118 ASSERT(Opcode == 0xEB);
1119
1120 /* Fetch the offset */
1121 if (!Soft386FetchByte(State, (PUCHAR)&Offset))
1122 {
1123 /* An exception occurred */
1124 return FALSE;
1125 }
1126
1127 /* Move the instruction pointer */
1128 State->InstPtr.Long += Offset;
1129
1130 return TRUE;
1131 }
1132
1133 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovRegImm)
1134 {
1135 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
1136
1137 /* Make sure this is the right instruction */
1138 ASSERT((Opcode & 0xF8) == 0xB8);
1139
1140 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
1141 {
1142 /* The OPSIZE prefix toggles the size */
1143 Size = !Size;
1144 }
1145 else if (State->PrefixFlags != 0)
1146 {
1147 /* Invalid prefix */
1148 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1149 return FALSE;
1150 }
1151
1152 if (Size)
1153 {
1154 ULONG Value;
1155
1156 /* Fetch the dword */
1157 if (!Soft386FetchDword(State, &Value))
1158 {
1159 /* Exception occurred */
1160 return FALSE;
1161 }
1162
1163 /* Store the value in the register */
1164 State->GeneralRegs[Opcode & 0x07].Long = Value;
1165 }
1166 else
1167 {
1168 USHORT Value;
1169
1170 /* Fetch the word */
1171 if (!Soft386FetchWord(State, &Value))
1172 {
1173 /* Exception occurred */
1174 return FALSE;
1175 }
1176
1177 /* Store the value in the register */
1178 State->GeneralRegs[Opcode & 0x07].LowWord = Value;
1179 }
1180
1181 return TRUE;
1182 }
1183
1184 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovByteRegImm)
1185 {
1186 UCHAR Value;
1187
1188 /* Make sure this is the right instruction */
1189 ASSERT((Opcode & 0xF8) == 0xB0);
1190
1191 if (State->PrefixFlags != 0)
1192 {
1193 /* Invalid prefix */
1194 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1195 return FALSE;
1196 }
1197
1198 /* Fetch the byte */
1199 if (!Soft386FetchByte(State, &Value))
1200 {
1201 /* Exception occurred */
1202 return FALSE;
1203 }
1204
1205 if (Opcode & 0x04)
1206 {
1207 /* AH, CH, DH or BH */
1208 State->GeneralRegs[Opcode & 0x03].HighByte = Value;
1209 }
1210 else
1211 {
1212 /* AL, CL, DL or BL */
1213 State->GeneralRegs[Opcode & 0x03].LowByte = Value;
1214 }
1215
1216 return TRUE;
1217 }
1218
1219 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddByteModrm)
1220 {
1221 UCHAR FirstValue, SecondValue, Result;
1222 SOFT386_MOD_REG_RM ModRegRm;
1223 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
1224
1225 /* Make sure this is the right instruction */
1226 ASSERT((Opcode & 0xFD) == 0x00);
1227
1228 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
1229 {
1230 /* The ADSIZE prefix toggles the size */
1231 AddressSize = !AddressSize;
1232 }
1233 else if (State->PrefixFlags
1234 & ~(SOFT386_PREFIX_ADSIZE
1235 | SOFT386_PREFIX_SEG
1236 | SOFT386_PREFIX_LOCK))
1237 {
1238 /* Invalid prefix */
1239 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1240 return FALSE;
1241 }
1242
1243 /* Get the operands */
1244 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
1245 {
1246 /* Exception occurred */
1247 return FALSE;
1248 }
1249
1250 if (!Soft386ReadModrmByteOperands(State,
1251 &ModRegRm,
1252 &FirstValue,
1253 &SecondValue))
1254 {
1255 /* Exception occurred */
1256 return FALSE;
1257 }
1258
1259 /* Calculate the result */
1260 Result = FirstValue + SecondValue;
1261
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);
1270
1271 /* Write back the result */
1272 return Soft386WriteModrmByteOperands(State,
1273 &ModRegRm,
1274 Opcode & SOFT386_OPCODE_WRITE_REG,
1275 Result);
1276 }
1277
1278 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddModrm)
1279 {
1280 SOFT386_MOD_REG_RM ModRegRm;
1281 BOOLEAN OperandSize, AddressSize;
1282
1283 /* Make sure this is the right instruction */
1284 ASSERT((Opcode & 0xFD) == 0x01);
1285
1286 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
1287
1288 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
1289 {
1290 /* The ADSIZE prefix toggles the address size */
1291 AddressSize = !AddressSize;
1292 }
1293
1294 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
1295 {
1296 /* The OPSIZE prefix toggles the operand size */
1297 OperandSize = !OperandSize;
1298 }
1299
1300 if (State->PrefixFlags
1301 & ~(SOFT386_PREFIX_ADSIZE
1302 | SOFT386_PREFIX_OPSIZE
1303 | SOFT386_PREFIX_SEG
1304 | SOFT386_PREFIX_LOCK))
1305 {
1306 /* Invalid prefix */
1307 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1308 return FALSE;
1309 }
1310
1311 /* Get the operands */
1312 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
1313 {
1314 /* Exception occurred */
1315 return FALSE;
1316 }
1317
1318 /* Check the operand size */
1319 if (OperandSize)
1320 {
1321 ULONG FirstValue, SecondValue, Result;
1322
1323 if (!Soft386ReadModrmDwordOperands(State,
1324 &ModRegRm,
1325 &FirstValue,
1326 &SecondValue))
1327 {
1328 /* Exception occurred */
1329 return FALSE;
1330 }
1331
1332 /* Calculate the result */
1333 Result = FirstValue + SecondValue;
1334
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);
1343
1344 /* Write back the result */
1345 return Soft386WriteModrmDwordOperands(State,
1346 &ModRegRm,
1347 Opcode & SOFT386_OPCODE_WRITE_REG,
1348 Result);
1349 }
1350 else
1351 {
1352 USHORT FirstValue, SecondValue, Result;
1353
1354 if (!Soft386ReadModrmWordOperands(State,
1355 &ModRegRm,
1356 &FirstValue,
1357 &SecondValue))
1358 {
1359 /* Exception occurred */
1360 return FALSE;
1361 }
1362
1363 /* Calculate the result */
1364 Result = FirstValue + SecondValue;
1365
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);
1374
1375 /* Write back the result */
1376 return Soft386WriteModrmWordOperands(State,
1377 &ModRegRm,
1378 Opcode & SOFT386_OPCODE_WRITE_REG,
1379 Result);
1380 }
1381 }
1382
1383 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddAl)
1384 {
1385 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
1386 UCHAR SecondValue, Result;
1387
1388 /* Make sure this is the right instruction */
1389 ASSERT(Opcode == 0x04);
1390
1391 if (State->PrefixFlags)
1392 {
1393 /* This opcode doesn't take any prefixes */
1394 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1395 return FALSE;
1396 }
1397
1398 if (!Soft386FetchByte(State, &SecondValue))
1399 {
1400 /* Exception occurred */
1401 return FALSE;
1402 }
1403
1404 /* Calculate the result */
1405 Result = FirstValue + SecondValue;
1406
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);
1415
1416 /* Write back the result */
1417 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
1418
1419 return TRUE;
1420 }
1421
1422 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddEax)
1423 {
1424 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
1425
1426 /* Make sure this is the right instruction */
1427 ASSERT(Opcode == 0x05);
1428
1429 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
1430 {
1431 /* Invalid prefix */
1432 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1433 return FALSE;
1434 }
1435
1436 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
1437 {
1438 /* The OPSIZE prefix toggles the size */
1439 Size = !Size;
1440 }
1441
1442 if (Size)
1443 {
1444 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
1445 ULONG SecondValue, Result;
1446
1447 if (!Soft386FetchDword(State, &SecondValue))
1448 {
1449 /* Exception occurred */
1450 return FALSE;
1451 }
1452
1453 /* Calculate the result */
1454 Result = FirstValue + SecondValue;
1455
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);
1464
1465 /* Write back the result */
1466 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
1467 }
1468 else
1469 {
1470 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
1471 USHORT SecondValue, Result;
1472
1473 if (!Soft386FetchWord(State, &SecondValue))
1474 {
1475 /* Exception occurred */
1476 return FALSE;
1477 }
1478
1479 /* Calculate the result */
1480 Result = FirstValue + SecondValue;
1481
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);
1490
1491 /* Write back the result */
1492 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
1493 }
1494
1495 return TRUE;
1496 }
1497
1498 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrByteModrm)
1499 {
1500 UCHAR FirstValue, SecondValue, Result;
1501 SOFT386_MOD_REG_RM ModRegRm;
1502 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
1503
1504 /* Make sure this is the right instruction */
1505 ASSERT((Opcode & 0xFD) == 0x08);
1506
1507 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
1508 {
1509 /* The ADSIZE prefix toggles the size */
1510 AddressSize = !AddressSize;
1511 }
1512 else if (State->PrefixFlags
1513 & ~(SOFT386_PREFIX_ADSIZE
1514 | SOFT386_PREFIX_SEG
1515 | SOFT386_PREFIX_LOCK))
1516 {
1517 /* Invalid prefix */
1518 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1519 return FALSE;
1520 }
1521
1522 /* Get the operands */
1523 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
1524 {
1525 /* Exception occurred */
1526 return FALSE;
1527 }
1528
1529 if (!Soft386ReadModrmByteOperands(State,
1530 &ModRegRm,
1531 &FirstValue,
1532 &SecondValue))
1533 {
1534 /* Exception occurred */
1535 return FALSE;
1536 }
1537
1538 /* Calculate the result */
1539 Result = FirstValue | SecondValue;
1540
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);
1547
1548 /* Write back the result */
1549 return Soft386WriteModrmByteOperands(State,
1550 &ModRegRm,
1551 Opcode & SOFT386_OPCODE_WRITE_REG,
1552 Result);
1553 }
1554
1555 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrModrm)
1556 {
1557 SOFT386_MOD_REG_RM ModRegRm;
1558 BOOLEAN OperandSize, AddressSize;
1559
1560 /* Make sure this is the right instruction */
1561 ASSERT((Opcode & 0xFD) == 0x09);
1562
1563 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
1564
1565 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
1566 {
1567 /* The ADSIZE prefix toggles the address size */
1568 AddressSize = !AddressSize;
1569 }
1570
1571 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
1572 {
1573 /* The OPSIZE prefix toggles the operand size */
1574 OperandSize = !OperandSize;
1575 }
1576
1577 if (State->PrefixFlags
1578 & ~(SOFT386_PREFIX_ADSIZE
1579 | SOFT386_PREFIX_OPSIZE
1580 | SOFT386_PREFIX_SEG
1581 | SOFT386_PREFIX_LOCK))
1582 {
1583 /* Invalid prefix */
1584 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1585 return FALSE;
1586 }
1587
1588 /* Get the operands */
1589 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
1590 {
1591 /* Exception occurred */
1592 return FALSE;
1593 }
1594
1595 /* Check the operand size */
1596 if (OperandSize)
1597 {
1598 ULONG FirstValue, SecondValue, Result;
1599
1600 if (!Soft386ReadModrmDwordOperands(State,
1601 &ModRegRm,
1602 &FirstValue,
1603 &SecondValue))
1604 {
1605 /* Exception occurred */
1606 return FALSE;
1607 }
1608
1609 /* Calculate the result */
1610 Result = FirstValue | SecondValue;
1611
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);
1618
1619 /* Write back the result */
1620 return Soft386WriteModrmDwordOperands(State,
1621 &ModRegRm,
1622 Opcode & SOFT386_OPCODE_WRITE_REG,
1623 Result);
1624 }
1625 else
1626 {
1627 USHORT FirstValue, SecondValue, Result;
1628
1629 if (!Soft386ReadModrmWordOperands(State,
1630 &ModRegRm,
1631 &FirstValue,
1632 &SecondValue))
1633 {
1634 /* Exception occurred */
1635 return FALSE;
1636 }
1637
1638 /* Calculate the result */
1639 Result = FirstValue | SecondValue;
1640
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);
1647
1648 /* Write back the result */
1649 return Soft386WriteModrmWordOperands(State,
1650 &ModRegRm,
1651 Opcode & SOFT386_OPCODE_WRITE_REG,
1652 Result);
1653 }
1654 }
1655
1656 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrAl)
1657 {
1658 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
1659 UCHAR SecondValue, Result;
1660
1661 /* Make sure this is the right instruction */
1662 ASSERT(Opcode == 0x0C);
1663
1664 if (State->PrefixFlags)
1665 {
1666 /* This opcode doesn't take any prefixes */
1667 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1668 return FALSE;
1669 }
1670
1671 if (!Soft386FetchByte(State, &SecondValue))
1672 {
1673 /* Exception occurred */
1674 return FALSE;
1675 }
1676
1677 /* Calculate the result */
1678 Result = FirstValue | SecondValue;
1679
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);
1686
1687 /* Write back the result */
1688 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
1689
1690 return TRUE;
1691 }
1692
1693 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrEax)
1694 {
1695 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
1696
1697 /* Make sure this is the right instruction */
1698 ASSERT(Opcode == 0x0D);
1699
1700 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
1701 {
1702 /* Invalid prefix */
1703 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1704 return FALSE;
1705 }
1706
1707 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
1708 {
1709 /* The OPSIZE prefix toggles the size */
1710 Size = !Size;
1711 }
1712
1713 if (Size)
1714 {
1715 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
1716 ULONG SecondValue, Result;
1717
1718 if (!Soft386FetchDword(State, &SecondValue))
1719 {
1720 /* Exception occurred */
1721 return FALSE;
1722 }
1723
1724 /* Calculate the result */
1725 Result = FirstValue | SecondValue;
1726
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);
1733
1734 /* Write back the result */
1735 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
1736 }
1737 else
1738 {
1739 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
1740 USHORT SecondValue, Result;
1741
1742 if (!Soft386FetchWord(State, &SecondValue))
1743 {
1744 /* Exception occurred */
1745 return FALSE;
1746 }
1747
1748 /* Calculate the result */
1749 Result = FirstValue | SecondValue;
1750
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);
1757
1758 /* Write back the result */
1759 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
1760 }
1761
1762 return TRUE;
1763 }
1764
1765 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndByteModrm)
1766 {
1767 UCHAR FirstValue, SecondValue, Result;
1768 SOFT386_MOD_REG_RM ModRegRm;
1769 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
1770
1771 /* Make sure this is the right instruction */
1772 ASSERT((Opcode & 0xFD) == 0x20);
1773
1774 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
1775 {
1776 /* The ADSIZE prefix toggles the size */
1777 AddressSize = !AddressSize;
1778 }
1779 else if (State->PrefixFlags
1780 & ~(SOFT386_PREFIX_ADSIZE
1781 | SOFT386_PREFIX_SEG
1782 | SOFT386_PREFIX_LOCK))
1783 {
1784 /* Invalid prefix */
1785 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1786 return FALSE;
1787 }
1788
1789 /* Get the operands */
1790 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
1791 {
1792 /* Exception occurred */
1793 return FALSE;
1794 }
1795
1796 if (!Soft386ReadModrmByteOperands(State,
1797 &ModRegRm,
1798 &FirstValue,
1799 &SecondValue))
1800 {
1801 /* Exception occurred */
1802 return FALSE;
1803 }
1804
1805 /* Calculate the result */
1806 Result = FirstValue & SecondValue;
1807
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);
1814
1815 /* Write back the result */
1816 return Soft386WriteModrmByteOperands(State,
1817 &ModRegRm,
1818 Opcode & SOFT386_OPCODE_WRITE_REG,
1819 Result);
1820 }
1821
1822 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndModrm)
1823 {
1824 SOFT386_MOD_REG_RM ModRegRm;
1825 BOOLEAN OperandSize, AddressSize;
1826
1827 /* Make sure this is the right instruction */
1828 ASSERT((Opcode & 0xFD) == 0x21);
1829
1830 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
1831
1832 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
1833 {
1834 /* The ADSIZE prefix toggles the address size */
1835 AddressSize = !AddressSize;
1836 }
1837
1838 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
1839 {
1840 /* The OPSIZE prefix toggles the operand size */
1841 OperandSize = !OperandSize;
1842 }
1843
1844 if (State->PrefixFlags
1845 & ~(SOFT386_PREFIX_ADSIZE
1846 | SOFT386_PREFIX_OPSIZE
1847 | SOFT386_PREFIX_SEG
1848 | SOFT386_PREFIX_LOCK))
1849 {
1850 /* Invalid prefix */
1851 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1852 return FALSE;
1853 }
1854
1855 /* Get the operands */
1856 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
1857 {
1858 /* Exception occurred */
1859 return FALSE;
1860 }
1861
1862 /* Check the operand size */
1863 if (OperandSize)
1864 {
1865 ULONG FirstValue, SecondValue, Result;
1866
1867 if (!Soft386ReadModrmDwordOperands(State,
1868 &ModRegRm,
1869 &FirstValue,
1870 &SecondValue))
1871 {
1872 /* Exception occurred */
1873 return FALSE;
1874 }
1875
1876 /* Calculate the result */
1877 Result = FirstValue & SecondValue;
1878
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);
1885
1886 /* Write back the result */
1887 return Soft386WriteModrmDwordOperands(State,
1888 &ModRegRm,
1889 Opcode & SOFT386_OPCODE_WRITE_REG,
1890 Result);
1891 }
1892 else
1893 {
1894 USHORT FirstValue, SecondValue, Result;
1895
1896 if (!Soft386ReadModrmWordOperands(State,
1897 &ModRegRm,
1898 &FirstValue,
1899 &SecondValue))
1900 {
1901 /* Exception occurred */
1902 return FALSE;
1903 }
1904
1905 /* Calculate the result */
1906 Result = FirstValue & SecondValue;
1907
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);
1914
1915 /* Write back the result */
1916 return Soft386WriteModrmWordOperands(State,
1917 &ModRegRm,
1918 Opcode & SOFT386_OPCODE_WRITE_REG,
1919 Result);
1920 }
1921 }
1922
1923 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndAl)
1924 {
1925 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
1926 UCHAR SecondValue, Result;
1927
1928 /* Make sure this is the right instruction */
1929 ASSERT(Opcode == 0x24);
1930
1931 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
1932 {
1933 /* Invalid prefix */
1934 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1935 return FALSE;
1936 }
1937
1938 if (!Soft386FetchByte(State, &SecondValue))
1939 {
1940 /* Exception occurred */
1941 return FALSE;
1942 }
1943
1944 /* Calculate the result */
1945 Result = FirstValue & SecondValue;
1946
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);
1953
1954 /* Write back the result */
1955 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
1956
1957 return TRUE;
1958 }
1959
1960 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndEax)
1961 {
1962 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
1963
1964 /* Make sure this is the right instruction */
1965 ASSERT(Opcode == 0x25);
1966
1967 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
1968 {
1969 /* Invalid prefix */
1970 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1971 return FALSE;
1972 }
1973
1974 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
1975 {
1976 /* The OPSIZE prefix toggles the size */
1977 Size = !Size;
1978 }
1979
1980 if (Size)
1981 {
1982 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
1983 ULONG SecondValue, Result;
1984
1985 if (!Soft386FetchDword(State, &SecondValue))
1986 {
1987 /* Exception occurred */
1988 return FALSE;
1989 }
1990
1991 /* Calculate the result */
1992 Result = FirstValue & SecondValue;
1993
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);
2000
2001 /* Write back the result */
2002 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
2003 }
2004 else
2005 {
2006 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
2007 USHORT SecondValue, Result;
2008
2009 if (!Soft386FetchWord(State, &SecondValue))
2010 {
2011 /* Exception occurred */
2012 return FALSE;
2013 }
2014
2015 /* Calculate the result */
2016 Result = FirstValue & SecondValue;
2017
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);
2024
2025 /* Write back the result */
2026 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
2027 }
2028
2029 return TRUE;
2030 }
2031
2032 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorByteModrm)
2033 {
2034 UCHAR FirstValue, SecondValue, Result;
2035 SOFT386_MOD_REG_RM ModRegRm;
2036 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2037
2038 /* Make sure this is the right instruction */
2039 ASSERT((Opcode & 0xFD) == 0x30);
2040
2041 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2042 {
2043 /* The ADSIZE prefix toggles the size */
2044 AddressSize = !AddressSize;
2045 }
2046 else if (State->PrefixFlags
2047 & ~(SOFT386_PREFIX_ADSIZE
2048 | SOFT386_PREFIX_SEG
2049 | SOFT386_PREFIX_LOCK))
2050 {
2051 /* Invalid prefix */
2052 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2053 return FALSE;
2054 }
2055
2056 /* Get the operands */
2057 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2058 {
2059 /* Exception occurred */
2060 return FALSE;
2061 }
2062
2063 if (!Soft386ReadModrmByteOperands(State,
2064 &ModRegRm,
2065 &FirstValue,
2066 &SecondValue))
2067 {
2068 /* Exception occurred */
2069 return FALSE;
2070 }
2071
2072 /* Calculate the result */
2073 Result = FirstValue ^ SecondValue;
2074
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);
2081
2082 /* Write back the result */
2083 return Soft386WriteModrmByteOperands(State,
2084 &ModRegRm,
2085 Opcode & SOFT386_OPCODE_WRITE_REG,
2086 Result);
2087 }
2088
2089 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorModrm)
2090 {
2091 SOFT386_MOD_REG_RM ModRegRm;
2092 BOOLEAN OperandSize, AddressSize;
2093
2094 /* Make sure this is the right instruction */
2095 ASSERT((Opcode & 0xFD) == 0x31);
2096
2097 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2098
2099 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2100 {
2101 /* The ADSIZE prefix toggles the address size */
2102 AddressSize = !AddressSize;
2103 }
2104
2105 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2106 {
2107 /* The OPSIZE prefix toggles the operand size */
2108 OperandSize = !OperandSize;
2109 }
2110
2111 if (State->PrefixFlags
2112 & ~(SOFT386_PREFIX_ADSIZE
2113 | SOFT386_PREFIX_OPSIZE
2114 | SOFT386_PREFIX_SEG
2115 | SOFT386_PREFIX_LOCK))
2116 {
2117 /* Invalid prefix */
2118 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2119 return FALSE;
2120 }
2121
2122 /* Get the operands */
2123 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2124 {
2125 /* Exception occurred */
2126 return FALSE;
2127 }
2128
2129 /* Check the operand size */
2130 if (OperandSize)
2131 {
2132 ULONG FirstValue, SecondValue, Result;
2133
2134 if (!Soft386ReadModrmDwordOperands(State,
2135 &ModRegRm,
2136 &FirstValue,
2137 &SecondValue))
2138 {
2139 /* Exception occurred */
2140 return FALSE;
2141 }
2142
2143 /* Calculate the result */
2144 Result = FirstValue ^ SecondValue;
2145
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);
2152
2153 /* Write back the result */
2154 return Soft386WriteModrmDwordOperands(State,
2155 &ModRegRm,
2156 Opcode & SOFT386_OPCODE_WRITE_REG,
2157 Result);
2158 }
2159 else
2160 {
2161 USHORT FirstValue, SecondValue, Result;
2162
2163 if (!Soft386ReadModrmWordOperands(State,
2164 &ModRegRm,
2165 &FirstValue,
2166 &SecondValue))
2167 {
2168 /* Exception occurred */
2169 return FALSE;
2170 }
2171
2172 /* Calculate the result */
2173 Result = FirstValue ^ SecondValue;
2174
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);
2181
2182 /* Write back the result */
2183 return Soft386WriteModrmWordOperands(State,
2184 &ModRegRm,
2185 Opcode & SOFT386_OPCODE_WRITE_REG,
2186 Result);
2187 }
2188 }
2189
2190 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorAl)
2191 {
2192 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
2193 UCHAR SecondValue, Result;
2194
2195 /* Make sure this is the right instruction */
2196 ASSERT(Opcode == 0x34);
2197
2198 if (State->PrefixFlags)
2199 {
2200 /* This opcode doesn't take any prefixes */
2201 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2202 return FALSE;
2203 }
2204
2205 if (!Soft386FetchByte(State, &SecondValue))
2206 {
2207 /* Exception occurred */
2208 return FALSE;
2209 }
2210
2211 /* Calculate the result */
2212 Result = FirstValue ^ SecondValue;
2213
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);
2220
2221 /* Write back the result */
2222 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
2223
2224 return TRUE;
2225 }
2226
2227 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorEax)
2228 {
2229 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
2230
2231 /* Make sure this is the right instruction */
2232 ASSERT(Opcode == 0x35);
2233
2234 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
2235 {
2236 /* Invalid prefix */
2237 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2238 return FALSE;
2239 }
2240
2241 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2242 {
2243 /* The OPSIZE prefix toggles the size */
2244 Size = !Size;
2245 }
2246
2247 if (Size)
2248 {
2249 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
2250 ULONG SecondValue, Result;
2251
2252 if (!Soft386FetchDword(State, &SecondValue))
2253 {
2254 /* Exception occurred */
2255 return FALSE;
2256 }
2257
2258 /* Calculate the result */
2259 Result = FirstValue ^ SecondValue;
2260
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);
2267
2268 /* Write back the result */
2269 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
2270 }
2271 else
2272 {
2273 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
2274 USHORT SecondValue, Result;
2275
2276 if (!Soft386FetchWord(State, &SecondValue))
2277 {
2278 /* Exception occurred */
2279 return FALSE;
2280 }
2281
2282 /* Calculate the result */
2283 Result = FirstValue ^ SecondValue;
2284
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);
2291
2292 /* Write back the result */
2293 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
2294 }
2295
2296 return TRUE;
2297 }
2298
2299 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestByteModrm)
2300 {
2301 UCHAR FirstValue, SecondValue, Result;
2302 SOFT386_MOD_REG_RM ModRegRm;
2303 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2304
2305 /* Make sure this is the right instruction */
2306 ASSERT(Opcode == 0x84);
2307
2308 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2309 {
2310 /* The ADSIZE prefix toggles the size */
2311 AddressSize = !AddressSize;
2312 }
2313 else if (State->PrefixFlags
2314 & ~(SOFT386_PREFIX_ADSIZE
2315 | SOFT386_PREFIX_SEG
2316 | SOFT386_PREFIX_LOCK))
2317 {
2318 /* Invalid prefix */
2319 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2320 return FALSE;
2321 }
2322
2323 /* Get the operands */
2324 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2325 {
2326 /* Exception occurred */
2327 return FALSE;
2328 }
2329
2330 if (!Soft386ReadModrmByteOperands(State,
2331 &ModRegRm,
2332 &FirstValue,
2333 &SecondValue))
2334 {
2335 /* Exception occurred */
2336 return FALSE;
2337 }
2338 /* Calculate the result */
2339 Result = FirstValue & SecondValue;
2340
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);
2347
2348 /* The result is discarded */
2349 return TRUE;
2350 }
2351
2352 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestModrm)
2353 {
2354 SOFT386_MOD_REG_RM ModRegRm;
2355 BOOLEAN OperandSize, AddressSize;
2356
2357 /* Make sure this is the right instruction */
2358 ASSERT(Opcode == 0x85);
2359
2360 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2361
2362 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2363 {
2364 /* The ADSIZE prefix toggles the address size */
2365 AddressSize = !AddressSize;
2366 }
2367
2368 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2369 {
2370 /* The OPSIZE prefix toggles the operand size */
2371 OperandSize = !OperandSize;
2372 }
2373
2374 if (State->PrefixFlags
2375 & ~(SOFT386_PREFIX_ADSIZE
2376 | SOFT386_PREFIX_OPSIZE
2377 | SOFT386_PREFIX_SEG
2378 | SOFT386_PREFIX_LOCK))
2379 {
2380 /* Invalid prefix */
2381 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2382 return FALSE;
2383 }
2384
2385 /* Get the operands */
2386 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2387 {
2388 /* Exception occurred */
2389 return FALSE;
2390 }
2391
2392 /* Check the operand size */
2393 if (OperandSize)
2394 {
2395 ULONG FirstValue, SecondValue, Result;
2396
2397 if (!Soft386ReadModrmDwordOperands(State,
2398 &ModRegRm,
2399 &FirstValue,
2400 &SecondValue))
2401 {
2402 /* Exception occurred */
2403 return FALSE;
2404 }
2405
2406 /* Calculate the result */
2407 Result = FirstValue & SecondValue;
2408
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);
2415 }
2416 else
2417 {
2418 USHORT FirstValue, SecondValue, Result;
2419
2420 if (!Soft386ReadModrmWordOperands(State,
2421 &ModRegRm,
2422 &FirstValue,
2423 &SecondValue))
2424 {
2425 /* Exception occurred */
2426 return FALSE;
2427 }
2428
2429 /* Calculate the result */
2430 Result = FirstValue & SecondValue;
2431
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);
2438 }
2439
2440 /* The result is discarded */
2441 return TRUE;
2442 }
2443
2444 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestAl)
2445 {
2446 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
2447 UCHAR SecondValue, Result;
2448
2449 /* Make sure this is the right instruction */
2450 ASSERT(Opcode == 0xA8);
2451
2452 if (State->PrefixFlags)
2453 {
2454 /* This opcode doesn't take any prefixes */
2455 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2456 return FALSE;
2457 }
2458
2459 if (!Soft386FetchByte(State, &SecondValue))
2460 {
2461 /* Exception occurred */
2462 return FALSE;
2463 }
2464
2465 /* Calculate the result */
2466 Result = FirstValue & SecondValue;
2467
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);
2474
2475 /* The result is discarded */
2476 return TRUE;
2477 }
2478
2479 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestEax)
2480 {
2481 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
2482
2483 /* Make sure this is the right instruction */
2484 ASSERT(Opcode == 0xA9);
2485
2486 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
2487 {
2488 /* Invalid prefix */
2489 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2490 return FALSE;
2491 }
2492
2493 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2494 {
2495 /* The OPSIZE prefix toggles the size */
2496 Size = !Size;
2497 }
2498
2499 if (Size)
2500 {
2501 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
2502 ULONG SecondValue, Result;
2503
2504 if (!Soft386FetchDword(State, &SecondValue))
2505 {
2506 /* Exception occurred */
2507 return FALSE;
2508 }
2509
2510 /* Calculate the result */
2511 Result = FirstValue & SecondValue;
2512
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);
2519 }
2520 else
2521 {
2522 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
2523 USHORT SecondValue, Result;
2524
2525 if (!Soft386FetchWord(State, &SecondValue))
2526 {
2527 /* Exception occurred */
2528 return FALSE;
2529 }
2530
2531 /* Calculate the result */
2532 Result = FirstValue & SecondValue;
2533
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);
2540 }
2541
2542 /* The result is discarded */
2543 return TRUE;
2544 }
2545
2546 SOFT386_OPCODE_HANDLER(Soft386OpcodeXchgByteModrm)
2547 {
2548 UCHAR FirstValue, SecondValue;
2549 SOFT386_MOD_REG_RM ModRegRm;
2550 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2551
2552 /* Make sure this is the right instruction */
2553 ASSERT(Opcode == 0x86);
2554
2555 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2556 {
2557 /* The ADSIZE prefix toggles the size */
2558 AddressSize = !AddressSize;
2559 }
2560 else if (State->PrefixFlags
2561 & ~(SOFT386_PREFIX_ADSIZE
2562 | SOFT386_PREFIX_SEG
2563 | SOFT386_PREFIX_LOCK))
2564 {
2565 /* Invalid prefix */
2566 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2567 return FALSE;
2568 }
2569
2570 /* Get the operands */
2571 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2572 {
2573 /* Exception occurred */
2574 return FALSE;
2575 }
2576
2577 if (!Soft386ReadModrmByteOperands(State,
2578 &ModRegRm,
2579 &FirstValue,
2580 &SecondValue))
2581 {
2582 /* Exception occurred */
2583 return FALSE;
2584 }
2585
2586 /* Write the value from the register to the R/M */
2587 if (!Soft386WriteModrmByteOperands(State,
2588 &ModRegRm,
2589 FALSE,
2590 FirstValue))
2591 {
2592 /* Exception occurred */
2593 return FALSE;
2594 }
2595
2596 /* Write the value from the R/M to the register */
2597 if (!Soft386WriteModrmByteOperands(State,
2598 &ModRegRm,
2599 TRUE,
2600 SecondValue))
2601 {
2602 /* Exception occurred */
2603 return FALSE;
2604 }
2605
2606 return TRUE;
2607 }
2608
2609 SOFT386_OPCODE_HANDLER(Soft386OpcodeXchgModrm)
2610 {
2611 SOFT386_MOD_REG_RM ModRegRm;
2612 BOOLEAN OperandSize, AddressSize;
2613
2614 /* Make sure this is the right instruction */
2615 ASSERT(Opcode == 0x87);
2616
2617 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2618
2619 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2620 {
2621 /* The ADSIZE prefix toggles the address size */
2622 AddressSize = !AddressSize;
2623 }
2624
2625 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2626 {
2627 /* The OPSIZE prefix toggles the operand size */
2628 OperandSize = !OperandSize;
2629 }
2630
2631 if (State->PrefixFlags
2632 & ~(SOFT386_PREFIX_ADSIZE
2633 | SOFT386_PREFIX_OPSIZE
2634 | SOFT386_PREFIX_SEG
2635 | SOFT386_PREFIX_LOCK))
2636 {
2637 /* Invalid prefix */
2638 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2639 return FALSE;
2640 }
2641
2642 /* Get the operands */
2643 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2644 {
2645 /* Exception occurred */
2646 return FALSE;
2647 }
2648
2649 /* Check the operand size */
2650 if (OperandSize)
2651 {
2652 ULONG FirstValue, SecondValue;
2653
2654 if (!Soft386ReadModrmDwordOperands(State,
2655 &ModRegRm,
2656 &FirstValue,
2657 &SecondValue))
2658 {
2659 /* Exception occurred */
2660 return FALSE;
2661 }
2662
2663 /* Write the value from the register to the R/M */
2664 if (!Soft386WriteModrmDwordOperands(State,
2665 &ModRegRm,
2666 FALSE,
2667 FirstValue))
2668 {
2669 /* Exception occurred */
2670 return FALSE;
2671 }
2672
2673 /* Write the value from the R/M to the register */
2674 if (!Soft386WriteModrmDwordOperands(State,
2675 &ModRegRm,
2676 TRUE,
2677 SecondValue))
2678 {
2679 /* Exception occurred */
2680 return FALSE;
2681 }
2682 }
2683 else
2684 {
2685 USHORT FirstValue, SecondValue;
2686
2687 if (!Soft386ReadModrmWordOperands(State,
2688 &ModRegRm,
2689 &FirstValue,
2690 &SecondValue))
2691 {
2692 /* Exception occurred */
2693 return FALSE;
2694 }
2695
2696 /* Write the value from the register to the R/M */
2697 if (!Soft386WriteModrmWordOperands(State,
2698 &ModRegRm,
2699 FALSE,
2700 FirstValue))
2701 {
2702 /* Exception occurred */
2703 return FALSE;
2704 }
2705
2706 /* Write the value from the R/M to the register */
2707 if (!Soft386WriteModrmWordOperands(State,
2708 &ModRegRm,
2709 TRUE,
2710 SecondValue))
2711 {
2712 /* Exception occurred */
2713 return FALSE;
2714 }
2715 }
2716
2717 /* The result is discarded */
2718 return TRUE;
2719 }
2720
2721 SOFT386_OPCODE_HANDLER(Soft386OpcodePushEs)
2722 {
2723 /* Call the internal API */
2724 return Soft386StackPush(State, State->SegmentRegs[SOFT386_REG_ES].Selector);
2725 }
2726
2727 SOFT386_OPCODE_HANDLER(Soft386OpcodePopEs)
2728 {
2729 ULONG NewSelector;
2730
2731 if (!Soft386StackPop(State, &NewSelector))
2732 {
2733 /* Exception occurred */
2734 return FALSE;
2735 }
2736
2737 /* Call the internal API */
2738 return Soft386LoadSegment(State, SOFT386_REG_ES, LOWORD(NewSelector));
2739 }
2740
2741 SOFT386_OPCODE_HANDLER(Soft386OpcodePushCs)
2742 {
2743 /* Call the internal API */
2744 return Soft386StackPush(State, State->SegmentRegs[SOFT386_REG_CS].Selector);
2745 }
2746
2747 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcByteModrm)
2748 {
2749 UCHAR FirstValue, SecondValue, Result;
2750 SOFT386_MOD_REG_RM ModRegRm;
2751 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2752
2753 /* Make sure this is the right instruction */
2754 ASSERT((Opcode & 0xFD) == 0x10);
2755
2756 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2757 {
2758 /* The ADSIZE prefix toggles the size */
2759 AddressSize = !AddressSize;
2760 }
2761 else if (State->PrefixFlags
2762 & ~(SOFT386_PREFIX_ADSIZE
2763 | SOFT386_PREFIX_SEG
2764 | SOFT386_PREFIX_LOCK))
2765 {
2766 /* Invalid prefix */
2767 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2768 return FALSE;
2769 }
2770
2771 /* Get the operands */
2772 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2773 {
2774 /* Exception occurred */
2775 return FALSE;
2776 }
2777
2778 if (!Soft386ReadModrmByteOperands(State,
2779 &ModRegRm,
2780 &FirstValue,
2781 &SecondValue))
2782 {
2783 /* Exception occurred */
2784 return FALSE;
2785 }
2786
2787 /* Calculate the result */
2788 Result = FirstValue + SecondValue + State->Flags.Cf;
2789
2790 /* Special exception for CF */
2791 State->Flags.Cf = State->Flags.Cf
2792 && ((FirstValue == 0xFF) || (SecondValue == 0xFF));
2793
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);
2802
2803 /* Write back the result */
2804 return Soft386WriteModrmByteOperands(State,
2805 &ModRegRm,
2806 Opcode & SOFT386_OPCODE_WRITE_REG,
2807 Result);
2808 }
2809
2810 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcModrm)
2811 {
2812 SOFT386_MOD_REG_RM ModRegRm;
2813 BOOLEAN OperandSize, AddressSize;
2814
2815 /* Make sure this is the right instruction */
2816 ASSERT((Opcode & 0xFD) == 0x11);
2817
2818 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2819
2820 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2821 {
2822 /* The ADSIZE prefix toggles the address size */
2823 AddressSize = !AddressSize;
2824 }
2825
2826 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2827 {
2828 /* The OPSIZE prefix toggles the operand size */
2829 OperandSize = !OperandSize;
2830 }
2831
2832 if (State->PrefixFlags
2833 & ~(SOFT386_PREFIX_ADSIZE
2834 | SOFT386_PREFIX_OPSIZE
2835 | SOFT386_PREFIX_SEG
2836 | SOFT386_PREFIX_LOCK))
2837 {
2838 /* Invalid prefix */
2839 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2840 return FALSE;
2841 }
2842
2843 /* Get the operands */
2844 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2845 {
2846 /* Exception occurred */
2847 return FALSE;
2848 }
2849
2850 /* Check the operand size */
2851 if (OperandSize)
2852 {
2853 ULONG FirstValue, SecondValue, Result;
2854
2855 if (!Soft386ReadModrmDwordOperands(State,
2856 &ModRegRm,
2857 &FirstValue,
2858 &SecondValue))
2859 {
2860 /* Exception occurred */
2861 return FALSE;
2862 }
2863
2864 /* Calculate the result */
2865 Result = FirstValue + SecondValue + State->Flags.Cf;
2866
2867 /* Special exception for CF */
2868 State->Flags.Cf = State->Flags.Cf
2869 && ((FirstValue == 0xFFFFFFFF) || (SecondValue == 0xFFFFFFFF));
2870
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);
2879
2880 /* Write back the result */
2881 return Soft386WriteModrmDwordOperands(State,
2882 &ModRegRm,
2883 Opcode & SOFT386_OPCODE_WRITE_REG,
2884 Result);
2885 }
2886 else
2887 {
2888 USHORT FirstValue, SecondValue, Result;
2889
2890 if (!Soft386ReadModrmWordOperands(State,
2891 &ModRegRm,
2892 &FirstValue,
2893 &SecondValue))
2894 {
2895 /* Exception occurred */
2896 return FALSE;
2897 }
2898
2899 /* Calculate the result */
2900 Result = FirstValue + SecondValue + State->Flags.Cf;
2901
2902 /* Special exception for CF */
2903 State->Flags.Cf = State->Flags.Cf
2904 && ((FirstValue == 0xFFFF) || (SecondValue == 0xFFFF));
2905
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);
2914
2915 /* Write back the result */
2916 return Soft386WriteModrmWordOperands(State,
2917 &ModRegRm,
2918 Opcode & SOFT386_OPCODE_WRITE_REG,
2919 Result);
2920 }
2921
2922 }
2923
2924 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcAl)
2925 {
2926 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
2927 UCHAR SecondValue, Result;
2928
2929 /* Make sure this is the right instruction */
2930 ASSERT(Opcode == 0x14);
2931
2932 if (State->PrefixFlags)
2933 {
2934 /* This opcode doesn't take any prefixes */
2935 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2936 return FALSE;
2937 }
2938
2939 if (!Soft386FetchByte(State, &SecondValue))
2940 {
2941 /* Exception occurred */
2942 return FALSE;
2943 }
2944
2945 /* Calculate the result */
2946 Result = FirstValue + SecondValue + State->Flags.Cf;
2947
2948 /* Special exception for CF */
2949 State->Flags.Cf = State->Flags.Cf &&
2950 ((FirstValue == 0xFF) || (SecondValue == 0xFF));
2951
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);
2960
2961 /* Write back the result */
2962 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
2963
2964 return TRUE;
2965 }
2966
2967 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcEax)
2968 {
2969 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
2970
2971 /* Make sure this is the right instruction */
2972 ASSERT(Opcode == 0x15);
2973
2974 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
2975 {
2976 /* Invalid prefix */
2977 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2978 return FALSE;
2979 }
2980
2981 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2982 {
2983 /* The OPSIZE prefix toggles the size */
2984 Size = !Size;
2985 }
2986
2987 if (Size)
2988 {
2989 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
2990 ULONG SecondValue, Result;
2991
2992 if (!Soft386FetchDword(State, &SecondValue))
2993 {
2994 /* Exception occurred */
2995 return FALSE;
2996 }
2997
2998 /* Calculate the result */
2999 Result = FirstValue + SecondValue + State->Flags.Cf;
3000
3001 /* Special exception for CF */
3002 State->Flags.Cf = State->Flags.Cf &&
3003 ((FirstValue == 0xFFFFFFFF) || (SecondValue == 0xFFFFFFFF));
3004
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);
3013
3014 /* Write back the result */
3015 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
3016 }
3017 else
3018 {
3019 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
3020 USHORT SecondValue, Result;
3021
3022 if (!Soft386FetchWord(State, &SecondValue))
3023 {
3024 /* Exception occurred */
3025 return FALSE;
3026 }
3027
3028 /* Calculate the result */
3029 Result = FirstValue + SecondValue + State->Flags.Cf;
3030
3031 /* Special exception for CF */
3032 State->Flags.Cf = State->Flags.Cf &&
3033 ((FirstValue == 0xFFFF) || (SecondValue == 0xFFFF));
3034
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);
3043
3044 /* Write back the result */
3045 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
3046 }
3047
3048 return TRUE;
3049 }
3050
3051 SOFT386_OPCODE_HANDLER(Soft386OpcodePushSs)
3052 {
3053 /* Call the internal API */
3054 return Soft386StackPush(State, State->SegmentRegs[SOFT386_REG_SS].Selector);
3055 }
3056
3057 SOFT386_OPCODE_HANDLER(Soft386OpcodePopSs)
3058 {
3059 ULONG NewSelector;
3060
3061 if (!Soft386StackPop(State, &NewSelector))
3062 {
3063 /* Exception occurred */
3064 return FALSE;
3065 }
3066
3067 /* Call the internal API */
3068 return Soft386LoadSegment(State, SOFT386_REG_SS, LOWORD(NewSelector));
3069 }
3070
3071 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbByteModrm)
3072 {
3073 // TODO: NOT IMPLEMENTED
3074 UNIMPLEMENTED;
3075
3076 return FALSE;
3077 }
3078
3079 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbModrm)
3080 {
3081 // TODO: NOT IMPLEMENTED
3082 UNIMPLEMENTED;
3083
3084 return FALSE;
3085 }
3086
3087 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbAl)
3088 {
3089 // TODO: NOT IMPLEMENTED
3090 UNIMPLEMENTED;
3091
3092 return FALSE;
3093 }
3094
3095 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbEax)
3096 {
3097 // TODO: NOT IMPLEMENTED
3098 UNIMPLEMENTED;
3099
3100 return FALSE;
3101 }
3102
3103 SOFT386_OPCODE_HANDLER(Soft386OpcodePushDs)
3104 {
3105 /* Call the internal API */
3106 return Soft386StackPush(State, State->SegmentRegs[SOFT386_REG_DS].Selector);
3107 }
3108
3109 SOFT386_OPCODE_HANDLER(Soft386OpcodePopDs)
3110 {
3111 ULONG NewSelector;
3112
3113 if (!Soft386StackPop(State, &NewSelector))
3114 {
3115 /* Exception occurred */
3116 return FALSE;
3117 }
3118
3119 /* Call the internal API */
3120 return Soft386LoadSegment(State, SOFT386_REG_DS, LOWORD(NewSelector));
3121 }
3122
3123 SOFT386_OPCODE_HANDLER(Soft386OpcodeDaa)
3124 {
3125 UCHAR Value = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
3126 BOOLEAN Carry = State->Flags.Cf;
3127
3128 /* Clear the carry flag */
3129 State->Flags.Cf = FALSE;
3130
3131 /* Check if the first BCD digit is invalid or there was a carry from it */
3132 if (((Value & 0x0F) > 9) || State->Flags.Af)
3133 {
3134 /* Correct it */
3135 State->GeneralRegs[SOFT386_REG_EAX].LowByte += 0x06;
3136 if (State->GeneralRegs[SOFT386_REG_EAX].LowByte < 0x06)
3137 {
3138 /* A carry occurred */
3139 State->Flags.Cf = TRUE;
3140 }
3141
3142 /* Set the adjust flag */
3143 State->Flags.Af = TRUE;
3144 }
3145
3146 /* Check if the second BCD digit is invalid or there was a carry from it */
3147 if ((Value > 0x99) || Carry)
3148 {
3149 /* Correct it */
3150 State->GeneralRegs[SOFT386_REG_EAX].LowByte += 0x60;
3151
3152 /* There was a carry */
3153 State->Flags.Cf = TRUE;
3154 }
3155
3156 return TRUE;
3157 }
3158
3159 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubByteModrm)
3160 {
3161 UCHAR FirstValue, SecondValue, Result;
3162 SOFT386_MOD_REG_RM ModRegRm;
3163 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
3164
3165 /* Make sure this is the right instruction */
3166 ASSERT((Opcode & 0xED) == 0x28);
3167
3168 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
3169 {
3170 /* The ADSIZE prefix toggles the size */
3171 AddressSize = !AddressSize;
3172 }
3173 else if (State->PrefixFlags
3174 & ~(SOFT386_PREFIX_ADSIZE
3175 | SOFT386_PREFIX_SEG
3176 | SOFT386_PREFIX_LOCK))
3177 {
3178 /* Invalid prefix */
3179 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3180 return FALSE;
3181 }
3182
3183 /* Get the operands */
3184 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
3185 {
3186 /* Exception occurred */
3187 return FALSE;
3188 }
3189
3190 if (!Soft386ReadModrmByteOperands(State,
3191 &ModRegRm,
3192 &FirstValue,
3193 &SecondValue))
3194 {
3195 /* Exception occurred */
3196 return FALSE;
3197 }
3198
3199 /* Check if this is the instruction that writes to R/M */
3200 if (!(Opcode & SOFT386_OPCODE_WRITE_REG))
3201 {
3202 /* Swap the order */
3203 FirstValue ^= SecondValue;
3204 SecondValue ^= FirstValue;
3205 FirstValue ^= SecondValue;
3206 }
3207
3208 /* Calculate the result */
3209 Result = FirstValue - SecondValue;
3210
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);
3219
3220 /* Check if this is not a CMP */
3221 if (!(Opcode & 0x10))
3222 {
3223 /* Write back the result */
3224 return Soft386WriteModrmByteOperands(State,
3225 &ModRegRm,
3226 Opcode & SOFT386_OPCODE_WRITE_REG,
3227 Result);
3228 }
3229 else
3230 {
3231 /* Discard the result */
3232 return TRUE;
3233 }
3234 }
3235
3236 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubModrm)
3237 {
3238 SOFT386_MOD_REG_RM ModRegRm;
3239 BOOLEAN OperandSize, AddressSize;
3240
3241 /* Make sure this is the right instruction */
3242 ASSERT((Opcode & 0xED) == 0x29);
3243
3244 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
3245
3246 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
3247 {
3248 /* The ADSIZE prefix toggles the address size */
3249 AddressSize = !AddressSize;
3250 }
3251
3252 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
3253 {
3254 /* The OPSIZE prefix toggles the operand size */
3255 OperandSize = !OperandSize;
3256 }
3257
3258 if (State->PrefixFlags
3259 & ~(SOFT386_PREFIX_ADSIZE
3260 | SOFT386_PREFIX_OPSIZE
3261 | SOFT386_PREFIX_SEG
3262 | SOFT386_PREFIX_LOCK))
3263 {
3264 /* Invalid prefix */
3265 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3266 return FALSE;
3267 }
3268
3269 /* Get the operands */
3270 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
3271 {
3272 /* Exception occurred */
3273 return FALSE;
3274 }
3275
3276 /* Check the operand size */
3277 if (OperandSize)
3278 {
3279 ULONG FirstValue, SecondValue, Result;
3280
3281 if (!Soft386ReadModrmDwordOperands(State,
3282 &ModRegRm,
3283 &FirstValue,
3284 &SecondValue))
3285 {
3286 /* Exception occurred */
3287 return FALSE;
3288 }
3289
3290 /* Check if this is the instruction that writes to R/M */
3291 if (!(Opcode & SOFT386_OPCODE_WRITE_REG))
3292 {
3293 /* Swap the order */
3294 FirstValue ^= SecondValue;
3295 SecondValue ^= FirstValue;
3296 FirstValue ^= SecondValue;
3297 }
3298
3299 /* Calculate the result */
3300 Result = FirstValue - SecondValue;
3301
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);
3310
3311 /* Check if this is not a CMP */
3312 if (!(Opcode & 0x10))
3313 {
3314 /* Write back the result */
3315 return Soft386WriteModrmDwordOperands(State,
3316 &ModRegRm,
3317 Opcode & SOFT386_OPCODE_WRITE_REG,
3318 Result);
3319 }
3320 else
3321 {
3322 /* Discard the result */
3323 return TRUE;
3324 }
3325 }
3326 else
3327 {
3328 USHORT FirstValue, SecondValue, Result;
3329
3330 if (!Soft386ReadModrmWordOperands(State,
3331 &ModRegRm,
3332 &FirstValue,
3333 &SecondValue))
3334 {
3335 /* Exception occurred */
3336 return FALSE;
3337 }
3338
3339 /* Check if this is the instruction that writes to R/M */
3340 if (!(Opcode & SOFT386_OPCODE_WRITE_REG))
3341 {
3342 /* Swap the order */
3343 FirstValue ^= SecondValue;
3344 SecondValue ^= FirstValue;
3345 FirstValue ^= SecondValue;
3346 }
3347
3348 /* Calculate the result */
3349 Result = FirstValue - SecondValue;
3350
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);
3359
3360 /* Check if this is not a CMP */
3361 if (!(Opcode & 0x10))
3362 {
3363 /* Write back the result */
3364 return Soft386WriteModrmWordOperands(State,
3365 &ModRegRm,
3366 Opcode & SOFT386_OPCODE_WRITE_REG,
3367 Result);
3368 }
3369 else
3370 {
3371 /* Discard the result */
3372 return TRUE;
3373 }
3374 }
3375
3376 }
3377
3378 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubAl)
3379 {
3380 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
3381 UCHAR SecondValue, Result;
3382
3383 /* Make sure this is the right instruction */
3384 ASSERT((Opcode & 0xEF) == 0x2C);
3385
3386 if (State->PrefixFlags)
3387 {
3388 /* This opcode doesn't take any prefixes */
3389 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3390 return FALSE;
3391 }
3392
3393 if (!Soft386FetchByte(State, &SecondValue))
3394 {
3395 /* Exception occurred */
3396 return FALSE;
3397 }
3398
3399 /* Calculate the result */
3400 Result = FirstValue - SecondValue;
3401
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);
3410
3411 /* Check if this is not a CMP */
3412 if (!(Opcode & 0x10))
3413 {
3414 /* Write back the result */
3415 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
3416 }
3417
3418 return TRUE;
3419 }
3420
3421 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubEax)
3422 {
3423 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
3424
3425 /* Make sure this is the right instruction */
3426 ASSERT((Opcode & 0xEF) == 0x2D);
3427
3428 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
3429 {
3430 /* Invalid prefix */
3431 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3432 return FALSE;
3433 }
3434
3435 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
3436 {
3437 /* The OPSIZE prefix toggles the size */
3438 Size = !Size;
3439 }
3440
3441 if (Size)
3442 {
3443 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
3444 ULONG SecondValue, Result;
3445
3446 if (!Soft386FetchDword(State, &SecondValue))
3447 {
3448 /* Exception occurred */
3449 return FALSE;
3450 }
3451
3452 /* Calculate the result */
3453 Result = FirstValue - SecondValue;
3454
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);
3463
3464 /* Check if this is not a CMP */
3465 if (!(Opcode & 0x10))
3466 {
3467 /* Write back the result */
3468 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
3469 }
3470 }
3471 else
3472 {
3473 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
3474 USHORT SecondValue, Result;
3475
3476 if (!Soft386FetchWord(State, &SecondValue))
3477 {
3478 /* Exception occurred */
3479 return FALSE;
3480 }
3481
3482 /* Calculate the result */
3483 Result = FirstValue - SecondValue;
3484
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);
3493
3494 /* Write back the result */
3495 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
3496 }
3497
3498 return TRUE;
3499 }
3500
3501 SOFT386_OPCODE_HANDLER(Soft386OpcodeDas)
3502 {
3503 UCHAR Value = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
3504 BOOLEAN Carry = State->Flags.Cf;
3505
3506 /* Clear the carry flag */
3507 State->Flags.Cf = FALSE;
3508
3509 /* Check if the first BCD digit is invalid or there was a borrow */
3510 if (((Value & 0x0F) > 9) || State->Flags.Af)
3511 {
3512 /* Correct it */
3513 State->GeneralRegs[SOFT386_REG_EAX].LowByte -= 0x06;
3514 if (State->GeneralRegs[SOFT386_REG_EAX].LowByte > 0xFB)
3515 {
3516 /* A borrow occurred */
3517 State->Flags.Cf = TRUE;
3518 }
3519
3520 /* Set the adjust flag */
3521 State->Flags.Af = TRUE;
3522 }
3523
3524 /* Check if the second BCD digit is invalid or there was a borrow */
3525 if ((Value > 0x99) || Carry)
3526 {
3527 /* Correct it */
3528 State->GeneralRegs[SOFT386_REG_EAX].LowByte -= 0x60;
3529
3530 /* There was a borrow */
3531 State->Flags.Cf = TRUE;
3532 }
3533
3534 return TRUE;
3535 }
3536
3537 SOFT386_OPCODE_HANDLER(Soft386OpcodeAaa)
3538 {
3539 UCHAR Value = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
3540
3541 /*
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
3544 */
3545 if (((Value & 0x0F) > 9) || State->Flags.Af)
3546 {
3547 /* Correct it */
3548 State->GeneralRegs[SOFT386_REG_EAX].LowByte += 0x06;
3549 State->GeneralRegs[SOFT386_REG_EAX].HighByte++;
3550
3551 /* Set CF and AF */
3552 State->Flags.Cf = State->Flags.Af = TRUE;
3553 }
3554 else
3555 {
3556 /* Clear CF and AF */
3557 State->Flags.Cf = State->Flags.Af = FALSE;
3558 }
3559
3560 /* Keep only the lowest 4 bits of AL */
3561 State->GeneralRegs[SOFT386_REG_EAX].LowByte &= 0x0F;
3562
3563 return TRUE;
3564 }
3565
3566 SOFT386_OPCODE_HANDLER(Soft386OpcodeAas)
3567 {
3568 UCHAR Value = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
3569
3570 /*
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
3573 */
3574 if (((Value & 0x0F) > 9) || State->Flags.Af)
3575 {
3576 /* Correct it */
3577 State->GeneralRegs[SOFT386_REG_EAX].LowByte -= 0x06;
3578 State->GeneralRegs[SOFT386_REG_EAX].HighByte--;
3579
3580 /* Set CF and AF */
3581 State->Flags.Cf = State->Flags.Af = TRUE;
3582 }
3583 else
3584 {
3585 /* Clear CF and AF */
3586 State->Flags.Cf = State->Flags.Af = FALSE;
3587 }
3588
3589 /* Keep only the lowest 4 bits of AL */
3590 State->GeneralRegs[SOFT386_REG_EAX].LowByte &= 0x0F;
3591
3592 return TRUE;
3593 }
3594
3595 SOFT386_OPCODE_HANDLER(Soft386OpcodePushAll)
3596 {
3597 INT i;
3598 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
3599 SOFT386_REG SavedEsp = State->GeneralRegs[SOFT386_REG_ESP];
3600
3601 /* Make sure this is the right instruction */
3602 ASSERT(Opcode == 0x60);
3603
3604 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
3605 {
3606 /* The OPSIZE prefix toggles the size */
3607 Size = !Size;
3608 }
3609 else
3610 {
3611 /* Invalid prefix */
3612 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3613 return FALSE;
3614 }
3615
3616 /* Push all the registers in order */
3617 for (i = 0; i < SOFT386_NUM_GEN_REGS; i++)
3618 {
3619 if (i == SOFT386_REG_ESP)
3620 {
3621 /* Use the saved ESP instead */
3622 if (!Soft386StackPush(State, Size ? SavedEsp.Long : SavedEsp.LowWord))
3623 {
3624 /* Exception occurred */
3625 return FALSE;
3626 }
3627 }
3628 else
3629 {
3630 /* Push the register */
3631 if (!Soft386StackPush(State, Size ? State->GeneralRegs[i].Long
3632 : State->GeneralRegs[i].LowWord))
3633 {
3634 /* Exception occurred */
3635 return FALSE;
3636 }
3637 }
3638 }
3639
3640 return TRUE;
3641 }
3642
3643 SOFT386_OPCODE_HANDLER(Soft386OpcodePopAll)
3644 {
3645 INT i;
3646 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
3647 ULONG Value;
3648
3649 /* Make sure this is the right instruction */
3650 ASSERT(Opcode == 0x61);
3651
3652 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
3653 {
3654 /* The OPSIZE prefix toggles the size */
3655 Size = !Size;
3656 }
3657 else
3658 {
3659 /* Invalid prefix */
3660 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3661 return FALSE;
3662 }
3663
3664 /* Pop all the registers in reverse order */
3665 for (i = SOFT386_NUM_GEN_REGS - 1; i >= 0; i--)
3666 {
3667 /* Pop the value */
3668 if (!Soft386StackPop(State, &Value))
3669 {
3670 /* Exception occurred */
3671 return FALSE;
3672 }
3673
3674 /* Don't modify ESP */
3675 if (i != SOFT386_REG_ESP)
3676 {
3677 if (Size) State->GeneralRegs[i].Long = Value;
3678 else State->GeneralRegs[i].LowWord = LOWORD(Value);
3679 }
3680 }
3681
3682 return TRUE;
3683 }
3684
3685 SOFT386_OPCODE_HANDLER(Soft386OpcodeBound)
3686 {
3687 // TODO: NOT IMPLEMENTED
3688 UNIMPLEMENTED;
3689
3690 return FALSE;
3691 }
3692
3693 SOFT386_OPCODE_HANDLER(Soft386OpcodeArpl)
3694 {
3695 USHORT FirstValue, SecondValue;
3696 SOFT386_MOD_REG_RM ModRegRm;
3697 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
3698
3699 if (!(State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE)
3700 || State->Flags.Vm
3701 || (State->PrefixFlags & SOFT386_PREFIX_LOCK))
3702 {
3703 /* Cannot be used in real mode or with a LOCK prefix */
3704 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3705 return FALSE;
3706 }
3707
3708 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
3709 {
3710 /* The ADSIZE prefix toggles the size */
3711 AddressSize = !AddressSize;
3712 }
3713
3714 /* Get the operands */
3715 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
3716 {
3717 /* Exception occurred */
3718 return FALSE;
3719 }
3720
3721 /* Read the operands */
3722 if (!Soft386ReadModrmWordOperands(State,
3723 &ModRegRm,
3724 &FirstValue,
3725 &SecondValue))
3726 {
3727 /* Exception occurred */
3728 return FALSE;
3729 }
3730
3731 /* Check if the RPL needs adjusting */
3732 if ((SecondValue & 3) < (FirstValue & 3))
3733 {
3734 /* Adjust the RPL */
3735 SecondValue &= ~3;
3736 SecondValue |= FirstValue & 3;
3737
3738 /* Set ZF */
3739 State->Flags.Zf = TRUE;
3740
3741 /* Write back the result */
3742 return Soft386WriteModrmWordOperands(State, &ModRegRm, FALSE, SecondValue);
3743 }
3744 else
3745 {
3746 /* Clear ZF */
3747 State->Flags.Zf = FALSE;
3748 return TRUE;
3749 }
3750 }
3751
3752 SOFT386_OPCODE_HANDLER(Soft386OpcodePushImm)
3753 {
3754 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
3755
3756 /* Make sure this is the right instruction */
3757 ASSERT(Opcode == 0x68);
3758
3759 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
3760 {
3761 /* The OPSIZE prefix toggles the size */
3762 Size = !Size;
3763 }
3764 else
3765 {
3766 /* Invalid prefix */
3767 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3768 return FALSE;
3769 }
3770
3771 if (Size)
3772 {
3773 ULONG Data;
3774
3775 if (!Soft386FetchDword(State, &Data))
3776 {
3777 /* Exception occurred */
3778 return FALSE;
3779 }
3780
3781 /* Call the internal API */
3782 return Soft386StackPush(State, Data);
3783 }
3784 else
3785 {
3786 USHORT Data;
3787
3788 if (!Soft386FetchWord(State, &Data))
3789 {
3790 /* Exception occurred */
3791 return FALSE;
3792 }
3793
3794 /* Call the internal API */
3795 return Soft386StackPush(State, Data);
3796 }
3797 }
3798
3799 SOFT386_OPCODE_HANDLER(Soft386OpcodeImulModrmImm)
3800 {
3801 BOOLEAN OperandSize, AddressSize;
3802 SOFT386_MOD_REG_RM ModRegRm;
3803 LONG Multiplier;
3804 LONGLONG Product;
3805
3806 /* Make sure this is the right instruction */
3807 ASSERT((Opcode & 0xFD) == 0x69);
3808
3809 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
3810
3811 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
3812 {
3813 /* The ADSIZE prefix toggles the address size */
3814 AddressSize = !AddressSize;
3815 }
3816
3817 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
3818 {
3819 /* The OPSIZE prefix toggles the operand size */
3820 OperandSize = !OperandSize;
3821 }
3822
3823 /* Fetch the parameters */
3824 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
3825 {
3826 /* Exception occurred */
3827 return FALSE;
3828 }
3829
3830 if (Opcode == 0x6B)
3831 {
3832 CHAR Byte;
3833
3834 /* Fetch the immediate operand */
3835 if (!Soft386FetchByte(State, (PUCHAR)&Byte))
3836 {
3837 /* Exception occurred */
3838 return FALSE;
3839 }
3840
3841 Multiplier = (LONG)Byte;
3842 }
3843 else
3844 {
3845 if (OperandSize)
3846 {
3847 LONG Dword;
3848
3849 /* Fetch the immediate operand */
3850 if (!Soft386FetchDword(State, (PULONG)&Dword))
3851 {
3852 /* Exception occurred */
3853 return FALSE;
3854 }
3855
3856 Multiplier = Dword;
3857 }
3858 else
3859 {
3860 SHORT Word;
3861
3862 /* Fetch the immediate operand */
3863 if (!Soft386FetchWord(State, (PUSHORT)&Word))
3864 {
3865 /* Exception occurred */
3866 return FALSE;
3867 }
3868
3869 Multiplier = (LONG)Word;
3870 }
3871 }
3872
3873 if (OperandSize)
3874 {
3875 LONG RegValue, Multiplicand;
3876
3877 /* Read the operands */
3878 if (!Soft386ReadModrmDwordOperands(State,
3879 &ModRegRm,
3880 (PULONG)&RegValue,
3881 (PULONG)&Multiplicand))
3882 {
3883 /* Exception occurred */
3884 return FALSE;
3885 }
3886
3887 /* Multiply */
3888 Product = (LONGLONG)Multiplicand * (LONGLONG)Multiplier;
3889 }
3890 else
3891 {
3892 SHORT RegValue, Multiplicand;
3893
3894 /* Read the operands */
3895 if (!Soft386ReadModrmWordOperands(State,
3896 &ModRegRm,
3897 (PUSHORT)&RegValue,
3898 (PUSHORT)&Multiplicand))
3899 {
3900 /* Exception occurred */
3901 return FALSE;
3902 }
3903
3904 /* Multiply */
3905 Product = (LONGLONG)Multiplicand * (LONGLONG)Multiplier;
3906 }
3907
3908 /* Check for carry/overflow */
3909 if ((Product < LONG_MIN) || (Product > LONG_MAX))
3910 {
3911 State->Flags.Cf = State->Flags.Of = TRUE;
3912 }
3913 else State->Flags.Cf = State->Flags.Of = FALSE;
3914
3915 /* Write-back the result */
3916 return Soft386WriteModrmDwordOperands(State,
3917 &ModRegRm,
3918 TRUE,
3919 (ULONG)((LONG)Product));
3920 }
3921
3922 SOFT386_OPCODE_HANDLER(Soft386OpcodePushByteImm)
3923 {
3924 UCHAR Data;
3925
3926 /* Make sure this is the right instruction */
3927 ASSERT(Opcode == 0x6A);
3928
3929 if (!Soft386FetchByte(State, &Data))
3930 {
3931 /* Exception occurred */
3932 return FALSE;
3933 }
3934
3935 /* Call the internal API */
3936 return Soft386StackPush(State, Data);
3937 }
3938
3939 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovByteModrm)
3940 {
3941 UCHAR FirstValue, SecondValue, Result;
3942 SOFT386_MOD_REG_RM ModRegRm;
3943 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
3944
3945 /* Make sure this is the right instruction */
3946 ASSERT((Opcode & 0xFD) == 0x88);
3947
3948 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
3949 {
3950 /* The ADSIZE prefix toggles the size */
3951 AddressSize = !AddressSize;
3952 }
3953 else if (State->PrefixFlags
3954 & ~(SOFT386_PREFIX_ADSIZE
3955 | SOFT386_PREFIX_SEG
3956 | SOFT386_PREFIX_LOCK))
3957 {
3958 /* Invalid prefix */
3959 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3960 return FALSE;
3961 }
3962
3963 /* Get the operands */
3964 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
3965 {
3966 /* Exception occurred */
3967 return FALSE;
3968 }
3969
3970 if (!Soft386ReadModrmByteOperands(State,
3971 &ModRegRm,
3972 &FirstValue,
3973 &SecondValue))
3974 {
3975 /* Exception occurred */
3976 return FALSE;
3977 }
3978
3979 if (Opcode & SOFT386_OPCODE_WRITE_REG) Result = SecondValue;
3980 else Result = FirstValue;
3981
3982 /* Write back the result */
3983 return Soft386WriteModrmByteOperands(State,
3984 &ModRegRm,
3985 Opcode & SOFT386_OPCODE_WRITE_REG,
3986 Result);
3987
3988 }
3989
3990 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovModrm)
3991 {
3992 SOFT386_MOD_REG_RM ModRegRm;
3993 BOOLEAN OperandSize, AddressSize;
3994
3995 /* Make sure this is the right instruction */
3996 ASSERT((Opcode & 0xFD) == 0x89);
3997
3998 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
3999
4000 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
4001 {
4002 /* The ADSIZE prefix toggles the address size */
4003 AddressSize = !AddressSize;
4004 }
4005
4006 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
4007 {
4008 /* The OPSIZE prefix toggles the operand size */
4009 OperandSize = !OperandSize;
4010 }
4011
4012 if (State->PrefixFlags
4013 & ~(SOFT386_PREFIX_ADSIZE
4014 | SOFT386_PREFIX_OPSIZE
4015 | SOFT386_PREFIX_SEG
4016 | SOFT386_PREFIX_LOCK))
4017 {
4018 /* Invalid prefix */
4019 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4020 return FALSE;
4021 }
4022
4023 /* Get the operands */
4024 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
4025 {
4026 /* Exception occurred */
4027 return FALSE;
4028 }
4029
4030 /* Check the operand size */
4031 if (OperandSize)
4032 {
4033 ULONG FirstValue, SecondValue, Result;
4034
4035 if (!Soft386ReadModrmDwordOperands(State,
4036 &ModRegRm,
4037 &FirstValue,
4038 &SecondValue))
4039 {
4040 /* Exception occurred */
4041 return FALSE;
4042 }
4043
4044 if (Opcode & SOFT386_OPCODE_WRITE_REG) Result = SecondValue;
4045 else Result = FirstValue;
4046
4047 /* Write back the result */
4048 return Soft386WriteModrmDwordOperands(State,
4049 &ModRegRm,
4050 Opcode & SOFT386_OPCODE_WRITE_REG,
4051 Result);
4052 }
4053 else
4054 {
4055 USHORT FirstValue, SecondValue, Result;
4056
4057 if (!Soft386ReadModrmWordOperands(State,
4058 &ModRegRm,
4059 &FirstValue,
4060 &SecondValue))
4061 {
4062 /* Exception occurred */
4063 return FALSE;
4064 }
4065
4066 if (Opcode & SOFT386_OPCODE_WRITE_REG) Result = SecondValue;
4067 else Result = FirstValue;
4068
4069 /* Write back the result */
4070 return Soft386WriteModrmWordOperands(State,
4071 &ModRegRm,
4072 Opcode & SOFT386_OPCODE_WRITE_REG,
4073 Result);
4074 }
4075 }
4076
4077 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovStoreSeg)
4078 {
4079 BOOLEAN OperandSize, AddressSize;
4080 SOFT386_MOD_REG_RM ModRegRm;
4081
4082 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
4083
4084 /* Make sure this is the right instruction */
4085 ASSERT(Opcode == 0x8C);
4086
4087 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
4088 {
4089 /* The ADSIZE prefix toggles the address size */
4090 AddressSize = !AddressSize;
4091 }
4092
4093 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
4094 {
4095 /* The OPSIZE prefix toggles the operand size */
4096 OperandSize = !OperandSize;
4097 }
4098
4099 /* Get the operands */
4100 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
4101 {
4102 /* Exception occurred */
4103 return FALSE;
4104 }
4105
4106 if (ModRegRm.Register >= SOFT386_NUM_SEG_REGS)
4107 {
4108 /* Invalid */
4109 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4110 return FALSE;
4111 }
4112
4113 if (OperandSize)
4114 {
4115 return Soft386WriteModrmDwordOperands(State,
4116 &ModRegRm,
4117 FALSE,
4118 State->SegmentRegs[ModRegRm.Register].Selector);
4119 }
4120 else
4121 {
4122 return Soft386WriteModrmWordOperands(State,
4123 &ModRegRm,
4124 FALSE,
4125 State->SegmentRegs[ModRegRm.Register].Selector);
4126 }
4127 }
4128
4129 SOFT386_OPCODE_HANDLER(Soft386OpcodeLea)
4130 {
4131 SOFT386_MOD_REG_RM ModRegRm;
4132 BOOLEAN OperandSize, AddressSize;
4133
4134 /* Make sure this is the right instruction */
4135 ASSERT(Opcode == 0x8D);
4136
4137 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
4138
4139 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
4140 {
4141 /* The ADSIZE prefix toggles the address size */
4142 AddressSize = !AddressSize;
4143 }
4144
4145 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
4146 {
4147 /* The OPSIZE prefix toggles the operand size */
4148 OperandSize = !OperandSize;
4149 }
4150
4151 /* Get the operands */
4152 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
4153 {
4154 /* Exception occurred */
4155 return FALSE;
4156 }
4157
4158 /* The second operand must be memory */
4159 if (!ModRegRm.Memory)
4160 {
4161 /* Invalid */
4162 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4163 return FALSE;
4164 }
4165
4166 /* Write the address to the register */
4167 if (OperandSize)
4168 {
4169 return Soft386WriteModrmDwordOperands(State,
4170 &ModRegRm,
4171 TRUE,
4172 ModRegRm.MemoryAddress);
4173 }
4174 else
4175 {
4176 return Soft386WriteModrmWordOperands(State,
4177 &ModRegRm,
4178 TRUE,
4179 ModRegRm.MemoryAddress);
4180
4181 }
4182 }
4183
4184 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovLoadSeg)
4185 {
4186 BOOLEAN OperandSize, AddressSize;
4187 SOFT386_MOD_REG_RM ModRegRm;
4188
4189 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
4190
4191 /* Make sure this is the right instruction */
4192 ASSERT(Opcode == 0x8E);
4193
4194 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
4195 {
4196 /* The ADSIZE prefix toggles the address size */
4197 AddressSize = !AddressSize;
4198 }
4199
4200 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
4201 {
4202 /* The OPSIZE prefix toggles the operand size */
4203 OperandSize = !OperandSize;
4204 }
4205
4206 /* Get the operands */
4207 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
4208 {
4209 /* Exception occurred */
4210 return FALSE;
4211 }
4212
4213 if (ModRegRm.Register >= SOFT386_NUM_SEG_REGS)
4214 {
4215 /* Invalid */
4216 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4217 return FALSE;
4218 }
4219
4220 if (OperandSize)
4221 {
4222 ULONG Dummy, Selector;
4223
4224 if (!Soft386ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Selector))
4225 {
4226 /* Exception occurred */
4227 return FALSE;
4228 }
4229
4230 return Soft386LoadSegment(State, ModRegRm.Register, LOWORD(Selector));
4231 }
4232 else
4233 {
4234 USHORT Dummy, Selector;
4235
4236 if (!Soft386ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Selector))
4237 {
4238 /* Exception occurred */
4239 return FALSE;
4240 }
4241
4242 return Soft386LoadSegment(State, ModRegRm.Register, Selector);
4243 }
4244 }
4245
4246 SOFT386_OPCODE_HANDLER(Soft386OpcodeCwde)
4247 {
4248 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4249
4250 /* Make sure this is the right instruction */
4251 ASSERT(Opcode == 0x98);
4252
4253 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
4254 {
4255 /* The OPSIZE prefix toggles the size */
4256 Size = !Size;
4257 }
4258 else if (State->PrefixFlags != 0)
4259 {
4260 /* Invalid prefix */
4261 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4262 return FALSE;
4263 }
4264
4265 if (Size)
4266 {
4267 /* Sign extend AX to EAX */
4268 State->GeneralRegs[SOFT386_REG_EAX].Long = MAKELONG
4269 (
4270 State->GeneralRegs[SOFT386_REG_EAX].LowWord,
4271 (State->GeneralRegs[SOFT386_REG_EAX].LowWord & SIGN_FLAG_WORD)
4272 ? 0xFFFF : 0x0000
4273 );
4274 }
4275 else
4276 {
4277 /* Sign extend AL to AX */
4278 State->GeneralRegs[SOFT386_REG_EAX].HighByte =
4279 (State->GeneralRegs[SOFT386_REG_EAX].LowByte & SIGN_FLAG_BYTE)
4280 ? 0xFF : 0x00;
4281 }
4282
4283 return TRUE;
4284 }
4285
4286 SOFT386_OPCODE_HANDLER(Soft386OpcodeCdq)
4287 {
4288 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4289
4290 /* Make sure this is the right instruction */
4291 ASSERT(Opcode == 0x99);
4292
4293 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
4294 {
4295 /* The OPSIZE prefix toggles the size */
4296 Size = !Size;
4297 }
4298 else if (State->PrefixFlags != 0)
4299 {
4300 /* Invalid prefix */
4301 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4302 return FALSE;
4303 }
4304
4305 if (Size)
4306 {
4307 /* Sign extend EAX to EDX:EAX */
4308 State->GeneralRegs[SOFT386_REG_EDX].Long =
4309 (State->GeneralRegs[SOFT386_REG_EAX].Long & SIGN_FLAG_LONG)
4310 ? 0xFFFFFFFF : 0x00000000;
4311 }
4312 else
4313 {
4314 /* Sign extend AX to DX:AX */
4315 State->GeneralRegs[SOFT386_REG_EDX].LowWord =
4316 (State->GeneralRegs[SOFT386_REG_EAX].LowWord & SIGN_FLAG_WORD)
4317 ? 0xFFFF : 0x0000;
4318 }
4319
4320 return TRUE;
4321 }
4322
4323 SOFT386_OPCODE_HANDLER(Soft386OpcodeCallAbs)
4324 {
4325 // TODO: NOT IMPLEMENTED
4326 UNIMPLEMENTED;
4327
4328 return FALSE;
4329 }
4330
4331 SOFT386_OPCODE_HANDLER(Soft386OpcodeWait)
4332 {
4333 // TODO: NOT IMPLEMENTED
4334 UNIMPLEMENTED;
4335
4336 return FALSE;
4337 }
4338
4339 SOFT386_OPCODE_HANDLER(Soft386OpcodePushFlags)
4340 {
4341 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4342
4343 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
4344 {
4345 /* Invalid prefix */
4346 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4347 return FALSE;
4348 }
4349
4350 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
4351 {
4352 /* This OPSIZE prefix toggles the size */
4353 Size = !Size;
4354 }
4355
4356 /* Check for VM86 mode when IOPL is not 3 */
4357 if (State->Flags.Vm && (State->Flags.Iopl != 3))
4358 {
4359 /* Call the VM86 monitor */
4360 Soft386ExceptionWithErrorCode(State, SOFT386_EXCEPTION_GP, 0);
4361 return FALSE;
4362 }
4363
4364 /* Push the flags */
4365 if (Size) return Soft386StackPush(State, State->Flags.Long);
4366 else return Soft386StackPush(State, LOWORD(State->Flags.Long));
4367 }
4368
4369 SOFT386_OPCODE_HANDLER(Soft386OpcodePopFlags)
4370 {
4371 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4372 INT Cpl = Soft386GetCurrentPrivLevel(State);
4373 ULONG NewFlags;
4374
4375 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
4376 {
4377 /* Invalid prefix */
4378 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4379 return FALSE;
4380 }
4381
4382 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
4383 {
4384 /* This OPSIZE prefix toggles the size */
4385 Size = !Size;
4386 }
4387
4388 /* Pop the new flags */
4389 if (!Soft386StackPop(State, &NewFlags))
4390 {
4391 /* Exception occurred */
4392 return FALSE;
4393 }
4394
4395 if (!State->Flags.Vm)
4396 {
4397 /* Check the current privilege level */
4398 if (Cpl == 0)
4399 {
4400 /* Supervisor */
4401
4402 /* Set the flags */
4403 if (Size)
4404 {
4405 /* Memorize the old state of RF */
4406 BOOLEAN OldRf = State->Flags.Rf;
4407
4408 State->Flags.Long = NewFlags;
4409
4410 /* Restore VM and RF */
4411 State->Flags.Vm = FALSE;
4412 State->Flags.Rf = OldRf;
4413
4414 /* Clear VIF and VIP */
4415 State->Flags.Vif = State->Flags.Vip = FALSE;
4416 }
4417 else State->Flags.LowWord = LOWORD(NewFlags);
4418
4419 /* Restore the reserved bits */
4420 State->Flags.AlwaysSet = TRUE;
4421 State->Flags.Reserved0 = FALSE;
4422 State->Flags.Reserved1 = FALSE;
4423 }
4424 else
4425 {
4426 /* User */
4427
4428 /* Memorize the old state of IF and IOPL */
4429 BOOLEAN OldIf = State->Flags.If;
4430 UINT OldIopl = State->Flags.Iopl;
4431
4432 /* Set the flags */
4433 if (Size)
4434 {
4435 /* Memorize the old state of RF */
4436 BOOLEAN OldRf = State->Flags.Rf;
4437
4438 State->Flags.Long = NewFlags;
4439
4440 /* Restore VM and RF */
4441 State->Flags.Vm = FALSE;
4442 State->Flags.Rf = OldRf;
4443
4444 /* Clear VIF and VIP */
4445 State->Flags.Vif = State->Flags.Vip = FALSE;
4446 }
4447 else State->Flags.LowWord = LOWORD(NewFlags);
4448
4449 /* Restore the reserved bits and IOPL */
4450 State->Flags.AlwaysSet = TRUE;
4451 State->Flags.Reserved0 = FALSE;
4452 State->Flags.Reserved1 = FALSE;
4453 State->Flags.Iopl = OldIopl;
4454
4455 /* Check if the user doesn't have the privilege to change IF */
4456 if (Cpl > State->Flags.Iopl)
4457 {
4458 /* Restore IF */
4459 State->Flags.If = OldIf;
4460 }
4461 }
4462 }
4463 else
4464 {
4465 /* Check the IOPL */
4466 if (State->Flags.Iopl == 3)
4467 {
4468 if (Size)
4469 {
4470 /* Memorize the old state of RF, VIF and VIP */
4471 BOOLEAN OldRf = State->Flags.Rf;
4472 BOOLEAN OldVif = State->Flags.Vif;
4473 BOOLEAN OldVip = State->Flags.Vip;
4474
4475 State->Flags.Long = NewFlags;
4476
4477 /* Restore VM, RF, VIF and VIP */
4478 State->Flags.Vm = TRUE;
4479 State->Flags.Rf = OldRf;
4480 State->Flags.Vif = OldVif;
4481 State->Flags.Vip = OldVip;
4482 }
4483 else State->Flags.LowWord = LOWORD(NewFlags);
4484
4485 /* Restore the reserved bits and IOPL */
4486 State->Flags.AlwaysSet = TRUE;
4487 State->Flags.Reserved0 = FALSE;
4488 State->Flags.Reserved1 = FALSE;
4489 State->Flags.Iopl = 3;
4490 }
4491 else
4492 {
4493 /* Call the VM86 monitor */
4494 Soft386ExceptionWithErrorCode(State, SOFT386_EXCEPTION_GP, 0);
4495 }
4496
4497 }
4498
4499 return TRUE;
4500 }
4501
4502 SOFT386_OPCODE_HANDLER(Soft386OpcodeSahf)
4503 {
4504 /* Make sure this is the right instruction */
4505 ASSERT(Opcode == 0x9E);
4506
4507 /* Set the low-order byte of FLAGS to AH */
4508 State->Flags.Long &= 0xFFFFFF00;
4509 State->Flags.Long |= State->GeneralRegs[SOFT386_REG_EAX].HighByte;
4510
4511 /* Restore the reserved bits of FLAGS */
4512 State->Flags.AlwaysSet = TRUE;
4513 State->Flags.Reserved0 = State->Flags.Reserved1 = FALSE;
4514
4515 return FALSE;
4516 }
4517
4518 SOFT386_OPCODE_HANDLER(Soft386OpcodeLahf)
4519 {
4520 /* Make sure this is the right instruction */
4521 ASSERT(Opcode == 0x9F);
4522
4523 /* Set AH to the low-order byte of FLAGS */
4524 State->GeneralRegs[SOFT386_REG_EAX].HighByte = LOBYTE(State->Flags.Long);
4525
4526 return FALSE;
4527 }
4528
4529 SOFT386_OPCODE_HANDLER(Soft386OpcodeRet)
4530 {
4531 ULONG ReturnAddress;
4532 USHORT BytesToPop = 0;
4533 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4534
4535 /* Make sure this is the right instruction */
4536 ASSERT((Opcode & 0xFE) == 0xC2);
4537
4538 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
4539 {
4540 /* Invalid prefix */
4541 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4542 return FALSE;
4543 }
4544
4545 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
4546 {
4547 /* The OPSIZE prefix toggles the size */
4548 Size = !Size;
4549 }
4550
4551 if (Opcode == 0xC2)
4552 {
4553 /* Fetch the number of bytes to pop after the return */
4554 if (!Soft386FetchWord(State, &BytesToPop)) return FALSE;
4555 }
4556
4557 /* Pop the return address */
4558 if (!Soft386StackPop(State, &ReturnAddress)) return FALSE;
4559
4560 /* Return to the calling procedure, and if necessary, pop the parameters */
4561 if (Size)
4562 {
4563 State->InstPtr.Long = ReturnAddress;
4564 State->GeneralRegs[SOFT386_REG_ESP].Long += BytesToPop;
4565 }
4566 else
4567 {
4568 State->InstPtr.LowWord = LOWORD(ReturnAddress);
4569 State->GeneralRegs[SOFT386_REG_ESP].LowWord += BytesToPop;
4570 }
4571
4572 return TRUE;
4573 }
4574
4575 SOFT386_OPCODE_HANDLER(Soft386OpcodeLdsLes)
4576 {
4577 UCHAR FarPointer[6];
4578 BOOLEAN OperandSize, AddressSize;
4579 SOFT386_MOD_REG_RM ModRegRm;
4580
4581 /* Make sure this is the right instruction */
4582 ASSERT((Opcode & 0xFE) == 0xC4);
4583
4584 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
4585
4586 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
4587 {
4588 /* The ADSIZE prefix toggles the size */
4589 AddressSize = !AddressSize;
4590 }
4591
4592 /* Get the operands */
4593 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
4594 {
4595 /* Exception occurred */
4596 return FALSE;
4597 }
4598
4599 if (!ModRegRm.Memory)
4600 {
4601 /* Check if this is a BOP and the host supports BOPs */
4602 if ((Opcode == 0xC4)
4603 && (ModRegRm.Register == SOFT386_REG_EAX)
4604 && (ModRegRm.SecondRegister == SOFT386_REG_ESP)
4605 && (State->BopCallback != NULL))
4606 {
4607 USHORT BopCode;
4608
4609 /* Fetch the BOP code */
4610 if (!Soft386FetchWord(State, &BopCode))
4611 {
4612 /* Exception occurred */
4613 return FALSE;
4614 }
4615
4616 /* Call the BOP handler */
4617 State->BopCallback(State, BopCode);
4618
4619 /* Return success */
4620 return TRUE;
4621 }
4622
4623 /* Invalid */
4624 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4625 return FALSE;
4626 }
4627
4628 if (!Soft386ReadMemory(State,
4629 (State->PrefixFlags & SOFT386_PREFIX_SEG)
4630 ? State->SegmentOverride : SOFT386_REG_DS,
4631 ModRegRm.MemoryAddress,
4632 FALSE,
4633 FarPointer,
4634 OperandSize ? 6 : 4))
4635 {
4636 /* Exception occurred */
4637 return FALSE;
4638 }
4639
4640 if (OperandSize)
4641 {
4642 ULONG Offset = *((PULONG)FarPointer);
4643 USHORT Segment = *((PUSHORT)&FarPointer[sizeof(ULONG)]);
4644
4645 /* Set the register to the offset */
4646 State->GeneralRegs[ModRegRm.Register].Long = Offset;
4647
4648 /* Load the segment */
4649 return Soft386LoadSegment(State,
4650 (Opcode == 0xC4)
4651 ? SOFT386_REG_ES : SOFT386_REG_DS,
4652 Segment);
4653 }
4654 else
4655 {
4656 USHORT Offset = *((PUSHORT)FarPointer);
4657 USHORT Segment = *((PUSHORT)&FarPointer[sizeof(USHORT)]);
4658
4659 /* Set the register to the offset */
4660 State->GeneralRegs[ModRegRm.Register].LowWord = Offset;
4661
4662 /* Load the segment */
4663 return Soft386LoadSegment(State,
4664 (Opcode == 0xC4)
4665 ? SOFT386_REG_ES : SOFT386_REG_DS,
4666 Segment);
4667 }
4668 }
4669
4670 SOFT386_OPCODE_HANDLER(Soft386OpcodeEnter)
4671 {
4672 INT i;
4673 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4674 USHORT FrameSize;
4675 UCHAR NestingLevel;
4676 SOFT386_REG FramePointer;
4677
4678 /* Make sure this is the right instruction */
4679 ASSERT(Opcode == 0xC8);
4680
4681 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
4682 {
4683 /* Invalid prefix */
4684 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4685 return FALSE;
4686 }
4687
4688 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
4689 {
4690 /* The OPSIZE prefix toggles the size */
4691 Size = !Size;
4692 }
4693
4694 if (!Soft386FetchWord(State, &FrameSize))
4695 {
4696 /* Exception occurred */
4697 return FALSE;
4698 }
4699
4700 if (!Soft386FetchByte(State, &NestingLevel))
4701 {
4702 /* Exception occurred */
4703 return FALSE;
4704 }
4705
4706 /* Push EBP */
4707 if (!Soft386StackPush(State, State->GeneralRegs[SOFT386_REG_EBP].Long))
4708 {
4709 /* Exception occurred */
4710 return FALSE;
4711 }
4712
4713 /* Save ESP */
4714 FramePointer = State->GeneralRegs[SOFT386_REG_ESP];
4715
4716 /* Set up the nested procedure stacks */
4717 for (i = 1; i < NestingLevel; i++)
4718 {
4719 if (Size)
4720 {
4721 State->GeneralRegs[SOFT386_REG_EBP].Long -= 4;
4722 Soft386StackPush(State, State->GeneralRegs[SOFT386_REG_EBP].Long);
4723 }
4724 else
4725 {
4726 State->GeneralRegs[SOFT386_REG_EBP].LowWord -= 2;
4727 Soft386StackPush(State, State->GeneralRegs[SOFT386_REG_EBP].LowWord);
4728 }
4729 }
4730
4731 if (NestingLevel > 0) Soft386StackPush(State, FramePointer.Long);
4732
4733 /* Set EBP to the frame pointer */
4734 State->GeneralRegs[SOFT386_REG_EBP] = FramePointer;
4735
4736 /* Reserve space for the frame */
4737 if (Size) State->GeneralRegs[SOFT386_REG_ESP].Long -= (ULONG)FrameSize;
4738 else State->GeneralRegs[SOFT386_REG_ESP].LowWord -= FrameSize;
4739
4740 return TRUE;
4741 }
4742
4743 SOFT386_OPCODE_HANDLER(Soft386OpcodeLeave)
4744 {
4745 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4746
4747 /* Make sure this is the right instruction */
4748 ASSERT(Opcode == 0xC9);
4749
4750 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
4751 {
4752 /* Invalid prefix */
4753 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4754 return FALSE;
4755 }
4756
4757 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
4758 {
4759 /* The OPSIZE prefix toggles the size */
4760 Size = !Size;
4761 }
4762
4763 if (Size)
4764 {
4765 /* Set the stack pointer (ESP) to the base pointer (EBP) */
4766 State->GeneralRegs[SOFT386_REG_ESP].Long = State->GeneralRegs[SOFT386_REG_EBP].Long;
4767
4768 /* Pop the saved base pointer from the stack */
4769 return Soft386StackPop(State, &State->GeneralRegs[SOFT386_REG_EBP].Long);
4770 }
4771 else
4772 {
4773 ULONG Value;
4774
4775 /* Set the stack pointer (SP) to the base pointer (BP) */
4776 State->GeneralRegs[SOFT386_REG_ESP].LowWord = State->GeneralRegs[SOFT386_REG_EBP].LowWord;
4777
4778 /* Pop the saved base pointer from the stack */
4779 if (Soft386StackPop(State, &Value))
4780 {
4781 State->GeneralRegs[SOFT386_REG_EBP].LowWord = LOWORD(Value);
4782 return TRUE;
4783 }
4784 else return FALSE;
4785 }
4786 }
4787
4788 SOFT386_OPCODE_HANDLER(Soft386OpcodeRetFarImm)
4789 {
4790 // TODO: NOT IMPLEMENTED
4791 UNIMPLEMENTED;
4792
4793 return FALSE;
4794 }
4795
4796 SOFT386_OPCODE_HANDLER(Soft386OpcodeRetFar)
4797 {
4798 // TODO: NOT IMPLEMENTED
4799 UNIMPLEMENTED;
4800
4801 return FALSE;
4802 }
4803
4804 SOFT386_OPCODE_HANDLER(Soft386OpcodeInt)
4805 {
4806 UCHAR IntNum;
4807 SOFT386_IDT_ENTRY IdtEntry;
4808
4809 switch (Opcode)
4810 {
4811 case 0xCC:
4812 {
4813 /* This is the INT3 instruction */
4814 IntNum = 3;
4815 break;
4816 }
4817
4818 case 0xCD:
4819 {
4820 /* Fetch the interrupt number */
4821 if (!Soft386FetchByte(State, &IntNum))
4822 {
4823 /* Exception occurred */
4824 return FALSE;
4825 }
4826
4827 break;
4828 }
4829
4830 case 0xCE:
4831 {
4832 /* Don't do anything if OF is cleared */
4833 if (!State->Flags.Of) return TRUE;
4834
4835 /* Exception #OF */
4836 IntNum = SOFT386_EXCEPTION_OF;
4837
4838 break;
4839 }
4840
4841 default:
4842 {
4843 /* Should not happen */
4844 ASSERT(FALSE);
4845 }
4846 }
4847
4848 /* Get the interrupt vector */
4849 if (!Soft386GetIntVector(State, IntNum, &IdtEntry))
4850 {
4851 /* Exception occurred */
4852 return FALSE;
4853 }
4854
4855 /* Perform the interrupt */
4856 if (!Soft386InterruptInternal(State,
4857 IdtEntry.Selector,
4858 MAKELONG(IdtEntry.Offset, IdtEntry.OffsetHigh),
4859 IdtEntry.Type))
4860 {
4861 /* Exception occurred */
4862 return FALSE;
4863 }
4864
4865 return TRUE;
4866 }
4867
4868 SOFT386_OPCODE_HANDLER(Soft386OpcodeIret)
4869 {
4870 INT i;
4871 ULONG InstPtr, CodeSel, StackPtr, StackSel;
4872 SOFT386_FLAGS_REG NewFlags;
4873 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4874
4875 /* Make sure this is the right instruction */
4876 ASSERT(Opcode == 0xCF);
4877
4878 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
4879 {
4880 /* Invalid prefix */
4881 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4882 return FALSE;
4883 }
4884
4885 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
4886 {
4887 /* The OPSIZE prefix toggles the size */
4888 Size = !Size;
4889 }
4890
4891 /* Pop EIP */
4892 if (!Soft386StackPop(State, &InstPtr))
4893 {
4894 /* Exception occurred */
4895 return FALSE;
4896 }
4897
4898 /* Pop CS */
4899 if (!Soft386StackPop(State, &CodeSel))
4900 {
4901 /* Exception occurred */
4902 return FALSE;
4903 }
4904
4905 /* Pop EFLAGS */
4906 if (!Soft386StackPop(State, &NewFlags.Long))
4907 {
4908 /* Exception occurred */
4909 return FALSE;
4910 }
4911
4912 /* Check for protected mode */
4913 if (State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE)
4914 {
4915 INT Cpl = Soft386GetCurrentPrivLevel(State);
4916
4917 if (State->Flags.Vm)
4918 {
4919 /* Return from VM86 mode */
4920
4921 /* Check the IOPL */
4922 if (State->Flags.Iopl == 3)
4923 {
4924 /* Set new EIP */
4925 State->InstPtr.Long = LOWORD(InstPtr);
4926
4927 /* Load new CS */
4928 if (!Soft386LoadSegment(State, SOFT386_REG_CS, CodeSel))
4929 {
4930 /* Exception occurred */
4931 return FALSE;
4932 }
4933
4934 /* Set the new flags */
4935 if (Size) State->Flags.Long = NewFlags.Long & REAL_MODE_FLAGS_MASK;
4936 else State->Flags.LowWord = NewFlags.LowWord & REAL_MODE_FLAGS_MASK;
4937 State->Flags.AlwaysSet = State->Flags.Vm = TRUE;
4938 State->Flags.Iopl = 3;
4939 }
4940 else
4941 {
4942 /* Call the VM86 monitor */
4943 Soft386ExceptionWithErrorCode(State, SOFT386_EXCEPTION_GP, 0);
4944 return FALSE;
4945 }
4946
4947 return TRUE;
4948 }
4949
4950 if (State->Flags.Nt)
4951 {
4952 /* Nested task return */
4953
4954 UNIMPLEMENTED;
4955 return FALSE;
4956 }
4957
4958 if (NewFlags.Vm)
4959 {
4960 /* Return to VM86 mode */
4961 ULONG Es, Ds, Fs, Gs;
4962
4963 /* Pop ESP, SS, ES, FS, GS */
4964 if (!Soft386StackPop(State, &StackPtr)) return FALSE;
4965 if (!Soft386StackPop(State, &StackSel)) return FALSE;
4966 if (!Soft386StackPop(State, &Es)) return FALSE;
4967 if (!Soft386StackPop(State, &Ds)) return FALSE;
4968 if (!Soft386StackPop(State, &Fs)) return FALSE;
4969 if (!Soft386StackPop(State, &Gs)) return FALSE;
4970
4971 /* Set the new IP */
4972 State->InstPtr.Long = LOWORD(InstPtr);
4973
4974 /* Set the new flags */
4975 if (Size) State->Flags.Long = NewFlags.Long & REAL_MODE_FLAGS_MASK;
4976 else State->Flags.LowWord = NewFlags.LowWord & REAL_MODE_FLAGS_MASK;
4977 State->Flags.AlwaysSet = State->Flags.Vm = TRUE;
4978
4979 /* Load the new segments */
4980 if (!Soft386LoadSegment(State, SOFT386_REG_CS, CodeSel)) return FALSE;
4981 if (!Soft386LoadSegment(State, SOFT386_REG_SS, StackSel)) return FALSE;
4982 if (!Soft386LoadSegment(State, SOFT386_REG_ES, Es)) return FALSE;
4983 if (!Soft386LoadSegment(State, SOFT386_REG_DS, Ds)) return FALSE;
4984 if (!Soft386LoadSegment(State, SOFT386_REG_FS, Fs)) return FALSE;
4985 if (!Soft386LoadSegment(State, SOFT386_REG_GS, Gs)) return FALSE;
4986
4987 return TRUE;
4988 }
4989
4990 /* Load the new CS */
4991 if (!Soft386LoadSegment(State, SOFT386_REG_CS, CodeSel))
4992 {
4993 /* Exception occurred */
4994 return FALSE;
4995 }
4996
4997 /* Set EIP */
4998 if (Size) State->InstPtr.Long = InstPtr;
4999 else State->InstPtr.LowWord = LOWORD(InstPtr);
5000
5001 if (GET_SEGMENT_RPL(CodeSel) > Cpl)
5002 {
5003 /* Pop ESP */
5004 if (!Soft386StackPop(State, &StackPtr))
5005 {
5006 /* Exception */
5007 return FALSE;
5008 }
5009
5010 /* Pop SS */
5011 if (!Soft386StackPop(State, &StackSel))
5012 {
5013 /* Exception */
5014 return FALSE;
5015 }
5016
5017 /* Load new SS */
5018 if (!Soft386LoadSegment(State, SOFT386_REG_SS, StackSel))
5019 {
5020 /* Exception */
5021 return FALSE;
5022 }
5023
5024 /* Set ESP */
5025 if (Size) State->GeneralRegs[SOFT386_REG_ESP].Long = StackPtr;
5026 else State->GeneralRegs[SOFT386_REG_ESP].LowWord = LOWORD(StackPtr);
5027 }
5028
5029 /* Set the new flags */
5030 if (Size) State->Flags.Long = NewFlags.Long & PROT_MODE_FLAGS_MASK;
5031 else State->Flags.LowWord = NewFlags.LowWord & PROT_MODE_FLAGS_MASK;
5032 State->Flags.AlwaysSet = TRUE;
5033
5034 /* Set additional flags */
5035 if (Cpl <= State->Flags.Iopl) State->Flags.If = NewFlags.If;
5036 if (Cpl == 0) State->Flags.Iopl = NewFlags.Iopl;
5037
5038 if (GET_SEGMENT_RPL(CodeSel) > Cpl)
5039 {
5040 /* Update the CPL */
5041 Cpl = Soft386GetCurrentPrivLevel(State);
5042
5043 /* Check segment security */
5044 for (i = 0; i <= SOFT386_NUM_SEG_REGS; i++)
5045 {
5046 /* Don't check CS or SS */
5047 if ((i == SOFT386_REG_CS) || (i == SOFT386_REG_SS)) continue;
5048
5049 if ((Cpl > State->SegmentRegs[i].Dpl)
5050 && (!State->SegmentRegs[i].Executable
5051 || !State->SegmentRegs[i].DirConf))
5052 {
5053 /* Load the NULL descriptor in the segment */
5054 if (!Soft386LoadSegment(State, i, 0)) return FALSE;
5055 }
5056 }
5057 }
5058 }
5059 else
5060 {
5061 if (Size && (InstPtr & 0xFFFF0000))
5062 {
5063 /* Invalid */
5064 Soft386ExceptionWithErrorCode(State, SOFT386_EXCEPTION_GP, 0);
5065 return FALSE;
5066 }
5067
5068 /* Set new EIP */
5069 State->InstPtr.Long = InstPtr;
5070
5071 /* Load new CS */
5072 if (!Soft386LoadSegment(State, SOFT386_REG_CS, CodeSel))
5073 {
5074 /* Exception occurred */
5075 return FALSE;
5076 }
5077
5078 /* Set the new flags */
5079 if (Size) State->Flags.Long = NewFlags.Long & REAL_MODE_FLAGS_MASK;
5080 else State->Flags.LowWord = NewFlags.LowWord & REAL_MODE_FLAGS_MASK;
5081 State->Flags.AlwaysSet = TRUE;
5082 }
5083
5084 return TRUE;
5085 }
5086
5087 SOFT386_OPCODE_HANDLER(Soft386OpcodeAam)
5088 {
5089 UCHAR Base;
5090 UCHAR Value = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
5091
5092 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
5093 {
5094 /* Invalid prefix */
5095 Soft386Exception(State, SOFT386_EXCEPTION_UD);
5096 return FALSE;
5097 }
5098
5099 /* Fetch the base */
5100 if (!Soft386FetchByte(State, &Base))
5101 {
5102 /* Exception occurred */
5103 return FALSE;
5104 }
5105
5106 /* Check if the base is zero */
5107 if (Base == 0)
5108 {
5109 /* Divide error */
5110 Soft386Exception(State, SOFT386_EXCEPTION_DE);
5111 return FALSE;
5112 }
5113
5114 /* Adjust */
5115 State->GeneralRegs[SOFT386_REG_EAX].HighByte = Value / Base;
5116 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Value %= Base;
5117
5118 /* Update flags */
5119 State->Flags.Zf = (Value == 0) ? TRUE : FALSE;
5120 State->Flags.Sf = (Value & SIGN_FLAG_BYTE) ? TRUE : FALSE;
5121 State->Flags.Pf = Soft386CalculateParity(Value);
5122
5123 return TRUE;
5124 }
5125
5126 SOFT386_OPCODE_HANDLER(Soft386OpcodeAad)
5127 {
5128 UCHAR Base;
5129 UCHAR Value = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
5130
5131 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
5132 {
5133 /* Invalid prefix */
5134 Soft386Exception(State, SOFT386_EXCEPTION_UD);
5135 return FALSE;
5136 }
5137
5138 /* Fetch the base */
5139 if (!Soft386FetchByte(State, &Base))
5140 {
5141 /* Exception occurred */
5142 return FALSE;
5143 }
5144
5145 /* Adjust */
5146 Value += State->GeneralRegs[SOFT386_REG_EAX].HighByte * Base;
5147 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Value;
5148
5149 /* Update flags */
5150 State->Flags.Zf = (Value == 0) ? TRUE : FALSE;
5151 State->Flags.Sf = (Value & SIGN_FLAG_BYTE) ? TRUE : FALSE;
5152 State->Flags.Pf = Soft386CalculateParity(Value);
5153
5154 return TRUE;
5155 }
5156
5157 SOFT386_OPCODE_HANDLER(Soft386OpcodeXlat)
5158 {
5159 // TODO: NOT IMPLEMENTED
5160 UNIMPLEMENTED;
5161
5162 return FALSE;
5163 }
5164
5165 SOFT386_OPCODE_HANDLER(Soft386OpcodeLoop)
5166 {
5167 BOOLEAN Condition;
5168 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
5169 CHAR Offset = 0;
5170
5171 /* Make sure this is the right instruction */
5172 ASSERT((Opcode >= 0xE0) && (Opcode <= 0xE2));
5173
5174 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
5175 {
5176 /* Invalid prefix */
5177 Soft386Exception(State, SOFT386_EXCEPTION_UD);
5178 return FALSE;
5179 }
5180
5181 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
5182 {
5183 /* The OPSIZE prefix toggles the size */
5184 Size = !Size;
5185 }
5186
5187 if (Size) Condition = ((--State->GeneralRegs[SOFT386_REG_ECX].Long) == 0);
5188 else Condition = ((--State->GeneralRegs[SOFT386_REG_ECX].LowWord) == 0);
5189
5190 if (Opcode == 0xE0)
5191 {
5192 /* Additional rule for LOOPNZ */
5193 if (State->Flags.Zf) Condition = FALSE;
5194 }
5195
5196 if (Opcode == 0xE1)
5197 {
5198 /* Additional rule for LOOPZ */
5199 if (!State->Flags.Zf) Condition = FALSE;
5200 }
5201
5202 /* Fetch the offset */
5203 if (!Soft386FetchByte(State, (PUCHAR)&Offset))
5204 {
5205 /* An exception occurred */
5206 return FALSE;
5207 }
5208
5209 if (Condition)
5210 {
5211 /* Move the instruction pointer */
5212 State->InstPtr.Long += Offset;
5213 }
5214
5215 return TRUE;
5216 }
5217
5218 SOFT386_OPCODE_HANDLER(Soft386OpcodeJecxz)
5219 {
5220 BOOLEAN Condition;
5221 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
5222 CHAR Offset = 0;
5223
5224 /* Make sure this is the right instruction */
5225 ASSERT(Opcode == 0xE3);
5226
5227 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
5228 {
5229 /* Invalid prefix */
5230 Soft386Exception(State, SOFT386_EXCEPTION_UD);
5231 return FALSE;
5232 }
5233
5234 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
5235 {
5236 /* The OPSIZE prefix toggles the size */
5237 Size = !Size;
5238 }
5239
5240 if (Size) Condition = (State->GeneralRegs[SOFT386_REG_ECX].Long == 0);
5241 else Condition = (State->GeneralRegs[SOFT386_REG_ECX].LowWord == 0);
5242
5243 /* Fetch the offset */
5244 if (!Soft386FetchByte(State, (PUCHAR)&Offset))
5245 {
5246 /* An exception occurred */
5247 return FALSE;
5248 }
5249
5250 if (Condition)
5251 {
5252 /* Move the instruction pointer */
5253 State->InstPtr.Long += Offset;
5254 }
5255
5256 return TRUE;
5257 }
5258
5259 SOFT386_OPCODE_HANDLER(Soft386OpcodeCall)
5260 {
5261 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
5262
5263 /* Make sure this is the right instruction */
5264 ASSERT(Opcode == 0xE8);
5265
5266 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
5267 {
5268 /* The OPSIZE prefix toggles the size */
5269 Size = !Size;
5270 }
5271 else if (State->PrefixFlags != 0)
5272 {
5273 /* Invalid prefix */
5274 Soft386Exception(State, SOFT386_EXCEPTION_UD);
5275 return FALSE;
5276 }
5277
5278 if (Size)
5279 {
5280 LONG Offset = 0;
5281
5282 /* Fetch the offset */
5283 if (!Soft386FetchDword(State, (PULONG)&Offset))
5284 {
5285 /* An exception occurred */
5286 return FALSE;
5287 }
5288
5289 /* Push the current value of the instruction pointer */
5290 if (!Soft386StackPush(State, State->InstPtr.Long))
5291 {
5292 /* Exception occurred */
5293 return FALSE;
5294 }
5295
5296 /* Move the instruction pointer */
5297 State->InstPtr.Long += Offset;
5298 }
5299 else
5300 {
5301 SHORT Offset = 0;
5302
5303 /* Fetch the offset */
5304 if (!Soft386FetchWord(State, (PUSHORT)&Offset))
5305 {
5306 /* An exception occurred */
5307 return FALSE;
5308 }
5309
5310 /* Push the current value of the instruction pointer */
5311 if (!Soft386StackPush(State, State->InstPtr.Long))
5312 {
5313 /* Exception occurred */
5314 return FALSE;
5315 }
5316
5317 /* Move the instruction pointer */
5318 State->InstPtr.LowWord += Offset;
5319 }
5320
5321 return TRUE;
5322 }
5323
5324 SOFT386_OPCODE_HANDLER(Soft386OpcodeJmp)
5325 {
5326 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
5327
5328 /* Make sure this is the right instruction */
5329 ASSERT(Opcode == 0xE9);
5330
5331 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
5332 {
5333 /* The OPSIZE prefix toggles the size */
5334 Size = !Size;
5335 }
5336 else if (State->PrefixFlags != 0)
5337 {
5338 /* Invalid prefix */
5339 Soft386Exception(State, SOFT386_EXCEPTION_UD);
5340 return FALSE;
5341 }
5342
5343 if (Size)
5344 {
5345 LONG Offset = 0;
5346
5347 /* Fetch the offset */
5348 if (!Soft386FetchDword(State, (PULONG)&Offset))
5349 {
5350 /* An exception occurred */
5351 return FALSE;
5352 }
5353
5354 /* Move the instruction pointer */
5355 State->InstPtr.Long += Offset;
5356 }
5357 else
5358 {
5359 SHORT Offset = 0;
5360
5361 /* Fetch the offset */
5362 if (!Soft386FetchWord(State, (PUSHORT)&Offset))
5363 {
5364 /* An exception occurred */
5365 return FALSE;
5366 }
5367
5368 /* Move the instruction pointer */
5369 State->InstPtr.LowWord += Offset;
5370 }
5371
5372 return TRUE;
5373 }
5374
5375 SOFT386_OPCODE_HANDLER(Soft386OpcodeJmpAbs)
5376 {
5377 // TODO: NOT IMPLEMENTED
5378 UNIMPLEMENTED;
5379
5380 return FALSE;
5381 }
5382
5383 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovAlOffset)
5384 {
5385 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
5386 ULONG Offset;
5387
5388 /* Make sure this is the right instruction */
5389 ASSERT(Opcode == 0xA0);
5390
5391 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
5392 {
5393 /* The OPSIZE prefix toggles the size */
5394 Size = !Size;
5395 }
5396
5397 if (Size)
5398 {
5399 if (!Soft386FetchDword(State, &Offset))
5400 {
5401 /* Exception occurred */
5402 return FALSE;
5403 }
5404 }
5405 else
5406 {
5407 USHORT WordOffset;
5408
5409 if (!Soft386FetchWord(State, &WordOffset))
5410 {
5411 /* Exception occurred */
5412 return FALSE;
5413 }
5414
5415 Offset = (ULONG)WordOffset;
5416 }
5417
5418 /* Read from memory */
5419 return Soft386ReadMemory(State,
5420 (State->PrefixFlags & SOFT386_PREFIX_SEG) ?
5421 State->SegmentOverride : SOFT386_REG_DS,
5422 Offset,
5423 FALSE,
5424 &State->GeneralRegs[SOFT386_REG_EAX].LowByte,
5425 sizeof(UCHAR));
5426 }
5427
5428 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovEaxOffset)
5429 {
5430 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
5431
5432 /* Make sure this is the right instruction */
5433 ASSERT(Opcode == 0xA1);
5434
5435 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
5436 {
5437 /* The OPSIZE prefix toggles the size */
5438 Size = !Size;
5439 }
5440
5441 if (Size)
5442 {
5443 ULONG Offset;
5444
5445 if (!Soft386FetchDword(State, &Offset))
5446 {
5447 /* Exception occurred */
5448 return FALSE;
5449 }
5450
5451 /* Read from memory */
5452 return Soft386ReadMemory(State,
5453 (State->PrefixFlags & SOFT386_PREFIX_SEG) ?
5454 State->SegmentOverride : SOFT386_REG_DS,
5455 Offset,
5456 FALSE,
5457 &State->GeneralRegs[SOFT386_REG_EAX].Long,
5458 sizeof(ULONG));
5459 }
5460 else
5461 {
5462 USHORT Offset;
5463
5464 if (!Soft386FetchWord(State, &Offset))
5465 {
5466 /* Exception occurred */
5467 return FALSE;
5468 }
5469
5470 /* Read from memory */
5471 return Soft386ReadMemory(State,
5472 (State->PrefixFlags & SOFT386_PREFIX_SEG) ?
5473 State->SegmentOverride : SOFT386_REG_DS,
5474 Offset,
5475 FALSE,
5476 &State->GeneralRegs[SOFT386_REG_EAX].LowWord,
5477 sizeof(USHORT));
5478 }
5479 }
5480
5481 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovOffsetAl)
5482 {
5483 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
5484 ULONG Offset;
5485
5486 /* Make sure this is the right instruction */
5487 ASSERT(Opcode == 0xA2);
5488
5489 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
5490 {
5491 /* The OPSIZE prefix toggles the size */
5492 Size = !Size;
5493 }
5494
5495 if (Size)
5496 {
5497 if (!Soft386FetchDword(State, &Offset))
5498 {
5499 /* Exception occurred */
5500 return FALSE;
5501 }
5502 }
5503 else
5504 {
5505 USHORT WordOffset;
5506
5507 if (!Soft386FetchWord(State, &WordOffset))
5508 {
5509 /* Exception occurred */
5510 return FALSE;
5511 }
5512
5513 Offset = (ULONG)WordOffset;
5514 }
5515
5516 /* Write to memory */
5517 return Soft386WriteMemory(State,
5518 (State->PrefixFlags & SOFT386_PREFIX_SEG) ?
5519 State->SegmentOverride : SOFT386_REG_DS,
5520 Offset,
5521 &State->GeneralRegs[SOFT386_REG_EAX].LowByte,
5522 sizeof(UCHAR));
5523 }
5524
5525 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovOffsetEax)
5526 {
5527 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
5528
5529 /* Make sure this is the right instruction */
5530 ASSERT(Opcode == 0xA3);
5531
5532 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
5533 {
5534 /* The OPSIZE prefix toggles the size */
5535 Size = !Size;
5536 }
5537
5538 if (Size)
5539 {
5540 ULONG Offset;
5541
5542 if (!Soft386FetchDword(State, &Offset))
5543 {
5544 /* Exception occurred */
5545 return FALSE;
5546 }
5547
5548 /* Write to memory */
5549 return Soft386WriteMemory(State,
5550 (State->PrefixFlags & SOFT386_PREFIX_SEG) ?
5551 State->SegmentOverride : SOFT386_REG_DS,
5552 Offset,
5553 &State->GeneralRegs[SOFT386_REG_EAX].Long,
5554 sizeof(ULONG));
5555 }
5556 else
5557 {
5558 USHORT Offset;
5559
5560 if (!Soft386FetchWord(State, &Offset))
5561 {
5562 /* Exception occurred */
5563 return FALSE;
5564 }
5565
5566 /* Write to memory */
5567 return Soft386WriteMemory(State,
5568 (State->PrefixFlags & SOFT386_PREFIX_SEG) ?
5569 State->SegmentOverride : SOFT386_REG_DS,
5570 Offset,
5571 &State->GeneralRegs[SOFT386_REG_EAX].LowWord,
5572 sizeof(USHORT));
5573 }
5574 }