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