1233c6bb867f197906abcd9d3172d10eb8ad3299
[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 Soft386OpcodeMovAlOffset,
188 Soft386OpcodeMovEaxOffset,
189 Soft386OpcodeMovOffsetAl,
190 Soft386OpcodeMovOffsetEax,
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 Soft386OpcodeInt,
232 Soft386OpcodeInt,
233 Soft386OpcodeInt,
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_LOCK)
1429 {
1430 /* Invalid prefix */
1431 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1432 return FALSE;
1433 }
1434
1435 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
1436 {
1437 /* The OPSIZE prefix toggles the size */
1438 Size = !Size;
1439 }
1440
1441 if (Size)
1442 {
1443 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
1444 ULONG SecondValue, Result;
1445
1446 if (!Soft386FetchDword(State, &SecondValue))
1447 {
1448 /* Exception occurred */
1449 return FALSE;
1450 }
1451
1452 /* Calculate the result */
1453 Result = FirstValue + SecondValue;
1454
1455 /* Update the flags */
1456 State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
1457 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG))
1458 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
1459 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
1460 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1461 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
1462 State->Flags.Pf = Soft386CalculateParity(Result);
1463
1464 /* Write back the result */
1465 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
1466 }
1467 else
1468 {
1469 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
1470 USHORT SecondValue, Result;
1471
1472 if (!Soft386FetchWord(State, &SecondValue))
1473 {
1474 /* Exception occurred */
1475 return FALSE;
1476 }
1477
1478 /* Calculate the result */
1479 Result = FirstValue + SecondValue;
1480
1481 /* Update the flags */
1482 State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
1483 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD))
1484 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
1485 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
1486 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1487 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
1488 State->Flags.Pf = Soft386CalculateParity(Result);
1489
1490 /* Write back the result */
1491 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
1492 }
1493
1494 return TRUE;
1495 }
1496
1497 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrByteModrm)
1498 {
1499 UCHAR FirstValue, SecondValue, Result;
1500 SOFT386_MOD_REG_RM ModRegRm;
1501 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
1502
1503 /* Make sure this is the right instruction */
1504 ASSERT((Opcode & 0xFD) == 0x08);
1505
1506 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
1507 {
1508 /* The ADSIZE prefix toggles the size */
1509 AddressSize = !AddressSize;
1510 }
1511 else if (State->PrefixFlags
1512 & ~(SOFT386_PREFIX_ADSIZE
1513 | SOFT386_PREFIX_SEG
1514 | SOFT386_PREFIX_LOCK))
1515 {
1516 /* Invalid prefix */
1517 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1518 return FALSE;
1519 }
1520
1521 /* Get the operands */
1522 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
1523 {
1524 /* Exception occurred */
1525 return FALSE;
1526 }
1527
1528 if (!Soft386ReadModrmByteOperands(State,
1529 &ModRegRm,
1530 &FirstValue,
1531 &SecondValue))
1532 {
1533 /* Exception occurred */
1534 return FALSE;
1535 }
1536
1537 /* Calculate the result */
1538 Result = FirstValue | SecondValue;
1539
1540 /* Update the flags */
1541 State->Flags.Cf = FALSE;
1542 State->Flags.Of = FALSE;
1543 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1544 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
1545 State->Flags.Pf = Soft386CalculateParity(Result);
1546
1547 /* Write back the result */
1548 return Soft386WriteModrmByteOperands(State,
1549 &ModRegRm,
1550 Opcode & SOFT386_OPCODE_WRITE_REG,
1551 Result);
1552 }
1553
1554 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrModrm)
1555 {
1556 SOFT386_MOD_REG_RM ModRegRm;
1557 BOOLEAN OperandSize, AddressSize;
1558
1559 /* Make sure this is the right instruction */
1560 ASSERT((Opcode & 0xFD) == 0x09);
1561
1562 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
1563
1564 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
1565 {
1566 /* The ADSIZE prefix toggles the address size */
1567 AddressSize = !AddressSize;
1568 }
1569
1570 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
1571 {
1572 /* The OPSIZE prefix toggles the operand size */
1573 OperandSize = !OperandSize;
1574 }
1575
1576 if (State->PrefixFlags
1577 & ~(SOFT386_PREFIX_ADSIZE
1578 | SOFT386_PREFIX_OPSIZE
1579 | SOFT386_PREFIX_SEG
1580 | SOFT386_PREFIX_LOCK))
1581 {
1582 /* Invalid prefix */
1583 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1584 return FALSE;
1585 }
1586
1587 /* Get the operands */
1588 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
1589 {
1590 /* Exception occurred */
1591 return FALSE;
1592 }
1593
1594 /* Check the operand size */
1595 if (OperandSize)
1596 {
1597 ULONG FirstValue, SecondValue, Result;
1598
1599 if (!Soft386ReadModrmDwordOperands(State,
1600 &ModRegRm,
1601 &FirstValue,
1602 &SecondValue))
1603 {
1604 /* Exception occurred */
1605 return FALSE;
1606 }
1607
1608 /* Calculate the result */
1609 Result = FirstValue | SecondValue;
1610
1611 /* Update the flags */
1612 State->Flags.Cf = FALSE;
1613 State->Flags.Of = FALSE;
1614 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1615 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
1616 State->Flags.Pf = Soft386CalculateParity(Result);
1617
1618 /* Write back the result */
1619 return Soft386WriteModrmDwordOperands(State,
1620 &ModRegRm,
1621 Opcode & SOFT386_OPCODE_WRITE_REG,
1622 Result);
1623 }
1624 else
1625 {
1626 USHORT FirstValue, SecondValue, Result;
1627
1628 if (!Soft386ReadModrmWordOperands(State,
1629 &ModRegRm,
1630 &FirstValue,
1631 &SecondValue))
1632 {
1633 /* Exception occurred */
1634 return FALSE;
1635 }
1636
1637 /* Calculate the result */
1638 Result = FirstValue | SecondValue;
1639
1640 /* Update the flags */
1641 State->Flags.Cf = FALSE;
1642 State->Flags.Of = FALSE;
1643 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1644 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
1645 State->Flags.Pf = Soft386CalculateParity(Result);
1646
1647 /* Write back the result */
1648 return Soft386WriteModrmWordOperands(State,
1649 &ModRegRm,
1650 Opcode & SOFT386_OPCODE_WRITE_REG,
1651 Result);
1652 }
1653 }
1654
1655 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrAl)
1656 {
1657 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
1658 UCHAR SecondValue, Result;
1659
1660 /* Make sure this is the right instruction */
1661 ASSERT(Opcode == 0x0C);
1662
1663 if (State->PrefixFlags)
1664 {
1665 /* This opcode doesn't take any prefixes */
1666 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1667 return FALSE;
1668 }
1669
1670 if (!Soft386FetchByte(State, &SecondValue))
1671 {
1672 /* Exception occurred */
1673 return FALSE;
1674 }
1675
1676 /* Calculate the result */
1677 Result = FirstValue | SecondValue;
1678
1679 /* Update the flags */
1680 State->Flags.Cf = FALSE;
1681 State->Flags.Of = FALSE;
1682 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1683 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
1684 State->Flags.Pf = Soft386CalculateParity(Result);
1685
1686 /* Write back the result */
1687 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
1688
1689 return TRUE;
1690 }
1691
1692 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrEax)
1693 {
1694 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
1695
1696 /* Make sure this is the right instruction */
1697 ASSERT(Opcode == 0x0D);
1698
1699 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
1700 {
1701 /* Invalid prefix */
1702 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1703 return FALSE;
1704 }
1705
1706 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
1707 {
1708 /* The OPSIZE prefix toggles the size */
1709 Size = !Size;
1710 }
1711
1712 if (Size)
1713 {
1714 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
1715 ULONG SecondValue, Result;
1716
1717 if (!Soft386FetchDword(State, &SecondValue))
1718 {
1719 /* Exception occurred */
1720 return FALSE;
1721 }
1722
1723 /* Calculate the result */
1724 Result = FirstValue | SecondValue;
1725
1726 /* Update the flags */
1727 State->Flags.Cf = FALSE;
1728 State->Flags.Of = FALSE;
1729 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1730 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
1731 State->Flags.Pf = Soft386CalculateParity(Result);
1732
1733 /* Write back the result */
1734 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
1735 }
1736 else
1737 {
1738 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
1739 USHORT SecondValue, Result;
1740
1741 if (!Soft386FetchWord(State, &SecondValue))
1742 {
1743 /* Exception occurred */
1744 return FALSE;
1745 }
1746
1747 /* Calculate the result */
1748 Result = FirstValue | SecondValue;
1749
1750 /* Update the flags */
1751 State->Flags.Cf = FALSE;
1752 State->Flags.Of = FALSE;
1753 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1754 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
1755 State->Flags.Pf = Soft386CalculateParity(Result);
1756
1757 /* Write back the result */
1758 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
1759 }
1760
1761 return TRUE;
1762 }
1763
1764 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndByteModrm)
1765 {
1766 UCHAR FirstValue, SecondValue, Result;
1767 SOFT386_MOD_REG_RM ModRegRm;
1768 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
1769
1770 /* Make sure this is the right instruction */
1771 ASSERT((Opcode & 0xFD) == 0x20);
1772
1773 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
1774 {
1775 /* The ADSIZE prefix toggles the size */
1776 AddressSize = !AddressSize;
1777 }
1778 else if (State->PrefixFlags
1779 & ~(SOFT386_PREFIX_ADSIZE
1780 | SOFT386_PREFIX_SEG
1781 | SOFT386_PREFIX_LOCK))
1782 {
1783 /* Invalid prefix */
1784 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1785 return FALSE;
1786 }
1787
1788 /* Get the operands */
1789 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
1790 {
1791 /* Exception occurred */
1792 return FALSE;
1793 }
1794
1795 if (!Soft386ReadModrmByteOperands(State,
1796 &ModRegRm,
1797 &FirstValue,
1798 &SecondValue))
1799 {
1800 /* Exception occurred */
1801 return FALSE;
1802 }
1803
1804 /* Calculate the result */
1805 Result = FirstValue & SecondValue;
1806
1807 /* Update the flags */
1808 State->Flags.Cf = FALSE;
1809 State->Flags.Of = FALSE;
1810 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1811 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
1812 State->Flags.Pf = Soft386CalculateParity(Result);
1813
1814 /* Write back the result */
1815 return Soft386WriteModrmByteOperands(State,
1816 &ModRegRm,
1817 Opcode & SOFT386_OPCODE_WRITE_REG,
1818 Result);
1819 }
1820
1821 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndModrm)
1822 {
1823 SOFT386_MOD_REG_RM ModRegRm;
1824 BOOLEAN OperandSize, AddressSize;
1825
1826 /* Make sure this is the right instruction */
1827 ASSERT((Opcode & 0xFD) == 0x21);
1828
1829 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
1830
1831 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
1832 {
1833 /* The ADSIZE prefix toggles the address size */
1834 AddressSize = !AddressSize;
1835 }
1836
1837 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
1838 {
1839 /* The OPSIZE prefix toggles the operand size */
1840 OperandSize = !OperandSize;
1841 }
1842
1843 if (State->PrefixFlags
1844 & ~(SOFT386_PREFIX_ADSIZE
1845 | SOFT386_PREFIX_OPSIZE
1846 | SOFT386_PREFIX_SEG
1847 | SOFT386_PREFIX_LOCK))
1848 {
1849 /* Invalid prefix */
1850 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1851 return FALSE;
1852 }
1853
1854 /* Get the operands */
1855 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
1856 {
1857 /* Exception occurred */
1858 return FALSE;
1859 }
1860
1861 /* Check the operand size */
1862 if (OperandSize)
1863 {
1864 ULONG FirstValue, SecondValue, Result;
1865
1866 if (!Soft386ReadModrmDwordOperands(State,
1867 &ModRegRm,
1868 &FirstValue,
1869 &SecondValue))
1870 {
1871 /* Exception occurred */
1872 return FALSE;
1873 }
1874
1875 /* Calculate the result */
1876 Result = FirstValue & SecondValue;
1877
1878 /* Update the flags */
1879 State->Flags.Cf = FALSE;
1880 State->Flags.Of = FALSE;
1881 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1882 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
1883 State->Flags.Pf = Soft386CalculateParity(Result);
1884
1885 /* Write back the result */
1886 return Soft386WriteModrmDwordOperands(State,
1887 &ModRegRm,
1888 Opcode & SOFT386_OPCODE_WRITE_REG,
1889 Result);
1890 }
1891 else
1892 {
1893 USHORT FirstValue, SecondValue, Result;
1894
1895 if (!Soft386ReadModrmWordOperands(State,
1896 &ModRegRm,
1897 &FirstValue,
1898 &SecondValue))
1899 {
1900 /* Exception occurred */
1901 return FALSE;
1902 }
1903
1904 /* Calculate the result */
1905 Result = FirstValue & SecondValue;
1906
1907 /* Update the flags */
1908 State->Flags.Cf = FALSE;
1909 State->Flags.Of = FALSE;
1910 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1911 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
1912 State->Flags.Pf = Soft386CalculateParity(Result);
1913
1914 /* Write back the result */
1915 return Soft386WriteModrmWordOperands(State,
1916 &ModRegRm,
1917 Opcode & SOFT386_OPCODE_WRITE_REG,
1918 Result);
1919 }
1920 }
1921
1922 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndAl)
1923 {
1924 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
1925 UCHAR SecondValue, Result;
1926
1927 /* Make sure this is the right instruction */
1928 ASSERT(Opcode == 0x24);
1929
1930 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
1931 {
1932 /* Invalid prefix */
1933 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1934 return FALSE;
1935 }
1936
1937 if (!Soft386FetchByte(State, &SecondValue))
1938 {
1939 /* Exception occurred */
1940 return FALSE;
1941 }
1942
1943 /* Calculate the result */
1944 Result = FirstValue & SecondValue;
1945
1946 /* Update the flags */
1947 State->Flags.Cf = FALSE;
1948 State->Flags.Of = FALSE;
1949 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1950 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
1951 State->Flags.Pf = Soft386CalculateParity(Result);
1952
1953 /* Write back the result */
1954 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
1955
1956 return TRUE;
1957 }
1958
1959 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndEax)
1960 {
1961 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
1962
1963 /* Make sure this is the right instruction */
1964 ASSERT(Opcode == 0x25);
1965
1966 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
1967 {
1968 /* Invalid prefix */
1969 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1970 return FALSE;
1971 }
1972
1973 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
1974 {
1975 /* The OPSIZE prefix toggles the size */
1976 Size = !Size;
1977 }
1978
1979 if (Size)
1980 {
1981 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
1982 ULONG SecondValue, Result;
1983
1984 if (!Soft386FetchDword(State, &SecondValue))
1985 {
1986 /* Exception occurred */
1987 return FALSE;
1988 }
1989
1990 /* Calculate the result */
1991 Result = FirstValue & SecondValue;
1992
1993 /* Update the flags */
1994 State->Flags.Cf = FALSE;
1995 State->Flags.Of = FALSE;
1996 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1997 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
1998 State->Flags.Pf = Soft386CalculateParity(Result);
1999
2000 /* Write back the result */
2001 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
2002 }
2003 else
2004 {
2005 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
2006 USHORT SecondValue, Result;
2007
2008 if (!Soft386FetchWord(State, &SecondValue))
2009 {
2010 /* Exception occurred */
2011 return FALSE;
2012 }
2013
2014 /* Calculate the result */
2015 Result = FirstValue & SecondValue;
2016
2017 /* Update the flags */
2018 State->Flags.Cf = FALSE;
2019 State->Flags.Of = FALSE;
2020 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2021 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
2022 State->Flags.Pf = Soft386CalculateParity(Result);
2023
2024 /* Write back the result */
2025 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
2026 }
2027
2028 return TRUE;
2029 }
2030
2031 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorByteModrm)
2032 {
2033 UCHAR FirstValue, SecondValue, Result;
2034 SOFT386_MOD_REG_RM ModRegRm;
2035 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2036
2037 /* Make sure this is the right instruction */
2038 ASSERT((Opcode & 0xFD) == 0x30);
2039
2040 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2041 {
2042 /* The ADSIZE prefix toggles the size */
2043 AddressSize = !AddressSize;
2044 }
2045 else if (State->PrefixFlags
2046 & ~(SOFT386_PREFIX_ADSIZE
2047 | SOFT386_PREFIX_SEG
2048 | SOFT386_PREFIX_LOCK))
2049 {
2050 /* Invalid prefix */
2051 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2052 return FALSE;
2053 }
2054
2055 /* Get the operands */
2056 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2057 {
2058 /* Exception occurred */
2059 return FALSE;
2060 }
2061
2062 if (!Soft386ReadModrmByteOperands(State,
2063 &ModRegRm,
2064 &FirstValue,
2065 &SecondValue))
2066 {
2067 /* Exception occurred */
2068 return FALSE;
2069 }
2070
2071 /* Calculate the result */
2072 Result = FirstValue ^ SecondValue;
2073
2074 /* Update the flags */
2075 State->Flags.Cf = FALSE;
2076 State->Flags.Of = FALSE;
2077 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2078 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
2079 State->Flags.Pf = Soft386CalculateParity(Result);
2080
2081 /* Write back the result */
2082 return Soft386WriteModrmByteOperands(State,
2083 &ModRegRm,
2084 Opcode & SOFT386_OPCODE_WRITE_REG,
2085 Result);
2086 }
2087
2088 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorModrm)
2089 {
2090 SOFT386_MOD_REG_RM ModRegRm;
2091 BOOLEAN OperandSize, AddressSize;
2092
2093 /* Make sure this is the right instruction */
2094 ASSERT((Opcode & 0xFD) == 0x31);
2095
2096 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2097
2098 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2099 {
2100 /* The ADSIZE prefix toggles the address size */
2101 AddressSize = !AddressSize;
2102 }
2103
2104 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2105 {
2106 /* The OPSIZE prefix toggles the operand size */
2107 OperandSize = !OperandSize;
2108 }
2109
2110 if (State->PrefixFlags
2111 & ~(SOFT386_PREFIX_ADSIZE
2112 | SOFT386_PREFIX_OPSIZE
2113 | SOFT386_PREFIX_SEG
2114 | SOFT386_PREFIX_LOCK))
2115 {
2116 /* Invalid prefix */
2117 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2118 return FALSE;
2119 }
2120
2121 /* Get the operands */
2122 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2123 {
2124 /* Exception occurred */
2125 return FALSE;
2126 }
2127
2128 /* Check the operand size */
2129 if (OperandSize)
2130 {
2131 ULONG FirstValue, SecondValue, Result;
2132
2133 if (!Soft386ReadModrmDwordOperands(State,
2134 &ModRegRm,
2135 &FirstValue,
2136 &SecondValue))
2137 {
2138 /* Exception occurred */
2139 return FALSE;
2140 }
2141
2142 /* Calculate the result */
2143 Result = FirstValue ^ SecondValue;
2144
2145 /* Update the flags */
2146 State->Flags.Cf = FALSE;
2147 State->Flags.Of = FALSE;
2148 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2149 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
2150 State->Flags.Pf = Soft386CalculateParity(Result);
2151
2152 /* Write back the result */
2153 return Soft386WriteModrmDwordOperands(State,
2154 &ModRegRm,
2155 Opcode & SOFT386_OPCODE_WRITE_REG,
2156 Result);
2157 }
2158 else
2159 {
2160 USHORT FirstValue, SecondValue, Result;
2161
2162 if (!Soft386ReadModrmWordOperands(State,
2163 &ModRegRm,
2164 &FirstValue,
2165 &SecondValue))
2166 {
2167 /* Exception occurred */
2168 return FALSE;
2169 }
2170
2171 /* Calculate the result */
2172 Result = FirstValue ^ SecondValue;
2173
2174 /* Update the flags */
2175 State->Flags.Cf = FALSE;
2176 State->Flags.Of = FALSE;
2177 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2178 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
2179 State->Flags.Pf = Soft386CalculateParity(Result);
2180
2181 /* Write back the result */
2182 return Soft386WriteModrmWordOperands(State,
2183 &ModRegRm,
2184 Opcode & SOFT386_OPCODE_WRITE_REG,
2185 Result);
2186 }
2187 }
2188
2189 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorAl)
2190 {
2191 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
2192 UCHAR SecondValue, Result;
2193
2194 /* Make sure this is the right instruction */
2195 ASSERT(Opcode == 0x34);
2196
2197 if (State->PrefixFlags)
2198 {
2199 /* This opcode doesn't take any prefixes */
2200 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2201 return FALSE;
2202 }
2203
2204 if (!Soft386FetchByte(State, &SecondValue))
2205 {
2206 /* Exception occurred */
2207 return FALSE;
2208 }
2209
2210 /* Calculate the result */
2211 Result = FirstValue ^ SecondValue;
2212
2213 /* Update the flags */
2214 State->Flags.Cf = FALSE;
2215 State->Flags.Of = FALSE;
2216 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2217 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
2218 State->Flags.Pf = Soft386CalculateParity(Result);
2219
2220 /* Write back the result */
2221 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
2222
2223 return TRUE;
2224 }
2225
2226 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorEax)
2227 {
2228 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
2229
2230 /* Make sure this is the right instruction */
2231 ASSERT(Opcode == 0x35);
2232
2233 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
2234 {
2235 /* Invalid prefix */
2236 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2237 return FALSE;
2238 }
2239
2240 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2241 {
2242 /* The OPSIZE prefix toggles the size */
2243 Size = !Size;
2244 }
2245
2246 if (Size)
2247 {
2248 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
2249 ULONG SecondValue, Result;
2250
2251 if (!Soft386FetchDword(State, &SecondValue))
2252 {
2253 /* Exception occurred */
2254 return FALSE;
2255 }
2256
2257 /* Calculate the result */
2258 Result = FirstValue ^ SecondValue;
2259
2260 /* Update the flags */
2261 State->Flags.Cf = FALSE;
2262 State->Flags.Of = FALSE;
2263 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2264 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
2265 State->Flags.Pf = Soft386CalculateParity(Result);
2266
2267 /* Write back the result */
2268 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
2269 }
2270 else
2271 {
2272 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
2273 USHORT SecondValue, Result;
2274
2275 if (!Soft386FetchWord(State, &SecondValue))
2276 {
2277 /* Exception occurred */
2278 return FALSE;
2279 }
2280
2281 /* Calculate the result */
2282 Result = FirstValue ^ SecondValue;
2283
2284 /* Update the flags */
2285 State->Flags.Cf = FALSE;
2286 State->Flags.Of = FALSE;
2287 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2288 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
2289 State->Flags.Pf = Soft386CalculateParity(Result);
2290
2291 /* Write back the result */
2292 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
2293 }
2294
2295 return TRUE;
2296 }
2297
2298 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestByteModrm)
2299 {
2300 UCHAR FirstValue, SecondValue, Result;
2301 SOFT386_MOD_REG_RM ModRegRm;
2302 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2303
2304 /* Make sure this is the right instruction */
2305 ASSERT(Opcode == 0x84);
2306
2307 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2308 {
2309 /* The ADSIZE prefix toggles the size */
2310 AddressSize = !AddressSize;
2311 }
2312 else if (State->PrefixFlags
2313 & ~(SOFT386_PREFIX_ADSIZE
2314 | SOFT386_PREFIX_SEG
2315 | SOFT386_PREFIX_LOCK))
2316 {
2317 /* Invalid prefix */
2318 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2319 return FALSE;
2320 }
2321
2322 /* Get the operands */
2323 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2324 {
2325 /* Exception occurred */
2326 return FALSE;
2327 }
2328
2329 if (!Soft386ReadModrmByteOperands(State,
2330 &ModRegRm,
2331 &FirstValue,
2332 &SecondValue))
2333 {
2334 /* Exception occurred */
2335 return FALSE;
2336 }
2337 /* Calculate the result */
2338 Result = FirstValue & SecondValue;
2339
2340 /* Update the flags */
2341 State->Flags.Cf = FALSE;
2342 State->Flags.Of = FALSE;
2343 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2344 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
2345 State->Flags.Pf = Soft386CalculateParity(Result);
2346
2347 /* The result is discarded */
2348 return TRUE;
2349 }
2350
2351 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestModrm)
2352 {
2353 SOFT386_MOD_REG_RM ModRegRm;
2354 BOOLEAN OperandSize, AddressSize;
2355
2356 /* Make sure this is the right instruction */
2357 ASSERT(Opcode == 0x85);
2358
2359 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2360
2361 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2362 {
2363 /* The ADSIZE prefix toggles the address size */
2364 AddressSize = !AddressSize;
2365 }
2366
2367 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2368 {
2369 /* The OPSIZE prefix toggles the operand size */
2370 OperandSize = !OperandSize;
2371 }
2372
2373 if (State->PrefixFlags
2374 & ~(SOFT386_PREFIX_ADSIZE
2375 | SOFT386_PREFIX_OPSIZE
2376 | SOFT386_PREFIX_SEG
2377 | SOFT386_PREFIX_LOCK))
2378 {
2379 /* Invalid prefix */
2380 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2381 return FALSE;
2382 }
2383
2384 /* Get the operands */
2385 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2386 {
2387 /* Exception occurred */
2388 return FALSE;
2389 }
2390
2391 /* Check the operand size */
2392 if (OperandSize)
2393 {
2394 ULONG FirstValue, SecondValue, Result;
2395
2396 if (!Soft386ReadModrmDwordOperands(State,
2397 &ModRegRm,
2398 &FirstValue,
2399 &SecondValue))
2400 {
2401 /* Exception occurred */
2402 return FALSE;
2403 }
2404
2405 /* Calculate the result */
2406 Result = FirstValue & SecondValue;
2407
2408 /* Update the flags */
2409 State->Flags.Cf = FALSE;
2410 State->Flags.Of = FALSE;
2411 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2412 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
2413 State->Flags.Pf = Soft386CalculateParity(Result);
2414 }
2415 else
2416 {
2417 USHORT FirstValue, SecondValue, Result;
2418
2419 if (!Soft386ReadModrmWordOperands(State,
2420 &ModRegRm,
2421 &FirstValue,
2422 &SecondValue))
2423 {
2424 /* Exception occurred */
2425 return FALSE;
2426 }
2427
2428 /* Calculate the result */
2429 Result = FirstValue & SecondValue;
2430
2431 /* Update the flags */
2432 State->Flags.Cf = FALSE;
2433 State->Flags.Of = FALSE;
2434 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2435 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
2436 State->Flags.Pf = Soft386CalculateParity(Result);
2437 }
2438
2439 /* The result is discarded */
2440 return TRUE;
2441 }
2442
2443 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestAl)
2444 {
2445 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
2446 UCHAR SecondValue, Result;
2447
2448 /* Make sure this is the right instruction */
2449 ASSERT(Opcode == 0xA8);
2450
2451 if (State->PrefixFlags)
2452 {
2453 /* This opcode doesn't take any prefixes */
2454 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2455 return FALSE;
2456 }
2457
2458 if (!Soft386FetchByte(State, &SecondValue))
2459 {
2460 /* Exception occurred */
2461 return FALSE;
2462 }
2463
2464 /* Calculate the result */
2465 Result = FirstValue & SecondValue;
2466
2467 /* Update the flags */
2468 State->Flags.Cf = FALSE;
2469 State->Flags.Of = FALSE;
2470 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2471 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
2472 State->Flags.Pf = Soft386CalculateParity(Result);
2473
2474 /* The result is discarded */
2475 return TRUE;
2476 }
2477
2478 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestEax)
2479 {
2480 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
2481
2482 /* Make sure this is the right instruction */
2483 ASSERT(Opcode == 0xA9);
2484
2485 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
2486 {
2487 /* Invalid prefix */
2488 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2489 return FALSE;
2490 }
2491
2492 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2493 {
2494 /* The OPSIZE prefix toggles the size */
2495 Size = !Size;
2496 }
2497
2498 if (Size)
2499 {
2500 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
2501 ULONG SecondValue, Result;
2502
2503 if (!Soft386FetchDword(State, &SecondValue))
2504 {
2505 /* Exception occurred */
2506 return FALSE;
2507 }
2508
2509 /* Calculate the result */
2510 Result = FirstValue & SecondValue;
2511
2512 /* Update the flags */
2513 State->Flags.Cf = FALSE;
2514 State->Flags.Of = FALSE;
2515 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2516 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
2517 State->Flags.Pf = Soft386CalculateParity(Result);
2518 }
2519 else
2520 {
2521 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
2522 USHORT SecondValue, Result;
2523
2524 if (!Soft386FetchWord(State, &SecondValue))
2525 {
2526 /* Exception occurred */
2527 return FALSE;
2528 }
2529
2530 /* Calculate the result */
2531 Result = FirstValue & SecondValue;
2532
2533 /* Update the flags */
2534 State->Flags.Cf = FALSE;
2535 State->Flags.Of = FALSE;
2536 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2537 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
2538 State->Flags.Pf = Soft386CalculateParity(Result);
2539 }
2540
2541 /* The result is discarded */
2542 return TRUE;
2543 }
2544
2545 SOFT386_OPCODE_HANDLER(Soft386OpcodeXchgByteModrm)
2546 {
2547 UCHAR FirstValue, SecondValue;
2548 SOFT386_MOD_REG_RM ModRegRm;
2549 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2550
2551 /* Make sure this is the right instruction */
2552 ASSERT(Opcode == 0x86);
2553
2554 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2555 {
2556 /* The ADSIZE prefix toggles the size */
2557 AddressSize = !AddressSize;
2558 }
2559 else if (State->PrefixFlags
2560 & ~(SOFT386_PREFIX_ADSIZE
2561 | SOFT386_PREFIX_SEG
2562 | SOFT386_PREFIX_LOCK))
2563 {
2564 /* Invalid prefix */
2565 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2566 return FALSE;
2567 }
2568
2569 /* Get the operands */
2570 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2571 {
2572 /* Exception occurred */
2573 return FALSE;
2574 }
2575
2576 if (!Soft386ReadModrmByteOperands(State,
2577 &ModRegRm,
2578 &FirstValue,
2579 &SecondValue))
2580 {
2581 /* Exception occurred */
2582 return FALSE;
2583 }
2584
2585 /* Write the value from the register to the R/M */
2586 if (!Soft386WriteModrmByteOperands(State,
2587 &ModRegRm,
2588 FALSE,
2589 FirstValue))
2590 {
2591 /* Exception occurred */
2592 return FALSE;
2593 }
2594
2595 /* Write the value from the R/M to the register */
2596 if (!Soft386WriteModrmByteOperands(State,
2597 &ModRegRm,
2598 TRUE,
2599 SecondValue))
2600 {
2601 /* Exception occurred */
2602 return FALSE;
2603 }
2604
2605 return TRUE;
2606 }
2607
2608 SOFT386_OPCODE_HANDLER(Soft386OpcodeXchgModrm)
2609 {
2610 SOFT386_MOD_REG_RM ModRegRm;
2611 BOOLEAN OperandSize, AddressSize;
2612
2613 /* Make sure this is the right instruction */
2614 ASSERT(Opcode == 0x87);
2615
2616 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2617
2618 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2619 {
2620 /* The ADSIZE prefix toggles the address size */
2621 AddressSize = !AddressSize;
2622 }
2623
2624 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2625 {
2626 /* The OPSIZE prefix toggles the operand size */
2627 OperandSize = !OperandSize;
2628 }
2629
2630 if (State->PrefixFlags
2631 & ~(SOFT386_PREFIX_ADSIZE
2632 | SOFT386_PREFIX_OPSIZE
2633 | SOFT386_PREFIX_SEG
2634 | SOFT386_PREFIX_LOCK))
2635 {
2636 /* Invalid prefix */
2637 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2638 return FALSE;
2639 }
2640
2641 /* Get the operands */
2642 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2643 {
2644 /* Exception occurred */
2645 return FALSE;
2646 }
2647
2648 /* Check the operand size */
2649 if (OperandSize)
2650 {
2651 ULONG FirstValue, SecondValue;
2652
2653 if (!Soft386ReadModrmDwordOperands(State,
2654 &ModRegRm,
2655 &FirstValue,
2656 &SecondValue))
2657 {
2658 /* Exception occurred */
2659 return FALSE;
2660 }
2661
2662 /* Write the value from the register to the R/M */
2663 if (!Soft386WriteModrmDwordOperands(State,
2664 &ModRegRm,
2665 FALSE,
2666 FirstValue))
2667 {
2668 /* Exception occurred */
2669 return FALSE;
2670 }
2671
2672 /* Write the value from the R/M to the register */
2673 if (!Soft386WriteModrmDwordOperands(State,
2674 &ModRegRm,
2675 TRUE,
2676 SecondValue))
2677 {
2678 /* Exception occurred */
2679 return FALSE;
2680 }
2681 }
2682 else
2683 {
2684 USHORT FirstValue, SecondValue;
2685
2686 if (!Soft386ReadModrmWordOperands(State,
2687 &ModRegRm,
2688 &FirstValue,
2689 &SecondValue))
2690 {
2691 /* Exception occurred */
2692 return FALSE;
2693 }
2694
2695 /* Write the value from the register to the R/M */
2696 if (!Soft386WriteModrmWordOperands(State,
2697 &ModRegRm,
2698 FALSE,
2699 FirstValue))
2700 {
2701 /* Exception occurred */
2702 return FALSE;
2703 }
2704
2705 /* Write the value from the R/M to the register */
2706 if (!Soft386WriteModrmWordOperands(State,
2707 &ModRegRm,
2708 TRUE,
2709 SecondValue))
2710 {
2711 /* Exception occurred */
2712 return FALSE;
2713 }
2714 }
2715
2716 /* The result is discarded */
2717 return TRUE;
2718 }
2719
2720 SOFT386_OPCODE_HANDLER(Soft386OpcodePushEs)
2721 {
2722 /* Call the internal API */
2723 return Soft386StackPush(State, State->SegmentRegs[SOFT386_REG_ES].Selector);
2724 }
2725
2726 SOFT386_OPCODE_HANDLER(Soft386OpcodePopEs)
2727 {
2728 ULONG NewSelector;
2729
2730 if (!Soft386StackPop(State, &NewSelector))
2731 {
2732 /* Exception occurred */
2733 return FALSE;
2734 }
2735
2736 /* Call the internal API */
2737 return Soft386LoadSegment(State, SOFT386_REG_ES, LOWORD(NewSelector));
2738 }
2739
2740 SOFT386_OPCODE_HANDLER(Soft386OpcodePushCs)
2741 {
2742 /* Call the internal API */
2743 return Soft386StackPush(State, State->SegmentRegs[SOFT386_REG_CS].Selector);
2744 }
2745
2746 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcByteModrm)
2747 {
2748 UCHAR FirstValue, SecondValue, Result;
2749 SOFT386_MOD_REG_RM ModRegRm;
2750 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2751
2752 /* Make sure this is the right instruction */
2753 ASSERT((Opcode & 0xFD) == 0x10);
2754
2755 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2756 {
2757 /* The ADSIZE prefix toggles the size */
2758 AddressSize = !AddressSize;
2759 }
2760 else if (State->PrefixFlags
2761 & ~(SOFT386_PREFIX_ADSIZE
2762 | SOFT386_PREFIX_SEG
2763 | SOFT386_PREFIX_LOCK))
2764 {
2765 /* Invalid prefix */
2766 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2767 return FALSE;
2768 }
2769
2770 /* Get the operands */
2771 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2772 {
2773 /* Exception occurred */
2774 return FALSE;
2775 }
2776
2777 if (!Soft386ReadModrmByteOperands(State,
2778 &ModRegRm,
2779 &FirstValue,
2780 &SecondValue))
2781 {
2782 /* Exception occurred */
2783 return FALSE;
2784 }
2785
2786 /* Calculate the result */
2787 Result = FirstValue + SecondValue + State->Flags.Cf;
2788
2789 /* Special exception for CF */
2790 State->Flags.Cf = State->Flags.Cf
2791 && ((FirstValue == 0xFF) || (SecondValue == 0xFF));
2792
2793 /* Update the flags */
2794 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
2795 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE))
2796 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
2797 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
2798 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2799 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
2800 State->Flags.Pf = Soft386CalculateParity(Result);
2801
2802 /* Write back the result */
2803 return Soft386WriteModrmByteOperands(State,
2804 &ModRegRm,
2805 Opcode & SOFT386_OPCODE_WRITE_REG,
2806 Result);
2807 }
2808
2809 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcModrm)
2810 {
2811 SOFT386_MOD_REG_RM ModRegRm;
2812 BOOLEAN OperandSize, AddressSize;
2813
2814 /* Make sure this is the right instruction */
2815 ASSERT((Opcode & 0xFD) == 0x11);
2816
2817 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2818
2819 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2820 {
2821 /* The ADSIZE prefix toggles the address size */
2822 AddressSize = !AddressSize;
2823 }
2824
2825 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2826 {
2827 /* The OPSIZE prefix toggles the operand size */
2828 OperandSize = !OperandSize;
2829 }
2830
2831 if (State->PrefixFlags
2832 & ~(SOFT386_PREFIX_ADSIZE
2833 | SOFT386_PREFIX_OPSIZE
2834 | SOFT386_PREFIX_SEG
2835 | SOFT386_PREFIX_LOCK))
2836 {
2837 /* Invalid prefix */
2838 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2839 return FALSE;
2840 }
2841
2842 /* Get the operands */
2843 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2844 {
2845 /* Exception occurred */
2846 return FALSE;
2847 }
2848
2849 /* Check the operand size */
2850 if (OperandSize)
2851 {
2852 ULONG FirstValue, SecondValue, Result;
2853
2854 if (!Soft386ReadModrmDwordOperands(State,
2855 &ModRegRm,
2856 &FirstValue,
2857 &SecondValue))
2858 {
2859 /* Exception occurred */
2860 return FALSE;
2861 }
2862
2863 /* Calculate the result */
2864 Result = FirstValue + SecondValue + State->Flags.Cf;
2865
2866 /* Special exception for CF */
2867 State->Flags.Cf = State->Flags.Cf
2868 && ((FirstValue == 0xFFFFFFFF) || (SecondValue == 0xFFFFFFFF));
2869
2870 /* Update the flags */
2871 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
2872 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG))
2873 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
2874 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
2875 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2876 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
2877 State->Flags.Pf = Soft386CalculateParity(Result);
2878
2879 /* Write back the result */
2880 return Soft386WriteModrmDwordOperands(State,
2881 &ModRegRm,
2882 Opcode & SOFT386_OPCODE_WRITE_REG,
2883 Result);
2884 }
2885 else
2886 {
2887 USHORT FirstValue, SecondValue, Result;
2888
2889 if (!Soft386ReadModrmWordOperands(State,
2890 &ModRegRm,
2891 &FirstValue,
2892 &SecondValue))
2893 {
2894 /* Exception occurred */
2895 return FALSE;
2896 }
2897
2898 /* Calculate the result */
2899 Result = FirstValue + SecondValue + State->Flags.Cf;
2900
2901 /* Special exception for CF */
2902 State->Flags.Cf = State->Flags.Cf
2903 && ((FirstValue == 0xFFFF) || (SecondValue == 0xFFFF));
2904
2905 /* Update the flags */
2906 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
2907 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD))
2908 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
2909 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
2910 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2911 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
2912 State->Flags.Pf = Soft386CalculateParity(Result);
2913
2914 /* Write back the result */
2915 return Soft386WriteModrmWordOperands(State,
2916 &ModRegRm,
2917 Opcode & SOFT386_OPCODE_WRITE_REG,
2918 Result);
2919 }
2920
2921 }
2922
2923 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcAl)
2924 {
2925 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
2926 UCHAR SecondValue, Result;
2927
2928 /* Make sure this is the right instruction */
2929 ASSERT(Opcode == 0x14);
2930
2931 if (State->PrefixFlags)
2932 {
2933 /* This opcode doesn't take any prefixes */
2934 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2935 return FALSE;
2936 }
2937
2938 if (!Soft386FetchByte(State, &SecondValue))
2939 {
2940 /* Exception occurred */
2941 return FALSE;
2942 }
2943
2944 /* Calculate the result */
2945 Result = FirstValue + SecondValue + State->Flags.Cf;
2946
2947 /* Special exception for CF */
2948 State->Flags.Cf = State->Flags.Cf &&
2949 ((FirstValue == 0xFF) || (SecondValue == 0xFF));
2950
2951 /* Update the flags */
2952 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
2953 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE))
2954 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
2955 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
2956 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2957 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
2958 State->Flags.Pf = Soft386CalculateParity(Result);
2959
2960 /* Write back the result */
2961 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
2962
2963 return TRUE;
2964 }
2965
2966 SOFT386_OPCODE_HANDLER(Soft386OpcodeAdcEax)
2967 {
2968 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
2969
2970 /* Make sure this is the right instruction */
2971 ASSERT(Opcode == 0x15);
2972
2973 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
2974 {
2975 /* Invalid prefix */
2976 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2977 return FALSE;
2978 }
2979
2980 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2981 {
2982 /* The OPSIZE prefix toggles the size */
2983 Size = !Size;
2984 }
2985
2986 if (Size)
2987 {
2988 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
2989 ULONG SecondValue, Result;
2990
2991 if (!Soft386FetchDword(State, &SecondValue))
2992 {
2993 /* Exception occurred */
2994 return FALSE;
2995 }
2996
2997 /* Calculate the result */
2998 Result = FirstValue + SecondValue + State->Flags.Cf;
2999
3000 /* Special exception for CF */
3001 State->Flags.Cf = State->Flags.Cf &&
3002 ((FirstValue == 0xFFFFFFFF) || (SecondValue == 0xFFFFFFFF));
3003
3004 /* Update the flags */
3005 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
3006 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG))
3007 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
3008 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
3009 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3010 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
3011 State->Flags.Pf = Soft386CalculateParity(Result);
3012
3013 /* Write back the result */
3014 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
3015 }
3016 else
3017 {
3018 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
3019 USHORT SecondValue, Result;
3020
3021 if (!Soft386FetchWord(State, &SecondValue))
3022 {
3023 /* Exception occurred */
3024 return FALSE;
3025 }
3026
3027 /* Calculate the result */
3028 Result = FirstValue + SecondValue + State->Flags.Cf;
3029
3030 /* Special exception for CF */
3031 State->Flags.Cf = State->Flags.Cf &&
3032 ((FirstValue == 0xFFFF) || (SecondValue == 0xFFFF));
3033
3034 /* Update the flags */
3035 State->Flags.Cf = State->Flags.Cf || ((Result < FirstValue) && (Result < SecondValue));
3036 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD))
3037 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
3038 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
3039 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3040 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
3041 State->Flags.Pf = Soft386CalculateParity(Result);
3042
3043 /* Write back the result */
3044 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
3045 }
3046
3047 return TRUE;
3048 }
3049
3050 SOFT386_OPCODE_HANDLER(Soft386OpcodePushSs)
3051 {
3052 /* Call the internal API */
3053 return Soft386StackPush(State, State->SegmentRegs[SOFT386_REG_SS].Selector);
3054 }
3055
3056 SOFT386_OPCODE_HANDLER(Soft386OpcodePopSs)
3057 {
3058 ULONG NewSelector;
3059
3060 if (!Soft386StackPop(State, &NewSelector))
3061 {
3062 /* Exception occurred */
3063 return FALSE;
3064 }
3065
3066 /* Call the internal API */
3067 return Soft386LoadSegment(State, SOFT386_REG_SS, LOWORD(NewSelector));
3068 }
3069
3070 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbByteModrm)
3071 {
3072 // TODO: NOT IMPLEMENTED
3073 UNIMPLEMENTED;
3074
3075 return FALSE;
3076 }
3077
3078 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbModrm)
3079 {
3080 // TODO: NOT IMPLEMENTED
3081 UNIMPLEMENTED;
3082
3083 return FALSE;
3084 }
3085
3086 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbAl)
3087 {
3088 // TODO: NOT IMPLEMENTED
3089 UNIMPLEMENTED;
3090
3091 return FALSE;
3092 }
3093
3094 SOFT386_OPCODE_HANDLER(Soft386OpcodeSbbEax)
3095 {
3096 // TODO: NOT IMPLEMENTED
3097 UNIMPLEMENTED;
3098
3099 return FALSE;
3100 }
3101
3102 SOFT386_OPCODE_HANDLER(Soft386OpcodePushDs)
3103 {
3104 /* Call the internal API */
3105 return Soft386StackPush(State, State->SegmentRegs[SOFT386_REG_DS].Selector);
3106 }
3107
3108 SOFT386_OPCODE_HANDLER(Soft386OpcodePopDs)
3109 {
3110 ULONG NewSelector;
3111
3112 if (!Soft386StackPop(State, &NewSelector))
3113 {
3114 /* Exception occurred */
3115 return FALSE;
3116 }
3117
3118 /* Call the internal API */
3119 return Soft386LoadSegment(State, SOFT386_REG_DS, LOWORD(NewSelector));
3120 }
3121
3122 SOFT386_OPCODE_HANDLER(Soft386OpcodeDaa)
3123 {
3124 UCHAR Value = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
3125 BOOLEAN Carry = State->Flags.Cf;
3126
3127 /* Clear the carry flag */
3128 State->Flags.Cf = FALSE;
3129
3130 /* Check if the first BCD digit is invalid or there was a carry from it */
3131 if (((Value & 0x0F) > 9) || State->Flags.Af)
3132 {
3133 /* Correct it */
3134 State->GeneralRegs[SOFT386_REG_EAX].LowByte += 0x06;
3135 if (State->GeneralRegs[SOFT386_REG_EAX].LowByte < 0x06)
3136 {
3137 /* A carry occurred */
3138 State->Flags.Cf = TRUE;
3139 }
3140
3141 /* Set the adjust flag */
3142 State->Flags.Af = TRUE;
3143 }
3144
3145 /* Check if the second BCD digit is invalid or there was a carry from it */
3146 if ((Value > 0x99) || Carry)
3147 {
3148 /* Correct it */
3149 State->GeneralRegs[SOFT386_REG_EAX].LowByte += 0x60;
3150
3151 /* There was a carry */
3152 State->Flags.Cf = TRUE;
3153 }
3154
3155 return TRUE;
3156 }
3157
3158 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubByteModrm)
3159 {
3160 UCHAR FirstValue, SecondValue, Result;
3161 SOFT386_MOD_REG_RM ModRegRm;
3162 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
3163
3164 /* Make sure this is the right instruction */
3165 ASSERT((Opcode & 0xED) == 0x28);
3166
3167 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
3168 {
3169 /* The ADSIZE prefix toggles the size */
3170 AddressSize = !AddressSize;
3171 }
3172 else if (State->PrefixFlags
3173 & ~(SOFT386_PREFIX_ADSIZE
3174 | SOFT386_PREFIX_SEG
3175 | SOFT386_PREFIX_LOCK))
3176 {
3177 /* Invalid prefix */
3178 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3179 return FALSE;
3180 }
3181
3182 /* Get the operands */
3183 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
3184 {
3185 /* Exception occurred */
3186 return FALSE;
3187 }
3188
3189 if (!Soft386ReadModrmByteOperands(State,
3190 &ModRegRm,
3191 &FirstValue,
3192 &SecondValue))
3193 {
3194 /* Exception occurred */
3195 return FALSE;
3196 }
3197
3198 /* Check if this is the instruction that writes to R/M */
3199 if (!(Opcode & SOFT386_OPCODE_WRITE_REG))
3200 {
3201 /* Swap the order */
3202 FirstValue ^= SecondValue;
3203 SecondValue ^= FirstValue;
3204 FirstValue ^= SecondValue;
3205 }
3206
3207 /* Calculate the result */
3208 Result = FirstValue - SecondValue;
3209
3210 /* Update the flags */
3211 State->Flags.Cf = FirstValue < SecondValue;
3212 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) != (SecondValue & SIGN_FLAG_BYTE))
3213 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
3214 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
3215 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3216 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
3217 State->Flags.Pf = Soft386CalculateParity(Result);
3218
3219 /* Check if this is not a CMP */
3220 if (!(Opcode & 0x10))
3221 {
3222 /* Write back the result */
3223 return Soft386WriteModrmByteOperands(State,
3224 &ModRegRm,
3225 Opcode & SOFT386_OPCODE_WRITE_REG,
3226 Result);
3227 }
3228 else
3229 {
3230 /* Discard the result */
3231 return TRUE;
3232 }
3233 }
3234
3235 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubModrm)
3236 {
3237 SOFT386_MOD_REG_RM ModRegRm;
3238 BOOLEAN OperandSize, AddressSize;
3239
3240 /* Make sure this is the right instruction */
3241 ASSERT((Opcode & 0xED) == 0x29);
3242
3243 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
3244
3245 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
3246 {
3247 /* The ADSIZE prefix toggles the address size */
3248 AddressSize = !AddressSize;
3249 }
3250
3251 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
3252 {
3253 /* The OPSIZE prefix toggles the operand size */
3254 OperandSize = !OperandSize;
3255 }
3256
3257 if (State->PrefixFlags
3258 & ~(SOFT386_PREFIX_ADSIZE
3259 | SOFT386_PREFIX_OPSIZE
3260 | SOFT386_PREFIX_SEG
3261 | SOFT386_PREFIX_LOCK))
3262 {
3263 /* Invalid prefix */
3264 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3265 return FALSE;
3266 }
3267
3268 /* Get the operands */
3269 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
3270 {
3271 /* Exception occurred */
3272 return FALSE;
3273 }
3274
3275 /* Check the operand size */
3276 if (OperandSize)
3277 {
3278 ULONG FirstValue, SecondValue, Result;
3279
3280 if (!Soft386ReadModrmDwordOperands(State,
3281 &ModRegRm,
3282 &FirstValue,
3283 &SecondValue))
3284 {
3285 /* Exception occurred */
3286 return FALSE;
3287 }
3288
3289 /* Check if this is the instruction that writes to R/M */
3290 if (!(Opcode & SOFT386_OPCODE_WRITE_REG))
3291 {
3292 /* Swap the order */
3293 FirstValue ^= SecondValue;
3294 SecondValue ^= FirstValue;
3295 FirstValue ^= SecondValue;
3296 }
3297
3298 /* Calculate the result */
3299 Result = FirstValue - SecondValue;
3300
3301 /* Update the flags */
3302 State->Flags.Cf = FirstValue < SecondValue;
3303 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) != (SecondValue & SIGN_FLAG_LONG))
3304 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
3305 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
3306 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3307 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
3308 State->Flags.Pf = Soft386CalculateParity(Result);
3309
3310 /* Check if this is not a CMP */
3311 if (!(Opcode & 0x10))
3312 {
3313 /* Write back the result */
3314 return Soft386WriteModrmDwordOperands(State,
3315 &ModRegRm,
3316 Opcode & SOFT386_OPCODE_WRITE_REG,
3317 Result);
3318 }
3319 else
3320 {
3321 /* Discard the result */
3322 return TRUE;
3323 }
3324 }
3325 else
3326 {
3327 USHORT FirstValue, SecondValue, Result;
3328
3329 if (!Soft386ReadModrmWordOperands(State,
3330 &ModRegRm,
3331 &FirstValue,
3332 &SecondValue))
3333 {
3334 /* Exception occurred */
3335 return FALSE;
3336 }
3337
3338 /* Check if this is the instruction that writes to R/M */
3339 if (!(Opcode & SOFT386_OPCODE_WRITE_REG))
3340 {
3341 /* Swap the order */
3342 FirstValue ^= SecondValue;
3343 SecondValue ^= FirstValue;
3344 FirstValue ^= SecondValue;
3345 }
3346
3347 /* Calculate the result */
3348 Result = FirstValue - SecondValue;
3349
3350 /* Update the flags */
3351 State->Flags.Cf = FirstValue < SecondValue;
3352 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) != (SecondValue & SIGN_FLAG_WORD))
3353 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
3354 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
3355 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3356 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
3357 State->Flags.Pf = Soft386CalculateParity(Result);
3358
3359 /* Check if this is not a CMP */
3360 if (!(Opcode & 0x10))
3361 {
3362 /* Write back the result */
3363 return Soft386WriteModrmWordOperands(State,
3364 &ModRegRm,
3365 Opcode & SOFT386_OPCODE_WRITE_REG,
3366 Result);
3367 }
3368 else
3369 {
3370 /* Discard the result */
3371 return TRUE;
3372 }
3373 }
3374
3375 }
3376
3377 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubAl)
3378 {
3379 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
3380 UCHAR SecondValue, Result;
3381
3382 /* Make sure this is the right instruction */
3383 ASSERT((Opcode & 0xEF) == 0x2C);
3384
3385 if (State->PrefixFlags)
3386 {
3387 /* This opcode doesn't take any prefixes */
3388 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3389 return FALSE;
3390 }
3391
3392 if (!Soft386FetchByte(State, &SecondValue))
3393 {
3394 /* Exception occurred */
3395 return FALSE;
3396 }
3397
3398 /* Calculate the result */
3399 Result = FirstValue - SecondValue;
3400
3401 /* Update the flags */
3402 State->Flags.Cf = FirstValue < SecondValue;
3403 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) != (SecondValue & SIGN_FLAG_BYTE))
3404 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
3405 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
3406 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3407 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
3408 State->Flags.Pf = Soft386CalculateParity(Result);
3409
3410 /* Check if this is not a CMP */
3411 if (!(Opcode & 0x10))
3412 {
3413 /* Write back the result */
3414 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
3415 }
3416
3417 return TRUE;
3418 }
3419
3420 SOFT386_OPCODE_HANDLER(Soft386OpcodeCmpSubEax)
3421 {
3422 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
3423
3424 /* Make sure this is the right instruction */
3425 ASSERT((Opcode & 0xEF) == 0x2D);
3426
3427 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
3428 {
3429 /* Invalid prefix */
3430 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3431 return FALSE;
3432 }
3433
3434 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
3435 {
3436 /* The OPSIZE prefix toggles the size */
3437 Size = !Size;
3438 }
3439
3440 if (Size)
3441 {
3442 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
3443 ULONG SecondValue, Result;
3444
3445 if (!Soft386FetchDword(State, &SecondValue))
3446 {
3447 /* Exception occurred */
3448 return FALSE;
3449 }
3450
3451 /* Calculate the result */
3452 Result = FirstValue - SecondValue;
3453
3454 /* Update the flags */
3455 State->Flags.Cf = FirstValue < SecondValue;
3456 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) != (SecondValue & SIGN_FLAG_LONG))
3457 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
3458 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
3459 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3460 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
3461 State->Flags.Pf = Soft386CalculateParity(Result);
3462
3463 /* Check if this is not a CMP */
3464 if (!(Opcode & 0x10))
3465 {
3466 /* Write back the result */
3467 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
3468 }
3469 }
3470 else
3471 {
3472 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
3473 USHORT SecondValue, Result;
3474
3475 if (!Soft386FetchWord(State, &SecondValue))
3476 {
3477 /* Exception occurred */
3478 return FALSE;
3479 }
3480
3481 /* Calculate the result */
3482 Result = FirstValue - SecondValue;
3483
3484 /* Update the flags */
3485 State->Flags.Cf = FirstValue < SecondValue;
3486 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) != (SecondValue & SIGN_FLAG_WORD))
3487 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
3488 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
3489 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
3490 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
3491 State->Flags.Pf = Soft386CalculateParity(Result);
3492
3493 /* Write back the result */
3494 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
3495 }
3496
3497 return TRUE;
3498 }
3499
3500 SOFT386_OPCODE_HANDLER(Soft386OpcodeDas)
3501 {
3502 UCHAR Value = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
3503 BOOLEAN Carry = State->Flags.Cf;
3504
3505 /* Clear the carry flag */
3506 State->Flags.Cf = FALSE;
3507
3508 /* Check if the first BCD digit is invalid or there was a borrow */
3509 if (((Value & 0x0F) > 9) || State->Flags.Af)
3510 {
3511 /* Correct it */
3512 State->GeneralRegs[SOFT386_REG_EAX].LowByte -= 0x06;
3513 if (State->GeneralRegs[SOFT386_REG_EAX].LowByte > 0xFB)
3514 {
3515 /* A borrow occurred */
3516 State->Flags.Cf = TRUE;
3517 }
3518
3519 /* Set the adjust flag */
3520 State->Flags.Af = TRUE;
3521 }
3522
3523 /* Check if the second BCD digit is invalid or there was a borrow */
3524 if ((Value > 0x99) || Carry)
3525 {
3526 /* Correct it */
3527 State->GeneralRegs[SOFT386_REG_EAX].LowByte -= 0x60;
3528
3529 /* There was a borrow */
3530 State->Flags.Cf = TRUE;
3531 }
3532
3533 return TRUE;
3534 }
3535
3536 SOFT386_OPCODE_HANDLER(Soft386OpcodeAaa)
3537 {
3538 UCHAR Value = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
3539
3540 /*
3541 * Check if the value in AL is not a valid BCD digit,
3542 * or there was a carry from the lowest 4 bits of AL
3543 */
3544 if (((Value & 0x0F) > 9) || State->Flags.Af)
3545 {
3546 /* Correct it */
3547 State->GeneralRegs[SOFT386_REG_EAX].LowByte += 0x06;
3548 State->GeneralRegs[SOFT386_REG_EAX].HighByte++;
3549
3550 /* Set CF and AF */
3551 State->Flags.Cf = State->Flags.Af = TRUE;
3552 }
3553 else
3554 {
3555 /* Clear CF and AF */
3556 State->Flags.Cf = State->Flags.Af = FALSE;
3557 }
3558
3559 /* Keep only the lowest 4 bits of AL */
3560 State->GeneralRegs[SOFT386_REG_EAX].LowByte &= 0x0F;
3561
3562 return TRUE;
3563 }
3564
3565 SOFT386_OPCODE_HANDLER(Soft386OpcodeAas)
3566 {
3567 UCHAR Value = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
3568
3569 /*
3570 * Check if the value in AL is not a valid BCD digit,
3571 * or there was a borrow from the lowest 4 bits of AL
3572 */
3573 if (((Value & 0x0F) > 9) || State->Flags.Af)
3574 {
3575 /* Correct it */
3576 State->GeneralRegs[SOFT386_REG_EAX].LowByte -= 0x06;
3577 State->GeneralRegs[SOFT386_REG_EAX].HighByte--;
3578
3579 /* Set CF and AF */
3580 State->Flags.Cf = State->Flags.Af = TRUE;
3581 }
3582 else
3583 {
3584 /* Clear CF and AF */
3585 State->Flags.Cf = State->Flags.Af = FALSE;
3586 }
3587
3588 /* Keep only the lowest 4 bits of AL */
3589 State->GeneralRegs[SOFT386_REG_EAX].LowByte &= 0x0F;
3590
3591 return TRUE;
3592 }
3593
3594 SOFT386_OPCODE_HANDLER(Soft386OpcodePushAll)
3595 {
3596 INT i;
3597 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
3598 SOFT386_REG SavedEsp = State->GeneralRegs[SOFT386_REG_ESP];
3599
3600 /* Make sure this is the right instruction */
3601 ASSERT(Opcode == 0x60);
3602
3603 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
3604 {
3605 /* The OPSIZE prefix toggles the size */
3606 Size = !Size;
3607 }
3608 else
3609 {
3610 /* Invalid prefix */
3611 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3612 return FALSE;
3613 }
3614
3615 /* Push all the registers in order */
3616 for (i = 0; i < SOFT386_NUM_GEN_REGS; i++)
3617 {
3618 if (i == SOFT386_REG_ESP)
3619 {
3620 /* Use the saved ESP instead */
3621 if (!Soft386StackPush(State, Size ? SavedEsp.Long : SavedEsp.LowWord))
3622 {
3623 /* Exception occurred */
3624 return FALSE;
3625 }
3626 }
3627 else
3628 {
3629 /* Push the register */
3630 if (!Soft386StackPush(State, Size ? State->GeneralRegs[i].Long
3631 : State->GeneralRegs[i].LowWord))
3632 {
3633 /* Exception occurred */
3634 return FALSE;
3635 }
3636 }
3637 }
3638
3639 return TRUE;
3640 }
3641
3642 SOFT386_OPCODE_HANDLER(Soft386OpcodePopAll)
3643 {
3644 INT i;
3645 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
3646 ULONG Value;
3647
3648 /* Make sure this is the right instruction */
3649 ASSERT(Opcode == 0x61);
3650
3651 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
3652 {
3653 /* The OPSIZE prefix toggles the size */
3654 Size = !Size;
3655 }
3656 else
3657 {
3658 /* Invalid prefix */
3659 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3660 return FALSE;
3661 }
3662
3663 /* Pop all the registers in reverse order */
3664 for (i = SOFT386_NUM_GEN_REGS - 1; i >= 0; i--)
3665 {
3666 /* Pop the value */
3667 if (!Soft386StackPop(State, &Value))
3668 {
3669 /* Exception occurred */
3670 return FALSE;
3671 }
3672
3673 /* Don't modify ESP */
3674 if (i != SOFT386_REG_ESP)
3675 {
3676 if (Size) State->GeneralRegs[i].Long = Value;
3677 else State->GeneralRegs[i].LowWord = LOWORD(Value);
3678 }
3679 }
3680
3681 return TRUE;
3682 }
3683
3684 SOFT386_OPCODE_HANDLER(Soft386OpcodeBound)
3685 {
3686 // TODO: NOT IMPLEMENTED
3687 UNIMPLEMENTED;
3688
3689 return FALSE;
3690 }
3691
3692 SOFT386_OPCODE_HANDLER(Soft386OpcodeArpl)
3693 {
3694 USHORT FirstValue, SecondValue;
3695 SOFT386_MOD_REG_RM ModRegRm;
3696 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
3697
3698 if (!(State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE)
3699 || State->Flags.Vm
3700 || (State->PrefixFlags & SOFT386_PREFIX_LOCK))
3701 {
3702 /* Cannot be used in real mode or with a LOCK prefix */
3703 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3704 return FALSE;
3705 }
3706
3707 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
3708 {
3709 /* The ADSIZE prefix toggles the size */
3710 AddressSize = !AddressSize;
3711 }
3712
3713 /* Get the operands */
3714 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
3715 {
3716 /* Exception occurred */
3717 return FALSE;
3718 }
3719
3720 /* Read the operands */
3721 if (!Soft386ReadModrmWordOperands(State,
3722 &ModRegRm,
3723 &FirstValue,
3724 &SecondValue))
3725 {
3726 /* Exception occurred */
3727 return FALSE;
3728 }
3729
3730 /* Check if the RPL needs adjusting */
3731 if ((SecondValue & 3) < (FirstValue & 3))
3732 {
3733 /* Adjust the RPL */
3734 SecondValue &= ~3;
3735 SecondValue |= FirstValue & 3;
3736
3737 /* Set ZF */
3738 State->Flags.Zf = TRUE;
3739
3740 /* Write back the result */
3741 return Soft386WriteModrmWordOperands(State, &ModRegRm, FALSE, SecondValue);
3742 }
3743 else
3744 {
3745 /* Clear ZF */
3746 State->Flags.Zf = FALSE;
3747 return TRUE;
3748 }
3749 }
3750
3751 SOFT386_OPCODE_HANDLER(Soft386OpcodePushImm)
3752 {
3753 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
3754
3755 /* Make sure this is the right instruction */
3756 ASSERT(Opcode == 0x68);
3757
3758 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
3759 {
3760 /* The OPSIZE prefix toggles the size */
3761 Size = !Size;
3762 }
3763 else
3764 {
3765 /* Invalid prefix */
3766 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3767 return FALSE;
3768 }
3769
3770 if (Size)
3771 {
3772 ULONG Data;
3773
3774 if (!Soft386FetchDword(State, &Data))
3775 {
3776 /* Exception occurred */
3777 return FALSE;
3778 }
3779
3780 /* Call the internal API */
3781 return Soft386StackPush(State, Data);
3782 }
3783 else
3784 {
3785 USHORT Data;
3786
3787 if (!Soft386FetchWord(State, &Data))
3788 {
3789 /* Exception occurred */
3790 return FALSE;
3791 }
3792
3793 /* Call the internal API */
3794 return Soft386StackPush(State, Data);
3795 }
3796 }
3797
3798 SOFT386_OPCODE_HANDLER(Soft386OpcodeImulModrmImm)
3799 {
3800 // TODO: NOT IMPLEMENTED
3801 UNIMPLEMENTED;
3802
3803 return FALSE;
3804 }
3805
3806 SOFT386_OPCODE_HANDLER(Soft386OpcodePushByteImm)
3807 {
3808 UCHAR Data;
3809
3810 /* Make sure this is the right instruction */
3811 ASSERT(Opcode == 0x6A);
3812
3813 if (!Soft386FetchByte(State, &Data))
3814 {
3815 /* Exception occurred */
3816 return FALSE;
3817 }
3818
3819 /* Call the internal API */
3820 return Soft386StackPush(State, Data);
3821 }
3822
3823 SOFT386_OPCODE_HANDLER(Soft386OpcodeImulModrmByteImm)
3824 {
3825 // TODO: NOT IMPLEMENTED
3826 UNIMPLEMENTED;
3827
3828 return FALSE;
3829 }
3830
3831 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovByteModrm)
3832 {
3833 UCHAR FirstValue, SecondValue, Result;
3834 SOFT386_MOD_REG_RM ModRegRm;
3835 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
3836
3837 /* Make sure this is the right instruction */
3838 ASSERT((Opcode & 0xFD) == 0x88);
3839
3840 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
3841 {
3842 /* The ADSIZE prefix toggles the size */
3843 AddressSize = !AddressSize;
3844 }
3845 else if (State->PrefixFlags
3846 & ~(SOFT386_PREFIX_ADSIZE
3847 | SOFT386_PREFIX_SEG
3848 | SOFT386_PREFIX_LOCK))
3849 {
3850 /* Invalid prefix */
3851 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3852 return FALSE;
3853 }
3854
3855 /* Get the operands */
3856 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
3857 {
3858 /* Exception occurred */
3859 return FALSE;
3860 }
3861
3862 if (!Soft386ReadModrmByteOperands(State,
3863 &ModRegRm,
3864 &FirstValue,
3865 &SecondValue))
3866 {
3867 /* Exception occurred */
3868 return FALSE;
3869 }
3870
3871 if (Opcode & SOFT386_OPCODE_WRITE_REG) Result = SecondValue;
3872 else Result = FirstValue;
3873
3874 /* Write back the result */
3875 return Soft386WriteModrmByteOperands(State,
3876 &ModRegRm,
3877 Opcode & SOFT386_OPCODE_WRITE_REG,
3878 Result);
3879
3880 }
3881
3882 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovModrm)
3883 {
3884 SOFT386_MOD_REG_RM ModRegRm;
3885 BOOLEAN OperandSize, AddressSize;
3886
3887 /* Make sure this is the right instruction */
3888 ASSERT((Opcode & 0xFD) == 0x89);
3889
3890 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
3891
3892 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
3893 {
3894 /* The ADSIZE prefix toggles the address size */
3895 AddressSize = !AddressSize;
3896 }
3897
3898 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
3899 {
3900 /* The OPSIZE prefix toggles the operand size */
3901 OperandSize = !OperandSize;
3902 }
3903
3904 if (State->PrefixFlags
3905 & ~(SOFT386_PREFIX_ADSIZE
3906 | SOFT386_PREFIX_OPSIZE
3907 | SOFT386_PREFIX_SEG
3908 | SOFT386_PREFIX_LOCK))
3909 {
3910 /* Invalid prefix */
3911 Soft386Exception(State, SOFT386_EXCEPTION_UD);
3912 return FALSE;
3913 }
3914
3915 /* Get the operands */
3916 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
3917 {
3918 /* Exception occurred */
3919 return FALSE;
3920 }
3921
3922 /* Check the operand size */
3923 if (OperandSize)
3924 {
3925 ULONG FirstValue, SecondValue, Result;
3926
3927 if (!Soft386ReadModrmDwordOperands(State,
3928 &ModRegRm,
3929 &FirstValue,
3930 &SecondValue))
3931 {
3932 /* Exception occurred */
3933 return FALSE;
3934 }
3935
3936 if (Opcode & SOFT386_OPCODE_WRITE_REG) Result = SecondValue;
3937 else Result = FirstValue;
3938
3939 /* Write back the result */
3940 return Soft386WriteModrmDwordOperands(State,
3941 &ModRegRm,
3942 Opcode & SOFT386_OPCODE_WRITE_REG,
3943 Result);
3944 }
3945 else
3946 {
3947 USHORT FirstValue, SecondValue, Result;
3948
3949 if (!Soft386ReadModrmWordOperands(State,
3950 &ModRegRm,
3951 &FirstValue,
3952 &SecondValue))
3953 {
3954 /* Exception occurred */
3955 return FALSE;
3956 }
3957
3958 if (Opcode & SOFT386_OPCODE_WRITE_REG) Result = SecondValue;
3959 else Result = FirstValue;
3960
3961 /* Write back the result */
3962 return Soft386WriteModrmWordOperands(State,
3963 &ModRegRm,
3964 Opcode & SOFT386_OPCODE_WRITE_REG,
3965 Result);
3966 }
3967 }
3968
3969 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovStoreSeg)
3970 {
3971 // TODO: NOT IMPLEMENTED
3972 UNIMPLEMENTED;
3973
3974 return FALSE;
3975 }
3976
3977 SOFT386_OPCODE_HANDLER(Soft386OpcodeLea)
3978 {
3979 SOFT386_MOD_REG_RM ModRegRm;
3980 BOOLEAN OperandSize, AddressSize;
3981
3982 /* Make sure this is the right instruction */
3983 ASSERT(Opcode == 0x8D);
3984
3985 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
3986
3987 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
3988 {
3989 /* The ADSIZE prefix toggles the address size */
3990 AddressSize = !AddressSize;
3991 }
3992
3993 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
3994 {
3995 /* The OPSIZE prefix toggles the operand size */
3996 OperandSize = !OperandSize;
3997 }
3998
3999 /* Get the operands */
4000 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
4001 {
4002 /* Exception occurred */
4003 return FALSE;
4004 }
4005
4006 /* The second operand must be memory */
4007 if (!ModRegRm.Memory)
4008 {
4009 /* Invalid */
4010 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4011 return FALSE;
4012 }
4013
4014 /* Write the address to the register */
4015 if (OperandSize)
4016 {
4017 return Soft386WriteModrmDwordOperands(State,
4018 &ModRegRm,
4019 TRUE,
4020 ModRegRm.MemoryAddress);
4021 }
4022 else
4023 {
4024 return Soft386WriteModrmWordOperands(State,
4025 &ModRegRm,
4026 TRUE,
4027 ModRegRm.MemoryAddress);
4028
4029 }
4030 }
4031
4032 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovLoadSeg)
4033 {
4034 // TODO: NOT IMPLEMENTED
4035 UNIMPLEMENTED;
4036
4037 return FALSE;
4038 }
4039
4040 SOFT386_OPCODE_HANDLER(Soft386OpcodeCwde)
4041 {
4042 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4043
4044 /* Make sure this is the right instruction */
4045 ASSERT(Opcode == 0x98);
4046
4047 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
4048 {
4049 /* The OPSIZE prefix toggles the size */
4050 Size = !Size;
4051 }
4052 else if (State->PrefixFlags != 0)
4053 {
4054 /* Invalid prefix */
4055 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4056 return FALSE;
4057 }
4058
4059 if (Size)
4060 {
4061 /* Sign extend AX to EAX */
4062 State->GeneralRegs[SOFT386_REG_EAX].Long = MAKELONG
4063 (
4064 State->GeneralRegs[SOFT386_REG_EAX].LowWord,
4065 (State->GeneralRegs[SOFT386_REG_EAX].LowWord & SIGN_FLAG_WORD)
4066 ? 0xFFFF : 0x0000
4067 );
4068 }
4069 else
4070 {
4071 /* Sign extend AL to AX */
4072 State->GeneralRegs[SOFT386_REG_EAX].HighByte =
4073 (State->GeneralRegs[SOFT386_REG_EAX].LowByte & SIGN_FLAG_BYTE)
4074 ? 0xFF : 0x00;
4075 }
4076
4077 return TRUE;
4078 }
4079
4080 SOFT386_OPCODE_HANDLER(Soft386OpcodeCdq)
4081 {
4082 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4083
4084 /* Make sure this is the right instruction */
4085 ASSERT(Opcode == 0x99);
4086
4087 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
4088 {
4089 /* The OPSIZE prefix toggles the size */
4090 Size = !Size;
4091 }
4092 else if (State->PrefixFlags != 0)
4093 {
4094 /* Invalid prefix */
4095 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4096 return FALSE;
4097 }
4098
4099 if (Size)
4100 {
4101 /* Sign extend EAX to EDX:EAX */
4102 State->GeneralRegs[SOFT386_REG_EDX].Long =
4103 (State->GeneralRegs[SOFT386_REG_EAX].Long & SIGN_FLAG_LONG)
4104 ? 0xFFFFFFFF : 0x00000000;
4105 }
4106 else
4107 {
4108 /* Sign extend AX to DX:AX */
4109 State->GeneralRegs[SOFT386_REG_EDX].LowWord =
4110 (State->GeneralRegs[SOFT386_REG_EAX].LowWord & SIGN_FLAG_WORD)
4111 ? 0xFFFF : 0x0000;
4112 }
4113
4114 return TRUE;
4115 }
4116
4117 SOFT386_OPCODE_HANDLER(Soft386OpcodeCallAbs)
4118 {
4119 // TODO: NOT IMPLEMENTED
4120 UNIMPLEMENTED;
4121
4122 return FALSE;
4123 }
4124
4125 SOFT386_OPCODE_HANDLER(Soft386OpcodeWait)
4126 {
4127 // TODO: NOT IMPLEMENTED
4128 UNIMPLEMENTED;
4129
4130 return FALSE;
4131 }
4132
4133 SOFT386_OPCODE_HANDLER(Soft386OpcodePushFlags)
4134 {
4135 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4136
4137 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
4138 {
4139 /* Invalid prefix */
4140 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4141 return FALSE;
4142 }
4143
4144 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
4145 {
4146 /* This OPSIZE prefix toggles the size */
4147 Size = !Size;
4148 }
4149
4150 /* Check for VM86 mode when IOPL is not 3 */
4151 if (State->Flags.Vm && (State->Flags.Iopl != 3))
4152 {
4153 /* Call the VM86 monitor */
4154 Soft386ExceptionWithErrorCode(State, SOFT386_EXCEPTION_GP, 0);
4155 return FALSE;
4156 }
4157
4158 /* Push the flags */
4159 if (Size) return Soft386StackPush(State, State->Flags.Long);
4160 else return Soft386StackPush(State, LOWORD(State->Flags.Long));
4161 }
4162
4163 SOFT386_OPCODE_HANDLER(Soft386OpcodePopFlags)
4164 {
4165 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4166 INT Cpl = Soft386GetCurrentPrivLevel(State);
4167 ULONG NewFlags;
4168
4169 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
4170 {
4171 /* Invalid prefix */
4172 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4173 return FALSE;
4174 }
4175
4176 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
4177 {
4178 /* This OPSIZE prefix toggles the size */
4179 Size = !Size;
4180 }
4181
4182 /* Pop the new flags */
4183 if (!Soft386StackPop(State, &NewFlags))
4184 {
4185 /* Exception occurred */
4186 return FALSE;
4187 }
4188
4189 if (!State->Flags.Vm)
4190 {
4191 /* Check the current privilege level */
4192 if (Cpl == 0)
4193 {
4194 /* Supervisor */
4195
4196 /* Set the flags */
4197 if (Size)
4198 {
4199 /* Memorize the old state of RF */
4200 BOOLEAN OldRf = State->Flags.Rf;
4201
4202 State->Flags.Long = NewFlags;
4203
4204 /* Restore VM and RF */
4205 State->Flags.Vm = FALSE;
4206 State->Flags.Rf = OldRf;
4207
4208 /* Clear VIF and VIP */
4209 State->Flags.Vif = State->Flags.Vip = FALSE;
4210 }
4211 else State->Flags.LowWord = LOWORD(NewFlags);
4212
4213 /* Restore the reserved bits */
4214 State->Flags.AlwaysSet = TRUE;
4215 State->Flags.Reserved0 = FALSE;
4216 State->Flags.Reserved1 = FALSE;
4217 }
4218 else
4219 {
4220 /* User */
4221
4222 /* Memorize the old state of IF and IOPL */
4223 BOOLEAN OldIf = State->Flags.If;
4224 UINT OldIopl = State->Flags.Iopl;
4225
4226 /* Set the flags */
4227 if (Size)
4228 {
4229 /* Memorize the old state of RF */
4230 BOOLEAN OldRf = State->Flags.Rf;
4231
4232 State->Flags.Long = NewFlags;
4233
4234 /* Restore VM and RF */
4235 State->Flags.Vm = FALSE;
4236 State->Flags.Rf = OldRf;
4237
4238 /* Clear VIF and VIP */
4239 State->Flags.Vif = State->Flags.Vip = FALSE;
4240 }
4241 else State->Flags.LowWord = LOWORD(NewFlags);
4242
4243 /* Restore the reserved bits and IOPL */
4244 State->Flags.AlwaysSet = TRUE;
4245 State->Flags.Reserved0 = FALSE;
4246 State->Flags.Reserved1 = FALSE;
4247 State->Flags.Iopl = OldIopl;
4248
4249 /* Check if the user doesn't have the privilege to change IF */
4250 if (Cpl > State->Flags.Iopl)
4251 {
4252 /* Restore IF */
4253 State->Flags.If = OldIf;
4254 }
4255 }
4256 }
4257 else
4258 {
4259 /* Check the IOPL */
4260 if (State->Flags.Iopl == 3)
4261 {
4262 if (Size)
4263 {
4264 /* Memorize the old state of RF, VIF and VIP */
4265 BOOLEAN OldRf = State->Flags.Rf;
4266 BOOLEAN OldVif = State->Flags.Vif;
4267 BOOLEAN OldVip = State->Flags.Vip;
4268
4269 State->Flags.Long = NewFlags;
4270
4271 /* Restore VM, RF, VIF and VIP */
4272 State->Flags.Vm = TRUE;
4273 State->Flags.Rf = OldRf;
4274 State->Flags.Vif = OldVif;
4275 State->Flags.Vip = OldVip;
4276 }
4277 else State->Flags.LowWord = LOWORD(NewFlags);
4278
4279 /* Restore the reserved bits and IOPL */
4280 State->Flags.AlwaysSet = TRUE;
4281 State->Flags.Reserved0 = FALSE;
4282 State->Flags.Reserved1 = FALSE;
4283 State->Flags.Iopl = 3;
4284 }
4285 else
4286 {
4287 /* Call the VM86 monitor */
4288 Soft386ExceptionWithErrorCode(State, SOFT386_EXCEPTION_GP, 0);
4289 }
4290
4291 }
4292
4293 return TRUE;
4294 }
4295
4296 SOFT386_OPCODE_HANDLER(Soft386OpcodeSahf)
4297 {
4298 /* Make sure this is the right instruction */
4299 ASSERT(Opcode == 0x9E);
4300
4301 /* Set the low-order byte of FLAGS to AH */
4302 State->Flags.Long &= 0xFFFFFF00;
4303 State->Flags.Long |= State->GeneralRegs[SOFT386_REG_EAX].HighByte;
4304
4305 /* Restore the reserved bits of FLAGS */
4306 State->Flags.AlwaysSet = TRUE;
4307 State->Flags.Reserved0 = State->Flags.Reserved1 = FALSE;
4308
4309 return FALSE;
4310 }
4311
4312 SOFT386_OPCODE_HANDLER(Soft386OpcodeLahf)
4313 {
4314 /* Make sure this is the right instruction */
4315 ASSERT(Opcode == 0x9F);
4316
4317 /* Set AH to the low-order byte of FLAGS */
4318 State->GeneralRegs[SOFT386_REG_EAX].HighByte = LOBYTE(State->Flags.Long);
4319
4320 return FALSE;
4321 }
4322
4323 SOFT386_OPCODE_HANDLER(Soft386OpcodeRet)
4324 {
4325 ULONG ReturnAddress;
4326 USHORT BytesToPop = 0;
4327 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4328
4329 /* Make sure this is the right instruction */
4330 ASSERT((Opcode & 0xFE) == 0xC2);
4331
4332 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
4333 {
4334 /* Invalid prefix */
4335 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4336 return FALSE;
4337 }
4338
4339 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
4340 {
4341 /* The OPSIZE prefix toggles the size */
4342 Size = !Size;
4343 }
4344
4345 if (Opcode == 0xC2)
4346 {
4347 /* Fetch the number of bytes to pop after the return */
4348 if (!Soft386FetchWord(State, &BytesToPop)) return FALSE;
4349 }
4350
4351 /* Pop the return address */
4352 if (!Soft386StackPop(State, &ReturnAddress)) return FALSE;
4353
4354 /* Return to the calling procedure, and if necessary, pop the parameters */
4355 if (Size)
4356 {
4357 State->InstPtr.Long = ReturnAddress;
4358 State->GeneralRegs[SOFT386_REG_ESP].Long += BytesToPop;
4359 }
4360 else
4361 {
4362 State->InstPtr.LowWord = LOWORD(ReturnAddress);
4363 State->GeneralRegs[SOFT386_REG_ESP].LowWord += BytesToPop;
4364 }
4365
4366 return TRUE;
4367 }
4368
4369 SOFT386_OPCODE_HANDLER(Soft386OpcodeLes)
4370 {
4371 // TODO: NOT IMPLEMENTED
4372 UNIMPLEMENTED;
4373
4374 return FALSE;
4375 }
4376
4377 SOFT386_OPCODE_HANDLER(Soft386OpcodeLds)
4378 {
4379 // TODO: NOT IMPLEMENTED
4380 UNIMPLEMENTED;
4381
4382 return FALSE;
4383 }
4384
4385 SOFT386_OPCODE_HANDLER(Soft386OpcodeEnter)
4386 {
4387 // TODO: NOT IMPLEMENTED
4388 UNIMPLEMENTED;
4389
4390 return FALSE;
4391 }
4392
4393 SOFT386_OPCODE_HANDLER(Soft386OpcodeLeave)
4394 {
4395 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4396
4397 /* Make sure this is the right instruction */
4398 ASSERT(Opcode == 0xC9);
4399
4400 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
4401 {
4402 /* Invalid prefix */
4403 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4404 return FALSE;
4405 }
4406
4407 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
4408 {
4409 /* The OPSIZE prefix toggles the size */
4410 Size = !Size;
4411 }
4412
4413 if (Size)
4414 {
4415 /* Set the stack pointer (ESP) to the base pointer (EBP) */
4416 State->GeneralRegs[SOFT386_REG_ESP].Long = State->GeneralRegs[SOFT386_REG_EBP].Long;
4417
4418 /* Pop the saved base pointer from the stack */
4419 return Soft386StackPop(State, &State->GeneralRegs[SOFT386_REG_EBP].Long);
4420 }
4421 else
4422 {
4423 ULONG Value;
4424
4425 /* Set the stack pointer (SP) to the base pointer (BP) */
4426 State->GeneralRegs[SOFT386_REG_ESP].LowWord = State->GeneralRegs[SOFT386_REG_EBP].LowWord;
4427
4428 /* Pop the saved base pointer from the stack */
4429 if (Soft386StackPop(State, &Value))
4430 {
4431 State->GeneralRegs[SOFT386_REG_EBP].LowWord = LOWORD(Value);
4432 return TRUE;
4433 }
4434 else return FALSE;
4435 }
4436 }
4437
4438 SOFT386_OPCODE_HANDLER(Soft386OpcodeRetFarImm)
4439 {
4440 // TODO: NOT IMPLEMENTED
4441 UNIMPLEMENTED;
4442
4443 return FALSE;
4444 }
4445
4446 SOFT386_OPCODE_HANDLER(Soft386OpcodeRetFar)
4447 {
4448 // TODO: NOT IMPLEMENTED
4449 UNIMPLEMENTED;
4450
4451 return FALSE;
4452 }
4453
4454 SOFT386_OPCODE_HANDLER(Soft386OpcodeInt)
4455 {
4456 UCHAR IntNum;
4457 SOFT386_IDT_ENTRY IdtEntry;
4458
4459 switch (Opcode)
4460 {
4461 case 0xCC:
4462 {
4463 /* This is the INT3 instruction */
4464 IntNum = 3;
4465 break;
4466 }
4467
4468 case 0xCD:
4469 {
4470 /* Fetch the interrupt number */
4471 if (!Soft386FetchByte(State, &IntNum))
4472 {
4473 /* Exception occurred */
4474 return FALSE;
4475 }
4476
4477 break;
4478 }
4479
4480 case 0xCE:
4481 {
4482 /* Don't do anything if OF is cleared */
4483 if (!State->Flags.Of) return TRUE;
4484
4485 /* Exception #OF */
4486 IntNum = SOFT386_EXCEPTION_OF;
4487
4488 break;
4489 }
4490
4491 default:
4492 {
4493 /* Should not happen */
4494 ASSERT(FALSE);
4495 }
4496 }
4497
4498 /* Get the interrupt vector */
4499 if (!Soft386GetIntVector(State, IntNum, &IdtEntry))
4500 {
4501 /* Exception occurred */
4502 return FALSE;
4503 }
4504
4505 /* Perform the interrupt */
4506 if (!Soft386InterruptInternal(State,
4507 IdtEntry.Selector,
4508 MAKELONG(IdtEntry.Offset, IdtEntry.OffsetHigh),
4509 IdtEntry.Type))
4510 {
4511 /* Exception occurred */
4512 return FALSE;
4513 }
4514
4515 return TRUE;
4516 }
4517
4518 SOFT386_OPCODE_HANDLER(Soft386OpcodeIret)
4519 {
4520 // TODO: NOT IMPLEMENTED
4521 UNIMPLEMENTED;
4522
4523 return FALSE;
4524 }
4525
4526 SOFT386_OPCODE_HANDLER(Soft386OpcodeAam)
4527 {
4528 UCHAR Base;
4529 UCHAR Value = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
4530
4531 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
4532 {
4533 /* Invalid prefix */
4534 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4535 return FALSE;
4536 }
4537
4538 /* Fetch the base */
4539 if (!Soft386FetchByte(State, &Base))
4540 {
4541 /* Exception occurred */
4542 return FALSE;
4543 }
4544
4545 /* Check if the base is zero */
4546 if (Base == 0)
4547 {
4548 /* Divide error */
4549 Soft386Exception(State, SOFT386_EXCEPTION_DE);
4550 return FALSE;
4551 }
4552
4553 /* Adjust */
4554 State->GeneralRegs[SOFT386_REG_EAX].HighByte = Value / Base;
4555 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Value %= Base;
4556
4557 /* Update flags */
4558 State->Flags.Zf = (Value == 0) ? TRUE : FALSE;
4559 State->Flags.Sf = (Value & SIGN_FLAG_BYTE) ? TRUE : FALSE;
4560 State->Flags.Pf = Soft386CalculateParity(Value);
4561
4562 return TRUE;
4563 }
4564
4565 SOFT386_OPCODE_HANDLER(Soft386OpcodeAad)
4566 {
4567 UCHAR Base;
4568 UCHAR Value = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
4569
4570 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
4571 {
4572 /* Invalid prefix */
4573 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4574 return FALSE;
4575 }
4576
4577 /* Fetch the base */
4578 if (!Soft386FetchByte(State, &Base))
4579 {
4580 /* Exception occurred */
4581 return FALSE;
4582 }
4583
4584 /* Adjust */
4585 Value += State->GeneralRegs[SOFT386_REG_EAX].HighByte * Base;
4586 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Value;
4587
4588 /* Update flags */
4589 State->Flags.Zf = (Value == 0) ? TRUE : FALSE;
4590 State->Flags.Sf = (Value & SIGN_FLAG_BYTE) ? TRUE : FALSE;
4591 State->Flags.Pf = Soft386CalculateParity(Value);
4592
4593 return TRUE;
4594 }
4595
4596 SOFT386_OPCODE_HANDLER(Soft386OpcodeXlat)
4597 {
4598 // TODO: NOT IMPLEMENTED
4599 UNIMPLEMENTED;
4600
4601 return FALSE;
4602 }
4603
4604 SOFT386_OPCODE_HANDLER(Soft386OpcodeLoop)
4605 {
4606 BOOLEAN Condition;
4607 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4608 CHAR Offset = 0;
4609
4610 /* Make sure this is the right instruction */
4611 ASSERT((Opcode >= 0xE0) && (Opcode <= 0xE2));
4612
4613 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
4614 {
4615 /* Invalid prefix */
4616 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4617 return FALSE;
4618 }
4619
4620 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
4621 {
4622 /* The OPSIZE prefix toggles the size */
4623 Size = !Size;
4624 }
4625
4626 if (Size) Condition = ((--State->GeneralRegs[SOFT386_REG_ECX].Long) == 0);
4627 else Condition = ((--State->GeneralRegs[SOFT386_REG_ECX].LowWord) == 0);
4628
4629 if (Opcode == 0xE0)
4630 {
4631 /* Additional rule for LOOPNZ */
4632 if (State->Flags.Zf) Condition = FALSE;
4633 }
4634
4635 if (Opcode == 0xE1)
4636 {
4637 /* Additional rule for LOOPZ */
4638 if (!State->Flags.Zf) Condition = FALSE;
4639 }
4640
4641 /* Fetch the offset */
4642 if (!Soft386FetchByte(State, (PUCHAR)&Offset))
4643 {
4644 /* An exception occurred */
4645 return FALSE;
4646 }
4647
4648 if (Condition)
4649 {
4650 /* Move the instruction pointer */
4651 State->InstPtr.Long += Offset;
4652 }
4653
4654 return TRUE;
4655 }
4656
4657 SOFT386_OPCODE_HANDLER(Soft386OpcodeJecxz)
4658 {
4659 BOOLEAN Condition;
4660 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4661 CHAR Offset = 0;
4662
4663 /* Make sure this is the right instruction */
4664 ASSERT(Opcode == 0xE3);
4665
4666 if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
4667 {
4668 /* Invalid prefix */
4669 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4670 return FALSE;
4671 }
4672
4673 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
4674 {
4675 /* The OPSIZE prefix toggles the size */
4676 Size = !Size;
4677 }
4678
4679 if (Size) Condition = (State->GeneralRegs[SOFT386_REG_ECX].Long == 0);
4680 else Condition = (State->GeneralRegs[SOFT386_REG_ECX].LowWord == 0);
4681
4682 /* Fetch the offset */
4683 if (!Soft386FetchByte(State, (PUCHAR)&Offset))
4684 {
4685 /* An exception occurred */
4686 return FALSE;
4687 }
4688
4689 if (Condition)
4690 {
4691 /* Move the instruction pointer */
4692 State->InstPtr.Long += Offset;
4693 }
4694
4695 return TRUE;
4696 }
4697
4698 SOFT386_OPCODE_HANDLER(Soft386OpcodeCall)
4699 {
4700 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4701
4702 /* Make sure this is the right instruction */
4703 ASSERT(Opcode == 0xE8);
4704
4705 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
4706 {
4707 /* The OPSIZE prefix toggles the size */
4708 Size = !Size;
4709 }
4710 else if (State->PrefixFlags != 0)
4711 {
4712 /* Invalid prefix */
4713 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4714 return FALSE;
4715 }
4716
4717 if (Size)
4718 {
4719 LONG Offset = 0;
4720
4721 /* Fetch the offset */
4722 if (!Soft386FetchDword(State, (PULONG)&Offset))
4723 {
4724 /* An exception occurred */
4725 return FALSE;
4726 }
4727
4728 /* Push the current value of the instruction pointer */
4729 if (!Soft386StackPush(State, State->InstPtr.Long))
4730 {
4731 /* Exception occurred */
4732 return FALSE;
4733 }
4734
4735 /* Move the instruction pointer */
4736 State->InstPtr.Long += Offset;
4737 }
4738 else
4739 {
4740 SHORT Offset = 0;
4741
4742 /* Fetch the offset */
4743 if (!Soft386FetchWord(State, (PUSHORT)&Offset))
4744 {
4745 /* An exception occurred */
4746 return FALSE;
4747 }
4748
4749 /* Push the current value of the instruction pointer */
4750 if (!Soft386StackPush(State, State->InstPtr.Long))
4751 {
4752 /* Exception occurred */
4753 return FALSE;
4754 }
4755
4756 /* Move the instruction pointer */
4757 State->InstPtr.LowWord += Offset;
4758 }
4759
4760 return TRUE;
4761 }
4762
4763 SOFT386_OPCODE_HANDLER(Soft386OpcodeJmp)
4764 {
4765 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4766
4767 /* Make sure this is the right instruction */
4768 ASSERT(Opcode == 0xE9);
4769
4770 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
4771 {
4772 /* The OPSIZE prefix toggles the size */
4773 Size = !Size;
4774 }
4775 else if (State->PrefixFlags != 0)
4776 {
4777 /* Invalid prefix */
4778 Soft386Exception(State, SOFT386_EXCEPTION_UD);
4779 return FALSE;
4780 }
4781
4782 if (Size)
4783 {
4784 LONG Offset = 0;
4785
4786 /* Fetch the offset */
4787 if (!Soft386FetchDword(State, (PULONG)&Offset))
4788 {
4789 /* An exception occurred */
4790 return FALSE;
4791 }
4792
4793 /* Move the instruction pointer */
4794 State->InstPtr.Long += Offset;
4795 }
4796 else
4797 {
4798 SHORT Offset = 0;
4799
4800 /* Fetch the offset */
4801 if (!Soft386FetchWord(State, (PUSHORT)&Offset))
4802 {
4803 /* An exception occurred */
4804 return FALSE;
4805 }
4806
4807 /* Move the instruction pointer */
4808 State->InstPtr.LowWord += Offset;
4809 }
4810
4811 return TRUE;
4812 }
4813
4814 SOFT386_OPCODE_HANDLER(Soft386OpcodeJmpAbs)
4815 {
4816 // TODO: NOT IMPLEMENTED
4817 UNIMPLEMENTED;
4818
4819 return FALSE;
4820 }
4821
4822 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovAlOffset)
4823 {
4824 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4825 ULONG Offset;
4826
4827 /* Make sure this is the right instruction */
4828 ASSERT(Opcode == 0xA0);
4829
4830 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
4831 {
4832 /* The OPSIZE prefix toggles the size */
4833 Size = !Size;
4834 }
4835
4836 if (Size)
4837 {
4838 if (!Soft386FetchDword(State, &Offset))
4839 {
4840 /* Exception occurred */
4841 return FALSE;
4842 }
4843 }
4844 else
4845 {
4846 USHORT WordOffset;
4847
4848 if (!Soft386FetchWord(State, &WordOffset))
4849 {
4850 /* Exception occurred */
4851 return FALSE;
4852 }
4853
4854 Offset = (ULONG)WordOffset;
4855 }
4856
4857 /* Read from memory */
4858 return Soft386ReadMemory(State,
4859 (State->PrefixFlags & SOFT386_PREFIX_SEG) ?
4860 State->SegmentOverride : SOFT386_REG_DS,
4861 Offset,
4862 FALSE,
4863 &State->GeneralRegs[SOFT386_REG_EAX].LowByte,
4864 sizeof(UCHAR));
4865 }
4866
4867 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovEaxOffset)
4868 {
4869 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4870
4871 /* Make sure this is the right instruction */
4872 ASSERT(Opcode == 0xA1);
4873
4874 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
4875 {
4876 /* The OPSIZE prefix toggles the size */
4877 Size = !Size;
4878 }
4879
4880 if (Size)
4881 {
4882 ULONG Offset;
4883
4884 if (!Soft386FetchDword(State, &Offset))
4885 {
4886 /* Exception occurred */
4887 return FALSE;
4888 }
4889
4890 /* Read from memory */
4891 return Soft386ReadMemory(State,
4892 (State->PrefixFlags & SOFT386_PREFIX_SEG) ?
4893 State->SegmentOverride : SOFT386_REG_DS,
4894 Offset,
4895 FALSE,
4896 &State->GeneralRegs[SOFT386_REG_EAX].Long,
4897 sizeof(ULONG));
4898 }
4899 else
4900 {
4901 USHORT Offset;
4902
4903 if (!Soft386FetchWord(State, &Offset))
4904 {
4905 /* Exception occurred */
4906 return FALSE;
4907 }
4908
4909 /* Read from memory */
4910 return Soft386ReadMemory(State,
4911 (State->PrefixFlags & SOFT386_PREFIX_SEG) ?
4912 State->SegmentOverride : SOFT386_REG_DS,
4913 Offset,
4914 FALSE,
4915 &State->GeneralRegs[SOFT386_REG_EAX].LowWord,
4916 sizeof(USHORT));
4917 }
4918 }
4919
4920 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovOffsetAl)
4921 {
4922 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4923 ULONG Offset;
4924
4925 /* Make sure this is the right instruction */
4926 ASSERT(Opcode == 0xA2);
4927
4928 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
4929 {
4930 /* The OPSIZE prefix toggles the size */
4931 Size = !Size;
4932 }
4933
4934 if (Size)
4935 {
4936 if (!Soft386FetchDword(State, &Offset))
4937 {
4938 /* Exception occurred */
4939 return FALSE;
4940 }
4941 }
4942 else
4943 {
4944 USHORT WordOffset;
4945
4946 if (!Soft386FetchWord(State, &WordOffset))
4947 {
4948 /* Exception occurred */
4949 return FALSE;
4950 }
4951
4952 Offset = (ULONG)WordOffset;
4953 }
4954
4955 /* Write to memory */
4956 return Soft386WriteMemory(State,
4957 (State->PrefixFlags & SOFT386_PREFIX_SEG) ?
4958 State->SegmentOverride : SOFT386_REG_DS,
4959 Offset,
4960 &State->GeneralRegs[SOFT386_REG_EAX].LowByte,
4961 sizeof(UCHAR));
4962 }
4963
4964 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovOffsetEax)
4965 {
4966 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
4967
4968 /* Make sure this is the right instruction */
4969 ASSERT(Opcode == 0xA3);
4970
4971 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
4972 {
4973 /* The OPSIZE prefix toggles the size */
4974 Size = !Size;
4975 }
4976
4977 if (Size)
4978 {
4979 ULONG Offset;
4980
4981 if (!Soft386FetchDword(State, &Offset))
4982 {
4983 /* Exception occurred */
4984 return FALSE;
4985 }
4986
4987 /* Write to memory */
4988 return Soft386WriteMemory(State,
4989 (State->PrefixFlags & SOFT386_PREFIX_SEG) ?
4990 State->SegmentOverride : SOFT386_REG_DS,
4991 Offset,
4992 &State->GeneralRegs[SOFT386_REG_EAX].Long,
4993 sizeof(ULONG));
4994 }
4995 else
4996 {
4997 USHORT Offset;
4998
4999 if (!Soft386FetchWord(State, &Offset))
5000 {
5001 /* Exception occurred */
5002 return FALSE;
5003 }
5004
5005 /* Write to memory */
5006 return Soft386WriteMemory(State,
5007 (State->PrefixFlags & SOFT386_PREFIX_SEG) ?
5008 State->SegmentOverride : SOFT386_REG_DS,
5009 Offset,
5010 &State->GeneralRegs[SOFT386_REG_EAX].LowWord,
5011 sizeof(USHORT));
5012 }
5013 }