[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 // #define NDEBUG
16 #include <debug.h>
17
18 #include <soft386.h>
19 #include "opcodes.h"
20 #include "common.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 Soft386OpcodeRet,
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 Soft386OpcodeLoop,
252 Soft386OpcodeLoop,
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(Soft386OpcodeTestAl)
2440 {
2441 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
2442 UCHAR SecondValue, Result;
2443
2444 /* Make sure this is the right instruction */
2445 ASSERT(Opcode == 0xA8);
2446
2447 if (State->PrefixFlags)
2448 {
2449 /* This opcode doesn't take any prefixes */
2450 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2451 return FALSE;
2452 }
2453
2454 if (!Soft386FetchByte(State, &SecondValue))
2455 {
2456 /* Exception occurred */
2457 return FALSE;
2458 }
2459
2460 /* Calculate the result */
2461 Result = FirstValue & SecondValue;
2462
2463 /* Update the flags */
2464 State->Flags.Cf = FALSE;
2465 State->Flags.Of = FALSE;
2466 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2467 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
2468 State->Flags.Pf = Soft386CalculateParity(Result);
2469
2470 /* The result is discarded */
2471 return TRUE;
2472 }
2473
2474 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestEax)
2475 {
2476 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
2477
2478 /* Make sure this is the right instruction */
2479 ASSERT(Opcode == 0xA9);
2480
2481 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
2482 {
2483 /* The OPSIZE prefix toggles the size */
2484 Size = !Size;
2485 }
2486 else
2487 {
2488 /* Invalid prefix */
2489 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2490 return FALSE;
2491 }
2492
2493 if (Size)
2494 {
2495 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
2496 ULONG SecondValue, Result;
2497
2498 if (!Soft386FetchDword(State, &SecondValue))
2499 {
2500 /* Exception occurred */
2501 return FALSE;
2502 }
2503
2504 /* Calculate the result */
2505 Result = FirstValue & SecondValue;
2506
2507 /* Update the flags */
2508 State->Flags.Cf = FALSE;
2509 State->Flags.Of = FALSE;
2510 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2511 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
2512 State->Flags.Pf = Soft386CalculateParity(Result);
2513 }
2514 else
2515 {
2516 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
2517 USHORT SecondValue, Result;
2518
2519 if (!Soft386FetchWord(State, &SecondValue))
2520 {
2521 /* Exception occurred */
2522 return FALSE;
2523 }
2524
2525 /* Calculate the result */
2526 Result = FirstValue & SecondValue;
2527
2528 /* Update the flags */
2529 State->Flags.Cf = FALSE;
2530 State->Flags.Of = FALSE;
2531 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2532 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
2533 State->Flags.Pf = Soft386CalculateParity(Result);
2534 }
2535
2536 /* The result is discarded */
2537 return TRUE;
2538 }
2539
2540 SOFT386_OPCODE_HANDLER(Soft386OpcodeXchgByteModrm)
2541 {
2542 UCHAR FirstValue, SecondValue;
2543 SOFT386_MOD_REG_RM ModRegRm;
2544 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2545
2546 /* Make sure this is the right instruction */
2547 ASSERT(Opcode == 0x86);
2548
2549 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2550 {
2551 /* The ADSIZE prefix toggles the size */
2552 AddressSize = !AddressSize;
2553 }
2554 else if (State->PrefixFlags
2555 & ~(SOFT386_PREFIX_ADSIZE
2556 | SOFT386_PREFIX_SEG
2557 | SOFT386_PREFIX_LOCK))
2558 {
2559 /* Invalid prefix */
2560 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2561 return FALSE;
2562 }
2563
2564 /* Get the operands */
2565 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2566 {
2567 /* Exception occurred */
2568 return FALSE;
2569 }
2570
2571 if (!Soft386ReadModrmByteOperands(State,
2572 &ModRegRm,
2573 &FirstValue,
2574 &SecondValue))
2575 {
2576 /* Exception occurred */
2577 return FALSE;
2578 }
2579
2580 /* Write the value from the register to the R/M */
2581 if (!Soft386WriteModrmByteOperands(State,
2582 &ModRegRm,
2583 FALSE,
2584 FirstValue))
2585 {
2586 /* Exception occurred */
2587 return FALSE;
2588 }
2589
2590 /* Write the value from the R/M to the register */
2591 if (!Soft386WriteModrmByteOperands(State,
2592 &ModRegRm,
2593 TRUE,
2594 SecondValue))
2595 {
2596 /* Exception occurred */
2597 return FALSE;
2598 }
2599
2600 return TRUE;
2601 }
2602
2603 SOFT386_OPCODE_HANDLER(Soft386OpcodeXchgModrm)
2604 {
2605 SOFT386_MOD_REG_RM ModRegRm;
2606 BOOLEAN OperandSize, AddressSize;
2607
2608 /* Make sure this is the right instruction */
2609 ASSERT(Opcode == 0x87);
2610
2611 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2612
2613 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2614 {
2615 /* The ADSIZE prefix toggles the address size */
2616 AddressSize = !AddressSize;
2617 }
2618
2619 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2620 {
2621 /* The OPSIZE prefix toggles the operand size */
2622 OperandSize = !OperandSize;
2623 }
2624
2625 if (State->PrefixFlags
2626 & ~(SOFT386_PREFIX_ADSIZE
2627 | SOFT386_PREFIX_OPSIZE
2628 | SOFT386_PREFIX_SEG
2629 | SOFT386_PREFIX_LOCK))
2630 {
2631 /* Invalid prefix */
2632 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2633 return FALSE;
2634 }
2635
2636 /* Get the operands */
2637 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2638 {
2639 /* Exception occurred */
2640 return FALSE;
2641 }
2642
2643 /* Check the operand size */
2644 if (OperandSize)
2645 {
2646 ULONG FirstValue, SecondValue;
2647
2648 if (!Soft386ReadModrmDwordOperands(State,
2649 &ModRegRm,
2650 &FirstValue,
2651 &SecondValue))
2652 {
2653 /* Exception occurred */
2654 return FALSE;
2655 }
2656
2657 /* Write the value from the register to the R/M */
2658 if (!Soft386WriteModrmDwordOperands(State,
2659 &ModRegRm,
2660 FALSE,
2661 FirstValue))
2662 {
2663 /* Exception occurred */
2664 return FALSE;
2665 }
2666
2667 /* Write the value from the R/M to the register */
2668 if (!Soft386WriteModrmDwordOperands(State,
2669 &ModRegRm,
2670 TRUE,
2671 SecondValue))
2672 {
2673 /* Exception occurred */
2674 return FALSE;
2675 }
2676 }
2677 else
2678 {
2679 USHORT FirstValue, SecondValue;
2680
2681 if (!Soft386ReadModrmWordOperands(State,
2682 &ModRegRm,
2683 &FirstValue,
2684 &SecondValue))
2685 {
2686 /* Exception occurred */
2687 return FALSE;
2688 }
2689
2690 /* Write the value from the register to the R/M */
2691 if (!Soft386WriteModrmWordOperands(State,
2692 &ModRegRm,
2693 FALSE,
2694 FirstValue))
2695 {
2696 /* Exception occurred */
2697 return FALSE;
2698 }
2699
2700 /* Write the value from the R/M to the register */
2701 if (!Soft386WriteModrmWordOperands(State,
2702 &ModRegRm,
2703 TRUE,
2704 SecondValue))
2705 {
2706 /* Exception occurred */
2707 return FALSE;
2708 }
2709 }
2710
2711 /* The result is discarded */
2712 return TRUE;
2713 }
2714
2715 SOFT386_OPCODE_HANDLER(Soft386OpcodePushEs)
2716 {
2717 /* Call the internal API */
2718 return Soft386StackPush(State, State->SegmentRegs[SOFT386_REG_ES].Selector);
2719 }
2720
2721 SOFT386_OPCODE_HANDLER(Soft386OpcodePopEs)
2722 {
2723 ULONG NewSelector;
2724
2725 if (!Soft386StackPop(State, &NewSelector))
2726 {
2727 /* Exception occurred */
2728 return FALSE;
2729 }
2730
2731 /* Call the internal API */
2732 return Soft386LoadSegment(State, SOFT386_REG_ES, LOWORD(NewSelector));
2733 }
2734
2735 SOFT386_OPCODE_HANDLER(Soft386OpcodePushCs)
2736 {
2737 /* Call the internal API */
2738 return Soft386StackPush(State, State->SegmentRegs[SOFT386_REG_CS].Selector);
2739 }
2740
2741 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcByteModrm)
2742 {
2743 UCHAR FirstValue, SecondValue, Result;
2744 SOFT386_MOD_REG_RM ModRegRm;
2745 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2746
2747 /* Make sure this is the right instruction */
2748 ASSERT((Opcode & 0xFD) == 0x10);
2749
2750 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2751 {
2752 /* The ADSIZE prefix toggles the size */
2753 AddressSize = !AddressSize;
2754 }
2755 else if (State->PrefixFlags
2756 & ~(SOFT386_PREFIX_ADSIZE
2757 | SOFT386_PREFIX_SEG
2758 | SOFT386_PREFIX_LOCK))
2759 {
2760 /* Invalid prefix */
2761 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2762 return FALSE;
2763 }
2764
2765 /* Get the operands */
2766 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2767 {
2768 /* Exception occurred */
2769 return FALSE;
2770 }
2771
2772 if (!Soft386ReadModrmByteOperands(State,
2773 &ModRegRm,
2774 &FirstValue,
2775 &SecondValue))
2776 {
2777 /* Exception occurred */
2778 return FALSE;
2779 }
2780
2781 /* Calculate the result */
2782 Result = FirstValue + SecondValue + State->Flags.Cf;
2783
2784 /* Special exception for CF */
2785 State->Flags.Cf = State->Flags.Cf
2786 && ((FirstValue == 0xFF) || (SecondValue == 0xFF));
2787
2788 /* Update the flags */
2789 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
2790 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE))
2791 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
2792 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
2793 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2794 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
2795 State->Flags.Pf = Soft386CalculateParity(Result);
2796
2797 /* Write back the result */
2798 return Soft386WriteModrmByteOperands(State,
2799 &ModRegRm,
2800 Opcode & SOFT386_OPCODE_WRITE_REG,
2801 Result);
2802 }
2803
2804 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcModrm)
2805 {
2806 SOFT386_MOD_REG_RM ModRegRm;
2807 BOOLEAN OperandSize, AddressSize;
2808
2809 /* Make sure this is the right instruction */
2810 ASSERT((Opcode & 0xFD) == 0x11);
2811
2812 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2813
2814 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2815 {
2816 /* The ADSIZE prefix toggles the address size */
2817 AddressSize = !AddressSize;
2818 }
2819
2820 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2821 {
2822 /* The OPSIZE prefix toggles the operand size */
2823 OperandSize = !OperandSize;
2824 }
2825
2826 if (State->PrefixFlags
2827 & ~(SOFT386_PREFIX_ADSIZE
2828 | SOFT386_PREFIX_OPSIZE
2829 | SOFT386_PREFIX_SEG
2830 | SOFT386_PREFIX_LOCK))
2831 {
2832 /* Invalid prefix */
2833 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2834 return FALSE;
2835 }
2836
2837 /* Get the operands */
2838 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2839 {
2840 /* Exception occurred */
2841 return FALSE;
2842 }
2843
2844 /* Check the operand size */
2845 if (OperandSize)
2846 {
2847 ULONG FirstValue, SecondValue, Result;
2848
2849 if (!Soft386ReadModrmDwordOperands(State,
2850 &ModRegRm,
2851 &FirstValue,
2852 &SecondValue))
2853 {
2854 /* Exception occurred */
2855 return FALSE;
2856 }
2857
2858 /* Calculate the result */
2859 Result = FirstValue + SecondValue + State->Flags.Cf;
2860
2861 /* Special exception for CF */
2862 State->Flags.Cf = State->Flags.Cf
2863 && ((FirstValue == 0xFFFFFFFF) || (SecondValue == 0xFFFFFFFF));
2864
2865 /* Update the flags */
2866 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
2867 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG))
2868 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
2869 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
2870 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2871 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
2872 State->Flags.Pf = Soft386CalculateParity(Result);
2873
2874 /* Write back the result */
2875 return Soft386WriteModrmDwordOperands(State,
2876 &ModRegRm,
2877 Opcode & SOFT386_OPCODE_WRITE_REG,
2878 Result);
2879 }
2880 else
2881 {
2882 USHORT FirstValue, SecondValue, Result;
2883
2884 if (!Soft386ReadModrmWordOperands(State,
2885 &ModRegRm,
2886 &FirstValue,
2887 &SecondValue))
2888 {
2889 /* Exception occurred */
2890 return FALSE;
2891 }
2892
2893 /* Calculate the result */
2894 Result = FirstValue + SecondValue + State->Flags.Cf;
2895
2896 /* Special exception for CF */
2897 State->Flags.Cf = State->Flags.Cf
2898 && ((FirstValue == 0xFFFF) || (SecondValue == 0xFFFF));
2899
2900 /* Update the flags */
2901 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
2902 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD))
2903 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
2904 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
2905 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2906 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
2907 State->Flags.Pf = Soft386CalculateParity(Result);
2908
2909 /* Write back the result */
2910 return Soft386WriteModrmWordOperands(State,
2911 &ModRegRm,
2912 Opcode & SOFT386_OPCODE_WRITE_REG,
2913 Result);
2914 }
2915
2916 }
2917
2918 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcAl)
2919 {
2920 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
2921 UCHAR SecondValue, Result;
2922
2923 /* Make sure this is the right instruction */
2924 ASSERT(Opcode == 0x14);
2925
2926 if (State->PrefixFlags)
2927 {
2928 /* This opcode doesn't take any prefixes */
2929 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2930 return FALSE;
2931 }
2932
2933 if (!Soft386FetchByte(State, &SecondValue))
2934 {
2935 /* Exception occurred */
2936 return FALSE;
2937 }
2938
2939 /* Calculate the result */
2940 Result = FirstValue + SecondValue + State->Flags.Cf;
2941
2942 /* Special exception for CF */
2943 State->Flags.Cf = State->Flags.Cf &&
2944 ((FirstValue == 0xFF) || (SecondValue == 0xFF));
2945
2946 /* Update the flags */
2947 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
2948 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE))
2949 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
2950 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
2951 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2952 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
2953 State->Flags.Pf = Soft386CalculateParity(Result);
2954
2955 /* Write back the result */
2956 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
2957
2958 return TRUE;
2959 }
2960
2961 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcEax)
2962 {
2963 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
2964
2965 /* Make sure this is the right instruction */
2966 ASSERT(Opcode == 0x15);
2967
2968 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
2969 {
2970 /* The OPSIZE prefix toggles the size */
2971 Size = !Size;
2972 }
2973 else
2974 {
2975 /* Invalid prefix */
2976 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2977 return FALSE;
2978 }
2979
2980 if (Size)
2981 {
2982 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
2983 ULONG SecondValue, Result;
2984
2985 if (!Soft386FetchDword(State, &SecondValue))
2986 {
2987 /* Exception occurred */
2988 return FALSE;
2989 }
2990
2991 /* Calculate the result */
2992 Result = FirstValue + SecondValue + State->Flags.Cf;
2993
2994 /* Special exception for CF */
2995 State->Flags.Cf = State->Flags.Cf &&
2996 ((FirstValue == 0xFFFFFFFF) || (SecondValue == 0xFFFFFFFF));
2997
2998 /* Update the flags */
2999 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
3000 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG))
3001 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
3002 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
3003 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3004 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
3005 State->Flags.Pf = Soft386CalculateParity(Result);
3006
3007 /* Write back the result */
3008 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
3009 }
3010 else
3011 {
3012 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
3013 USHORT SecondValue, Result;
3014
3015 if (!Soft386FetchWord(State, &SecondValue))
3016 {
3017 /* Exception occurred */
3018 return FALSE;
3019 }
3020
3021 /* Calculate the result */
3022 Result = FirstValue + SecondValue + State->Flags.Cf;
3023
3024 /* Special exception for CF */
3025 State->Flags.Cf = State->Flags.Cf &&
3026 ((FirstValue == 0xFFFF) || (SecondValue == 0xFFFF));
3027
3028 /* Update the flags */
3029 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
3030 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD))
3031 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
3032 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
3033 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3034 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
3035 State->Flags.Pf = Soft386CalculateParity(Result);
3036
3037 /* Write back the result */
3038 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
3039 }
3040
3041 return TRUE;
3042 }
3043
3044 SOFT386_OPCODE_HANDLER(Soft386OpcodePushSs)
3045 {
3046 /* Call the internal API */
3047 return Soft386StackPush(State, State->SegmentRegs[SOFT386_REG_SS].Selector);
3048 }
3049
3050 SOFT386_OPCODE_HANDLER(Soft386OpcodePopSs)
3051 {
3052 ULONG NewSelector;
3053
3054 if (!Soft386StackPop(State, &NewSelector))
3055 {
3056 /* Exception occurred */
3057 return FALSE;
3058 }
3059
3060 /* Call the internal API */
3061 return Soft386LoadSegment(State, SOFT386_REG_SS, LOWORD(NewSelector));
3062 }
3063
3064 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbByteModrm)
3065 {
3066 // TODO: NOT IMPLEMENTED
3067 UNIMPLEMENTED;
3068
3069 return FALSE;
3070 }
3071
3072 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbModrm)
3073 {
3074 // TODO: NOT IMPLEMENTED
3075 UNIMPLEMENTED;
3076
3077 return FALSE;
3078 }
3079
3080 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbAl)
3081 {
3082 // TODO: NOT IMPLEMENTED
3083 UNIMPLEMENTED;
3084
3085 return FALSE;
3086 }
3087
3088 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbEax)
3089 {
3090 // TODO: NOT IMPLEMENTED
3091 UNIMPLEMENTED;
3092
3093 return FALSE;
3094 }
3095
3096 SOFT386_OPCODE_HANDLER(Soft386OpcodePushDs)
3097 {
3098 /* Call the internal API */
3099 return Soft386StackPush(State, State->SegmentRegs[SOFT386_REG_DS].Selector);
3100 }
3101
3102 SOFT386_OPCODE_HANDLER(Soft386OpcodePopDs)
3103 {
3104 ULONG NewSelector;
3105
3106 if (!Soft386StackPop(State, &NewSelector))
3107 {
3108 /* Exception occurred */
3109 return FALSE;
3110 }
3111
3112 /* Call the internal API */
3113 return Soft386LoadSegment(State, SOFT386_REG_DS, LOWORD(NewSelector));
3114 }
3115
3116 SOFT386_OPCODE_HANDLER(Soft386OpcodeDaa)
3117 {
3118 UCHAR Value = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
3119 BOOLEAN Carry = State->Flags.Cf;
3120
3121 /* Clear the carry flag */
3122 State->Flags.Cf = FALSE;
3123
3124 /* Check if the first BCD digit is invalid or there was a carry from it */
3125 if (((Value & 0x0F) > 9) || State->Flags.Af)
3126 {
3127 /* Correct it */
3128 State->GeneralRegs[SOFT386_REG_EAX].LowByte += 0x06;
3129 if (State->GeneralRegs[SOFT386_REG_EAX].LowByte < 0x06)
3130 {
3131 /* A carry occurred */
3132 State->Flags.Cf = TRUE;
3133 }
3134
3135 /* Set the adjust flag */
3136 State->Flags.Af = TRUE;
3137 }
3138
3139 /* Check if the second BCD digit is invalid or there was a carry from it */
3140 if ((Value > 0x99) || Carry)
3141 {
3142 /* Correct it */
3143 State->GeneralRegs[SOFT386_REG_EAX].LowByte += 0x60;
3144
3145 /* There was a carry */
3146 State->Flags.Cf = TRUE;
3147 }
3148
3149 return TRUE;
3150 }
3151
3152 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubByteModrm)
3153 {
3154 UCHAR FirstValue, SecondValue, Result;
3155 SOFT386_MOD_REG_RM ModRegRm;
3156 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
3157
3158 /* Make sure this is the right instruction */
3159 ASSERT((Opcode & 0xED) == 0x28);
3160
3161 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
3162 {
3163 /* The ADSIZE prefix toggles the size */
3164 AddressSize = !AddressSize;
3165 }
3166 else if (State->PrefixFlags
3167 & ~(SOFT386_PREFIX_ADSIZE
3168 | SOFT386_PREFIX_SEG
3169 | SOFT386_PREFIX_LOCK))
3170 {
3171 /* Invalid prefix */
3172 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3173 return FALSE;
3174 }
3175
3176 /* Get the operands */
3177 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
3178 {
3179 /* Exception occurred */
3180 return FALSE;
3181 }
3182
3183 if (!Soft386ReadModrmByteOperands(State,
3184 &ModRegRm,
3185 &FirstValue,
3186 &SecondValue))
3187 {
3188 /* Exception occurred */
3189 return FALSE;
3190 }
3191
3192 /* Check if this is the instruction that writes to R/M */
3193 if (!(Opcode & SOFT386_OPCODE_WRITE_REG))
3194 {
3195 /* Swap the order */
3196 FirstValue ^= SecondValue;
3197 SecondValue ^= FirstValue;
3198 FirstValue ^= SecondValue;
3199 }
3200
3201 /* Calculate the result */
3202 Result = FirstValue - SecondValue;
3203
3204 /* Update the flags */
3205 State->Flags.Cf = FirstValue < SecondValue;
3206 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) != (SecondValue & SIGN_FLAG_BYTE))
3207 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
3208 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
3209 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3210 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
3211 State->Flags.Pf = Soft386CalculateParity(Result);
3212
3213 /* Check if this is not a CMP */
3214 if (!(Opcode & 0x10))
3215 {
3216 /* Write back the result */
3217 return Soft386WriteModrmByteOperands(State,
3218 &ModRegRm,
3219 Opcode & SOFT386_OPCODE_WRITE_REG,
3220 Result);
3221 }
3222 else
3223 {
3224 /* Discard the result */
3225 return TRUE;
3226 }
3227 }
3228
3229 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubModrm)
3230 {
3231 SOFT386_MOD_REG_RM ModRegRm;
3232 BOOLEAN OperandSize, AddressSize;
3233
3234 /* Make sure this is the right instruction */
3235 ASSERT((Opcode & 0xED) == 0x29);
3236
3237 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
3238
3239 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
3240 {
3241 /* The ADSIZE prefix toggles the address size */
3242 AddressSize = !AddressSize;
3243 }
3244
3245 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
3246 {
3247 /* The OPSIZE prefix toggles the operand size */
3248 OperandSize = !OperandSize;
3249 }
3250
3251 if (State->PrefixFlags
3252 & ~(SOFT386_PREFIX_ADSIZE
3253 | SOFT386_PREFIX_OPSIZE
3254 | SOFT386_PREFIX_SEG
3255 | SOFT386_PREFIX_LOCK))
3256 {
3257 /* Invalid prefix */
3258 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3259 return FALSE;
3260 }
3261
3262 /* Get the operands */
3263 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
3264 {
3265 /* Exception occurred */
3266 return FALSE;
3267 }
3268
3269 /* Check the operand size */
3270 if (OperandSize)
3271 {
3272 ULONG FirstValue, SecondValue, Result;
3273
3274 if (!Soft386ReadModrmDwordOperands(State,
3275 &ModRegRm,
3276 &FirstValue,
3277 &SecondValue))
3278 {
3279 /* Exception occurred */
3280 return FALSE;
3281 }
3282
3283 /* Check if this is the instruction that writes to R/M */
3284 if (!(Opcode & SOFT386_OPCODE_WRITE_REG))
3285 {
3286 /* Swap the order */
3287 FirstValue ^= SecondValue;
3288 SecondValue ^= FirstValue;
3289 FirstValue ^= SecondValue;
3290 }
3291
3292 /* Calculate the result */
3293 Result = FirstValue - SecondValue;
3294
3295 /* Update the flags */
3296 State->Flags.Cf = FirstValue < SecondValue;
3297 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) != (SecondValue & SIGN_FLAG_LONG))
3298 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
3299 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
3300 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3301 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
3302 State->Flags.Pf = Soft386CalculateParity(Result);
3303
3304 /* Check if this is not a CMP */
3305 if (!(Opcode & 0x10))
3306 {
3307 /* Write back the result */
3308 return Soft386WriteModrmDwordOperands(State,
3309 &ModRegRm,
3310 Opcode & SOFT386_OPCODE_WRITE_REG,
3311 Result);
3312 }
3313 else
3314 {
3315 /* Discard the result */
3316 return TRUE;
3317 }
3318 }
3319 else
3320 {
3321 USHORT FirstValue, SecondValue, Result;
3322
3323 if (!Soft386ReadModrmWordOperands(State,
3324 &ModRegRm,
3325 &FirstValue,
3326 &SecondValue))
3327 {
3328 /* Exception occurred */
3329 return FALSE;
3330 }
3331
3332 /* Check if this is the instruction that writes to R/M */
3333 if (!(Opcode & SOFT386_OPCODE_WRITE_REG))
3334 {
3335 /* Swap the order */
3336 FirstValue ^= SecondValue;
3337 SecondValue ^= FirstValue;
3338 FirstValue ^= SecondValue;
3339 }
3340
3341 /* Calculate the result */
3342 Result = FirstValue - SecondValue;
3343
3344 /* Update the flags */
3345 State->Flags.Cf = FirstValue < SecondValue;
3346 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) != (SecondValue & SIGN_FLAG_WORD))
3347 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
3348 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
3349 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3350 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
3351 State->Flags.Pf = Soft386CalculateParity(Result);
3352
3353 /* Check if this is not a CMP */
3354 if (!(Opcode & 0x10))
3355 {
3356 /* Write back the result */
3357 return Soft386WriteModrmWordOperands(State,
3358 &ModRegRm,
3359 Opcode & SOFT386_OPCODE_WRITE_REG,
3360 Result);
3361 }
3362 else
3363 {
3364 /* Discard the result */
3365 return TRUE;
3366 }
3367 }
3368
3369 }
3370
3371 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubAl)
3372 {
3373 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
3374 UCHAR SecondValue, Result;
3375
3376 /* Make sure this is the right instruction */
3377 ASSERT((Opcode & 0xEF) == 0x2C);
3378
3379 if (State->PrefixFlags)
3380 {
3381 /* This opcode doesn't take any prefixes */
3382 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3383 return FALSE;
3384 }
3385
3386 if (!Soft386FetchByte(State, &SecondValue))
3387 {
3388 /* Exception occurred */
3389 return FALSE;
3390 }
3391
3392 /* Calculate the result */
3393 Result = FirstValue - SecondValue;
3394
3395 /* Update the flags */
3396 State->Flags.Cf = FirstValue < SecondValue;
3397 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) != (SecondValue & SIGN_FLAG_BYTE))
3398 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
3399 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
3400 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3401 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
3402 State->Flags.Pf = Soft386CalculateParity(Result);
3403
3404 /* Check if this is not a CMP */
3405 if (!(Opcode & 0x10))
3406 {
3407 /* Write back the result */
3408 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
3409 }
3410
3411 return TRUE;
3412 }
3413
3414 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubEax)
3415 {
3416 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
3417
3418 /* Make sure this is the right instruction */
3419 ASSERT((Opcode & 0xEF) == 0x2D);
3420
3421 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
3422 {
3423 /* The OPSIZE prefix toggles the size */
3424 Size = !Size;
3425 }
3426 else
3427 {
3428 /* Invalid prefix */
3429 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3430 return FALSE;
3431 }
3432
3433 if (Size)
3434 {
3435 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
3436 ULONG SecondValue, Result;
3437
3438 if (!Soft386FetchDword(State, &SecondValue))
3439 {
3440 /* Exception occurred */
3441 return FALSE;
3442 }
3443
3444 /* Calculate the result */
3445 Result = FirstValue - SecondValue;
3446
3447 /* Update the flags */
3448 State->Flags.Cf = FirstValue < SecondValue;
3449 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) != (SecondValue & SIGN_FLAG_LONG))
3450 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
3451 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
3452 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3453 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
3454 State->Flags.Pf = Soft386CalculateParity(Result);
3455
3456 /* Check if this is not a CMP */
3457 if (!(Opcode & 0x10))
3458 {
3459 /* Write back the result */
3460 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
3461 }
3462 }
3463 else
3464 {
3465 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
3466 USHORT SecondValue, Result;
3467
3468 if (!Soft386FetchWord(State, &SecondValue))
3469 {
3470 /* Exception occurred */
3471 return FALSE;
3472 }
3473
3474 /* Calculate the result */
3475 Result = FirstValue - SecondValue;
3476
3477 /* Update the flags */
3478 State->Flags.Cf = FirstValue < SecondValue;
3479 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) != (SecondValue & SIGN_FLAG_WORD))
3480 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
3481 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
3482 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3483 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
3484 State->Flags.Pf = Soft386CalculateParity(Result);
3485
3486 /* Write back the result */
3487 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
3488 }
3489
3490 return TRUE;
3491 }
3492
3493 SOFT386_OPCODE_HANDLER(Soft386OpcodeDas)
3494 {
3495 UCHAR Value = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
3496 BOOLEAN Carry = State->Flags.Cf;
3497
3498 /* Clear the carry flag */
3499 State->Flags.Cf = FALSE;
3500
3501 /* Check if the first BCD digit is invalid or there was a borrow */
3502 if (((Value & 0x0F) > 9) || State->Flags.Af)
3503 {
3504 /* Correct it */
3505 State->GeneralRegs[SOFT386_REG_EAX].LowByte -= 0x06;
3506 if (State->GeneralRegs[SOFT386_REG_EAX].LowByte > 0xFB)
3507 {
3508 /* A borrow occurred */
3509 State->Flags.Cf = TRUE;
3510 }
3511
3512 /* Set the adjust flag */
3513 State->Flags.Af = TRUE;
3514 }
3515
3516 /* Check if the second BCD digit is invalid or there was a borrow */
3517 if ((Value > 0x99) || Carry)
3518 {
3519 /* Correct it */
3520 State->GeneralRegs[SOFT386_REG_EAX].LowByte -= 0x60;
3521
3522 /* There was a borrow */
3523 State->Flags.Cf = TRUE;
3524 }
3525
3526 return TRUE;
3527 }
3528
3529 SOFT386_OPCODE_HANDLER(Soft386OpcodeAaa)
3530 {
3531 UCHAR Value = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
3532
3533 /*
3534 * Check if the value in AL is not a valid BCD digit,
3535 * or there was a carry from the lowest 4 bits of AL
3536 */
3537 if (((Value & 0x0F) > 9) || State->Flags.Af)
3538 {
3539 /* Correct it */
3540 State->GeneralRegs[SOFT386_REG_EAX].LowByte += 0x06;
3541 State->GeneralRegs[SOFT386_REG_EAX].HighByte++;
3542
3543 /* Set CF and AF */
3544 State->Flags.Cf = State->Flags.Af = TRUE;
3545 }
3546 else
3547 {
3548 /* Clear CF and AF */
3549 State->Flags.Cf = State->Flags.Af = FALSE;
3550 }
3551
3552 /* Keep only the lowest 4 bits of AL */
3553 State->GeneralRegs[SOFT386_REG_EAX].LowByte &= 0x0F;
3554
3555 return TRUE;
3556 }
3557
3558 SOFT386_OPCODE_HANDLER(Soft386OpcodeAas)
3559 {
3560 UCHAR Value = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
3561
3562 /*
3563 * Check if the value in AL is not a valid BCD digit,
3564 * or there was a borrow from the lowest 4 bits of AL
3565 */
3566 if (((Value & 0x0F) > 9) || State->Flags.Af)
3567 {
3568 /* Correct it */
3569 State->GeneralRegs[SOFT386_REG_EAX].LowByte -= 0x06;
3570 State->GeneralRegs[SOFT386_REG_EAX].HighByte--;
3571
3572 /* Set CF and AF */
3573 State->Flags.Cf = State->Flags.Af = TRUE;
3574 }
3575 else
3576 {
3577 /* Clear CF and AF */
3578 State->Flags.Cf = State->Flags.Af = FALSE;
3579 }
3580
3581 /* Keep only the lowest 4 bits of AL */
3582 State->GeneralRegs[SOFT386_REG_EAX].LowByte &= 0x0F;
3583
3584 return TRUE;
3585 }
3586
3587 SOFT386_OPCODE_HANDLER(Soft386OpcodePushAll)
3588 {
3589 INT i;
3590 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
3591 SOFT386_REG SavedEsp = State->GeneralRegs[SOFT386_REG_ESP];
3592
3593 /* Make sure this is the right instruction */
3594 ASSERT(Opcode == 0x60);
3595
3596 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
3597 {
3598 /* The OPSIZE prefix toggles the size */
3599 Size = !Size;
3600 }
3601 else
3602 {
3603 /* Invalid prefix */
3604 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3605 return FALSE;
3606 }
3607
3608 /* Push all the registers in order */
3609 for (i = 0; i < SOFT386_NUM_GEN_REGS; i++)
3610 {
3611 if (i == SOFT386_REG_ESP)
3612 {
3613 /* Use the saved ESP instead */
3614 if (!Soft386StackPush(State, Size ? SavedEsp.Long : SavedEsp.LowWord))
3615 {
3616 /* Exception occurred */
3617 return FALSE;
3618 }
3619 }
3620 else
3621 {
3622 /* Push the register */
3623 if (!Soft386StackPush(State, Size ? State->GeneralRegs[i].Long
3624 : State->GeneralRegs[i].LowWord))
3625 {
3626 /* Exception occurred */
3627 return FALSE;
3628 }
3629 }
3630 }
3631
3632 return TRUE;
3633 }
3634
3635 SOFT386_OPCODE_HANDLER(Soft386OpcodePopAll)
3636 {
3637 INT i;
3638 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
3639 ULONG Value;
3640
3641 /* Make sure this is the right instruction */
3642 ASSERT(Opcode == 0x61);
3643
3644 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
3645 {
3646 /* The OPSIZE prefix toggles the size */
3647 Size = !Size;
3648 }
3649 else
3650 {
3651 /* Invalid prefix */
3652 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3653 return FALSE;
3654 }
3655
3656 /* Pop all the registers in reverse order */
3657 for (i = SOFT386_NUM_GEN_REGS - 1; i >= 0; i--)
3658 {
3659 /* Pop the value */
3660 if (!Soft386StackPop(State, &Value))
3661 {
3662 /* Exception occurred */
3663 return FALSE;
3664 }
3665
3666 /* Don't modify ESP */
3667 if (i != SOFT386_REG_ESP)
3668 {
3669 if (Size) State->GeneralRegs[i].Long = Value;
3670 else State->GeneralRegs[i].LowWord = LOWORD(Value);
3671 }
3672 }
3673
3674 return TRUE;
3675 }
3676
3677 SOFT386_OPCODE_HANDLER(Soft386OpcodeBound)
3678 {
3679 // TODO: NOT IMPLEMENTED
3680 UNIMPLEMENTED;
3681
3682 return FALSE;
3683 }
3684
3685 SOFT386_OPCODE_HANDLER(Soft386OpcodeArpl)
3686 {
3687 USHORT FirstValue, SecondValue;
3688 SOFT386_MOD_REG_RM ModRegRm;
3689 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
3690
3691 if (!(State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE)
3692 || State->Flags.Vm
3693 || (State->PrefixFlags & SOFT386_PREFIX_LOCK))
3694 {
3695 /* Cannot be used in real mode or with a LOCK prefix */
3696 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3697 return FALSE;
3698 }
3699
3700 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
3701 {
3702 /* The ADSIZE prefix toggles the size */
3703 AddressSize = !AddressSize;
3704 }
3705
3706 /* Get the operands */
3707 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
3708 {
3709 /* Exception occurred */
3710 return FALSE;
3711 }
3712
3713 /* Read the operands */
3714 if (!Soft386ReadModrmWordOperands(State,
3715 &ModRegRm,
3716 &FirstValue,
3717 &SecondValue))
3718 {
3719 /* Exception occurred */
3720 return FALSE;
3721 }
3722
3723 /* Check if the RPL needs adjusting */
3724 if ((SecondValue & 3) < (FirstValue & 3))
3725 {
3726 /* Adjust the RPL */
3727 SecondValue &= ~3;
3728 SecondValue |= FirstValue & 3;
3729
3730 /* Set ZF */
3731 State->Flags.Zf = TRUE;
3732
3733 /* Write back the result */
3734 return Soft386WriteModrmWordOperands(State, &ModRegRm, FALSE, SecondValue);
3735 }
3736 else
3737 {
3738 /* Clear ZF */
3739 State->Flags.Zf = FALSE;
3740 return TRUE;
3741 }
3742 }
3743
3744 SOFT386_OPCODE_HANDLER(Soft386OpcodePushImm)
3745 {
3746 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
3747
3748 /* Make sure this is the right instruction */
3749 ASSERT(Opcode == 0x68);
3750
3751 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
3752 {
3753 /* The OPSIZE prefix toggles the size */
3754 Size = !Size;
3755 }
3756 else
3757 {
3758 /* Invalid prefix */
3759 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3760 return FALSE;
3761 }
3762
3763 if (Size)
3764 {
3765 ULONG Data;
3766
3767 if (!Soft386FetchDword(State, &Data))
3768 {
3769 /* Exception occurred */
3770 return FALSE;
3771 }
3772
3773 /* Call the internal API */
3774 return Soft386StackPush(State, Data);
3775 }
3776 else
3777 {
3778 USHORT Data;
3779
3780 if (!Soft386FetchWord(State, &Data))
3781 {
3782 /* Exception occurred */
3783 return FALSE;
3784 }
3785
3786 /* Call the internal API */
3787 return Soft386StackPush(State, Data);
3788 }
3789 }
3790
3791 SOFT386_OPCODE_HANDLER(Soft386OpcodeImulModrmImm)
3792 {
3793 // TODO: NOT IMPLEMENTED
3794 UNIMPLEMENTED;
3795
3796 return FALSE;
3797 }
3798
3799 SOFT386_OPCODE_HANDLER(Soft386OpcodePushByteImm)
3800 {
3801 UCHAR Data;
3802
3803 /* Make sure this is the right instruction */
3804 ASSERT(Opcode == 0x6A);
3805
3806 if (!Soft386FetchByte(State, &Data))
3807 {
3808 /* Exception occurred */
3809 return FALSE;
3810 }
3811
3812 /* Call the internal API */
3813 return Soft386StackPush(State, Data);
3814 }
3815
3816 SOFT386_OPCODE_HANDLER(Soft386OpcodeImulModrmByteImm)
3817 {
3818 // TODO: NOT IMPLEMENTED
3819 UNIMPLEMENTED;
3820
3821 return FALSE;
3822 }
3823
3824 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovByteModrm)
3825 {
3826 UCHAR FirstValue, SecondValue, Result;
3827 SOFT386_MOD_REG_RM ModRegRm;
3828 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
3829
3830 /* Make sure this is the right instruction */
3831 ASSERT((Opcode & 0xFD) == 0x88);
3832
3833 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
3834 {
3835 /* The ADSIZE prefix toggles the size */
3836 AddressSize = !AddressSize;
3837 }
3838 else if (State->PrefixFlags
3839 & ~(SOFT386_PREFIX_ADSIZE
3840 | SOFT386_PREFIX_SEG
3841 | SOFT386_PREFIX_LOCK))
3842 {
3843 /* Invalid prefix */
3844 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3845 return FALSE;
3846 }
3847
3848 /* Get the operands */
3849 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
3850 {
3851 /* Exception occurred */
3852 return FALSE;
3853 }
3854
3855 if (!Soft386ReadModrmByteOperands(State,
3856 &ModRegRm,
3857 &FirstValue,
3858 &SecondValue))
3859 {
3860 /* Exception occurred */
3861 return FALSE;
3862 }
3863
3864 if (Opcode & SOFT386_OPCODE_WRITE_REG) Result = SecondValue;
3865 else Result = FirstValue;
3866
3867 /* Write back the result */
3868 return Soft386WriteModrmByteOperands(State,
3869 &ModRegRm,
3870 Opcode & SOFT386_OPCODE_WRITE_REG,
3871 Result);
3872
3873 }
3874
3875 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovModrm)
3876 {
3877 SOFT386_MOD_REG_RM ModRegRm;
3878 BOOLEAN OperandSize, AddressSize;
3879
3880 /* Make sure this is the right instruction */
3881 ASSERT((Opcode & 0xFD) == 0x89);
3882
3883 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
3884
3885 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
3886 {
3887 /* The ADSIZE prefix toggles the address size */
3888 AddressSize = !AddressSize;
3889 }
3890
3891 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
3892 {
3893 /* The OPSIZE prefix toggles the operand size */
3894 OperandSize = !OperandSize;
3895 }
3896
3897 if (State->PrefixFlags
3898 & ~(SOFT386_PREFIX_ADSIZE
3899 | SOFT386_PREFIX_OPSIZE
3900 | SOFT386_PREFIX_SEG
3901 | SOFT386_PREFIX_LOCK))
3902 {
3903 /* Invalid prefix */
3904 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3905 return FALSE;
3906 }
3907
3908 /* Get the operands */
3909 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
3910 {
3911 /* Exception occurred */
3912 return FALSE;
3913 }
3914
3915 /* Check the operand size */
3916 if (OperandSize)
3917 {
3918 ULONG FirstValue, SecondValue, Result;
3919
3920 if (!Soft386ReadModrmDwordOperands(State,
3921 &ModRegRm,
3922 &FirstValue,
3923 &SecondValue))
3924 {
3925 /* Exception occurred */
3926 return FALSE;
3927 }
3928
3929 if (Opcode & SOFT386_OPCODE_WRITE_REG) Result = SecondValue;
3930 else Result = FirstValue;
3931
3932 /* Write back the result */
3933 return Soft386WriteModrmDwordOperands(State,
3934 &ModRegRm,
3935 Opcode & SOFT386_OPCODE_WRITE_REG,
3936 Result);
3937 }
3938 else
3939 {
3940 USHORT FirstValue, SecondValue, Result;
3941
3942 if (!Soft386ReadModrmWordOperands(State,
3943 &ModRegRm,
3944 &FirstValue,
3945 &SecondValue))
3946 {
3947 /* Exception occurred */
3948 return FALSE;
3949 }
3950
3951 if (Opcode & SOFT386_OPCODE_WRITE_REG) Result = SecondValue;
3952 else Result = FirstValue;
3953
3954 /* Write back the result */
3955 return Soft386WriteModrmWordOperands(State,
3956 &ModRegRm,
3957 Opcode & SOFT386_OPCODE_WRITE_REG,
3958 Result);
3959 }
3960 }
3961
3962 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovStoreSeg)
3963 {
3964 // TODO: NOT IMPLEMENTED
3965 UNIMPLEMENTED;
3966
3967 return FALSE;
3968 }
3969
3970 SOFT386_OPCODE_HANDLER(Soft386OpcodeLea)
3971 {
3972 SOFT386_MOD_REG_RM ModRegRm;
3973 BOOLEAN OperandSize, AddressSize;
3974
3975 /* Make sure this is the right instruction */
3976 ASSERT(Opcode == 0x8D);
3977
3978 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
3979
3980 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
3981 {
3982 /* The ADSIZE prefix toggles the address size */
3983 AddressSize = !AddressSize;
3984 }
3985
3986 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
3987 {
3988 /* The OPSIZE prefix toggles the operand size */
3989 OperandSize = !OperandSize;
3990 }
3991
3992 /* Get the operands */
3993 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
3994 {
3995 /* Exception occurred */
3996 return FALSE;
3997 }
3998
3999 /* The second operand must be memory */
4000 if (!ModRegRm.Memory)
4001 {
4002 /* Invalid */
4003 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4004 return FALSE;
4005 }
4006
4007 /* Write the address to the register */
4008 if (OperandSize)
4009 {
4010 return Soft386WriteModrmDwordOperands(State,
4011 &ModRegRm,
4012 TRUE,
4013 ModRegRm.MemoryAddress);
4014 }
4015 else
4016 {
4017 return Soft386WriteModrmWordOperands(State,
4018 &ModRegRm,
4019 TRUE,
4020 ModRegRm.MemoryAddress);
4021
4022 }
4023 }
4024
4025 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovLoadSeg)
4026 {
4027 // TODO: NOT IMPLEMENTED
4028 UNIMPLEMENTED;
4029
4030 return FALSE;
4031 }
4032
4033 SOFT386_OPCODE_HANDLER(Soft386OpcodeCwde)
4034 {
4035 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4036
4037 /* Make sure this is the right instruction */
4038 ASSERT(Opcode == 0x98);
4039
4040 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
4041 {
4042 /* The OPSIZE prefix toggles the size */
4043 Size = !Size;
4044 }
4045 else if (State->PrefixFlags != 0)
4046 {
4047 /* Invalid prefix */
4048 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4049 return FALSE;
4050 }
4051
4052 if (Size)
4053 {
4054 /* Sign extend AX to EAX */
4055 State->GeneralRegs[SOFT386_REG_EAX].Long = MAKELONG
4056 (
4057 State->GeneralRegs[SOFT386_REG_EAX].LowWord,
4058 (State->GeneralRegs[SOFT386_REG_EAX].LowWord & SIGN_FLAG_WORD)
4059 ? 0xFFFF : 0x0000
4060 );
4061 }
4062 else
4063 {
4064 /* Sign extend AL to AX */
4065 State->GeneralRegs[SOFT386_REG_EAX].HighByte =
4066 (State->GeneralRegs[SOFT386_REG_EAX].LowByte & SIGN_FLAG_BYTE)
4067 ? 0xFF : 0x00;
4068 }
4069
4070 return TRUE;
4071 }
4072
4073 SOFT386_OPCODE_HANDLER(Soft386OpcodeCdq)
4074 {
4075 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4076
4077 /* Make sure this is the right instruction */
4078 ASSERT(Opcode == 0x99);
4079
4080 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
4081 {
4082 /* The OPSIZE prefix toggles the size */
4083 Size = !Size;
4084 }
4085 else if (State->PrefixFlags != 0)
4086 {
4087 /* Invalid prefix */
4088 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4089 return FALSE;
4090 }
4091
4092 if (Size)
4093 {
4094 /* Sign extend EAX to EDX:EAX */
4095 State->GeneralRegs[SOFT386_REG_EDX].Long =
4096 (State->GeneralRegs[SOFT386_REG_EAX].Long & SIGN_FLAG_LONG)
4097 ? 0xFFFFFFFF : 0x00000000;
4098 }
4099 else
4100 {
4101 /* Sign extend AX to DX:AX */
4102 State->GeneralRegs[SOFT386_REG_EDX].LowWord =
4103 (State->GeneralRegs[SOFT386_REG_EAX].LowWord & SIGN_FLAG_WORD)
4104 ? 0xFFFF : 0x0000;
4105 }
4106
4107 return TRUE;
4108 }
4109
4110 SOFT386_OPCODE_HANDLER(Soft386OpcodeCallAbs)
4111 {
4112 // TODO: NOT IMPLEMENTED
4113 UNIMPLEMENTED;
4114
4115 return FALSE;
4116 }
4117
4118 SOFT386_OPCODE_HANDLER(Soft386OpcodeWait)
4119 {
4120 // TODO: NOT IMPLEMENTED
4121 UNIMPLEMENTED;
4122
4123 return FALSE;
4124 }
4125
4126 SOFT386_OPCODE_HANDLER(Soft386OpcodePushFlags)
4127 {
4128 // TODO: NOT IMPLEMENTED
4129 UNIMPLEMENTED;
4130
4131 return FALSE;
4132 }
4133
4134 SOFT386_OPCODE_HANDLER(Soft386OpcodePopFlags)
4135 {
4136 // TODO: NOT IMPLEMENTED
4137 UNIMPLEMENTED;
4138
4139 return FALSE;
4140 }
4141
4142 SOFT386_OPCODE_HANDLER(Soft386OpcodeSahf)
4143 {
4144 /* Make sure this is the right instruction */
4145 ASSERT(Opcode == 0x9E);
4146
4147 /* Set the low-order byte of FLAGS to AH */
4148 State->Flags.Long &= 0xFFFFFF00;
4149 State->Flags.Long |= State->GeneralRegs[SOFT386_REG_EAX].HighByte;
4150
4151 /* Restore the reserved bits of FLAGS */
4152 State->Flags.AlwaysSet = TRUE;
4153 State->Flags.Reserved0 = State->Flags.Reserved1 = FALSE;
4154
4155 return FALSE;
4156 }
4157
4158 SOFT386_OPCODE_HANDLER(Soft386OpcodeLahf)
4159 {
4160 /* Make sure this is the right instruction */
4161 ASSERT(Opcode == 0x9F);
4162
4163 /* Set AH to the low-order byte of FLAGS */
4164 State->GeneralRegs[SOFT386_REG_EAX].HighByte = LOBYTE(State->Flags.Long);
4165
4166 return FALSE;
4167 }
4168
4169 SOFT386_OPCODE_HANDLER(Soft386OpcodeRet)
4170 {
4171 ULONG ReturnAddress;
4172 USHORT BytesToPop = 0;
4173 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4174
4175 /* Make sure this is the right instruction */
4176 ASSERT((Opcode & 0xFE) == 0xC2);
4177
4178 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
4179 {
4180 /* Invalid prefix */
4181 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4182 return FALSE;
4183 }
4184
4185 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
4186 {
4187 /* The OPSIZE prefix toggles the size */
4188 Size = !Size;
4189 }
4190
4191 if (Opcode == 0xC2)
4192 {
4193 /* Fetch the number of bytes to pop after the return */
4194 if (!Soft386FetchWord(State, &BytesToPop)) return FALSE;
4195 }
4196
4197 /* Pop the return address */
4198 if (!Soft386StackPop(State, &ReturnAddress)) return FALSE;
4199
4200 /* Return to the calling procedure, and if necessary, pop the parameters */
4201 if (Size)
4202 {
4203 State->InstPtr.Long = ReturnAddress;
4204 State->GeneralRegs[SOFT386_REG_ESP].Long += BytesToPop;
4205 }
4206 else
4207 {
4208 State->InstPtr.LowWord = LOWORD(ReturnAddress);
4209 State->GeneralRegs[SOFT386_REG_ESP].LowWord += BytesToPop;
4210 }
4211
4212 return TRUE;
4213 }
4214
4215 SOFT386_OPCODE_HANDLER(Soft386OpcodeLes)
4216 {
4217 // TODO: NOT IMPLEMENTED
4218 UNIMPLEMENTED;
4219
4220 return FALSE;
4221 }
4222
4223 SOFT386_OPCODE_HANDLER(Soft386OpcodeLds)
4224 {
4225 // TODO: NOT IMPLEMENTED
4226 UNIMPLEMENTED;
4227
4228 return FALSE;
4229 }
4230
4231 SOFT386_OPCODE_HANDLER(Soft386OpcodeEnter)
4232 {
4233 // TODO: NOT IMPLEMENTED
4234 UNIMPLEMENTED;
4235
4236 return FALSE;
4237 }
4238
4239 SOFT386_OPCODE_HANDLER(Soft386OpcodeLeave)
4240 {
4241 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4242
4243 /* Make sure this is the right instruction */
4244 ASSERT(Opcode == 0xC9);
4245
4246 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
4247 {
4248 /* Invalid prefix */
4249 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4250 return FALSE;
4251 }
4252
4253 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
4254 {
4255 /* The OPSIZE prefix toggles the size */
4256 Size = !Size;
4257 }
4258
4259 if (Size)
4260 {
4261 /* Set the stack pointer (ESP) to the base pointer (EBP) */
4262 State->GeneralRegs[SOFT386_REG_ESP].Long = State->GeneralRegs[SOFT386_REG_EBP].Long;
4263
4264 /* Pop the saved base pointer from the stack */
4265 return Soft386StackPop(State, &State->GeneralRegs[SOFT386_REG_EBP].Long);
4266 }
4267 else
4268 {
4269 ULONG Value;
4270
4271 /* Set the stack pointer (SP) to the base pointer (BP) */
4272 State->GeneralRegs[SOFT386_REG_ESP].LowWord = State->GeneralRegs[SOFT386_REG_EBP].LowWord;
4273
4274 /* Pop the saved base pointer from the stack */
4275 if (Soft386StackPop(State, &Value))
4276 {
4277 State->GeneralRegs[SOFT386_REG_EBP].LowWord = LOWORD(Value);
4278 return TRUE;
4279 }
4280 else return FALSE;
4281 }
4282 }
4283
4284 SOFT386_OPCODE_HANDLER(Soft386OpcodeRetFarImm)
4285 {
4286 // TODO: NOT IMPLEMENTED
4287 UNIMPLEMENTED;
4288
4289 return FALSE;
4290 }
4291
4292 SOFT386_OPCODE_HANDLER(Soft386OpcodeRetFar)
4293 {
4294 // TODO: NOT IMPLEMENTED
4295 UNIMPLEMENTED;
4296
4297 return FALSE;
4298 }
4299
4300 SOFT386_OPCODE_HANDLER(Soft386OpcodeInt3)
4301 {
4302 // TODO: NOT IMPLEMENTED
4303 UNIMPLEMENTED;
4304
4305 return FALSE;
4306 }
4307
4308 SOFT386_OPCODE_HANDLER(Soft386OpcodeInt)
4309 {
4310 // TODO: NOT IMPLEMENTED
4311 UNIMPLEMENTED;
4312
4313 return FALSE;
4314 }
4315
4316 SOFT386_OPCODE_HANDLER(Soft386OpcodeIntOverflow)
4317 {
4318 // TODO: NOT IMPLEMENTED
4319 UNIMPLEMENTED;
4320
4321 return FALSE;
4322 }
4323
4324 SOFT386_OPCODE_HANDLER(Soft386OpcodeIret)
4325 {
4326 // TODO: NOT IMPLEMENTED
4327 UNIMPLEMENTED;
4328
4329 return FALSE;
4330 }
4331
4332 SOFT386_OPCODE_HANDLER(Soft386OpcodeAam)
4333 {
4334 // TODO: NOT IMPLEMENTED
4335 UNIMPLEMENTED;
4336
4337 return FALSE;
4338 }
4339
4340 SOFT386_OPCODE_HANDLER(Soft386OpcodeAad)
4341 {
4342 // TODO: NOT IMPLEMENTED
4343 UNIMPLEMENTED;
4344
4345 return FALSE;
4346 }
4347
4348 SOFT386_OPCODE_HANDLER(Soft386OpcodeXlat)
4349 {
4350 // TODO: NOT IMPLEMENTED
4351 UNIMPLEMENTED;
4352
4353 return FALSE;
4354 }
4355
4356 SOFT386_OPCODE_HANDLER(Soft386OpcodeLoop)
4357 {
4358 BOOLEAN Condition;
4359 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4360 CHAR Offset = 0;
4361
4362 /* Make sure this is the right instruction */
4363 ASSERT((Opcode >= 0xE0) && (Opcode <= 0xE2));
4364
4365 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
4366 {
4367 /* Invalid prefix */
4368 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4369 return FALSE;
4370 }
4371
4372 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
4373 {
4374 /* The OPSIZE prefix toggles the size */
4375 Size = !Size;
4376 }
4377
4378 if (Size) Condition = ((--State->GeneralRegs[SOFT386_REG_ECX].Long) == 0);
4379 else Condition = ((--State->GeneralRegs[SOFT386_REG_ECX].LowWord) == 0);
4380
4381 if (Opcode == 0xE0)
4382 {
4383 /* Additional rule for LOOPNZ */
4384 if (State->Flags.Zf) Condition = FALSE;
4385 }
4386
4387 if (Opcode == 0xE1)
4388 {
4389 /* Additional rule for LOOPZ */
4390 if (!State->Flags.Zf) Condition = FALSE;
4391 }
4392
4393 /* Fetch the offset */
4394 if (!Soft386FetchByte(State, (PUCHAR)&Offset))
4395 {
4396 /* An exception occurred */
4397 return FALSE;
4398 }
4399
4400 if (Condition)
4401 {
4402 /* Move the instruction pointer */
4403 State->InstPtr.Long += Offset;
4404 }
4405
4406 return TRUE;
4407 }
4408
4409 SOFT386_OPCODE_HANDLER(Soft386OpcodeJecxz)
4410 {
4411 BOOLEAN Condition;
4412 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4413 CHAR Offset = 0;
4414
4415 /* Make sure this is the right instruction */
4416 ASSERT(Opcode == 0xE3);
4417
4418 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
4419 {
4420 /* Invalid prefix */
4421 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4422 return FALSE;
4423 }
4424
4425 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
4426 {
4427 /* The OPSIZE prefix toggles the size */
4428 Size = !Size;
4429 }
4430
4431 if (Size) Condition = (State->GeneralRegs[SOFT386_REG_ECX].Long == 0);
4432 else Condition = (State->GeneralRegs[SOFT386_REG_ECX].LowWord == 0);
4433
4434 /* Fetch the offset */
4435 if (!Soft386FetchByte(State, (PUCHAR)&Offset))
4436 {
4437 /* An exception occurred */
4438 return FALSE;
4439 }
4440
4441 if (Condition)
4442 {
4443 /* Move the instruction pointer */
4444 State->InstPtr.Long += Offset;
4445 }
4446
4447 return TRUE;
4448 }
4449
4450 SOFT386_OPCODE_HANDLER(Soft386OpcodeCall)
4451 {
4452 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4453
4454 /* Make sure this is the right instruction */
4455 ASSERT(Opcode == 0xE8);
4456
4457 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
4458 {
4459 /* The OPSIZE prefix toggles the size */
4460 Size = !Size;
4461 }
4462 else if (State->PrefixFlags != 0)
4463 {
4464 /* Invalid prefix */
4465 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4466 return FALSE;
4467 }
4468
4469 /* Push the current value of the instruction pointer */
4470 if (!Soft386StackPush(State, State->InstPtr.Long))
4471 {
4472 /* Exception occurred */
4473 return FALSE;
4474 }
4475
4476 if (Size)
4477 {
4478 LONG Offset = 0;
4479
4480 /* Fetch the offset */
4481 if (!Soft386FetchDword(State, (PULONG)&Offset))
4482 {
4483 /* An exception occurred */
4484 return FALSE;
4485 }
4486
4487 /* Move the instruction pointer */
4488 State->InstPtr.Long += Offset;
4489 }
4490 else
4491 {
4492 SHORT Offset = 0;
4493
4494 /* Fetch the offset */
4495 if (!Soft386FetchWord(State, (PUSHORT)&Offset))
4496 {
4497 /* An exception occurred */
4498 return FALSE;
4499 }
4500
4501 /* Move the instruction pointer */
4502 State->InstPtr.LowWord += Offset;
4503 }
4504
4505 return TRUE;
4506 }
4507
4508 SOFT386_OPCODE_HANDLER(Soft386OpcodeJmp)
4509 {
4510 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4511
4512 /* Make sure this is the right instruction */
4513 ASSERT(Opcode == 0xE9);
4514
4515 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
4516 {
4517 /* The OPSIZE prefix toggles the size */
4518 Size = !Size;
4519 }
4520 else if (State->PrefixFlags != 0)
4521 {
4522 /* Invalid prefix */
4523 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4524 return FALSE;
4525 }
4526
4527 if (Size)
4528 {
4529 LONG Offset = 0;
4530
4531 /* Fetch the offset */
4532 if (!Soft386FetchDword(State, (PULONG)&Offset))
4533 {
4534 /* An exception occurred */
4535 return FALSE;
4536 }
4537
4538 /* Move the instruction pointer */
4539 State->InstPtr.Long += Offset;
4540 }
4541 else
4542 {
4543 SHORT Offset = 0;
4544
4545 /* Fetch the offset */
4546 if (!Soft386FetchWord(State, (PUSHORT)&Offset))
4547 {
4548 /* An exception occurred */
4549 return FALSE;
4550 }
4551
4552 /* Move the instruction pointer */
4553 State->InstPtr.LowWord += Offset;
4554 }
4555
4556 return TRUE;
4557 }
4558
4559 SOFT386_OPCODE_HANDLER(Soft386OpcodeJmpAbs)
4560 {
4561 // TODO: NOT IMPLEMENTED
4562 UNIMPLEMENTED;
4563
4564 return FALSE;
4565 }