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