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