e2dac35583b4adb12248592f2238f1edfebb926f
[reactos.git] / lib / soft386 / opcodes.c
1 /*
2 * Soft386 386/486 CPU Emulation Library
3 * opcodes.c
4 *
5 * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
21
22 /* INCLUDES *******************************************************************/
23
24 // #define WIN32_NO_STATUS
25 // #define _INC_WINDOWS
26 #include <windef.h>
27 #include <limits.h>
28
29 // #define NDEBUG
30 #include <debug.h>
31
32 #include <soft386.h>
33 #include "opcodes.h"
34 #include "opgroups.h"
35 #include "extraops.h"
36 #include "common.h"
37
38 /* PUBLIC VARIABLES ***********************************************************/
39
40 SOFT386_OPCODE_HANDLER_PROC
41 Soft386OpcodeHandlers[SOFT386_NUM_OPCODE_HANDLERS] =
42 {
43 Soft386OpcodeAddByteModrm,
44 Soft386OpcodeAddModrm,
45 Soft386OpcodeAddByteModrm,
46 Soft386OpcodeAddModrm,
47 Soft386OpcodeAddAl,
48 Soft386OpcodeAddEax,
49 Soft386OpcodePushEs,
50 Soft386OpcodePopEs,
51 Soft386OpcodeOrByteModrm,
52 Soft386OpcodeOrModrm,
53 Soft386OpcodeOrByteModrm,
54 Soft386OpcodeOrModrm,
55 Soft386OpcodeOrAl,
56 Soft386OpcodeOrEax,
57 Soft386OpcodePushCs,
58 Soft386OpcodeExtended,
59 Soft386OpcodeAdcByteModrm,
60 Soft386OpcodeAdcModrm,
61 Soft386OpcodeAdcByteModrm,
62 Soft386OpcodeAdcModrm,
63 Soft386OpcodeAdcAl,
64 Soft386OpcodeAdcEax,
65 Soft386OpcodePushSs,
66 Soft386OpcodePopSs,
67 Soft386OpcodeSbbByteModrm,
68 Soft386OpcodeSbbModrm,
69 Soft386OpcodeSbbByteModrm,
70 Soft386OpcodeSbbModrm,
71 Soft386OpcodeSbbAl,
72 Soft386OpcodeSbbEax,
73 Soft386OpcodePushDs,
74 Soft386OpcodePopDs,
75 Soft386OpcodeAndByteModrm,
76 Soft386OpcodeAndModrm,
77 Soft386OpcodeAndByteModrm,
78 Soft386OpcodeAndModrm,
79 Soft386OpcodeAndAl,
80 Soft386OpcodeAndEax,
81 Soft386OpcodePrefix,
82 Soft386OpcodeDaa,
83 Soft386OpcodeCmpSubByteModrm,
84 Soft386OpcodeCmpSubModrm,
85 Soft386OpcodeCmpSubByteModrm,
86 Soft386OpcodeCmpSubModrm,
87 Soft386OpcodeCmpSubAl,
88 Soft386OpcodeCmpSubEax,
89 Soft386OpcodePrefix,
90 Soft386OpcodeDas,
91 Soft386OpcodeXorByteModrm,
92 Soft386OpcodeXorModrm,
93 Soft386OpcodeXorByteModrm,
94 Soft386OpcodeXorModrm,
95 Soft386OpcodeXorAl,
96 Soft386OpcodeXorEax,
97 Soft386OpcodePrefix,
98 Soft386OpcodeAaa,
99 Soft386OpcodeCmpSubByteModrm,
100 Soft386OpcodeCmpSubModrm,
101 Soft386OpcodeCmpSubByteModrm,
102 Soft386OpcodeCmpSubModrm,
103 Soft386OpcodeCmpSubAl,
104 Soft386OpcodeCmpSubEax,
105 Soft386OpcodePrefix,
106 Soft386OpcodeAas,
107 Soft386OpcodeIncrement,
108 Soft386OpcodeIncrement,
109 Soft386OpcodeIncrement,
110 Soft386OpcodeIncrement,
111 Soft386OpcodeIncrement,
112 Soft386OpcodeIncrement,
113 Soft386OpcodeIncrement,
114 Soft386OpcodeIncrement,
115 Soft386OpcodeDecrement,
116 Soft386OpcodeDecrement,
117 Soft386OpcodeDecrement,
118 Soft386OpcodeDecrement,
119 Soft386OpcodeDecrement,
120 Soft386OpcodeDecrement,
121 Soft386OpcodeDecrement,
122 Soft386OpcodeDecrement,
123 Soft386OpcodePushReg,
124 Soft386OpcodePushReg,
125 Soft386OpcodePushReg,
126 Soft386OpcodePushReg,
127 Soft386OpcodePushReg,
128 Soft386OpcodePushReg,
129 Soft386OpcodePushReg,
130 Soft386OpcodePushReg,
131 Soft386OpcodePopReg,
132 Soft386OpcodePopReg,
133 Soft386OpcodePopReg,
134 Soft386OpcodePopReg,
135 Soft386OpcodePopReg,
136 Soft386OpcodePopReg,
137 Soft386OpcodePopReg,
138 Soft386OpcodePopReg,
139 Soft386OpcodePushAll,
140 Soft386OpcodePopAll,
141 Soft386OpcodeBound,
142 Soft386OpcodeArpl,
143 Soft386OpcodePrefix,
144 Soft386OpcodePrefix,
145 Soft386OpcodePrefix,
146 Soft386OpcodePrefix,
147 Soft386OpcodePushImm,
148 Soft386OpcodeImulModrmImm,
149 Soft386OpcodePushByteImm,
150 Soft386OpcodeImulModrmImm,
151 Soft386OpcodeIns,
152 Soft386OpcodeIns,
153 Soft386OpcodeOuts,
154 Soft386OpcodeOuts,
155 Soft386OpcodeShortConditionalJmp,
156 Soft386OpcodeShortConditionalJmp,
157 Soft386OpcodeShortConditionalJmp,
158 Soft386OpcodeShortConditionalJmp,
159 Soft386OpcodeShortConditionalJmp,
160 Soft386OpcodeShortConditionalJmp,
161 Soft386OpcodeShortConditionalJmp,
162 Soft386OpcodeShortConditionalJmp,
163 Soft386OpcodeShortConditionalJmp,
164 Soft386OpcodeShortConditionalJmp,
165 Soft386OpcodeShortConditionalJmp,
166 Soft386OpcodeShortConditionalJmp,
167 Soft386OpcodeShortConditionalJmp,
168 Soft386OpcodeShortConditionalJmp,
169 Soft386OpcodeShortConditionalJmp,
170 Soft386OpcodeShortConditionalJmp,
171 Soft386OpcodeGroup8082,
172 Soft386OpcodeGroup81,
173 Soft386OpcodeGroup8082,
174 Soft386OpcodeGroup83,
175 Soft386OpcodeTestByteModrm,
176 Soft386OpcodeTestModrm,
177 Soft386OpcodeXchgByteModrm,
178 Soft386OpcodeXchgModrm,
179 Soft386OpcodeMovByteModrm,
180 Soft386OpcodeMovModrm,
181 Soft386OpcodeMovByteModrm,
182 Soft386OpcodeMovModrm,
183 Soft386OpcodeMovStoreSeg,
184 Soft386OpcodeLea,
185 Soft386OpcodeMovLoadSeg,
186 Soft386OpcodeGroup8F,
187 Soft386OpcodeNop,
188 Soft386OpcodeExchangeEax,
189 Soft386OpcodeExchangeEax,
190 Soft386OpcodeExchangeEax,
191 Soft386OpcodeExchangeEax,
192 Soft386OpcodeExchangeEax,
193 Soft386OpcodeExchangeEax,
194 Soft386OpcodeExchangeEax,
195 Soft386OpcodeCwde,
196 Soft386OpcodeCdq,
197 Soft386OpcodeCallAbs,
198 Soft386OpcodeWait,
199 Soft386OpcodePushFlags,
200 Soft386OpcodePopFlags,
201 Soft386OpcodeSahf,
202 Soft386OpcodeLahf,
203 Soft386OpcodeMovAlOffset,
204 Soft386OpcodeMovEaxOffset,
205 Soft386OpcodeMovOffsetAl,
206 Soft386OpcodeMovOffsetEax,
207 Soft386OpcodeMovs,
208 Soft386OpcodeMovs,
209 Soft386OpcodeCmps,
210 Soft386OpcodeCmps,
211 Soft386OpcodeTestAl,
212 Soft386OpcodeTestEax,
213 Soft386OpcodeStos,
214 Soft386OpcodeStos,
215 Soft386OpcodeLods,
216 Soft386OpcodeLods,
217 Soft386OpcodeScas,
218 Soft386OpcodeScas,
219 Soft386OpcodeMovByteRegImm,
220 Soft386OpcodeMovByteRegImm,
221 Soft386OpcodeMovByteRegImm,
222 Soft386OpcodeMovByteRegImm,
223 Soft386OpcodeMovByteRegImm,
224 Soft386OpcodeMovByteRegImm,
225 Soft386OpcodeMovByteRegImm,
226 Soft386OpcodeMovByteRegImm,
227 Soft386OpcodeMovRegImm,
228 Soft386OpcodeMovRegImm,
229 Soft386OpcodeMovRegImm,
230 Soft386OpcodeMovRegImm,
231 Soft386OpcodeMovRegImm,
232 Soft386OpcodeMovRegImm,
233 Soft386OpcodeMovRegImm,
234 Soft386OpcodeMovRegImm,
235 Soft386OpcodeGroupC0,
236 Soft386OpcodeGroupC1,
237 Soft386OpcodeRet,
238 Soft386OpcodeRet,
239 Soft386OpcodeLdsLes,
240 Soft386OpcodeLdsLes,
241 Soft386OpcodeGroupC6,
242 Soft386OpcodeGroupC7,
243 Soft386OpcodeEnter,
244 Soft386OpcodeLeave,
245 Soft386OpcodeRetFarImm,
246 Soft386OpcodeRetFar,
247 Soft386OpcodeInt,
248 Soft386OpcodeInt,
249 Soft386OpcodeInt,
250 Soft386OpcodeIret,
251 Soft386OpcodeGroupD0,
252 Soft386OpcodeGroupD1,
253 Soft386OpcodeGroupD2,
254 Soft386OpcodeGroupD3,
255 Soft386OpcodeAam,
256 Soft386OpcodeAad,
257 Soft386OpcodeSalc,
258 Soft386OpcodeXlat,
259 NULL, // TODO: OPCODE 0xD8 NOT SUPPORTED
260 NULL, // TODO: OPCODE 0xD9 NOT SUPPORTED
261 NULL, // TODO: OPCODE 0xDA NOT SUPPORTED
262 NULL, // TODO: OPCODE 0xDB NOT SUPPORTED
263 NULL, // TODO: OPCODE 0xDC NOT SUPPORTED
264 NULL, // TODO: OPCODE 0xDD NOT SUPPORTED
265 NULL, // TODO: OPCODE 0xDE NOT SUPPORTED
266 NULL, // TODO: OPCODE 0xDF NOT SUPPORTED
267 Soft386OpcodeLoop,
268 Soft386OpcodeLoop,
269 Soft386OpcodeLoop,
270 Soft386OpcodeJecxz,
271 Soft386OpcodeInByte,
272 Soft386OpcodeIn,
273 Soft386OpcodeOutByte,
274 Soft386OpcodeOut,
275 Soft386OpcodeCall,
276 Soft386OpcodeJmp,
277 Soft386OpcodeJmpAbs,
278 Soft386OpcodeShortJump,
279 Soft386OpcodeInByte,
280 Soft386OpcodeIn,
281 Soft386OpcodeOutByte,
282 Soft386OpcodeOut,
283 Soft386OpcodePrefix,
284 NULL, // Invalid
285 Soft386OpcodePrefix,
286 Soft386OpcodePrefix,
287 Soft386OpcodeHalt,
288 Soft386OpcodeComplCarry,
289 Soft386OpcodeGroupF6,
290 Soft386OpcodeGroupF7,
291 Soft386OpcodeClearCarry,
292 Soft386OpcodeSetCarry,
293 Soft386OpcodeClearInt,
294 Soft386OpcodeSetInt,
295 Soft386OpcodeClearDir,
296 Soft386OpcodeSetDir,
297 Soft386OpcodeGroupFE,
298 Soft386OpcodeGroupFF,
299 };
300
301 /* PUBLIC FUNCTIONS ***********************************************************/
302
303 SOFT386_OPCODE_HANDLER(Soft386OpcodePrefix)
304 {
305 BOOLEAN Valid = FALSE;
306
307 switch (Opcode)
308 {
309 /* ES: */
310 case 0x26:
311 {
312 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
313 {
314 State->PrefixFlags |= SOFT386_PREFIX_SEG;
315 State->SegmentOverride = SOFT386_REG_ES;
316 Valid = TRUE;
317 }
318
319 break;
320 }
321
322 /* CS: */
323 case 0x2E:
324 {
325 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
326 {
327 State->PrefixFlags |= SOFT386_PREFIX_SEG;
328 State->SegmentOverride = SOFT386_REG_CS;
329 Valid = TRUE;
330 }
331
332 break;
333 }
334
335 /* SS: */
336 case 0x36:
337 {
338 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
339 {
340 State->PrefixFlags |= SOFT386_PREFIX_SEG;
341 State->SegmentOverride = SOFT386_REG_SS;
342 Valid = TRUE;
343 }
344
345 break;
346 }
347
348 /* DS: */
349 case 0x3E:
350 {
351 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
352 {
353 State->PrefixFlags |= SOFT386_PREFIX_SEG;
354 State->SegmentOverride = SOFT386_REG_DS;
355 Valid = TRUE;
356 }
357
358 break;
359 }
360
361 /* FS: */
362 case 0x64:
363 {
364 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
365 {
366 State->PrefixFlags |= SOFT386_PREFIX_SEG;
367 State->SegmentOverride = SOFT386_REG_FS;
368 Valid = TRUE;
369 }
370
371 break;
372 }
373
374 /* GS: */
375 case 0x65:
376 {
377 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
378 {
379 State->PrefixFlags |= SOFT386_PREFIX_SEG;
380 State->SegmentOverride = SOFT386_REG_GS;
381 Valid = TRUE;
382 }
383
384 break;
385 }
386
387 /* OPSIZE */
388 case 0x66:
389 {
390 if (!(State->PrefixFlags & SOFT386_PREFIX_OPSIZE))
391 {
392 State->PrefixFlags |= SOFT386_PREFIX_OPSIZE;
393 Valid = TRUE;
394 }
395
396 break;
397 }
398
399 /* ADSIZE */
400 case 0x67:
401 {
402 if (!(State->PrefixFlags & SOFT386_PREFIX_ADSIZE))
403 {
404 State->PrefixFlags |= SOFT386_PREFIX_ADSIZE;
405 Valid = TRUE;
406 }
407 break;
408 }
409
410 /* LOCK */
411 case 0xF0:
412 {
413 if (!(State->PrefixFlags & SOFT386_PREFIX_LOCK))
414 {
415 State->PrefixFlags |= SOFT386_PREFIX_LOCK;
416 Valid = TRUE;
417 }
418
419 break;
420 }
421
422 /* REPNZ */
423 case 0xF2:
424 {
425 /* Mutually exclusive with REP */
426 if (!(State->PrefixFlags
427 & (SOFT386_PREFIX_REPNZ | SOFT386_PREFIX_REP)))
428 {
429 State->PrefixFlags |= SOFT386_PREFIX_REPNZ;
430 Valid = TRUE;
431 }
432
433 break;
434 }
435
436 /* REP / REPZ */
437 case 0xF3:
438 {
439 /* Mutually exclusive with REPNZ */
440 if (!(State->PrefixFlags
441 & (SOFT386_PREFIX_REPNZ | SOFT386_PREFIX_REP)))
442 {
443 State->PrefixFlags |= SOFT386_PREFIX_REP;
444 Valid = TRUE;
445 }
446
447 break;
448 }
449 }
450
451 if (!Valid)
452 {
453 /* Clear all prefixes */
454 State->PrefixFlags = 0;
455
456 /* Throw an exception */
457 Soft386Exception(State, SOFT386_EXCEPTION_UD);
458 return FALSE;
459 }
460
461 return TRUE;
462 }
463
464 SOFT386_OPCODE_HANDLER(Soft386OpcodeIncrement)
465 {
466 ULONG Value;
467 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
468
469 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
470 {
471 /* The OPSIZE prefix toggles the size */
472 Size = !Size;
473 }
474
475 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
476 {
477 /* Invalid prefix */
478 Soft386Exception(State, SOFT386_EXCEPTION_UD);
479 return FALSE;
480 }
481
482 /* Make sure this is the right instruction */
483 ASSERT((Opcode & 0xF8) == 0x40);
484
485 if (Size)
486 {
487 Value = ++State->GeneralRegs[Opcode & 0x07].Long;
488
489 State->Flags.Of = (Value == SIGN_FLAG_LONG) ? TRUE : FALSE;
490 State->Flags.Sf = (Value & SIGN_FLAG_LONG) ? TRUE : FALSE;
491 }
492 else
493 {
494 Value = ++State->GeneralRegs[Opcode & 0x07].LowWord;
495
496 State->Flags.Of = (Value == SIGN_FLAG_WORD) ? TRUE : FALSE;
497 State->Flags.Sf = (Value & SIGN_FLAG_WORD) ? TRUE : FALSE;
498 }
499
500 State->Flags.Zf = (Value == 0) ? TRUE : FALSE;
501 State->Flags.Af = ((Value & 0x0F) == 0) ? TRUE : FALSE;
502 State->Flags.Pf = Soft386CalculateParity(LOBYTE(Value));
503
504 /* Return success */
505 return TRUE;
506 }
507
508 SOFT386_OPCODE_HANDLER(Soft386OpcodeDecrement)
509 {
510 ULONG Value;
511 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
512
513 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
514 {
515 /* The OPSIZE prefix toggles the size */
516 Size = !Size;
517 }
518
519 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
520 {
521 /* Invalid prefix */
522 Soft386Exception(State, SOFT386_EXCEPTION_UD);
523 return FALSE;
524 }
525
526 /* Make sure this is the right instruction */
527 ASSERT((Opcode & 0xF8) == 0x48);
528
529 if (Size)
530 {
531 Value = --State->GeneralRegs[Opcode & 0x07].Long;
532
533 State->Flags.Of = (Value == (SIGN_FLAG_LONG - 1)) ? TRUE : FALSE;
534 State->Flags.Sf = (Value & SIGN_FLAG_LONG) ? TRUE : FALSE;
535 }
536 else
537 {
538 Value = --State->GeneralRegs[Opcode & 0x07].LowWord;
539
540 State->Flags.Of = (Value == (SIGN_FLAG_WORD - 1)) ? TRUE : FALSE;
541 State->Flags.Sf = (Value & SIGN_FLAG_WORD) ? TRUE : FALSE;
542 }
543
544 State->Flags.Zf = (Value == 0) ? TRUE : FALSE;
545 State->Flags.Af = ((Value & 0x0F) == 0x0F) ? TRUE : FALSE;
546 State->Flags.Pf = Soft386CalculateParity(LOBYTE(Value));
547
548 /* Return success */
549 return TRUE;
550 }
551
552 SOFT386_OPCODE_HANDLER(Soft386OpcodePushReg)
553 {
554 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
555 {
556 /* Invalid prefix */
557 Soft386Exception(State, SOFT386_EXCEPTION_UD);
558 return FALSE;
559 }
560
561 /* Make sure this is the right instruction */
562 ASSERT((Opcode & 0xF8) == 0x50);
563
564 /* Call the internal function */
565 return Soft386StackPush(State, State->GeneralRegs[Opcode & 0x07].Long);
566 }
567
568 SOFT386_OPCODE_HANDLER(Soft386OpcodePopReg)
569 {
570 ULONG Value;
571 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_SS].Size;
572
573 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
574 {
575 /* The OPSIZE prefix toggles the size */
576 Size = !Size;
577 }
578
579 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
580 {
581 /* Invalid prefix */
582 Soft386Exception(State, SOFT386_EXCEPTION_UD);
583 return FALSE;
584 }
585
586 /* Make sure this is the right instruction */
587 ASSERT((Opcode & 0xF8) == 0x58);
588
589 /* Call the internal function */
590 if (!Soft386StackPop(State, &Value)) return FALSE;
591
592 /* Store the value */
593 if (Size) State->GeneralRegs[Opcode & 0x07].Long = Value;
594 else State->GeneralRegs[Opcode & 0x07].LowWord = Value;
595
596 /* Return success */
597 return TRUE;
598 }
599
600 SOFT386_OPCODE_HANDLER(Soft386OpcodeNop)
601 {
602 if (State->PrefixFlags & ~(SOFT386_PREFIX_OPSIZE | SOFT386_PREFIX_REP))
603 {
604 /* Allowed prefixes are REP and OPSIZE */
605 Soft386Exception(State, SOFT386_EXCEPTION_UD);
606 return FALSE;
607 }
608
609 if (State->PrefixFlags & SOFT386_PREFIX_REP)
610 {
611 /* Idle cycle */
612 State->IdleCallback(State);
613 }
614
615 return TRUE;
616 }
617
618 SOFT386_OPCODE_HANDLER(Soft386OpcodeExchangeEax)
619 {
620 INT Reg = Opcode & 0x07;
621 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
622
623 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
624 {
625 /* The OPSIZE prefix toggles the size */
626 Size = !Size;
627 }
628
629 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
630 {
631 /* Invalid prefix */
632 Soft386Exception(State, SOFT386_EXCEPTION_UD);
633 return FALSE;
634 }
635
636 /* Make sure this is the right instruction */
637 ASSERT((Opcode & 0xF8) == 0x90);
638
639 /* Exchange the values */
640 if (Size)
641 {
642 ULONG Value;
643
644 Value = State->GeneralRegs[Reg].Long;
645 State->GeneralRegs[Reg].Long = State->GeneralRegs[SOFT386_REG_EAX].Long;
646 State->GeneralRegs[SOFT386_REG_EAX].Long = Value;
647 }
648 else
649 {
650 USHORT Value;
651
652 Value = State->GeneralRegs[Reg].LowWord;
653 State->GeneralRegs[Reg].LowWord = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
654 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Value;
655 }
656
657 return TRUE;
658 }
659
660 SOFT386_OPCODE_HANDLER(Soft386OpcodeShortConditionalJmp)
661 {
662 BOOLEAN Jump = FALSE;
663 CHAR Offset = 0;
664
665 /* Make sure this is the right instruction */
666 ASSERT((Opcode & 0xF0) == 0x70);
667
668 /* Fetch the offset */
669 if (!Soft386FetchByte(State, (PUCHAR)&Offset))
670 {
671 /* An exception occurred */
672 return FALSE;
673 }
674
675 switch ((Opcode & 0x0F) >> 1)
676 {
677 /* JO / JNO */
678 case 0:
679 {
680 Jump = State->Flags.Of;
681 break;
682 }
683
684 /* JC / JNC */
685 case 1:
686 {
687 Jump = State->Flags.Cf;
688 break;
689 }
690
691 /* JZ / JNZ */
692 case 2:
693 {
694 Jump = State->Flags.Zf;
695 break;
696 }
697
698 /* JBE / JNBE */
699 case 3:
700 {
701 Jump = State->Flags.Cf || State->Flags.Zf;
702 break;
703 }
704
705 /* JS / JNS */
706 case 4:
707 {
708 Jump = State->Flags.Sf;
709 break;
710 }
711
712 /* JP / JNP */
713 case 5:
714 {
715 Jump = State->Flags.Pf;
716 break;
717 }
718
719 /* JL / JNL */
720 case 6:
721 {
722 Jump = State->Flags.Sf != State->Flags.Of;
723 break;
724 }
725
726 /* JLE / JNLE */
727 case 7:
728 {
729 Jump = (State->Flags.Sf != State->Flags.Of) || State->Flags.Zf;
730 break;
731 }
732 }
733
734 if (Opcode & 1)
735 {
736 /* Invert the result */
737 Jump = !Jump;
738 }
739
740 if (Jump)
741 {
742 /* Move the instruction pointer */
743 State->InstPtr.Long += Offset;
744 }
745
746 /* Return success */
747 return TRUE;
748 }
749
750 SOFT386_OPCODE_HANDLER(Soft386OpcodeClearCarry)
751 {
752 /* Make sure this is the right instruction */
753 ASSERT(Opcode == 0xF8);
754
755 /* No prefixes allowed */
756 if (State->PrefixFlags)
757 {
758 Soft386Exception(State, SOFT386_EXCEPTION_UD);
759 return FALSE;
760 }
761
762 /* Clear CF and return success */
763 State->Flags.Cf = FALSE;
764 return TRUE;
765 }
766
767 SOFT386_OPCODE_HANDLER(Soft386OpcodeSetCarry)
768 {
769 /* Make sure this is the right instruction */
770 ASSERT(Opcode == 0xF9);
771
772 /* No prefixes allowed */
773 if (State->PrefixFlags)
774 {
775 Soft386Exception(State, SOFT386_EXCEPTION_UD);
776 return FALSE;
777 }
778
779 /* Set CF and return success*/
780 State->Flags.Cf = TRUE;
781 return TRUE;
782 }
783
784 SOFT386_OPCODE_HANDLER(Soft386OpcodeComplCarry)
785 {
786 /* Make sure this is the right instruction */
787 ASSERT(Opcode == 0xF5);
788
789 /* No prefixes allowed */
790 if (State->PrefixFlags)
791 {
792 Soft386Exception(State, SOFT386_EXCEPTION_UD);
793 return FALSE;
794 }
795
796 /* Toggle CF and return success */
797 State->Flags.Cf = !State->Flags.Cf;
798 return TRUE;
799 }
800
801 SOFT386_OPCODE_HANDLER(Soft386OpcodeClearInt)
802 {
803 /* Make sure this is the right instruction */
804 ASSERT(Opcode == 0xFA);
805
806 /* No prefixes allowed */
807 if (State->PrefixFlags)
808 {
809 Soft386Exception(State, SOFT386_EXCEPTION_UD);
810 return FALSE;
811 }
812
813 /* Check for protected mode */
814 if (State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE)
815 {
816 /* Check IOPL */
817 if (State->Flags.Iopl >= State->SegmentRegs[SOFT386_REG_CS].Dpl)
818 {
819 /* Clear the interrupt flag */
820 State->Flags.If = FALSE;
821 }
822 else
823 {
824 /* General Protection Fault */
825 Soft386Exception(State, SOFT386_EXCEPTION_GP);
826 return FALSE;
827 }
828 }
829 else
830 {
831 /* Just clear the interrupt flag */
832 State->Flags.If = FALSE;
833 }
834
835 /* Return success */
836 return TRUE;
837 }
838
839 SOFT386_OPCODE_HANDLER(Soft386OpcodeSetInt)
840 {
841 /* Make sure this is the right instruction */
842 ASSERT(Opcode == 0xFB);
843
844 /* No prefixes allowed */
845 if (State->PrefixFlags)
846 {
847 Soft386Exception(State, SOFT386_EXCEPTION_UD);
848 return FALSE;
849 }
850
851 /* Check for protected mode */
852 if (State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE)
853 {
854 /* Check IOPL */
855 if (State->Flags.Iopl >= State->SegmentRegs[SOFT386_REG_CS].Dpl)
856 {
857 /* Set the interrupt flag */
858 State->Flags.If = TRUE;
859 }
860 else
861 {
862 /* General Protection Fault */
863 Soft386Exception(State, SOFT386_EXCEPTION_GP);
864 return FALSE;
865 }
866 }
867 else
868 {
869 /* Just set the interrupt flag */
870 State->Flags.If = TRUE;
871 }
872
873 /* Return success */
874 return TRUE;
875 }
876
877 SOFT386_OPCODE_HANDLER(Soft386OpcodeClearDir)
878 {
879 /* Make sure this is the right instruction */
880 ASSERT(Opcode == 0xFC);
881
882 /* No prefixes allowed */
883 if (State->PrefixFlags)
884 {
885 Soft386Exception(State, SOFT386_EXCEPTION_UD);
886 return FALSE;
887 }
888
889 /* Clear DF and return success */
890 State->Flags.Df = FALSE;
891 return TRUE;
892 }
893
894 SOFT386_OPCODE_HANDLER(Soft386OpcodeSetDir)
895 {
896 /* Make sure this is the right instruction */
897 ASSERT(Opcode == 0xFD);
898
899 /* No prefixes allowed */
900 if (State->PrefixFlags)
901 {
902 Soft386Exception(State, SOFT386_EXCEPTION_UD);
903 return FALSE;
904 }
905
906 /* Set DF and return success*/
907 State->Flags.Df = TRUE;
908 return TRUE;
909 }
910
911 SOFT386_OPCODE_HANDLER(Soft386OpcodeHalt)
912 {
913 /* Make sure this is the right instruction */
914 ASSERT(Opcode == 0xF4);
915
916 /* No prefixes allowed */
917 if (State->PrefixFlags)
918 {
919 Soft386Exception(State, SOFT386_EXCEPTION_UD);
920 return FALSE;
921 }
922
923 /* Privileged instructions can only be executed under CPL = 0 */
924 if (State->SegmentRegs[SOFT386_REG_CS].Dpl != 0)
925 {
926 Soft386Exception(State, SOFT386_EXCEPTION_GP);
927 return FALSE;
928 }
929
930 /* Halt */
931 while (!State->HardwareInt) State->IdleCallback(State);
932
933 /* Return success */
934 return TRUE;
935 }
936
937 SOFT386_OPCODE_HANDLER(Soft386OpcodeInByte)
938 {
939 UCHAR Data;
940 ULONG Port;
941
942 /* Make sure this is the right instruction */
943 ASSERT((Opcode & 0xF7) == 0xE4);
944
945 if (Opcode == 0xE4)
946 {
947 /* Fetch the parameter */
948 if (!Soft386FetchByte(State, &Data))
949 {
950 /* Exception occurred */
951 return FALSE;
952 }
953
954 /* Set the port number to the parameter */
955 Port = Data;
956 }
957 else
958 {
959 /* The port number is in DX */
960 Port = State->GeneralRegs[SOFT386_REG_EDX].LowWord;
961 }
962
963 /* Read a byte from the I/O port */
964 State->IoReadCallback(State, Port, &Data, sizeof(UCHAR));
965
966 /* Store the result in AL */
967 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Data;
968
969 return TRUE;
970 }
971
972 SOFT386_OPCODE_HANDLER(Soft386OpcodeIn)
973 {
974 ULONG Port;
975 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
976
977 /* Make sure this is the right instruction */
978 ASSERT((Opcode & 0xF7) == 0xE5);
979
980 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
981 {
982 /* The OPSIZE prefix toggles the size */
983 Size = !Size;
984 }
985
986 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
987 {
988 /* Invalid prefix */
989 Soft386Exception(State, SOFT386_EXCEPTION_UD);
990 return FALSE;
991 }
992
993 if (Opcode == 0xE5)
994 {
995 UCHAR Data;
996
997 /* Fetch the parameter */
998 if (!Soft386FetchByte(State, &Data))
999 {
1000 /* Exception occurred */
1001 return FALSE;
1002 }
1003
1004 /* Set the port number to the parameter */
1005 Port = Data;
1006 }
1007 else
1008 {
1009 /* The port number is in DX */
1010 Port = State->GeneralRegs[SOFT386_REG_EDX].LowWord;
1011 }
1012
1013 if (Size)
1014 {
1015 ULONG Data;
1016
1017 /* Read a dword from the I/O port */
1018 State->IoReadCallback(State, Port, &Data, sizeof(ULONG));
1019
1020 /* Store the value in EAX */
1021 State->GeneralRegs[SOFT386_REG_EAX].Long = Data;
1022 }
1023 else
1024 {
1025 USHORT Data;
1026
1027 /* Read a word from the I/O port */
1028 State->IoReadCallback(State, Port, &Data, sizeof(USHORT));
1029
1030 /* Store the value in AX */
1031 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Data;
1032 }
1033
1034 return TRUE;
1035 }
1036
1037 SOFT386_OPCODE_HANDLER(Soft386OpcodeOutByte)
1038 {
1039 UCHAR Data;
1040 ULONG Port;
1041
1042 /* Make sure this is the right instruction */
1043 ASSERT((Opcode & 0xF7) == 0xE6);
1044
1045 if (Opcode == 0xE6)
1046 {
1047 /* Fetch the parameter */
1048 if (!Soft386FetchByte(State, &Data))
1049 {
1050 /* Exception occurred */
1051 return FALSE;
1052 }
1053
1054 /* Set the port number to the parameter */
1055 Port = Data;
1056 }
1057 else
1058 {
1059 /* The port number is in DX */
1060 Port = State->GeneralRegs[SOFT386_REG_EDX].LowWord;
1061 }
1062
1063 /* Read the value from AL */
1064 Data = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
1065
1066 /* Write the byte to the I/O port */
1067 State->IoWriteCallback(State, Port, &Data, sizeof(UCHAR));
1068
1069 return TRUE;
1070 }
1071
1072 SOFT386_OPCODE_HANDLER(Soft386OpcodeOut)
1073 {
1074 ULONG Port;
1075 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
1076
1077 /* Make sure this is the right instruction */
1078 ASSERT((Opcode & 0xF7) == 0xE7);
1079
1080 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
1081 {
1082 /* The OPSIZE prefix toggles the size */
1083 Size = !Size;
1084 }
1085
1086 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
1087 {
1088 /* Invalid prefix */
1089 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1090 return FALSE;
1091 }
1092
1093 if (Opcode == 0xE7)
1094 {
1095 UCHAR Data;
1096
1097 /* Fetch the parameter */
1098 if (!Soft386FetchByte(State, &Data))
1099 {
1100 /* Exception occurred */
1101 return FALSE;
1102 }
1103
1104 /* Set the port number to the parameter */
1105 Port = Data;
1106 }
1107 else
1108 {
1109 /* The port number is in DX */
1110 Port = State->GeneralRegs[SOFT386_REG_EDX].LowWord;
1111 }
1112
1113 if (Size)
1114 {
1115 /* Get the value from EAX */
1116 ULONG Data = State->GeneralRegs[SOFT386_REG_EAX].Long;
1117
1118 /* Write a dword to the I/O port */
1119 State->IoReadCallback(State, Port, &Data, sizeof(ULONG));
1120 }
1121 else
1122 {
1123 /* Get the value from AX */
1124 USHORT Data = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
1125
1126 /* Write a word to the I/O port */
1127 State->IoWriteCallback(State, Port, &Data, sizeof(USHORT));
1128 }
1129
1130 return TRUE;
1131 }
1132
1133 SOFT386_OPCODE_HANDLER(Soft386OpcodeShortJump)
1134 {
1135 CHAR Offset = 0;
1136
1137 /* Make sure this is the right instruction */
1138 ASSERT(Opcode == 0xEB);
1139
1140 /* Fetch the offset */
1141 if (!Soft386FetchByte(State, (PUCHAR)&Offset))
1142 {
1143 /* An exception occurred */
1144 return FALSE;
1145 }
1146
1147 /* Move the instruction pointer */
1148 State->InstPtr.Long += Offset;
1149
1150 return TRUE;
1151 }
1152
1153 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovRegImm)
1154 {
1155 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
1156
1157 /* Make sure this is the right instruction */
1158 ASSERT((Opcode & 0xF8) == 0xB8);
1159
1160 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
1161 {
1162 /* The OPSIZE prefix toggles the size */
1163 Size = !Size;
1164 }
1165
1166 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
1167 {
1168 /* Invalid prefix */
1169 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1170 return FALSE;
1171 }
1172
1173 if (Size)
1174 {
1175 ULONG Value;
1176
1177 /* Fetch the dword */
1178 if (!Soft386FetchDword(State, &Value))
1179 {
1180 /* Exception occurred */
1181 return FALSE;
1182 }
1183
1184 /* Store the value in the register */
1185 State->GeneralRegs[Opcode & 0x07].Long = Value;
1186 }
1187 else
1188 {
1189 USHORT Value;
1190
1191 /* Fetch the word */
1192 if (!Soft386FetchWord(State, &Value))
1193 {
1194 /* Exception occurred */
1195 return FALSE;
1196 }
1197
1198 /* Store the value in the register */
1199 State->GeneralRegs[Opcode & 0x07].LowWord = Value;
1200 }
1201
1202 return TRUE;
1203 }
1204
1205 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovByteRegImm)
1206 {
1207 UCHAR Value;
1208
1209 /* Make sure this is the right instruction */
1210 ASSERT((Opcode & 0xF8) == 0xB0);
1211
1212 if (State->PrefixFlags != 0)
1213 {
1214 /* Invalid prefix */
1215 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1216 return FALSE;
1217 }
1218
1219 /* Fetch the byte */
1220 if (!Soft386FetchByte(State, &Value))
1221 {
1222 /* Exception occurred */
1223 return FALSE;
1224 }
1225
1226 if (Opcode & 0x04)
1227 {
1228 /* AH, CH, DH or BH */
1229 State->GeneralRegs[Opcode & 0x03].HighByte = Value;
1230 }
1231 else
1232 {
1233 /* AL, CL, DL or BL */
1234 State->GeneralRegs[Opcode & 0x03].LowByte = Value;
1235 }
1236
1237 return TRUE;
1238 }
1239
1240 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddByteModrm)
1241 {
1242 UCHAR FirstValue, SecondValue, Result;
1243 SOFT386_MOD_REG_RM ModRegRm;
1244 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
1245
1246 /* Make sure this is the right instruction */
1247 ASSERT((Opcode & 0xFD) == 0x00);
1248
1249 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
1250 {
1251 /* The ADSIZE prefix toggles the size */
1252 AddressSize = !AddressSize;
1253 }
1254 else if (State->PrefixFlags
1255 & ~(SOFT386_PREFIX_ADSIZE
1256 | SOFT386_PREFIX_SEG
1257 | SOFT386_PREFIX_LOCK))
1258 {
1259 /* Invalid prefix */
1260 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1261 return FALSE;
1262 }
1263
1264 /* Get the operands */
1265 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
1266 {
1267 /* Exception occurred */
1268 return FALSE;
1269 }
1270
1271 if (!Soft386ReadModrmByteOperands(State,
1272 &ModRegRm,
1273 &FirstValue,
1274 &SecondValue))
1275 {
1276 /* Exception occurred */
1277 return FALSE;
1278 }
1279
1280 /* Calculate the result */
1281 Result = FirstValue + SecondValue;
1282
1283 /* Update the flags */
1284 State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
1285 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE))
1286 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
1287 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
1288 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1289 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
1290 State->Flags.Pf = Soft386CalculateParity(Result);
1291
1292 /* Write back the result */
1293 return Soft386WriteModrmByteOperands(State,
1294 &ModRegRm,
1295 Opcode & SOFT386_OPCODE_WRITE_REG,
1296 Result);
1297 }
1298
1299 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddModrm)
1300 {
1301 SOFT386_MOD_REG_RM ModRegRm;
1302 BOOLEAN OperandSize, AddressSize;
1303
1304 /* Make sure this is the right instruction */
1305 ASSERT((Opcode & 0xFD) == 0x01);
1306
1307 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
1308
1309 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
1310 {
1311 /* The ADSIZE prefix toggles the address size */
1312 AddressSize = !AddressSize;
1313 }
1314
1315 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
1316 {
1317 /* The OPSIZE prefix toggles the operand size */
1318 OperandSize = !OperandSize;
1319 }
1320
1321 if (State->PrefixFlags
1322 & ~(SOFT386_PREFIX_ADSIZE
1323 | SOFT386_PREFIX_OPSIZE
1324 | SOFT386_PREFIX_SEG
1325 | SOFT386_PREFIX_LOCK))
1326 {
1327 /* Invalid prefix */
1328 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1329 return FALSE;
1330 }
1331
1332 /* Get the operands */
1333 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
1334 {
1335 /* Exception occurred */
1336 return FALSE;
1337 }
1338
1339 /* Check the operand size */
1340 if (OperandSize)
1341 {
1342 ULONG FirstValue, SecondValue, Result;
1343
1344 if (!Soft386ReadModrmDwordOperands(State,
1345 &ModRegRm,
1346 &FirstValue,
1347 &SecondValue))
1348 {
1349 /* Exception occurred */
1350 return FALSE;
1351 }
1352
1353 /* Calculate the result */
1354 Result = FirstValue + SecondValue;
1355
1356 /* Update the flags */
1357 State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
1358 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG))
1359 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
1360 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
1361 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1362 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
1363 State->Flags.Pf = Soft386CalculateParity(Result);
1364
1365 /* Write back the result */
1366 return Soft386WriteModrmDwordOperands(State,
1367 &ModRegRm,
1368 Opcode & SOFT386_OPCODE_WRITE_REG,
1369 Result);
1370 }
1371 else
1372 {
1373 USHORT FirstValue, SecondValue, Result;
1374
1375 if (!Soft386ReadModrmWordOperands(State,
1376 &ModRegRm,
1377 &FirstValue,
1378 &SecondValue))
1379 {
1380 /* Exception occurred */
1381 return FALSE;
1382 }
1383
1384 /* Calculate the result */
1385 Result = FirstValue + SecondValue;
1386
1387 /* Update the flags */
1388 State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
1389 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD))
1390 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
1391 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
1392 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1393 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
1394 State->Flags.Pf = Soft386CalculateParity(Result);
1395
1396 /* Write back the result */
1397 return Soft386WriteModrmWordOperands(State,
1398 &ModRegRm,
1399 Opcode & SOFT386_OPCODE_WRITE_REG,
1400 Result);
1401 }
1402 }
1403
1404 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddAl)
1405 {
1406 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
1407 UCHAR SecondValue, Result;
1408
1409 /* Make sure this is the right instruction */
1410 ASSERT(Opcode == 0x04);
1411
1412 if (State->PrefixFlags)
1413 {
1414 /* This opcode doesn't take any prefixes */
1415 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1416 return FALSE;
1417 }
1418
1419 if (!Soft386FetchByte(State, &SecondValue))
1420 {
1421 /* Exception occurred */
1422 return FALSE;
1423 }
1424
1425 /* Calculate the result */
1426 Result = FirstValue + SecondValue;
1427
1428 /* Update the flags */
1429 State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
1430 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE))
1431 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
1432 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
1433 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1434 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
1435 State->Flags.Pf = Soft386CalculateParity(Result);
1436
1437 /* Write back the result */
1438 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
1439
1440 return TRUE;
1441 }
1442
1443 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddEax)
1444 {
1445 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
1446
1447 /* Make sure this is the right instruction */
1448 ASSERT(Opcode == 0x05);
1449
1450 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
1451 {
1452 /* Invalid prefix */
1453 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1454 return FALSE;
1455 }
1456
1457 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
1458 {
1459 /* The OPSIZE prefix toggles the size */
1460 Size = !Size;
1461 }
1462
1463 if (Size)
1464 {
1465 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
1466 ULONG SecondValue, Result;
1467
1468 if (!Soft386FetchDword(State, &SecondValue))
1469 {
1470 /* Exception occurred */
1471 return FALSE;
1472 }
1473
1474 /* Calculate the result */
1475 Result = FirstValue + SecondValue;
1476
1477 /* Update the flags */
1478 State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
1479 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG))
1480 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
1481 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
1482 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1483 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
1484 State->Flags.Pf = Soft386CalculateParity(Result);
1485
1486 /* Write back the result */
1487 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
1488 }
1489 else
1490 {
1491 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
1492 USHORT SecondValue, Result;
1493
1494 if (!Soft386FetchWord(State, &SecondValue))
1495 {
1496 /* Exception occurred */
1497 return FALSE;
1498 }
1499
1500 /* Calculate the result */
1501 Result = FirstValue + SecondValue;
1502
1503 /* Update the flags */
1504 State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
1505 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD))
1506 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
1507 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
1508 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1509 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
1510 State->Flags.Pf = Soft386CalculateParity(Result);
1511
1512 /* Write back the result */
1513 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
1514 }
1515
1516 return TRUE;
1517 }
1518
1519 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrByteModrm)
1520 {
1521 UCHAR FirstValue, SecondValue, Result;
1522 SOFT386_MOD_REG_RM ModRegRm;
1523 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
1524
1525 /* Make sure this is the right instruction */
1526 ASSERT((Opcode & 0xFD) == 0x08);
1527
1528 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
1529 {
1530 /* The ADSIZE prefix toggles the size */
1531 AddressSize = !AddressSize;
1532 }
1533 else if (State->PrefixFlags
1534 & ~(SOFT386_PREFIX_ADSIZE
1535 | SOFT386_PREFIX_SEG
1536 | SOFT386_PREFIX_LOCK))
1537 {
1538 /* Invalid prefix */
1539 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1540 return FALSE;
1541 }
1542
1543 /* Get the operands */
1544 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
1545 {
1546 /* Exception occurred */
1547 return FALSE;
1548 }
1549
1550 if (!Soft386ReadModrmByteOperands(State,
1551 &ModRegRm,
1552 &FirstValue,
1553 &SecondValue))
1554 {
1555 /* Exception occurred */
1556 return FALSE;
1557 }
1558
1559 /* Calculate the result */
1560 Result = FirstValue | SecondValue;
1561
1562 /* Update the flags */
1563 State->Flags.Cf = FALSE;
1564 State->Flags.Of = FALSE;
1565 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1566 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
1567 State->Flags.Pf = Soft386CalculateParity(Result);
1568
1569 /* Write back the result */
1570 return Soft386WriteModrmByteOperands(State,
1571 &ModRegRm,
1572 Opcode & SOFT386_OPCODE_WRITE_REG,
1573 Result);
1574 }
1575
1576 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrModrm)
1577 {
1578 SOFT386_MOD_REG_RM ModRegRm;
1579 BOOLEAN OperandSize, AddressSize;
1580
1581 /* Make sure this is the right instruction */
1582 ASSERT((Opcode & 0xFD) == 0x09);
1583
1584 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
1585
1586 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
1587 {
1588 /* The ADSIZE prefix toggles the address size */
1589 AddressSize = !AddressSize;
1590 }
1591
1592 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
1593 {
1594 /* The OPSIZE prefix toggles the operand size */
1595 OperandSize = !OperandSize;
1596 }
1597
1598 if (State->PrefixFlags
1599 & ~(SOFT386_PREFIX_ADSIZE
1600 | SOFT386_PREFIX_OPSIZE
1601 | SOFT386_PREFIX_SEG
1602 | SOFT386_PREFIX_LOCK))
1603 {
1604 /* Invalid prefix */
1605 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1606 return FALSE;
1607 }
1608
1609 /* Get the operands */
1610 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
1611 {
1612 /* Exception occurred */
1613 return FALSE;
1614 }
1615
1616 /* Check the operand size */
1617 if (OperandSize)
1618 {
1619 ULONG FirstValue, SecondValue, Result;
1620
1621 if (!Soft386ReadModrmDwordOperands(State,
1622 &ModRegRm,
1623 &FirstValue,
1624 &SecondValue))
1625 {
1626 /* Exception occurred */
1627 return FALSE;
1628 }
1629
1630 /* Calculate the result */
1631 Result = FirstValue | SecondValue;
1632
1633 /* Update the flags */
1634 State->Flags.Cf = FALSE;
1635 State->Flags.Of = FALSE;
1636 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1637 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
1638 State->Flags.Pf = Soft386CalculateParity(Result);
1639
1640 /* Write back the result */
1641 return Soft386WriteModrmDwordOperands(State,
1642 &ModRegRm,
1643 Opcode & SOFT386_OPCODE_WRITE_REG,
1644 Result);
1645 }
1646 else
1647 {
1648 USHORT FirstValue, SecondValue, Result;
1649
1650 if (!Soft386ReadModrmWordOperands(State,
1651 &ModRegRm,
1652 &FirstValue,
1653 &SecondValue))
1654 {
1655 /* Exception occurred */
1656 return FALSE;
1657 }
1658
1659 /* Calculate the result */
1660 Result = FirstValue | SecondValue;
1661
1662 /* Update the flags */
1663 State->Flags.Cf = FALSE;
1664 State->Flags.Of = FALSE;
1665 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1666 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
1667 State->Flags.Pf = Soft386CalculateParity(Result);
1668
1669 /* Write back the result */
1670 return Soft386WriteModrmWordOperands(State,
1671 &ModRegRm,
1672 Opcode & SOFT386_OPCODE_WRITE_REG,
1673 Result);
1674 }
1675 }
1676
1677 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrAl)
1678 {
1679 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
1680 UCHAR SecondValue, Result;
1681
1682 /* Make sure this is the right instruction */
1683 ASSERT(Opcode == 0x0C);
1684
1685 if (State->PrefixFlags)
1686 {
1687 /* This opcode doesn't take any prefixes */
1688 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1689 return FALSE;
1690 }
1691
1692 if (!Soft386FetchByte(State, &SecondValue))
1693 {
1694 /* Exception occurred */
1695 return FALSE;
1696 }
1697
1698 /* Calculate the result */
1699 Result = FirstValue | SecondValue;
1700
1701 /* Update the flags */
1702 State->Flags.Cf = FALSE;
1703 State->Flags.Of = FALSE;
1704 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1705 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
1706 State->Flags.Pf = Soft386CalculateParity(Result);
1707
1708 /* Write back the result */
1709 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
1710
1711 return TRUE;
1712 }
1713
1714 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrEax)
1715 {
1716 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
1717
1718 /* Make sure this is the right instruction */
1719 ASSERT(Opcode == 0x0D);
1720
1721 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
1722 {
1723 /* Invalid prefix */
1724 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1725 return FALSE;
1726 }
1727
1728 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
1729 {
1730 /* The OPSIZE prefix toggles the size */
1731 Size = !Size;
1732 }
1733
1734 if (Size)
1735 {
1736 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
1737 ULONG SecondValue, Result;
1738
1739 if (!Soft386FetchDword(State, &SecondValue))
1740 {
1741 /* Exception occurred */
1742 return FALSE;
1743 }
1744
1745 /* Calculate the result */
1746 Result = FirstValue | SecondValue;
1747
1748 /* Update the flags */
1749 State->Flags.Cf = FALSE;
1750 State->Flags.Of = FALSE;
1751 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1752 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
1753 State->Flags.Pf = Soft386CalculateParity(Result);
1754
1755 /* Write back the result */
1756 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
1757 }
1758 else
1759 {
1760 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
1761 USHORT SecondValue, Result;
1762
1763 if (!Soft386FetchWord(State, &SecondValue))
1764 {
1765 /* Exception occurred */
1766 return FALSE;
1767 }
1768
1769 /* Calculate the result */
1770 Result = FirstValue | SecondValue;
1771
1772 /* Update the flags */
1773 State->Flags.Cf = FALSE;
1774 State->Flags.Of = FALSE;
1775 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1776 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
1777 State->Flags.Pf = Soft386CalculateParity(Result);
1778
1779 /* Write back the result */
1780 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
1781 }
1782
1783 return TRUE;
1784 }
1785
1786 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndByteModrm)
1787 {
1788 UCHAR FirstValue, SecondValue, Result;
1789 SOFT386_MOD_REG_RM ModRegRm;
1790 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
1791
1792 /* Make sure this is the right instruction */
1793 ASSERT((Opcode & 0xFD) == 0x20);
1794
1795 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
1796 {
1797 /* The ADSIZE prefix toggles the size */
1798 AddressSize = !AddressSize;
1799 }
1800 else if (State->PrefixFlags
1801 & ~(SOFT386_PREFIX_ADSIZE
1802 | SOFT386_PREFIX_SEG
1803 | SOFT386_PREFIX_LOCK))
1804 {
1805 /* Invalid prefix */
1806 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1807 return FALSE;
1808 }
1809
1810 /* Get the operands */
1811 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
1812 {
1813 /* Exception occurred */
1814 return FALSE;
1815 }
1816
1817 if (!Soft386ReadModrmByteOperands(State,
1818 &ModRegRm,
1819 &FirstValue,
1820 &SecondValue))
1821 {
1822 /* Exception occurred */
1823 return FALSE;
1824 }
1825
1826 /* Calculate the result */
1827 Result = FirstValue & SecondValue;
1828
1829 /* Update the flags */
1830 State->Flags.Cf = FALSE;
1831 State->Flags.Of = FALSE;
1832 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1833 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
1834 State->Flags.Pf = Soft386CalculateParity(Result);
1835
1836 /* Write back the result */
1837 return Soft386WriteModrmByteOperands(State,
1838 &ModRegRm,
1839 Opcode & SOFT386_OPCODE_WRITE_REG,
1840 Result);
1841 }
1842
1843 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndModrm)
1844 {
1845 SOFT386_MOD_REG_RM ModRegRm;
1846 BOOLEAN OperandSize, AddressSize;
1847
1848 /* Make sure this is the right instruction */
1849 ASSERT((Opcode & 0xFD) == 0x21);
1850
1851 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
1852
1853 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
1854 {
1855 /* The ADSIZE prefix toggles the address size */
1856 AddressSize = !AddressSize;
1857 }
1858
1859 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
1860 {
1861 /* The OPSIZE prefix toggles the operand size */
1862 OperandSize = !OperandSize;
1863 }
1864
1865 if (State->PrefixFlags
1866 & ~(SOFT386_PREFIX_ADSIZE
1867 | SOFT386_PREFIX_OPSIZE
1868 | SOFT386_PREFIX_SEG
1869 | SOFT386_PREFIX_LOCK))
1870 {
1871 /* Invalid prefix */
1872 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1873 return FALSE;
1874 }
1875
1876 /* Get the operands */
1877 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
1878 {
1879 /* Exception occurred */
1880 return FALSE;
1881 }
1882
1883 /* Check the operand size */
1884 if (OperandSize)
1885 {
1886 ULONG FirstValue, SecondValue, Result;
1887
1888 if (!Soft386ReadModrmDwordOperands(State,
1889 &ModRegRm,
1890 &FirstValue,
1891 &SecondValue))
1892 {
1893 /* Exception occurred */
1894 return FALSE;
1895 }
1896
1897 /* Calculate the result */
1898 Result = FirstValue & SecondValue;
1899
1900 /* Update the flags */
1901 State->Flags.Cf = FALSE;
1902 State->Flags.Of = FALSE;
1903 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1904 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
1905 State->Flags.Pf = Soft386CalculateParity(Result);
1906
1907 /* Write back the result */
1908 return Soft386WriteModrmDwordOperands(State,
1909 &ModRegRm,
1910 Opcode & SOFT386_OPCODE_WRITE_REG,
1911 Result);
1912 }
1913 else
1914 {
1915 USHORT FirstValue, SecondValue, Result;
1916
1917 if (!Soft386ReadModrmWordOperands(State,
1918 &ModRegRm,
1919 &FirstValue,
1920 &SecondValue))
1921 {
1922 /* Exception occurred */
1923 return FALSE;
1924 }
1925
1926 /* Calculate the result */
1927 Result = FirstValue & SecondValue;
1928
1929 /* Update the flags */
1930 State->Flags.Cf = FALSE;
1931 State->Flags.Of = FALSE;
1932 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1933 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
1934 State->Flags.Pf = Soft386CalculateParity(Result);
1935
1936 /* Write back the result */
1937 return Soft386WriteModrmWordOperands(State,
1938 &ModRegRm,
1939 Opcode & SOFT386_OPCODE_WRITE_REG,
1940 Result);
1941 }
1942 }
1943
1944 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndAl)
1945 {
1946 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
1947 UCHAR SecondValue, Result;
1948
1949 /* Make sure this is the right instruction */
1950 ASSERT(Opcode == 0x24);
1951
1952 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
1953 {
1954 /* Invalid prefix */
1955 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1956 return FALSE;
1957 }
1958
1959 if (!Soft386FetchByte(State, &SecondValue))
1960 {
1961 /* Exception occurred */
1962 return FALSE;
1963 }
1964
1965 /* Calculate the result */
1966 Result = FirstValue & SecondValue;
1967
1968 /* Update the flags */
1969 State->Flags.Cf = FALSE;
1970 State->Flags.Of = FALSE;
1971 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1972 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
1973 State->Flags.Pf = Soft386CalculateParity(Result);
1974
1975 /* Write back the result */
1976 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
1977
1978 return TRUE;
1979 }
1980
1981 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndEax)
1982 {
1983 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
1984
1985 /* Make sure this is the right instruction */
1986 ASSERT(Opcode == 0x25);
1987
1988 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
1989 {
1990 /* Invalid prefix */
1991 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1992 return FALSE;
1993 }
1994
1995 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
1996 {
1997 /* The OPSIZE prefix toggles the size */
1998 Size = !Size;
1999 }
2000
2001 if (Size)
2002 {
2003 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
2004 ULONG SecondValue, Result;
2005
2006 if (!Soft386FetchDword(State, &SecondValue))
2007 {
2008 /* Exception occurred */
2009 return FALSE;
2010 }
2011
2012 /* Calculate the result */
2013 Result = FirstValue & SecondValue;
2014
2015 /* Update the flags */
2016 State->Flags.Cf = FALSE;
2017 State->Flags.Of = FALSE;
2018 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2019 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
2020 State->Flags.Pf = Soft386CalculateParity(Result);
2021
2022 /* Write back the result */
2023 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
2024 }
2025 else
2026 {
2027 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
2028 USHORT SecondValue, Result;
2029
2030 if (!Soft386FetchWord(State, &SecondValue))
2031 {
2032 /* Exception occurred */
2033 return FALSE;
2034 }
2035
2036 /* Calculate the result */
2037 Result = FirstValue & SecondValue;
2038
2039 /* Update the flags */
2040 State->Flags.Cf = FALSE;
2041 State->Flags.Of = FALSE;
2042 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2043 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
2044 State->Flags.Pf = Soft386CalculateParity(Result);
2045
2046 /* Write back the result */
2047 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
2048 }
2049
2050 return TRUE;
2051 }
2052
2053 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorByteModrm)
2054 {
2055 UCHAR FirstValue, SecondValue, Result;
2056 SOFT386_MOD_REG_RM ModRegRm;
2057 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2058
2059 /* Make sure this is the right instruction */
2060 ASSERT((Opcode & 0xFD) == 0x30);
2061
2062 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2063 {
2064 /* The ADSIZE prefix toggles the size */
2065 AddressSize = !AddressSize;
2066 }
2067 else if (State->PrefixFlags
2068 & ~(SOFT386_PREFIX_ADSIZE
2069 | SOFT386_PREFIX_SEG
2070 | SOFT386_PREFIX_LOCK))
2071 {
2072 /* Invalid prefix */
2073 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2074 return FALSE;
2075 }
2076
2077 /* Get the operands */
2078 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2079 {
2080 /* Exception occurred */
2081 return FALSE;
2082 }
2083
2084 if (!Soft386ReadModrmByteOperands(State,
2085 &ModRegRm,
2086 &FirstValue,
2087 &SecondValue))
2088 {
2089 /* Exception occurred */
2090 return FALSE;
2091 }
2092
2093 /* Calculate the result */
2094 Result = FirstValue ^ SecondValue;
2095
2096 /* Update the flags */
2097 State->Flags.Cf = FALSE;
2098 State->Flags.Of = FALSE;
2099 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2100 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
2101 State->Flags.Pf = Soft386CalculateParity(Result);
2102
2103 /* Write back the result */
2104 return Soft386WriteModrmByteOperands(State,
2105 &ModRegRm,
2106 Opcode & SOFT386_OPCODE_WRITE_REG,
2107 Result);
2108 }
2109
2110 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorModrm)
2111 {
2112 SOFT386_MOD_REG_RM ModRegRm;
2113 BOOLEAN OperandSize, AddressSize;
2114
2115 /* Make sure this is the right instruction */
2116 ASSERT((Opcode & 0xFD) == 0x31);
2117
2118 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2119
2120 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2121 {
2122 /* The ADSIZE prefix toggles the address size */
2123 AddressSize = !AddressSize;
2124 }
2125
2126 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2127 {
2128 /* The OPSIZE prefix toggles the operand size */
2129 OperandSize = !OperandSize;
2130 }
2131
2132 if (State->PrefixFlags
2133 & ~(SOFT386_PREFIX_ADSIZE
2134 | SOFT386_PREFIX_OPSIZE
2135 | SOFT386_PREFIX_SEG
2136 | SOFT386_PREFIX_LOCK))
2137 {
2138 /* Invalid prefix */
2139 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2140 return FALSE;
2141 }
2142
2143 /* Get the operands */
2144 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2145 {
2146 /* Exception occurred */
2147 return FALSE;
2148 }
2149
2150 /* Check the operand size */
2151 if (OperandSize)
2152 {
2153 ULONG FirstValue, SecondValue, Result;
2154
2155 if (!Soft386ReadModrmDwordOperands(State,
2156 &ModRegRm,
2157 &FirstValue,
2158 &SecondValue))
2159 {
2160 /* Exception occurred */
2161 return FALSE;
2162 }
2163
2164 /* Calculate the result */
2165 Result = FirstValue ^ SecondValue;
2166
2167 /* Update the flags */
2168 State->Flags.Cf = FALSE;
2169 State->Flags.Of = FALSE;
2170 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2171 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
2172 State->Flags.Pf = Soft386CalculateParity(Result);
2173
2174 /* Write back the result */
2175 return Soft386WriteModrmDwordOperands(State,
2176 &ModRegRm,
2177 Opcode & SOFT386_OPCODE_WRITE_REG,
2178 Result);
2179 }
2180 else
2181 {
2182 USHORT FirstValue, SecondValue, Result;
2183
2184 if (!Soft386ReadModrmWordOperands(State,
2185 &ModRegRm,
2186 &FirstValue,
2187 &SecondValue))
2188 {
2189 /* Exception occurred */
2190 return FALSE;
2191 }
2192
2193 /* Calculate the result */
2194 Result = FirstValue ^ SecondValue;
2195
2196 /* Update the flags */
2197 State->Flags.Cf = FALSE;
2198 State->Flags.Of = FALSE;
2199 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2200 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
2201 State->Flags.Pf = Soft386CalculateParity(Result);
2202
2203 /* Write back the result */
2204 return Soft386WriteModrmWordOperands(State,
2205 &ModRegRm,
2206 Opcode & SOFT386_OPCODE_WRITE_REG,
2207 Result);
2208 }
2209 }
2210
2211 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorAl)
2212 {
2213 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
2214 UCHAR SecondValue, Result;
2215
2216 /* Make sure this is the right instruction */
2217 ASSERT(Opcode == 0x34);
2218
2219 if (State->PrefixFlags)
2220 {
2221 /* This opcode doesn't take any prefixes */
2222 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2223 return FALSE;
2224 }
2225
2226 if (!Soft386FetchByte(State, &SecondValue))
2227 {
2228 /* Exception occurred */
2229 return FALSE;
2230 }
2231
2232 /* Calculate the result */
2233 Result = FirstValue ^ SecondValue;
2234
2235 /* Update the flags */
2236 State->Flags.Cf = FALSE;
2237 State->Flags.Of = FALSE;
2238 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2239 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
2240 State->Flags.Pf = Soft386CalculateParity(Result);
2241
2242 /* Write back the result */
2243 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
2244
2245 return TRUE;
2246 }
2247
2248 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorEax)
2249 {
2250 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
2251
2252 /* Make sure this is the right instruction */
2253 ASSERT(Opcode == 0x35);
2254
2255 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
2256 {
2257 /* Invalid prefix */
2258 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2259 return FALSE;
2260 }
2261
2262 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2263 {
2264 /* The OPSIZE prefix toggles the size */
2265 Size = !Size;
2266 }
2267
2268 if (Size)
2269 {
2270 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
2271 ULONG SecondValue, Result;
2272
2273 if (!Soft386FetchDword(State, &SecondValue))
2274 {
2275 /* Exception occurred */
2276 return FALSE;
2277 }
2278
2279 /* Calculate the result */
2280 Result = FirstValue ^ SecondValue;
2281
2282 /* Update the flags */
2283 State->Flags.Cf = FALSE;
2284 State->Flags.Of = FALSE;
2285 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2286 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
2287 State->Flags.Pf = Soft386CalculateParity(Result);
2288
2289 /* Write back the result */
2290 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
2291 }
2292 else
2293 {
2294 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
2295 USHORT SecondValue, Result;
2296
2297 if (!Soft386FetchWord(State, &SecondValue))
2298 {
2299 /* Exception occurred */
2300 return FALSE;
2301 }
2302
2303 /* Calculate the result */
2304 Result = FirstValue ^ SecondValue;
2305
2306 /* Update the flags */
2307 State->Flags.Cf = FALSE;
2308 State->Flags.Of = FALSE;
2309 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2310 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
2311 State->Flags.Pf = Soft386CalculateParity(Result);
2312
2313 /* Write back the result */
2314 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
2315 }
2316
2317 return TRUE;
2318 }
2319
2320 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestByteModrm)
2321 {
2322 UCHAR FirstValue, SecondValue, Result;
2323 SOFT386_MOD_REG_RM ModRegRm;
2324 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2325
2326 /* Make sure this is the right instruction */
2327 ASSERT(Opcode == 0x84);
2328
2329 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2330 {
2331 /* The ADSIZE prefix toggles the size */
2332 AddressSize = !AddressSize;
2333 }
2334 else if (State->PrefixFlags
2335 & ~(SOFT386_PREFIX_ADSIZE
2336 | SOFT386_PREFIX_SEG
2337 | SOFT386_PREFIX_LOCK))
2338 {
2339 /* Invalid prefix */
2340 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2341 return FALSE;
2342 }
2343
2344 /* Get the operands */
2345 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2346 {
2347 /* Exception occurred */
2348 return FALSE;
2349 }
2350
2351 if (!Soft386ReadModrmByteOperands(State,
2352 &ModRegRm,
2353 &FirstValue,
2354 &SecondValue))
2355 {
2356 /* Exception occurred */
2357 return FALSE;
2358 }
2359 /* Calculate the result */
2360 Result = FirstValue & SecondValue;
2361
2362 /* Update the flags */
2363 State->Flags.Cf = FALSE;
2364 State->Flags.Of = FALSE;
2365 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2366 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
2367 State->Flags.Pf = Soft386CalculateParity(Result);
2368
2369 /* The result is discarded */
2370 return TRUE;
2371 }
2372
2373 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestModrm)
2374 {
2375 SOFT386_MOD_REG_RM ModRegRm;
2376 BOOLEAN OperandSize, AddressSize;
2377
2378 /* Make sure this is the right instruction */
2379 ASSERT(Opcode == 0x85);
2380
2381 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2382
2383 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2384 {
2385 /* The ADSIZE prefix toggles the address size */
2386 AddressSize = !AddressSize;
2387 }
2388
2389 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2390 {
2391 /* The OPSIZE prefix toggles the operand size */
2392 OperandSize = !OperandSize;
2393 }
2394
2395 if (State->PrefixFlags
2396 & ~(SOFT386_PREFIX_ADSIZE
2397 | SOFT386_PREFIX_OPSIZE
2398 | SOFT386_PREFIX_SEG
2399 | SOFT386_PREFIX_LOCK))
2400 {
2401 /* Invalid prefix */
2402 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2403 return FALSE;
2404 }
2405
2406 /* Get the operands */
2407 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2408 {
2409 /* Exception occurred */
2410 return FALSE;
2411 }
2412
2413 /* Check the operand size */
2414 if (OperandSize)
2415 {
2416 ULONG FirstValue, SecondValue, Result;
2417
2418 if (!Soft386ReadModrmDwordOperands(State,
2419 &ModRegRm,
2420 &FirstValue,
2421 &SecondValue))
2422 {
2423 /* Exception occurred */
2424 return FALSE;
2425 }
2426
2427 /* Calculate the result */
2428 Result = FirstValue & SecondValue;
2429
2430 /* Update the flags */
2431 State->Flags.Cf = FALSE;
2432 State->Flags.Of = FALSE;
2433 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2434 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
2435 State->Flags.Pf = Soft386CalculateParity(Result);
2436 }
2437 else
2438 {
2439 USHORT FirstValue, SecondValue, Result;
2440
2441 if (!Soft386ReadModrmWordOperands(State,
2442 &ModRegRm,
2443 &FirstValue,
2444 &SecondValue))
2445 {
2446 /* Exception occurred */
2447 return FALSE;
2448 }
2449
2450 /* Calculate the result */
2451 Result = FirstValue & SecondValue;
2452
2453 /* Update the flags */
2454 State->Flags.Cf = FALSE;
2455 State->Flags.Of = FALSE;
2456 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2457 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
2458 State->Flags.Pf = Soft386CalculateParity(Result);
2459 }
2460
2461 /* The result is discarded */
2462 return TRUE;
2463 }
2464
2465 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestAl)
2466 {
2467 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
2468 UCHAR SecondValue, Result;
2469
2470 /* Make sure this is the right instruction */
2471 ASSERT(Opcode == 0xA8);
2472
2473 if (State->PrefixFlags)
2474 {
2475 /* This opcode doesn't take any prefixes */
2476 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2477 return FALSE;
2478 }
2479
2480 if (!Soft386FetchByte(State, &SecondValue))
2481 {
2482 /* Exception occurred */
2483 return FALSE;
2484 }
2485
2486 /* Calculate the result */
2487 Result = FirstValue & SecondValue;
2488
2489 /* Update the flags */
2490 State->Flags.Cf = FALSE;
2491 State->Flags.Of = FALSE;
2492 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2493 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
2494 State->Flags.Pf = Soft386CalculateParity(Result);
2495
2496 /* The result is discarded */
2497 return TRUE;
2498 }
2499
2500 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestEax)
2501 {
2502 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
2503
2504 /* Make sure this is the right instruction */
2505 ASSERT(Opcode == 0xA9);
2506
2507 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
2508 {
2509 /* Invalid prefix */
2510 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2511 return FALSE;
2512 }
2513
2514 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2515 {
2516 /* The OPSIZE prefix toggles the size */
2517 Size = !Size;
2518 }
2519
2520 if (Size)
2521 {
2522 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
2523 ULONG SecondValue, Result;
2524
2525 if (!Soft386FetchDword(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_LONG) ? TRUE : FALSE;
2539 State->Flags.Pf = Soft386CalculateParity(Result);
2540 }
2541 else
2542 {
2543 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
2544 USHORT SecondValue, Result;
2545
2546 if (!Soft386FetchWord(State, &SecondValue))
2547 {
2548 /* Exception occurred */
2549 return FALSE;
2550 }
2551
2552 /* Calculate the result */
2553 Result = FirstValue & SecondValue;
2554
2555 /* Update the flags */
2556 State->Flags.Cf = FALSE;
2557 State->Flags.Of = FALSE;
2558 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2559 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
2560 State->Flags.Pf = Soft386CalculateParity(Result);
2561 }
2562
2563 /* The result is discarded */
2564 return TRUE;
2565 }
2566
2567 SOFT386_OPCODE_HANDLER(Soft386OpcodeXchgByteModrm)
2568 {
2569 UCHAR FirstValue, SecondValue;
2570 SOFT386_MOD_REG_RM ModRegRm;
2571 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2572
2573 /* Make sure this is the right instruction */
2574 ASSERT(Opcode == 0x86);
2575
2576 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2577 {
2578 /* The ADSIZE prefix toggles the size */
2579 AddressSize = !AddressSize;
2580 }
2581 else if (State->PrefixFlags
2582 & ~(SOFT386_PREFIX_ADSIZE
2583 | SOFT386_PREFIX_SEG
2584 | SOFT386_PREFIX_LOCK))
2585 {
2586 /* Invalid prefix */
2587 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2588 return FALSE;
2589 }
2590
2591 /* Get the operands */
2592 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2593 {
2594 /* Exception occurred */
2595 return FALSE;
2596 }
2597
2598 if (!Soft386ReadModrmByteOperands(State,
2599 &ModRegRm,
2600 &FirstValue,
2601 &SecondValue))
2602 {
2603 /* Exception occurred */
2604 return FALSE;
2605 }
2606
2607 /* Write the value from the register to the R/M */
2608 if (!Soft386WriteModrmByteOperands(State,
2609 &ModRegRm,
2610 FALSE,
2611 FirstValue))
2612 {
2613 /* Exception occurred */
2614 return FALSE;
2615 }
2616
2617 /* Write the value from the R/M to the register */
2618 if (!Soft386WriteModrmByteOperands(State,
2619 &ModRegRm,
2620 TRUE,
2621 SecondValue))
2622 {
2623 /* Exception occurred */
2624 return FALSE;
2625 }
2626
2627 return TRUE;
2628 }
2629
2630 SOFT386_OPCODE_HANDLER(Soft386OpcodeXchgModrm)
2631 {
2632 SOFT386_MOD_REG_RM ModRegRm;
2633 BOOLEAN OperandSize, AddressSize;
2634
2635 /* Make sure this is the right instruction */
2636 ASSERT(Opcode == 0x87);
2637
2638 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2639
2640 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2641 {
2642 /* The ADSIZE prefix toggles the address size */
2643 AddressSize = !AddressSize;
2644 }
2645
2646 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2647 {
2648 /* The OPSIZE prefix toggles the operand size */
2649 OperandSize = !OperandSize;
2650 }
2651
2652 if (State->PrefixFlags
2653 & ~(SOFT386_PREFIX_ADSIZE
2654 | SOFT386_PREFIX_OPSIZE
2655 | SOFT386_PREFIX_SEG
2656 | SOFT386_PREFIX_LOCK))
2657 {
2658 /* Invalid prefix */
2659 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2660 return FALSE;
2661 }
2662
2663 /* Get the operands */
2664 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2665 {
2666 /* Exception occurred */
2667 return FALSE;
2668 }
2669
2670 /* Check the operand size */
2671 if (OperandSize)
2672 {
2673 ULONG FirstValue, SecondValue;
2674
2675 if (!Soft386ReadModrmDwordOperands(State,
2676 &ModRegRm,
2677 &FirstValue,
2678 &SecondValue))
2679 {
2680 /* Exception occurred */
2681 return FALSE;
2682 }
2683
2684 /* Write the value from the register to the R/M */
2685 if (!Soft386WriteModrmDwordOperands(State,
2686 &ModRegRm,
2687 FALSE,
2688 FirstValue))
2689 {
2690 /* Exception occurred */
2691 return FALSE;
2692 }
2693
2694 /* Write the value from the R/M to the register */
2695 if (!Soft386WriteModrmDwordOperands(State,
2696 &ModRegRm,
2697 TRUE,
2698 SecondValue))
2699 {
2700 /* Exception occurred */
2701 return FALSE;
2702 }
2703 }
2704 else
2705 {
2706 USHORT FirstValue, SecondValue;
2707
2708 if (!Soft386ReadModrmWordOperands(State,
2709 &ModRegRm,
2710 &FirstValue,
2711 &SecondValue))
2712 {
2713 /* Exception occurred */
2714 return FALSE;
2715 }
2716
2717 /* Write the value from the register to the R/M */
2718 if (!Soft386WriteModrmWordOperands(State,
2719 &ModRegRm,
2720 FALSE,
2721 FirstValue))
2722 {
2723 /* Exception occurred */
2724 return FALSE;
2725 }
2726
2727 /* Write the value from the R/M to the register */
2728 if (!Soft386WriteModrmWordOperands(State,
2729 &ModRegRm,
2730 TRUE,
2731 SecondValue))
2732 {
2733 /* Exception occurred */
2734 return FALSE;
2735 }
2736 }
2737
2738 /* The result is discarded */
2739 return TRUE;
2740 }
2741
2742 SOFT386_OPCODE_HANDLER(Soft386OpcodePushEs)
2743 {
2744 /* Call the internal API */
2745 return Soft386StackPush(State, State->SegmentRegs[SOFT386_REG_ES].Selector);
2746 }
2747
2748 SOFT386_OPCODE_HANDLER(Soft386OpcodePopEs)
2749 {
2750 ULONG NewSelector;
2751
2752 if (!Soft386StackPop(State, &NewSelector))
2753 {
2754 /* Exception occurred */
2755 return FALSE;
2756 }
2757
2758 /* Call the internal API */
2759 return Soft386LoadSegment(State, SOFT386_REG_ES, LOWORD(NewSelector));
2760 }
2761
2762 SOFT386_OPCODE_HANDLER(Soft386OpcodePushCs)
2763 {
2764 /* Call the internal API */
2765 return Soft386StackPush(State, State->SegmentRegs[SOFT386_REG_CS].Selector);
2766 }
2767
2768 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcByteModrm)
2769 {
2770 UCHAR FirstValue, SecondValue, Result;
2771 SOFT386_MOD_REG_RM ModRegRm;
2772 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2773
2774 /* Make sure this is the right instruction */
2775 ASSERT((Opcode & 0xFD) == 0x10);
2776
2777 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2778 {
2779 /* The ADSIZE prefix toggles the size */
2780 AddressSize = !AddressSize;
2781 }
2782 else if (State->PrefixFlags
2783 & ~(SOFT386_PREFIX_ADSIZE
2784 | SOFT386_PREFIX_SEG
2785 | SOFT386_PREFIX_LOCK))
2786 {
2787 /* Invalid prefix */
2788 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2789 return FALSE;
2790 }
2791
2792 /* Get the operands */
2793 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2794 {
2795 /* Exception occurred */
2796 return FALSE;
2797 }
2798
2799 if (!Soft386ReadModrmByteOperands(State,
2800 &ModRegRm,
2801 &FirstValue,
2802 &SecondValue))
2803 {
2804 /* Exception occurred */
2805 return FALSE;
2806 }
2807
2808 /* Calculate the result */
2809 Result = FirstValue + SecondValue + State->Flags.Cf;
2810
2811 /* Special exception for CF */
2812 State->Flags.Cf = State->Flags.Cf
2813 && ((FirstValue == 0xFF) || (SecondValue == 0xFF));
2814
2815 /* Update the flags */
2816 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
2817 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE))
2818 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
2819 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
2820 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2821 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
2822 State->Flags.Pf = Soft386CalculateParity(Result);
2823
2824 /* Write back the result */
2825 return Soft386WriteModrmByteOperands(State,
2826 &ModRegRm,
2827 Opcode & SOFT386_OPCODE_WRITE_REG,
2828 Result);
2829 }
2830
2831 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcModrm)
2832 {
2833 SOFT386_MOD_REG_RM ModRegRm;
2834 BOOLEAN OperandSize, AddressSize;
2835
2836 /* Make sure this is the right instruction */
2837 ASSERT((Opcode & 0xFD) == 0x11);
2838
2839 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2840
2841 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2842 {
2843 /* The ADSIZE prefix toggles the address size */
2844 AddressSize = !AddressSize;
2845 }
2846
2847 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2848 {
2849 /* The OPSIZE prefix toggles the operand size */
2850 OperandSize = !OperandSize;
2851 }
2852
2853 if (State->PrefixFlags
2854 & ~(SOFT386_PREFIX_ADSIZE
2855 | SOFT386_PREFIX_OPSIZE
2856 | SOFT386_PREFIX_SEG
2857 | SOFT386_PREFIX_LOCK))
2858 {
2859 /* Invalid prefix */
2860 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2861 return FALSE;
2862 }
2863
2864 /* Get the operands */
2865 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2866 {
2867 /* Exception occurred */
2868 return FALSE;
2869 }
2870
2871 /* Check the operand size */
2872 if (OperandSize)
2873 {
2874 ULONG FirstValue, SecondValue, Result;
2875
2876 if (!Soft386ReadModrmDwordOperands(State,
2877 &ModRegRm,
2878 &FirstValue,
2879 &SecondValue))
2880 {
2881 /* Exception occurred */
2882 return FALSE;
2883 }
2884
2885 /* Calculate the result */
2886 Result = FirstValue + SecondValue + State->Flags.Cf;
2887
2888 /* Special exception for CF */
2889 State->Flags.Cf = State->Flags.Cf
2890 && ((FirstValue == 0xFFFFFFFF) || (SecondValue == 0xFFFFFFFF));
2891
2892 /* Update the flags */
2893 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
2894 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG))
2895 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
2896 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
2897 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2898 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
2899 State->Flags.Pf = Soft386CalculateParity(Result);
2900
2901 /* Write back the result */
2902 return Soft386WriteModrmDwordOperands(State,
2903 &ModRegRm,
2904 Opcode & SOFT386_OPCODE_WRITE_REG,
2905 Result);
2906 }
2907 else
2908 {
2909 USHORT FirstValue, SecondValue, Result;
2910
2911 if (!Soft386ReadModrmWordOperands(State,
2912 &ModRegRm,
2913 &FirstValue,
2914 &SecondValue))
2915 {
2916 /* Exception occurred */
2917 return FALSE;
2918 }
2919
2920 /* Calculate the result */
2921 Result = FirstValue + SecondValue + State->Flags.Cf;
2922
2923 /* Special exception for CF */
2924 State->Flags.Cf = State->Flags.Cf
2925 && ((FirstValue == 0xFFFF) || (SecondValue == 0xFFFF));
2926
2927 /* Update the flags */
2928 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
2929 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD))
2930 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
2931 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
2932 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2933 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
2934 State->Flags.Pf = Soft386CalculateParity(Result);
2935
2936 /* Write back the result */
2937 return Soft386WriteModrmWordOperands(State,
2938 &ModRegRm,
2939 Opcode & SOFT386_OPCODE_WRITE_REG,
2940 Result);
2941 }
2942
2943 }
2944
2945 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcAl)
2946 {
2947 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
2948 UCHAR SecondValue, Result;
2949
2950 /* Make sure this is the right instruction */
2951 ASSERT(Opcode == 0x14);
2952
2953 if (State->PrefixFlags)
2954 {
2955 /* This opcode doesn't take any prefixes */
2956 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2957 return FALSE;
2958 }
2959
2960 if (!Soft386FetchByte(State, &SecondValue))
2961 {
2962 /* Exception occurred */
2963 return FALSE;
2964 }
2965
2966 /* Calculate the result */
2967 Result = FirstValue + SecondValue + State->Flags.Cf;
2968
2969 /* Special exception for CF */
2970 State->Flags.Cf = State->Flags.Cf &&
2971 ((FirstValue == 0xFF) || (SecondValue == 0xFF));
2972
2973 /* Update the flags */
2974 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
2975 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE))
2976 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
2977 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
2978 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2979 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
2980 State->Flags.Pf = Soft386CalculateParity(Result);
2981
2982 /* Write back the result */
2983 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
2984
2985 return TRUE;
2986 }
2987
2988 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcEax)
2989 {
2990 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
2991
2992 /* Make sure this is the right instruction */
2993 ASSERT(Opcode == 0x15);
2994
2995 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
2996 {
2997 /* Invalid prefix */
2998 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2999 return FALSE;
3000 }
3001
3002 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
3003 {
3004 /* The OPSIZE prefix toggles the size */
3005 Size = !Size;
3006 }
3007
3008 if (Size)
3009 {
3010 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
3011 ULONG SecondValue, Result;
3012
3013 if (!Soft386FetchDword(State, &SecondValue))
3014 {
3015 /* Exception occurred */
3016 return FALSE;
3017 }
3018
3019 /* Calculate the result */
3020 Result = FirstValue + SecondValue + State->Flags.Cf;
3021
3022 /* Special exception for CF */
3023 State->Flags.Cf = State->Flags.Cf &&
3024 ((FirstValue == 0xFFFFFFFF) || (SecondValue == 0xFFFFFFFF));
3025
3026 /* Update the flags */
3027 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
3028 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG))
3029 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
3030 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
3031 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3032 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
3033 State->Flags.Pf = Soft386CalculateParity(Result);
3034
3035 /* Write back the result */
3036 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
3037 }
3038 else
3039 {
3040 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
3041 USHORT SecondValue, Result;
3042
3043 if (!Soft386FetchWord(State, &SecondValue))
3044 {
3045 /* Exception occurred */
3046 return FALSE;
3047 }
3048
3049 /* Calculate the result */
3050 Result = FirstValue + SecondValue + State->Flags.Cf;
3051
3052 /* Special exception for CF */
3053 State->Flags.Cf = State->Flags.Cf &&
3054 ((FirstValue == 0xFFFF) || (SecondValue == 0xFFFF));
3055
3056 /* Update the flags */
3057 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
3058 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD))
3059 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
3060 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
3061 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3062 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
3063 State->Flags.Pf = Soft386CalculateParity(Result);
3064
3065 /* Write back the result */
3066 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
3067 }
3068
3069 return TRUE;
3070 }
3071
3072 SOFT386_OPCODE_HANDLER(Soft386OpcodePushSs)
3073 {
3074 /* Call the internal API */
3075 return Soft386StackPush(State, State->SegmentRegs[SOFT386_REG_SS].Selector);
3076 }
3077
3078 SOFT386_OPCODE_HANDLER(Soft386OpcodePopSs)
3079 {
3080 ULONG NewSelector;
3081
3082 if (!Soft386StackPop(State, &NewSelector))
3083 {
3084 /* Exception occurred */
3085 return FALSE;
3086 }
3087
3088 /* Call the internal API */
3089 return Soft386LoadSegment(State, SOFT386_REG_SS, LOWORD(NewSelector));
3090 }
3091
3092 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbByteModrm)
3093 {
3094 UCHAR FirstValue, SecondValue, Result;
3095 SOFT386_MOD_REG_RM ModRegRm;
3096 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
3097 INT Carry = State->Flags.Cf ? 1 : 0;
3098
3099 /* Make sure this is the right instruction */
3100 ASSERT((Opcode & 0xFD) == 0x18);
3101
3102 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
3103 {
3104 /* The ADSIZE prefix toggles the size */
3105 AddressSize = !AddressSize;
3106 }
3107
3108 /* Get the operands */
3109 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
3110 {
3111 /* Exception occurred */
3112 return FALSE;
3113 }
3114
3115 if (!Soft386ReadModrmByteOperands(State,
3116 &ModRegRm,
3117 &FirstValue,
3118 &SecondValue))
3119 {
3120 /* Exception occurred */
3121 return FALSE;
3122 }
3123
3124 /* Check if this is the instruction that writes to R/M */
3125 if (!(Opcode & SOFT386_OPCODE_WRITE_REG))
3126 {
3127 /* Swap the order */
3128 FirstValue ^= SecondValue;
3129 SecondValue ^= FirstValue;
3130 FirstValue ^= SecondValue;
3131 }
3132
3133 /* Calculate the result */
3134 Result = FirstValue - SecondValue - Carry;
3135
3136 /* Update the flags */
3137 State->Flags.Cf = FirstValue < (SecondValue + 1);
3138 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) != (SecondValue & SIGN_FLAG_BYTE))
3139 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
3140 State->Flags.Af = (FirstValue & 0x0F) < ((SecondValue + 1) & 0x0F);
3141 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3142 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
3143 State->Flags.Pf = Soft386CalculateParity(Result);
3144
3145 /* Write back the result */
3146 return Soft386WriteModrmByteOperands(State,
3147 &ModRegRm,
3148 Opcode & SOFT386_OPCODE_WRITE_REG,
3149 Result);
3150 }
3151
3152 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbModrm)
3153 {
3154 SOFT386_MOD_REG_RM ModRegRm;
3155 BOOLEAN OperandSize, AddressSize;
3156 INT Carry = State->Flags.Cf ? 1 : 0;
3157
3158 /* Make sure this is the right instruction */
3159 ASSERT((Opcode & 0xFD) == 0x19);
3160
3161 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
3162
3163 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
3164 {
3165 /* The ADSIZE prefix toggles the address size */
3166 AddressSize = !AddressSize;
3167 }
3168
3169 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
3170 {
3171 /* The OPSIZE prefix toggles the operand size */
3172 OperandSize = !OperandSize;
3173 }
3174
3175 /* Get the operands */
3176 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
3177 {
3178 /* Exception occurred */
3179 return FALSE;
3180 }
3181
3182 /* Check the operand size */
3183 if (OperandSize)
3184 {
3185 ULONG FirstValue, SecondValue, Result;
3186
3187 if (!Soft386ReadModrmDwordOperands(State,
3188 &ModRegRm,
3189 &FirstValue,
3190 &SecondValue))
3191 {
3192 /* Exception occurred */
3193 return FALSE;
3194 }
3195
3196 /* Check if this is the instruction that writes to R/M */
3197 if (!(Opcode & SOFT386_OPCODE_WRITE_REG))
3198 {
3199 /* Swap the order */
3200 FirstValue ^= SecondValue;
3201 SecondValue ^= FirstValue;
3202 FirstValue ^= SecondValue;
3203 }
3204
3205 /* Calculate the result */
3206 Result = FirstValue - SecondValue - Carry;
3207
3208 /* Update the flags */
3209 State->Flags.Cf = FirstValue < (SecondValue + Carry);
3210 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) != (SecondValue & SIGN_FLAG_LONG))
3211 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
3212 State->Flags.Af = (FirstValue & 0x0F) < ((SecondValue + 1) & 0x0F);
3213 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3214 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
3215 State->Flags.Pf = Soft386CalculateParity(Result);
3216
3217 /* Write back the result */
3218 return Soft386WriteModrmDwordOperands(State,
3219 &ModRegRm,
3220 Opcode & SOFT386_OPCODE_WRITE_REG,
3221 Result);
3222 }
3223 else
3224 {
3225 USHORT FirstValue, SecondValue, Result;
3226
3227 if (!Soft386ReadModrmWordOperands(State,
3228 &ModRegRm,
3229 &FirstValue,
3230 &SecondValue))
3231 {
3232 /* Exception occurred */
3233 return FALSE;
3234 }
3235
3236 /* Check if this is the instruction that writes to R/M */
3237 if (!(Opcode & SOFT386_OPCODE_WRITE_REG))
3238 {
3239 /* Swap the order */
3240 FirstValue ^= SecondValue;
3241 SecondValue ^= FirstValue;
3242 FirstValue ^= SecondValue;
3243 }
3244
3245 /* Calculate the result */
3246 Result = FirstValue - SecondValue - Carry;
3247
3248 /* Update the flags */
3249 State->Flags.Cf = FirstValue < (SecondValue + Carry);
3250 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) != (SecondValue & SIGN_FLAG_WORD))
3251 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
3252 State->Flags.Af = (FirstValue & 0x0F) < ((SecondValue + 1) & 0x0F);
3253 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3254 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
3255 State->Flags.Pf = Soft386CalculateParity(Result);
3256
3257 /* Write back the result */
3258 return Soft386WriteModrmWordOperands(State,
3259 &ModRegRm,
3260 Opcode & SOFT386_OPCODE_WRITE_REG,
3261 Result);
3262 }
3263 }
3264
3265 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbAl)
3266 {
3267 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
3268 UCHAR SecondValue, Result;
3269 INT Carry = State->Flags.Cf ? 1 : 0;
3270
3271 /* Make sure this is the right instruction */
3272 ASSERT(Opcode == 0x1C);
3273
3274 if (State->PrefixFlags)
3275 {
3276 /* This opcode doesn't take any prefixes */
3277 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3278 return FALSE;
3279 }
3280
3281 if (!Soft386FetchByte(State, &SecondValue))
3282 {
3283 /* Exception occurred */
3284 return FALSE;
3285 }
3286
3287 /* Calculate the result */
3288 Result = FirstValue - SecondValue - Carry;
3289
3290 /* Update the flags */
3291 State->Flags.Cf = FirstValue < (SecondValue + Carry);
3292 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) != (SecondValue & SIGN_FLAG_BYTE))
3293 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
3294 State->Flags.Af = (FirstValue & 0x0F) < ((SecondValue + 1) & 0x0F);
3295 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3296 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
3297 State->Flags.Pf = Soft386CalculateParity(Result);
3298
3299 /* Write back the result */
3300 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
3301
3302 return TRUE;
3303
3304 }
3305
3306 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbEax)
3307 {
3308 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
3309 INT Carry = State->Flags.Cf ? 1 : 0;
3310
3311 /* Make sure this is the right instruction */
3312 ASSERT(Opcode == 0x1D);
3313
3314 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
3315 {
3316 /* Invalid prefix */
3317 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3318 return FALSE;
3319 }
3320
3321 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
3322 {
3323 /* The OPSIZE prefix toggles the size */
3324 Size = !Size;
3325 }
3326
3327 if (Size)
3328 {
3329 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
3330 ULONG SecondValue, Result;
3331
3332 if (!Soft386FetchDword(State, &SecondValue))
3333 {
3334 /* Exception occurred */
3335 return FALSE;
3336 }
3337
3338 /* Calculate the result */
3339 Result = FirstValue - SecondValue - Carry;
3340
3341 /* Update the flags */
3342 State->Flags.Cf = FirstValue < (SecondValue + Carry);
3343 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) != (SecondValue & SIGN_FLAG_LONG))
3344 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
3345 State->Flags.Af = (FirstValue & 0x0F) < ((SecondValue + Carry) & 0x0F);
3346 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3347 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
3348 State->Flags.Pf = Soft386CalculateParity(Result);
3349
3350 /* Write back the result */
3351 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
3352 }
3353 else
3354 {
3355 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
3356 USHORT SecondValue, Result;
3357
3358 if (!Soft386FetchWord(State, &SecondValue))
3359 {
3360 /* Exception occurred */
3361 return FALSE;
3362 }
3363
3364 /* Calculate the result */
3365 Result = FirstValue - SecondValue - Carry;
3366
3367 /* Update the flags */
3368 State->Flags.Cf = FirstValue < (SecondValue + Carry);
3369 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) != (SecondValue & SIGN_FLAG_WORD))
3370 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
3371 State->Flags.Af = (FirstValue & 0x0F) < ((SecondValue + Carry) & 0x0F);
3372 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3373 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
3374 State->Flags.Pf = Soft386CalculateParity(Result);
3375
3376 /* Write back the result */
3377 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
3378 }
3379
3380 return TRUE;
3381
3382 }
3383
3384 SOFT386_OPCODE_HANDLER(Soft386OpcodePushDs)
3385 {
3386 /* Call the internal API */
3387 return Soft386StackPush(State, State->SegmentRegs[SOFT386_REG_DS].Selector);
3388 }
3389
3390 SOFT386_OPCODE_HANDLER(Soft386OpcodePopDs)
3391 {
3392 ULONG NewSelector;
3393
3394 if (!Soft386StackPop(State, &NewSelector))
3395 {
3396 /* Exception occurred */
3397 return FALSE;
3398 }
3399
3400 /* Call the internal API */
3401 return Soft386LoadSegment(State, SOFT386_REG_DS, LOWORD(NewSelector));
3402 }
3403
3404 SOFT386_OPCODE_HANDLER(Soft386OpcodeDaa)
3405 {
3406 UCHAR Value = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
3407 BOOLEAN Carry = State->Flags.Cf;
3408
3409 /* Clear the carry flag */
3410 State->Flags.Cf = FALSE;
3411
3412 /* Check if the first BCD digit is invalid or there was a carry from it */
3413 if (((Value & 0x0F) > 9) || State->Flags.Af)
3414 {
3415 /* Correct it */
3416 State->GeneralRegs[SOFT386_REG_EAX].LowByte += 0x06;
3417 if (State->GeneralRegs[SOFT386_REG_EAX].LowByte < 0x06)
3418 {
3419 /* A carry occurred */
3420 State->Flags.Cf = TRUE;
3421 }
3422
3423 /* Set the adjust flag */
3424 State->Flags.Af = TRUE;
3425 }
3426
3427 /* Check if the second BCD digit is invalid or there was a carry from it */
3428 if ((Value > 0x99) || Carry)
3429 {
3430 /* Correct it */
3431 State->GeneralRegs[SOFT386_REG_EAX].LowByte += 0x60;
3432
3433 /* There was a carry */
3434 State->Flags.Cf = TRUE;
3435 }
3436
3437 return TRUE;
3438 }
3439
3440 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubByteModrm)
3441 {
3442 UCHAR FirstValue, SecondValue, Result;
3443 SOFT386_MOD_REG_RM ModRegRm;
3444 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
3445
3446 /* Make sure this is the right instruction */
3447 ASSERT((Opcode & 0xED) == 0x28);
3448
3449 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
3450 {
3451 /* The ADSIZE prefix toggles the size */
3452 AddressSize = !AddressSize;
3453 }
3454 else if (State->PrefixFlags
3455 & ~(SOFT386_PREFIX_ADSIZE
3456 | SOFT386_PREFIX_SEG
3457 | SOFT386_PREFIX_LOCK))
3458 {
3459 /* Invalid prefix */
3460 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3461 return FALSE;
3462 }
3463
3464 /* Get the operands */
3465 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
3466 {
3467 /* Exception occurred */
3468 return FALSE;
3469 }
3470
3471 if (!Soft386ReadModrmByteOperands(State,
3472 &ModRegRm,
3473 &FirstValue,
3474 &SecondValue))
3475 {
3476 /* Exception occurred */
3477 return FALSE;
3478 }
3479
3480 /* Check if this is the instruction that writes to R/M */
3481 if (!(Opcode & SOFT386_OPCODE_WRITE_REG))
3482 {
3483 /* Swap the order */
3484 FirstValue ^= SecondValue;
3485 SecondValue ^= FirstValue;
3486 FirstValue ^= SecondValue;
3487 }
3488
3489 /* Calculate the result */
3490 Result = FirstValue - SecondValue;
3491
3492 /* Update the flags */
3493 State->Flags.Cf = FirstValue < SecondValue;
3494 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) != (SecondValue & SIGN_FLAG_BYTE))
3495 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
3496 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
3497 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3498 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
3499 State->Flags.Pf = Soft386CalculateParity(Result);
3500
3501 /* Check if this is not a CMP */
3502 if (!(Opcode & 0x10))
3503 {
3504 /* Write back the result */
3505 return Soft386WriteModrmByteOperands(State,
3506 &ModRegRm,
3507 Opcode & SOFT386_OPCODE_WRITE_REG,
3508 Result);
3509 }
3510 else
3511 {
3512 /* Discard the result */
3513 return TRUE;
3514 }
3515 }
3516
3517 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubModrm)
3518 {
3519 SOFT386_MOD_REG_RM ModRegRm;
3520 BOOLEAN OperandSize, AddressSize;
3521
3522 /* Make sure this is the right instruction */
3523 ASSERT((Opcode & 0xED) == 0x29);
3524
3525 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
3526
3527 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
3528 {
3529 /* The ADSIZE prefix toggles the address size */
3530 AddressSize = !AddressSize;
3531 }
3532
3533 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
3534 {
3535 /* The OPSIZE prefix toggles the operand size */
3536 OperandSize = !OperandSize;
3537 }
3538
3539 if (State->PrefixFlags
3540 & ~(SOFT386_PREFIX_ADSIZE
3541 | SOFT386_PREFIX_OPSIZE
3542 | SOFT386_PREFIX_SEG
3543 | SOFT386_PREFIX_LOCK))
3544 {
3545 /* Invalid prefix */
3546 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3547 return FALSE;
3548 }
3549
3550 /* Get the operands */
3551 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
3552 {
3553 /* Exception occurred */
3554 return FALSE;
3555 }
3556
3557 /* Check the operand size */
3558 if (OperandSize)
3559 {
3560 ULONG FirstValue, SecondValue, Result;
3561
3562 if (!Soft386ReadModrmDwordOperands(State,
3563 &ModRegRm,
3564 &FirstValue,
3565 &SecondValue))
3566 {
3567 /* Exception occurred */
3568 return FALSE;
3569 }
3570
3571 /* Check if this is the instruction that writes to R/M */
3572 if (!(Opcode & SOFT386_OPCODE_WRITE_REG))
3573 {
3574 /* Swap the order */
3575 FirstValue ^= SecondValue;
3576 SecondValue ^= FirstValue;
3577 FirstValue ^= SecondValue;
3578 }
3579
3580 /* Calculate the result */
3581 Result = FirstValue - SecondValue;
3582
3583 /* Update the flags */
3584 State->Flags.Cf = FirstValue < SecondValue;
3585 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) != (SecondValue & SIGN_FLAG_LONG))
3586 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
3587 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
3588 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3589 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
3590 State->Flags.Pf = Soft386CalculateParity(Result);
3591
3592 /* Check if this is not a CMP */
3593 if (!(Opcode & 0x10))
3594 {
3595 /* Write back the result */
3596 return Soft386WriteModrmDwordOperands(State,
3597 &ModRegRm,
3598 Opcode & SOFT386_OPCODE_WRITE_REG,
3599 Result);
3600 }
3601 else
3602 {
3603 /* Discard the result */
3604 return TRUE;
3605 }
3606 }
3607 else
3608 {
3609 USHORT FirstValue, SecondValue, Result;
3610
3611 if (!Soft386ReadModrmWordOperands(State,
3612 &ModRegRm,
3613 &FirstValue,
3614 &SecondValue))
3615 {
3616 /* Exception occurred */
3617 return FALSE;
3618 }
3619
3620 /* Check if this is the instruction that writes to R/M */
3621 if (!(Opcode & SOFT386_OPCODE_WRITE_REG))
3622 {
3623 /* Swap the order */
3624 FirstValue ^= SecondValue;
3625 SecondValue ^= FirstValue;
3626 FirstValue ^= SecondValue;
3627 }
3628
3629 /* Calculate the result */
3630 Result = FirstValue - SecondValue;
3631
3632 /* Update the flags */
3633 State->Flags.Cf = FirstValue < SecondValue;
3634 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) != (SecondValue & SIGN_FLAG_WORD))
3635 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
3636 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
3637 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3638 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
3639 State->Flags.Pf = Soft386CalculateParity(Result);
3640
3641 /* Check if this is not a CMP */
3642 if (!(Opcode & 0x10))
3643 {
3644 /* Write back the result */
3645 return Soft386WriteModrmWordOperands(State,
3646 &ModRegRm,
3647 Opcode & SOFT386_OPCODE_WRITE_REG,
3648 Result);
3649 }
3650 else
3651 {
3652 /* Discard the result */
3653 return TRUE;
3654 }
3655 }
3656 }
3657
3658 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubAl)
3659 {
3660 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
3661 UCHAR SecondValue, Result;
3662
3663 /* Make sure this is the right instruction */
3664 ASSERT((Opcode & 0xEF) == 0x2C);
3665
3666 if (State->PrefixFlags)
3667 {
3668 /* This opcode doesn't take any prefixes */
3669 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3670 return FALSE;
3671 }
3672
3673 if (!Soft386FetchByte(State, &SecondValue))
3674 {
3675 /* Exception occurred */
3676 return FALSE;
3677 }
3678
3679 /* Calculate the result */
3680 Result = FirstValue - SecondValue;
3681
3682 /* Update the flags */
3683 State->Flags.Cf = FirstValue < SecondValue;
3684 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) != (SecondValue & SIGN_FLAG_BYTE))
3685 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
3686 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
3687 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3688 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
3689 State->Flags.Pf = Soft386CalculateParity(Result);
3690
3691 /* Check if this is not a CMP */
3692 if (!(Opcode & 0x10))
3693 {
3694 /* Write back the result */
3695 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
3696 }
3697
3698 return TRUE;
3699 }
3700
3701 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubEax)
3702 {
3703 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
3704
3705 /* Make sure this is the right instruction */
3706 ASSERT((Opcode & 0xEF) == 0x2D);
3707
3708 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
3709 {
3710 /* Invalid prefix */
3711 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3712 return FALSE;
3713 }
3714
3715 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
3716 {
3717 /* The OPSIZE prefix toggles the size */
3718 Size = !Size;
3719 }
3720
3721 if (Size)
3722 {
3723 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
3724 ULONG SecondValue, Result;
3725
3726 if (!Soft386FetchDword(State, &SecondValue))
3727 {
3728 /* Exception occurred */
3729 return FALSE;
3730 }
3731
3732 /* Calculate the result */
3733 Result = FirstValue - SecondValue;
3734
3735 /* Update the flags */
3736 State->Flags.Cf = FirstValue < SecondValue;
3737 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) != (SecondValue & SIGN_FLAG_LONG))
3738 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
3739 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
3740 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3741 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
3742 State->Flags.Pf = Soft386CalculateParity(Result);
3743
3744 /* Check if this is not a CMP */
3745 if (!(Opcode & 0x10))
3746 {
3747 /* Write back the result */
3748 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
3749 }
3750 }
3751 else
3752 {
3753 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
3754 USHORT SecondValue, Result;
3755
3756 if (!Soft386FetchWord(State, &SecondValue))
3757 {
3758 /* Exception occurred */
3759 return FALSE;
3760 }
3761
3762 /* Calculate the result */
3763 Result = FirstValue - SecondValue;
3764
3765 /* Update the flags */
3766 State->Flags.Cf = FirstValue < SecondValue;
3767 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) != (SecondValue & SIGN_FLAG_WORD))
3768 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
3769 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
3770 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3771 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
3772 State->Flags.Pf = Soft386CalculateParity(Result);
3773
3774 /* Check if this is not a CMP */
3775 if (!(Opcode & 0x10))
3776 {
3777 /* Write back the result */
3778 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
3779 }
3780 }
3781
3782 return TRUE;
3783 }
3784
3785 SOFT386_OPCODE_HANDLER(Soft386OpcodeDas)
3786 {
3787 UCHAR Value = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
3788 BOOLEAN Carry = State->Flags.Cf;
3789
3790 /* Clear the carry flag */
3791 State->Flags.Cf = FALSE;
3792
3793 /* Check if the first BCD digit is invalid or there was a borrow */
3794 if (((Value & 0x0F) > 9) || State->Flags.Af)
3795 {
3796 /* Correct it */
3797 State->GeneralRegs[SOFT386_REG_EAX].LowByte -= 0x06;
3798 if (State->GeneralRegs[SOFT386_REG_EAX].LowByte > 0xFB)
3799 {
3800 /* A borrow occurred */
3801 State->Flags.Cf = TRUE;
3802 }
3803
3804 /* Set the adjust flag */
3805 State->Flags.Af = TRUE;
3806 }
3807
3808 /* Check if the second BCD digit is invalid or there was a borrow */
3809 if ((Value > 0x99) || Carry)
3810 {
3811 /* Correct it */
3812 State->GeneralRegs[SOFT386_REG_EAX].LowByte -= 0x60;
3813
3814 /* There was a borrow */
3815 State->Flags.Cf = TRUE;
3816 }
3817
3818 return TRUE;
3819 }
3820
3821 SOFT386_OPCODE_HANDLER(Soft386OpcodeAaa)
3822 {
3823 UCHAR Value = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
3824
3825 /*
3826 * Check if the value in AL is not a valid BCD digit,
3827 * or there was a carry from the lowest 4 bits of AL
3828 */
3829 if (((Value & 0x0F) > 9) || State->Flags.Af)
3830 {
3831 /* Correct it */
3832 State->GeneralRegs[SOFT386_REG_EAX].LowByte += 0x06;
3833 State->GeneralRegs[SOFT386_REG_EAX].HighByte++;
3834
3835 /* Set CF and AF */
3836 State->Flags.Cf = State->Flags.Af = TRUE;
3837 }
3838 else
3839 {
3840 /* Clear CF and AF */
3841 State->Flags.Cf = State->Flags.Af = FALSE;
3842 }
3843
3844 /* Keep only the lowest 4 bits of AL */
3845 State->GeneralRegs[SOFT386_REG_EAX].LowByte &= 0x0F;
3846
3847 return TRUE;
3848 }
3849
3850 SOFT386_OPCODE_HANDLER(Soft386OpcodeAas)
3851 {
3852 UCHAR Value = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
3853
3854 /*
3855 * Check if the value in AL is not a valid BCD digit,
3856 * or there was a borrow from the lowest 4 bits of AL
3857 */
3858 if (((Value & 0x0F) > 9) || State->Flags.Af)
3859 {
3860 /* Correct it */
3861 State->GeneralRegs[SOFT386_REG_EAX].LowByte -= 0x06;
3862 State->GeneralRegs[SOFT386_REG_EAX].HighByte--;
3863
3864 /* Set CF and AF */
3865 State->Flags.Cf = State->Flags.Af = TRUE;
3866 }
3867 else
3868 {
3869 /* Clear CF and AF */
3870 State->Flags.Cf = State->Flags.Af = FALSE;
3871 }
3872
3873 /* Keep only the lowest 4 bits of AL */
3874 State->GeneralRegs[SOFT386_REG_EAX].LowByte &= 0x0F;
3875
3876 return TRUE;
3877 }
3878
3879 SOFT386_OPCODE_HANDLER(Soft386OpcodePushAll)
3880 {
3881 INT i;
3882 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
3883 SOFT386_REG SavedEsp = State->GeneralRegs[SOFT386_REG_ESP];
3884
3885 /* Make sure this is the right instruction */
3886 ASSERT(Opcode == 0x60);
3887
3888 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
3889 {
3890 /* The OPSIZE prefix toggles the size */
3891 Size = !Size;
3892 }
3893
3894 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
3895 {
3896 /* Invalid prefix */
3897 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3898 return FALSE;
3899 }
3900
3901 /* Push all the registers in order */
3902 for (i = 0; i < SOFT386_NUM_GEN_REGS; i++)
3903 {
3904 if (i == SOFT386_REG_ESP)
3905 {
3906 /* Use the saved ESP instead */
3907 if (!Soft386StackPush(State, Size ? SavedEsp.Long : SavedEsp.LowWord))
3908 {
3909 /* Exception occurred */
3910 return FALSE;
3911 }
3912 }
3913 else
3914 {
3915 /* Push the register */
3916 if (!Soft386StackPush(State, Size ? State->GeneralRegs[i].Long
3917 : State->GeneralRegs[i].LowWord))
3918 {
3919 /* Exception occurred */
3920 return FALSE;
3921 }
3922 }
3923 }
3924
3925 return TRUE;
3926 }
3927
3928 SOFT386_OPCODE_HANDLER(Soft386OpcodePopAll)
3929 {
3930 INT i;
3931 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
3932 ULONG Value;
3933
3934 /* Make sure this is the right instruction */
3935 ASSERT(Opcode == 0x61);
3936
3937 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
3938 {
3939 /* The OPSIZE prefix toggles the size */
3940 Size = !Size;
3941 }
3942
3943 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
3944 {
3945 /* Invalid prefix */
3946 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3947 return FALSE;
3948 }
3949
3950 /* Pop all the registers in reverse order */
3951 for (i = SOFT386_NUM_GEN_REGS - 1; i >= 0; i--)
3952 {
3953 /* Pop the value */
3954 if (!Soft386StackPop(State, &Value))
3955 {
3956 /* Exception occurred */
3957 return FALSE;
3958 }
3959
3960 /* Don't modify ESP */
3961 if (i != SOFT386_REG_ESP)
3962 {
3963 if (Size) State->GeneralRegs[i].Long = Value;
3964 else State->GeneralRegs[i].LowWord = LOWORD(Value);
3965 }
3966 }
3967
3968 return TRUE;
3969 }
3970
3971 SOFT386_OPCODE_HANDLER(Soft386OpcodeBound)
3972 {
3973 // TODO: NOT IMPLEMENTED
3974 UNIMPLEMENTED;
3975
3976 return FALSE;
3977 }
3978
3979 SOFT386_OPCODE_HANDLER(Soft386OpcodeArpl)
3980 {
3981 USHORT FirstValue, SecondValue;
3982 SOFT386_MOD_REG_RM ModRegRm;
3983 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
3984
3985 if (!(State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE)
3986 || State->Flags.Vm
3987 || (State->PrefixFlags & SOFT386_PREFIX_LOCK))
3988 {
3989 /* Cannot be used in real mode or with a LOCK prefix */
3990 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3991 return FALSE;
3992 }
3993
3994 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
3995 {
3996 /* The ADSIZE prefix toggles the size */
3997 AddressSize = !AddressSize;
3998 }
3999
4000 /* Get the operands */
4001 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
4002 {
4003 /* Exception occurred */
4004 return FALSE;
4005 }
4006
4007 /* Read the operands */
4008 if (!Soft386ReadModrmWordOperands(State,
4009 &ModRegRm,
4010 &FirstValue,
4011 &SecondValue))
4012 {
4013 /* Exception occurred */
4014 return FALSE;
4015 }
4016
4017 /* Check if the RPL needs adjusting */
4018 if ((SecondValue & 3) < (FirstValue & 3))
4019 {
4020 /* Adjust the RPL */
4021 SecondValue &= ~3;
4022 SecondValue |= FirstValue & 3;
4023
4024 /* Set ZF */
4025 State->Flags.Zf = TRUE;
4026
4027 /* Write back the result */
4028 return Soft386WriteModrmWordOperands(State, &ModRegRm, FALSE, SecondValue);
4029 }
4030 else
4031 {
4032 /* Clear ZF */
4033 State->Flags.Zf = FALSE;
4034 return TRUE;
4035 }
4036 }
4037
4038 SOFT386_OPCODE_HANDLER(Soft386OpcodePushImm)
4039 {
4040 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4041
4042 /* Make sure this is the right instruction */
4043 ASSERT(Opcode == 0x68);
4044
4045 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
4046 {
4047 /* Invalid prefix */
4048 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4049 return FALSE;
4050 }
4051
4052 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
4053 {
4054 /* The OPSIZE prefix toggles the size */
4055 Size = !Size;
4056 }
4057
4058 if (Size)
4059 {
4060 ULONG Data;
4061
4062 if (!Soft386FetchDword(State, &Data))
4063 {
4064 /* Exception occurred */
4065 return FALSE;
4066 }
4067
4068 /* Call the internal API */
4069 return Soft386StackPush(State, Data);
4070 }
4071 else
4072 {
4073 USHORT Data;
4074
4075 if (!Soft386FetchWord(State, &Data))
4076 {
4077 /* Exception occurred */
4078 return FALSE;
4079 }
4080
4081 /* Call the internal API */
4082 return Soft386StackPush(State, Data);
4083 }
4084 }
4085
4086 SOFT386_OPCODE_HANDLER(Soft386OpcodeImulModrmImm)
4087 {
4088 BOOLEAN OperandSize, AddressSize;
4089 SOFT386_MOD_REG_RM ModRegRm;
4090 LONG Multiplier;
4091 LONGLONG Product;
4092
4093 /* Make sure this is the right instruction */
4094 ASSERT((Opcode & 0xFD) == 0x69);
4095
4096 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
4097
4098 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
4099 {
4100 /* The ADSIZE prefix toggles the address size */
4101 AddressSize = !AddressSize;
4102 }
4103
4104 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
4105 {
4106 /* The OPSIZE prefix toggles the operand size */
4107 OperandSize = !OperandSize;
4108 }
4109
4110 /* Fetch the parameters */
4111 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
4112 {
4113 /* Exception occurred */
4114 return FALSE;
4115 }
4116
4117 if (Opcode == 0x6B)
4118 {
4119 CHAR Byte;
4120
4121 /* Fetch the immediate operand */
4122 if (!Soft386FetchByte(State, (PUCHAR)&Byte))
4123 {
4124 /* Exception occurred */
4125 return FALSE;
4126 }
4127
4128 Multiplier = (LONG)Byte;
4129 }
4130 else
4131 {
4132 if (OperandSize)
4133 {
4134 LONG Dword;
4135
4136 /* Fetch the immediate operand */
4137 if (!Soft386FetchDword(State, (PULONG)&Dword))
4138 {
4139 /* Exception occurred */
4140 return FALSE;
4141 }
4142
4143 Multiplier = Dword;
4144 }
4145 else
4146 {
4147 SHORT Word;
4148
4149 /* Fetch the immediate operand */
4150 if (!Soft386FetchWord