454773cea662205b4d4ea84f95a05dfb08948e19
[reactos.git] / lib / soft386 / opcodes.c
1 /*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: 386/486 CPU Emulation Library
4 * FILE: opcodes.c
5 * PURPOSE: Opcode handlers.
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 // #define WIN32_NO_STATUS
12 // #define _INC_WINDOWS
13 #include <windef.h>
14
15 #include <soft386.h>
16 #include "opcodes.h"
17 #include "common.h"
18
19 // #define NDEBUG
20 #include <debug.h>
21
22 /* PUBLIC VARIABLES ***********************************************************/
23
24 SOFT386_OPCODE_HANDLER_PROC
25 Soft386OpcodeHandlers[SOFT386_NUM_OPCODE_HANDLERS] =
26 {
27 Soft386OpcodeAddByteModrm,
28 Soft386OpcodeAddModrm,
29 Soft386OpcodeAddByteModrm,
30 Soft386OpcodeAddModrm,
31 Soft386OpcodeAddAl,
32 Soft386OpcodeAddEax,
33 NULL, // TODO: OPCODE 0x06 NOT SUPPORTED
34 NULL, // TODO: OPCODE 0x07 NOT SUPPORTED
35 Soft386OpcodeOrByteModrm,
36 Soft386OpcodeOrModrm,
37 Soft386OpcodeOrByteModrm,
38 Soft386OpcodeOrModrm,
39 Soft386OpcodeOrAl,
40 Soft386OpcodeOrEax,
41 NULL, // TODO: OPCODE 0x0E NOT SUPPORTED
42 NULL, // TODO: OPCODE 0x0F NOT SUPPORTED
43 NULL, // TODO: OPCODE 0x10 NOT SUPPORTED
44 NULL, // TODO: OPCODE 0x11 NOT SUPPORTED
45 NULL, // TODO: OPCODE 0x12 NOT SUPPORTED
46 NULL, // TODO: OPCODE 0x13 NOT SUPPORTED
47 NULL, // TODO: OPCODE 0x14 NOT SUPPORTED
48 NULL, // TODO: OPCODE 0x15 NOT SUPPORTED
49 NULL, // TODO: OPCODE 0x16 NOT SUPPORTED
50 NULL, // TODO: OPCODE 0x17 NOT SUPPORTED
51 NULL, // TODO: OPCODE 0x18 NOT SUPPORTED
52 NULL, // TODO: OPCODE 0x19 NOT SUPPORTED
53 NULL, // TODO: OPCODE 0x1A NOT SUPPORTED
54 NULL, // TODO: OPCODE 0x1B NOT SUPPORTED
55 NULL, // TODO: OPCODE 0x1C NOT SUPPORTED
56 NULL, // TODO: OPCODE 0x1D NOT SUPPORTED
57 NULL, // TODO: OPCODE 0x1E NOT SUPPORTED
58 NULL, // TODO: OPCODE 0x1F NOT SUPPORTED
59 Soft386OpcodeAndByteModrm,
60 Soft386OpcodeAndModrm,
61 Soft386OpcodeAndByteModrm,
62 Soft386OpcodeAndModrm,
63 Soft386OpcodeAndAl,
64 Soft386OpcodeAndEax,
65 Soft386OpcodePrefix,
66 NULL, // TODO: OPCODE 0x27 NOT SUPPORTED
67 NULL, // TODO: OPCODE 0x28 NOT SUPPORTED
68 NULL, // TODO: OPCODE 0x29 NOT SUPPORTED
69 NULL, // TODO: OPCODE 0x2A NOT SUPPORTED
70 NULL, // TODO: OPCODE 0x2B NOT SUPPORTED
71 NULL, // TODO: OPCODE 0x2C NOT SUPPORTED
72 NULL, // TODO: OPCODE 0x2D NOT SUPPORTED
73 Soft386OpcodePrefix,
74 NULL, // TODO: OPCODE 0x2F NOT SUPPORTED
75 Soft386OpcodeXorByteModrm,
76 Soft386OpcodeXorModrm,
77 Soft386OpcodeXorByteModrm,
78 Soft386OpcodeXorModrm,
79 Soft386OpcodeXorAl,
80 Soft386OpcodeXorEax,
81 Soft386OpcodePrefix,
82 NULL, // TODO: OPCODE 0x37 NOT SUPPORTED
83 NULL, // TODO: OPCODE 0x38 NOT SUPPORTED
84 NULL, // TODO: OPCODE 0x39 NOT SUPPORTED
85 NULL, // TODO: OPCODE 0x3A NOT SUPPORTED
86 NULL, // TODO: OPCODE 0x3B NOT SUPPORTED
87 NULL, // TODO: OPCODE 0x3C NOT SUPPORTED
88 NULL, // TODO: OPCODE 0x3D NOT SUPPORTED
89 Soft386OpcodePrefix,
90 NULL, // TODO: OPCODE 0x3F NOT SUPPORTED
91 Soft386OpcodeIncrement,
92 Soft386OpcodeIncrement,
93 Soft386OpcodeIncrement,
94 Soft386OpcodeIncrement,
95 Soft386OpcodeIncrement,
96 Soft386OpcodeIncrement,
97 Soft386OpcodeIncrement,
98 Soft386OpcodeIncrement,
99 Soft386OpcodeDecrement,
100 Soft386OpcodeDecrement,
101 Soft386OpcodeDecrement,
102 Soft386OpcodeDecrement,
103 Soft386OpcodeDecrement,
104 Soft386OpcodeDecrement,
105 Soft386OpcodeDecrement,
106 Soft386OpcodeDecrement,
107 Soft386OpcodePushReg,
108 Soft386OpcodePushReg,
109 Soft386OpcodePushReg,
110 Soft386OpcodePushReg,
111 Soft386OpcodePushReg,
112 Soft386OpcodePushReg,
113 Soft386OpcodePushReg,
114 Soft386OpcodePushReg,
115 Soft386OpcodePopReg,
116 Soft386OpcodePopReg,
117 Soft386OpcodePopReg,
118 Soft386OpcodePopReg,
119 Soft386OpcodePopReg,
120 Soft386OpcodePopReg,
121 Soft386OpcodePopReg,
122 Soft386OpcodePopReg,
123 NULL, // TODO: OPCODE 0x60 NOT SUPPORTED
124 NULL, // TODO: OPCODE 0x61 NOT SUPPORTED
125 NULL, // TODO: OPCODE 0x62 NOT SUPPORTED
126 NULL, // TODO: OPCODE 0x63 NOT SUPPORTED
127 Soft386OpcodePrefix,
128 Soft386OpcodePrefix,
129 Soft386OpcodePrefix,
130 Soft386OpcodePrefix,
131 NULL, // TODO: OPCODE 0x68 NOT SUPPORTED
132 NULL, // TODO: OPCODE 0x69 NOT SUPPORTED
133 NULL, // TODO: OPCODE 0x6A NOT SUPPORTED
134 NULL, // TODO: OPCODE 0x6B NOT SUPPORTED
135 NULL, // TODO: OPCODE 0x6C NOT SUPPORTED
136 NULL, // TODO: OPCODE 0x6D NOT SUPPORTED
137 NULL, // TODO: OPCODE 0x6E NOT SUPPORTED
138 NULL, // TODO: OPCODE 0x6F NOT SUPPORTED
139 Soft386OpcodeShortConditionalJmp,
140 Soft386OpcodeShortConditionalJmp,
141 Soft386OpcodeShortConditionalJmp,
142 Soft386OpcodeShortConditionalJmp,
143 Soft386OpcodeShortConditionalJmp,
144 Soft386OpcodeShortConditionalJmp,
145 Soft386OpcodeShortConditionalJmp,
146 Soft386OpcodeShortConditionalJmp,
147 Soft386OpcodeShortConditionalJmp,
148 Soft386OpcodeShortConditionalJmp,
149 Soft386OpcodeShortConditionalJmp,
150 Soft386OpcodeShortConditionalJmp,
151 Soft386OpcodeShortConditionalJmp,
152 Soft386OpcodeShortConditionalJmp,
153 Soft386OpcodeShortConditionalJmp,
154 Soft386OpcodeShortConditionalJmp,
155 NULL, // TODO: OPCODE 0x80 NOT SUPPORTED
156 NULL, // TODO: OPCODE 0x81 NOT SUPPORTED
157 NULL, // TODO: OPCODE 0x82 NOT SUPPORTED
158 NULL, // TODO: OPCODE 0x83 NOT SUPPORTED
159 Soft386OpcodeTestByteModrm,
160 Soft386OpcodeTestModrm,
161 Soft386OpcodeXchgByteModrm,
162 Soft386OpcodeXchgModrm,
163 NULL, // TODO: OPCODE 0x88 NOT SUPPORTED
164 NULL, // TODO: OPCODE 0x89 NOT SUPPORTED
165 NULL, // TODO: OPCODE 0x8A NOT SUPPORTED
166 NULL, // TODO: OPCODE 0x8B NOT SUPPORTED
167 NULL, // TODO: OPCODE 0x8C NOT SUPPORTED
168 NULL, // TODO: OPCODE 0x8D NOT SUPPORTED
169 NULL, // TODO: OPCODE 0x8E NOT SUPPORTED
170 NULL, // TODO: OPCODE 0x8F NOT SUPPORTED
171 Soft386OpcodeNop,
172 Soft386OpcodeExchangeEax,
173 Soft386OpcodeExchangeEax,
174 Soft386OpcodeExchangeEax,
175 Soft386OpcodeExchangeEax,
176 Soft386OpcodeExchangeEax,
177 Soft386OpcodeExchangeEax,
178 Soft386OpcodeExchangeEax,
179 NULL, // TODO: OPCODE 0x98 NOT SUPPORTED
180 NULL, // TODO: OPCODE 0x99 NOT SUPPORTED
181 NULL, // TODO: OPCODE 0x9A NOT SUPPORTED
182 NULL, // TODO: OPCODE 0x9B NOT SUPPORTED
183 NULL, // TODO: OPCODE 0x9C NOT SUPPORTED
184 NULL, // TODO: OPCODE 0x9D NOT SUPPORTED
185 NULL, // TODO: OPCODE 0x9E NOT SUPPORTED
186 NULL, // TODO: OPCODE 0x9F NOT SUPPORTED
187 NULL, // TODO: OPCODE 0xA0 NOT SUPPORTED
188 NULL, // TODO: OPCODE 0xA1 NOT SUPPORTED
189 NULL, // TODO: OPCODE 0xA2 NOT SUPPORTED
190 NULL, // TODO: OPCODE 0xA3 NOT SUPPORTED
191 NULL, // TODO: OPCODE 0xA4 NOT SUPPORTED
192 NULL, // TODO: OPCODE 0xA5 NOT SUPPORTED
193 NULL, // TODO: OPCODE 0xA6 NOT SUPPORTED
194 NULL, // TODO: OPCODE 0xA7 NOT SUPPORTED
195 NULL, // TODO: OPCODE 0xA8 NOT SUPPORTED
196 NULL, // TODO: OPCODE 0xA9 NOT SUPPORTED
197 NULL, // TODO: OPCODE 0xAA NOT SUPPORTED
198 NULL, // TODO: OPCODE 0xAB NOT SUPPORTED
199 NULL, // TODO: OPCODE 0xAC NOT SUPPORTED
200 NULL, // TODO: OPCODE 0xAD NOT SUPPORTED
201 NULL, // TODO: OPCODE 0xAE NOT SUPPORTED
202 NULL, // TODO: OPCODE 0xAF NOT SUPPORTED
203 Soft386OpcodeMovByteRegImm,
204 Soft386OpcodeMovByteRegImm,
205 Soft386OpcodeMovByteRegImm,
206 Soft386OpcodeMovByteRegImm,
207 Soft386OpcodeMovByteRegImm,
208 Soft386OpcodeMovByteRegImm,
209 Soft386OpcodeMovByteRegImm,
210 Soft386OpcodeMovByteRegImm,
211 Soft386OpcodeMovRegImm,
212 Soft386OpcodeMovRegImm,
213 Soft386OpcodeMovRegImm,
214 Soft386OpcodeMovRegImm,
215 Soft386OpcodeMovRegImm,
216 Soft386OpcodeMovRegImm,
217 Soft386OpcodeMovRegImm,
218 Soft386OpcodeMovRegImm,
219 NULL, // TODO: OPCODE 0xC0 NOT SUPPORTED
220 NULL, // TODO: OPCODE 0xC1 NOT SUPPORTED
221 NULL, // TODO: OPCODE 0xC2 NOT SUPPORTED
222 NULL, // TODO: OPCODE 0xC3 NOT SUPPORTED
223 NULL, // TODO: OPCODE 0xC4 NOT SUPPORTED
224 NULL, // TODO: OPCODE 0xC5 NOT SUPPORTED
225 NULL, // TODO: OPCODE 0xC6 NOT SUPPORTED
226 NULL, // TODO: OPCODE 0xC7 NOT SUPPORTED
227 NULL, // TODO: OPCODE 0xC8 NOT SUPPORTED
228 NULL, // TODO: OPCODE 0xC9 NOT SUPPORTED
229 NULL, // TODO: OPCODE 0xCA NOT SUPPORTED
230 NULL, // TODO: OPCODE 0xCB NOT SUPPORTED
231 NULL, // TODO: OPCODE 0xCC NOT SUPPORTED
232 NULL, // TODO: OPCODE 0xCD NOT SUPPORTED
233 NULL, // TODO: OPCODE 0xCE NOT SUPPORTED
234 NULL, // TODO: OPCODE 0xCF NOT SUPPORTED
235 NULL, // TODO: OPCODE 0xD0 NOT SUPPORTED
236 NULL, // TODO: OPCODE 0xD1 NOT SUPPORTED
237 NULL, // TODO: OPCODE 0xD2 NOT SUPPORTED
238 NULL, // TODO: OPCODE 0xD3 NOT SUPPORTED
239 NULL, // TODO: OPCODE 0xD4 NOT SUPPORTED
240 NULL, // TODO: OPCODE 0xD5 NOT SUPPORTED
241 NULL, // TODO: OPCODE 0xD6 NOT SUPPORTED
242 NULL, // TODO: OPCODE 0xD7 NOT SUPPORTED
243 NULL, // TODO: OPCODE 0xD8 NOT SUPPORTED
244 NULL, // TODO: OPCODE 0xD9 NOT SUPPORTED
245 NULL, // TODO: OPCODE 0xDA NOT SUPPORTED
246 NULL, // TODO: OPCODE 0xDB NOT SUPPORTED
247 NULL, // TODO: OPCODE 0xDC NOT SUPPORTED
248 NULL, // TODO: OPCODE 0xDD NOT SUPPORTED
249 NULL, // TODO: OPCODE 0xDE NOT SUPPORTED
250 NULL, // TODO: OPCODE 0xDF NOT SUPPORTED
251 NULL, // TODO: OPCODE 0xE0 NOT SUPPORTED
252 NULL, // TODO: OPCODE 0xE1 NOT SUPPORTED
253 NULL, // TODO: OPCODE 0xE2 NOT SUPPORTED
254 NULL, // TODO: OPCODE 0xE3 NOT SUPPORTED
255 Soft386OpcodeInByte,
256 Soft386OpcodeIn,
257 Soft386OpcodeOutByte,
258 Soft386OpcodeOut,
259 NULL, // TODO: OPCODE 0xE8 NOT SUPPORTED
260 NULL, // TODO: OPCODE 0xE9 NOT SUPPORTED
261 NULL, // TODO: OPCODE 0xEA NOT SUPPORTED
262 Soft386OpcodeShortJump,
263 Soft386OpcodeInByte,
264 Soft386OpcodeIn,
265 Soft386OpcodeOutByte,
266 Soft386OpcodeOut,
267 Soft386OpcodePrefix,
268 NULL, // Invalid
269 Soft386OpcodePrefix,
270 Soft386OpcodePrefix,
271 Soft386OpcodeHalt,
272 Soft386OpcodeComplCarry,
273 NULL, // TODO: OPCODE 0xF6 NOT SUPPORTED
274 NULL, // TODO: OPCODE 0xF7 NOT SUPPORTED
275 Soft386OpcodeClearCarry,
276 Soft386OpcodeSetCarry,
277 Soft386OpcodeClearInt,
278 Soft386OpcodeSetInt,
279 Soft386OpcodeClearDir,
280 Soft386OpcodeSetDir,
281 NULL, // TODO: OPCODE 0xFE NOT SUPPORTED
282 NULL, // TODO: OPCODE 0xFF NOT SUPPORTED
283 };
284
285 /* PUBLIC FUNCTIONS ***********************************************************/
286
287 SOFT386_OPCODE_HANDLER(Soft386OpcodePrefix)
288 {
289 BOOLEAN Valid = FALSE;
290
291 switch (Opcode)
292 {
293 /* ES: */
294 case 0x26:
295 {
296 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
297 {
298 State->PrefixFlags |= SOFT386_PREFIX_SEG;
299 State->SegmentOverride = SOFT386_REG_ES;
300 Valid = TRUE;
301 }
302
303 break;
304 }
305
306 /* CS: */
307 case 0x2E:
308 {
309 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
310 {
311 State->PrefixFlags |= SOFT386_PREFIX_SEG;
312 State->SegmentOverride = SOFT386_REG_CS;
313 Valid = TRUE;
314 }
315
316 break;
317 }
318
319 /* SS: */
320 case 0x36:
321 {
322 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
323 {
324 State->PrefixFlags |= SOFT386_PREFIX_SEG;
325 State->SegmentOverride = SOFT386_REG_SS;
326 Valid = TRUE;
327 }
328
329 break;
330 }
331
332 /* DS: */
333 case 0x3E:
334 {
335 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
336 {
337 State->PrefixFlags |= SOFT386_PREFIX_SEG;
338 State->SegmentOverride = SOFT386_REG_DS;
339 Valid = TRUE;
340 }
341
342 break;
343 }
344
345 /* FS: */
346 case 0x64:
347 {
348 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
349 {
350 State->PrefixFlags |= SOFT386_PREFIX_SEG;
351 State->SegmentOverride = SOFT386_REG_FS;
352 Valid = TRUE;
353 }
354
355 break;
356 }
357
358 /* GS: */
359 case 0x65:
360 {
361 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
362 {
363 State->PrefixFlags |= SOFT386_PREFIX_SEG;
364 State->SegmentOverride = SOFT386_REG_GS;
365 Valid = TRUE;
366 }
367
368 break;
369 }
370
371 /* OPSIZE */
372 case 0x66:
373 {
374 if (!(State->PrefixFlags & SOFT386_PREFIX_OPSIZE))
375 {
376 State->PrefixFlags |= SOFT386_PREFIX_OPSIZE;
377 Valid = TRUE;
378 }
379
380 break;
381 }
382
383 /* ADSIZE */
384 case 0x67:
385 {
386 if (!(State->PrefixFlags & SOFT386_PREFIX_ADSIZE))
387 {
388 State->PrefixFlags |= SOFT386_PREFIX_ADSIZE;
389 Valid = TRUE;
390 }
391 break;
392 }
393
394 /* LOCK */
395 case 0xF0:
396 {
397 if (!(State->PrefixFlags & SOFT386_PREFIX_LOCK))
398 {
399 State->PrefixFlags |= SOFT386_PREFIX_LOCK;
400 Valid = TRUE;
401 }
402
403 break;
404 }
405
406 /* REPNZ */
407 case 0xF2:
408 {
409 /* Mutually exclusive with REP */
410 if (!(State->PrefixFlags
411 & (SOFT386_PREFIX_REPNZ | SOFT386_PREFIX_REP)))
412 {
413 State->PrefixFlags |= SOFT386_PREFIX_REPNZ;
414 Valid = TRUE;
415 }
416
417 break;
418 }
419
420 /* REP / REPZ */
421 case 0xF3:
422 {
423 /* Mutually exclusive with REPNZ */
424 if (!(State->PrefixFlags
425 & (SOFT386_PREFIX_REPNZ | SOFT386_PREFIX_REP)))
426 {
427 State->PrefixFlags |= SOFT386_PREFIX_REP;
428 Valid = TRUE;
429 }
430
431 break;
432 }
433 }
434
435 if (!Valid)
436 {
437 /* Clear all prefixes */
438 State->PrefixFlags = 0;
439
440 /* Throw an exception */
441 Soft386Exception(State, SOFT386_EXCEPTION_UD);
442 return FALSE;
443 }
444
445 return TRUE;
446 }
447
448 SOFT386_OPCODE_HANDLER(Soft386OpcodeIncrement)
449 {
450 ULONG Value;
451 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
452
453 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
454 {
455 /* The OPSIZE prefix toggles the size */
456 Size = !Size;
457 }
458 else if (State->PrefixFlags != 0)
459 {
460 /* Invalid prefix */
461 Soft386Exception(State, SOFT386_EXCEPTION_UD);
462 return FALSE;
463 }
464
465 /* Make sure this is the right instruction */
466 ASSERT((Opcode & 0xF8) == 0x40);
467
468 if (Size)
469 {
470 Value = ++State->GeneralRegs[Opcode & 0x07].Long;
471
472 State->Flags.Of = (Value == SIGN_FLAG_LONG) ? TRUE : FALSE;
473 State->Flags.Sf = (Value & SIGN_FLAG_LONG) ? TRUE : FALSE;
474 }
475 else
476 {
477 Value = ++State->GeneralRegs[Opcode & 0x07].LowWord;
478
479 State->Flags.Of = (Value == SIGN_FLAG_WORD) ? TRUE : FALSE;
480 State->Flags.Sf = (Value & SIGN_FLAG_WORD) ? TRUE : FALSE;
481 }
482
483 State->Flags.Zf = (Value == 0) ? TRUE : FALSE;
484 State->Flags.Af = ((Value & 0x0F) == 0) ? TRUE : FALSE;
485 State->Flags.Pf = Soft386CalculateParity(LOBYTE(Value));
486
487 /* Return success */
488 return TRUE;
489 }
490
491 SOFT386_OPCODE_HANDLER(Soft386OpcodeDecrement)
492 {
493 ULONG Value;
494 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
495
496 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
497 {
498 /* The OPSIZE prefix toggles the size */
499 Size = !Size;
500 }
501 else if (State->PrefixFlags != 0)
502 {
503 /* Invalid prefix */
504 Soft386Exception(State, SOFT386_EXCEPTION_UD);
505 return FALSE;
506 }
507
508 /* Make sure this is the right instruction */
509 ASSERT((Opcode & 0xF8) == 0x48);
510
511 if (Size)
512 {
513 Value = --State->GeneralRegs[Opcode & 0x07].Long;
514
515 State->Flags.Of = (Value == (SIGN_FLAG_LONG - 1)) ? TRUE : FALSE;
516 State->Flags.Sf = (Value & SIGN_FLAG_LONG) ? TRUE : FALSE;
517 }
518 else
519 {
520 Value = --State->GeneralRegs[Opcode & 0x07].LowWord;
521
522 State->Flags.Of = (Value == (SIGN_FLAG_WORD - 1)) ? TRUE : FALSE;
523 State->Flags.Sf = (Value & SIGN_FLAG_WORD) ? TRUE : FALSE;
524 }
525
526 State->Flags.Zf = (Value == 0) ? TRUE : FALSE;
527 State->Flags.Af = ((Value & 0x0F) == 0x0F) ? TRUE : FALSE;
528 State->Flags.Pf = Soft386CalculateParity(LOBYTE(Value));
529
530 /* Return success */
531 return TRUE;
532 }
533
534 SOFT386_OPCODE_HANDLER(Soft386OpcodePushReg)
535 {
536 if ((State->PrefixFlags != SOFT386_PREFIX_OPSIZE)
537 && (State->PrefixFlags != 0))
538 {
539 /* Invalid prefix */
540 Soft386Exception(State, SOFT386_EXCEPTION_UD);
541 return FALSE;
542 }
543
544 /* Make sure this is the right instruction */
545 ASSERT((Opcode & 0xF8) == 0x50);
546
547 /* Call the internal function */
548 return Soft386StackPush(State, State->GeneralRegs[Opcode & 0x07].Long);
549 }
550
551 SOFT386_OPCODE_HANDLER(Soft386OpcodePopReg)
552 {
553 ULONG Value;
554 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_SS].Size;
555
556 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
557 {
558 /* The OPSIZE prefix toggles the size */
559 Size = !Size;
560 }
561 else if (State->PrefixFlags != 0)
562 {
563 /* Invalid prefix */
564 Soft386Exception(State, SOFT386_EXCEPTION_UD);
565 return FALSE;
566 }
567
568 /* Make sure this is the right instruction */
569 ASSERT((Opcode & 0xF8) == 0x58);
570
571 /* Call the internal function */
572 if (!Soft386StackPop(State, &Value)) return FALSE;
573
574 /* Store the value */
575 if (Size) State->GeneralRegs[Opcode & 0x07].Long = Value;
576 else State->GeneralRegs[Opcode & 0x07].LowWord = Value;
577
578 /* Return success */
579 return TRUE;
580 }
581
582 SOFT386_OPCODE_HANDLER(Soft386OpcodeNop)
583 {
584 if (State->PrefixFlags & ~(SOFT386_PREFIX_OPSIZE | SOFT386_PREFIX_REP))
585 {
586 /* Allowed prefixes are REP and OPSIZE */
587 Soft386Exception(State, SOFT386_EXCEPTION_UD);
588 return FALSE;
589 }
590
591 if (State->PrefixFlags & SOFT386_PREFIX_REP)
592 {
593 /* Idle cycle */
594 State->IdleCallback(State);
595 }
596
597 return TRUE;
598 }
599
600 SOFT386_OPCODE_HANDLER(Soft386OpcodeExchangeEax)
601 {
602 INT Reg = Opcode & 0x07;
603 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
604
605 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
606 {
607 /* The OPSIZE prefix toggles the size */
608 Size = !Size;
609 }
610 else if (State->PrefixFlags != 0)
611 {
612 /* Invalid prefix */
613 Soft386Exception(State, SOFT386_EXCEPTION_UD);
614 return FALSE;
615 }
616
617 /* Make sure this is the right instruction */
618 ASSERT((Opcode & 0xF8) == 0x90);
619
620 /* Exchange the values */
621 if (Size)
622 {
623 ULONG Value;
624
625 Value = State->GeneralRegs[Reg].Long;
626 State->GeneralRegs[Reg].Long = State->GeneralRegs[SOFT386_REG_EAX].Long;
627 State->GeneralRegs[SOFT386_REG_EAX].Long = Value;
628 }
629 else
630 {
631 USHORT Value;
632
633 Value = State->GeneralRegs[Reg].LowWord;
634 State->GeneralRegs[Reg].LowWord = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
635 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Value;
636 }
637
638 return TRUE;
639 }
640
641 SOFT386_OPCODE_HANDLER(Soft386OpcodeShortConditionalJmp)
642 {
643 BOOLEAN Jump = FALSE;
644 CHAR Offset = 0;
645
646 /* Make sure this is the right instruction */
647 ASSERT((Opcode & 0xF0) == 0x70);
648
649 /* Fetch the offset */
650 if (!Soft386FetchByte(State, (PUCHAR)&Offset))
651 {
652 /* An exception occurred */
653 return FALSE;
654 }
655
656 switch ((Opcode & 0x0F) >> 1)
657 {
658 /* JO / JNO */
659 case 0:
660 {
661 Jump = State->Flags.Of;
662 break;
663 }
664
665 /* JC / JNC */
666 case 1:
667 {
668 Jump = State->Flags.Cf;
669 break;
670 }
671
672 /* JZ / JNZ */
673 case 2:
674 {
675 Jump = State->Flags.Zf;
676 break;
677 }
678
679 /* JBE / JNBE */
680 case 3:
681 {
682 Jump = State->Flags.Cf || State->Flags.Zf;
683 break;
684 }
685
686 /* JS / JNS */
687 case 4:
688 {
689 Jump = State->Flags.Sf;
690 break;
691 }
692
693 /* JP / JNP */
694 case 5:
695 {
696 Jump = State->Flags.Pf;
697 break;
698 }
699
700 /* JL / JNL */
701 case 6:
702 {
703 Jump = State->Flags.Sf != State->Flags.Of;
704 break;
705 }
706
707 /* JLE / JNLE */
708 case 7:
709 {
710 Jump = (State->Flags.Sf != State->Flags.Of) || State->Flags.Zf;
711 break;
712 }
713 }
714
715 if (Opcode & 1)
716 {
717 /* Invert the result */
718 Jump = !Jump;
719 }
720
721 if (Jump)
722 {
723 /* Move the instruction pointer */
724 State->InstPtr.Long += Offset;
725 }
726
727 /* Return success */
728 return TRUE;
729 }
730
731 SOFT386_OPCODE_HANDLER(Soft386OpcodeClearCarry)
732 {
733 /* Make sure this is the right instruction */
734 ASSERT(Opcode == 0xF8);
735
736 /* No prefixes allowed */
737 if (State->PrefixFlags)
738 {
739 Soft386Exception(State, SOFT386_EXCEPTION_UD);
740 return FALSE;
741 }
742
743 /* Clear CF and return success */
744 State->Flags.Cf = FALSE;
745 return TRUE;
746 }
747
748 SOFT386_OPCODE_HANDLER(Soft386OpcodeSetCarry)
749 {
750 /* Make sure this is the right instruction */
751 ASSERT(Opcode == 0xF9);
752
753 /* No prefixes allowed */
754 if (State->PrefixFlags)
755 {
756 Soft386Exception(State, SOFT386_EXCEPTION_UD);
757 return FALSE;
758 }
759
760 /* Set CF and return success*/
761 State->Flags.Cf = TRUE;
762 return TRUE;
763 }
764
765 SOFT386_OPCODE_HANDLER(Soft386OpcodeComplCarry)
766 {
767 /* Make sure this is the right instruction */
768 ASSERT(Opcode == 0xF5);
769
770 /* No prefixes allowed */
771 if (State->PrefixFlags)
772 {
773 Soft386Exception(State, SOFT386_EXCEPTION_UD);
774 return FALSE;
775 }
776
777 /* Toggle CF and return success */
778 State->Flags.Cf = !State->Flags.Cf;
779 return TRUE;
780 }
781
782 SOFT386_OPCODE_HANDLER(Soft386OpcodeClearInt)
783 {
784 /* Make sure this is the right instruction */
785 ASSERT(Opcode == 0xFA);
786
787 /* No prefixes allowed */
788 if (State->PrefixFlags)
789 {
790 Soft386Exception(State, SOFT386_EXCEPTION_UD);
791 return FALSE;
792 }
793
794 /* Check for protected mode */
795 if (State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE)
796 {
797 /* Check IOPL */
798 if (State->Flags.Iopl >= State->SegmentRegs[SOFT386_REG_CS].Dpl)
799 {
800 /* Clear the interrupt flag */
801 State->Flags.If = FALSE;
802 }
803 else
804 {
805 /* General Protection Fault */
806 Soft386Exception(State, SOFT386_EXCEPTION_GP);
807 return FALSE;
808 }
809 }
810 else
811 {
812 /* Just clear the interrupt flag */
813 State->Flags.If = FALSE;
814 }
815
816 /* Return success */
817 return TRUE;
818 }
819
820 SOFT386_OPCODE_HANDLER(Soft386OpcodeSetInt)
821 {
822 /* Make sure this is the right instruction */
823 ASSERT(Opcode == 0xFB);
824
825 /* No prefixes allowed */
826 if (State->PrefixFlags)
827 {
828 Soft386Exception(State, SOFT386_EXCEPTION_UD);
829 return FALSE;
830 }
831
832 /* Check for protected mode */
833 if (State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE)
834 {
835 /* Check IOPL */
836 if (State->Flags.Iopl >= State->SegmentRegs[SOFT386_REG_CS].Dpl)
837 {
838 /* Set the interrupt flag */
839 State->Flags.If = TRUE;
840 }
841 else
842 {
843 /* General Protection Fault */
844 Soft386Exception(State, SOFT386_EXCEPTION_GP);
845 return FALSE;
846 }
847 }
848 else
849 {
850 /* Just set the interrupt flag */
851 State->Flags.If = TRUE;
852 }
853
854 /* Return success */
855 return TRUE;
856 }
857
858 SOFT386_OPCODE_HANDLER(Soft386OpcodeClearDir)
859 {
860 /* Make sure this is the right instruction */
861 ASSERT(Opcode == 0xFC);
862
863 /* No prefixes allowed */
864 if (State->PrefixFlags)
865 {
866 Soft386Exception(State, SOFT386_EXCEPTION_UD);
867 return FALSE;
868 }
869
870 /* Clear DF and return success */
871 State->Flags.Df = FALSE;
872 return TRUE;
873 }
874
875 SOFT386_OPCODE_HANDLER(Soft386OpcodeSetDir)
876 {
877 /* Make sure this is the right instruction */
878 ASSERT(Opcode == 0xFD);
879
880 /* No prefixes allowed */
881 if (State->PrefixFlags)
882 {
883 Soft386Exception(State, SOFT386_EXCEPTION_UD);
884 return FALSE;
885 }
886
887 /* Set DF and return success*/
888 State->Flags.Df = TRUE;
889 return TRUE;
890 }
891
892 SOFT386_OPCODE_HANDLER(Soft386OpcodeHalt)
893 {
894 /* Make sure this is the right instruction */
895 ASSERT(Opcode == 0xF4);
896
897 /* No prefixes allowed */
898 if (State->PrefixFlags)
899 {
900 Soft386Exception(State, SOFT386_EXCEPTION_UD);
901 return FALSE;
902 }
903
904 /* Privileged instructions can only be executed under CPL = 0 */
905 if (State->SegmentRegs[SOFT386_REG_CS].Dpl != 0)
906 {
907 Soft386Exception(State, SOFT386_EXCEPTION_GP);
908 return FALSE;
909 }
910
911 /* Halt */
912 while (!State->HardwareInt) State->IdleCallback(State);
913
914 /* Return success */
915 return TRUE;
916 }
917
918 SOFT386_OPCODE_HANDLER(Soft386OpcodeInByte)
919 {
920 UCHAR Data;
921 ULONG Port;
922
923 /* Make sure this is the right instruction */
924 ASSERT((Opcode & 0xF7) == 0xE4);
925
926 if (Opcode == 0xE4)
927 {
928 /* Fetch the parameter */
929 if (!Soft386FetchByte(State, &Data))
930 {
931 /* Exception occurred */
932 return FALSE;
933 }
934
935 /* Set the port number to the parameter */
936 Port = Data;
937 }
938 else
939 {
940 /* The port number is in DX */
941 Port = State->GeneralRegs[SOFT386_REG_EDX].LowWord;
942 }
943
944 /* Read a byte from the I/O port */
945 State->IoReadCallback(State, Port, &Data, sizeof(UCHAR));
946
947 /* Store the result in AL */
948 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Data;
949
950 return TRUE;
951 }
952
953 SOFT386_OPCODE_HANDLER(Soft386OpcodeIn)
954 {
955 ULONG Port;
956 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
957
958 /* Make sure this is the right instruction */
959 ASSERT((Opcode & 0xF7) == 0xE5);
960
961 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
962 {
963 /* The OPSIZE prefix toggles the size */
964 Size = !Size;
965 }
966 else if (State->PrefixFlags != 0)
967 {
968 /* Invalid prefix */
969 Soft386Exception(State, SOFT386_EXCEPTION_UD);
970 return FALSE;
971 }
972
973 if (Opcode == 0xE5)
974 {
975 UCHAR Data;
976
977 /* Fetch the parameter */
978 if (!Soft386FetchByte(State, &Data))
979 {
980 /* Exception occurred */
981 return FALSE;
982 }
983
984 /* Set the port number to the parameter */
985 Port = Data;
986 }
987 else
988 {
989 /* The port number is in DX */
990 Port = State->GeneralRegs[SOFT386_REG_EDX].LowWord;
991 }
992
993 if (Size)
994 {
995 ULONG Data;
996
997 /* Read a dword from the I/O port */
998 State->IoReadCallback(State, Port, &Data, sizeof(ULONG));
999
1000 /* Store the value in EAX */
1001 State->GeneralRegs[SOFT386_REG_EAX].Long = Data;
1002 }
1003 else
1004 {
1005 USHORT Data;
1006
1007 /* Read a word from the I/O port */
1008 State->IoReadCallback(State, Port, &Data, sizeof(USHORT));
1009
1010 /* Store the value in AX */
1011 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Data;
1012 }
1013
1014 return TRUE;
1015 }
1016
1017 SOFT386_OPCODE_HANDLER(Soft386OpcodeOutByte)
1018 {
1019 UCHAR Data;
1020 ULONG Port;
1021
1022 /* Make sure this is the right instruction */
1023 ASSERT((Opcode & 0xF7) == 0xE6);
1024
1025 if (Opcode == 0xE6)
1026 {
1027 /* Fetch the parameter */
1028 if (!Soft386FetchByte(State, &Data))
1029 {
1030 /* Exception occurred */
1031 return FALSE;
1032 }
1033
1034 /* Set the port number to the parameter */
1035 Port = Data;
1036 }
1037 else
1038 {
1039 /* The port number is in DX */
1040 Port = State->GeneralRegs[SOFT386_REG_EDX].LowWord;
1041 }
1042
1043 /* Read the value from AL */
1044 Data = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
1045
1046 /* Write the byte to the I/O port */
1047 State->IoWriteCallback(State, Port, &Data, sizeof(UCHAR));
1048
1049 return TRUE;
1050 }
1051
1052 SOFT386_OPCODE_HANDLER(Soft386OpcodeOut)
1053 {
1054 ULONG Port;
1055 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
1056
1057 /* Make sure this is the right instruction */
1058 ASSERT((Opcode & 0xF7) == 0xE7);
1059
1060 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
1061 {
1062 /* The OPSIZE prefix toggles the size */
1063 Size = !Size;
1064 }
1065 else if (State->PrefixFlags != 0)
1066 {
1067 /* Invalid prefix */
1068 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1069 return FALSE;
1070 }
1071
1072 if (Opcode == 0xE7)
1073 {
1074 UCHAR Data;
1075
1076 /* Fetch the parameter */
1077 if (!Soft386FetchByte(State, &Data))
1078 {
1079 /* Exception occurred */
1080 return FALSE;
1081 }
1082
1083 /* Set the port number to the parameter */
1084 Port = Data;
1085 }
1086 else
1087 {
1088 /* The port number is in DX */
1089 Port = State->GeneralRegs[SOFT386_REG_EDX].LowWord;
1090 }
1091
1092 if (Size)
1093 {
1094 /* Get the value from EAX */
1095 ULONG Data = State->GeneralRegs[SOFT386_REG_EAX].Long;
1096
1097 /* Write a dword to the I/O port */
1098 State->IoReadCallback(State, Port, &Data, sizeof(ULONG));
1099 }
1100 else
1101 {
1102 /* Get the value from AX */
1103 USHORT Data = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
1104
1105 /* Write a word to the I/O port */
1106 State->IoWriteCallback(State, Port, &Data, sizeof(USHORT));
1107 }
1108
1109 return TRUE;
1110 }
1111
1112 SOFT386_OPCODE_HANDLER(Soft386OpcodeShortJump)
1113 {
1114 CHAR Offset = 0;
1115
1116 /* Make sure this is the right instruction */
1117 ASSERT(Opcode == 0xEB);
1118
1119 /* Fetch the offset */
1120 if (!Soft386FetchByte(State, (PUCHAR)&Offset))
1121 {
1122 /* An exception occurred */
1123 return FALSE;
1124 }
1125
1126 /* Move the instruction pointer */
1127 State->InstPtr.Long += Offset;
1128
1129 return TRUE;
1130 }
1131
1132 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovRegImm)
1133 {
1134 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
1135
1136 /* Make sure this is the right instruction */
1137 ASSERT((Opcode & 0xF8) == 0xB8);
1138
1139 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
1140 {
1141 /* The OPSIZE prefix toggles the size */
1142 Size = !Size;
1143 }
1144 else if (State->PrefixFlags != 0)
1145 {
1146 /* Invalid prefix */
1147 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1148 return FALSE;
1149 }
1150
1151 if (Size)
1152 {
1153 ULONG Value;
1154
1155 /* Fetch the dword */
1156 if (!Soft386FetchDword(State, &Value))
1157 {
1158 /* Exception occurred */
1159 return FALSE;
1160 }
1161
1162 /* Store the value in the register */
1163 State->GeneralRegs[Opcode & 0x07].Long = Value;
1164 }
1165 else
1166 {
1167 USHORT Value;
1168
1169 /* Fetch the word */
1170 if (!Soft386FetchWord(State, &Value))
1171 {
1172 /* Exception occurred */
1173 return FALSE;
1174 }
1175
1176 /* Store the value in the register */
1177 State->GeneralRegs[Opcode & 0x07].LowWord = Value;
1178 }
1179
1180 return TRUE;
1181 }
1182
1183 SOFT386_OPCODE_HANDLER(Soft386OpcodeMovByteRegImm)
1184 {
1185 UCHAR Value;
1186
1187 /* Make sure this is the right instruction */
1188 ASSERT((Opcode & 0xF8) == 0xB0);
1189
1190 if (State->PrefixFlags != 0)
1191 {
1192 /* Invalid prefix */
1193 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1194 return FALSE;
1195 }
1196
1197 /* Fetch the byte */
1198 if (!Soft386FetchByte(State, &Value))
1199 {
1200 /* Exception occurred */
1201 return FALSE;
1202 }
1203
1204 if (Opcode & 0x04)
1205 {
1206 /* AH, CH, DH or BH */
1207 State->GeneralRegs[Opcode & 0x03].HighByte = Value;
1208 }
1209 else
1210 {
1211 /* AL, CL, DL or BL */
1212 State->GeneralRegs[Opcode & 0x03].LowByte = Value;
1213 }
1214
1215 return TRUE;
1216 }
1217
1218 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddByteModrm)
1219 {
1220 UCHAR FirstValue, SecondValue, Result;
1221 SOFT386_MOD_REG_RM ModRegRm;
1222 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
1223
1224 /* Make sure this is the right instruction */
1225 ASSERT((Opcode & 0xFD) == 0x00);
1226
1227 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
1228 {
1229 /* The ADSIZE prefix toggles the size */
1230 AddressSize = !AddressSize;
1231 }
1232 else if (State->PrefixFlags
1233 & ~(SOFT386_PREFIX_ADSIZE
1234 | SOFT386_PREFIX_SEG
1235 | SOFT386_PREFIX_LOCK))
1236 {
1237 /* Invalid prefix */
1238 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1239 return FALSE;
1240 }
1241
1242 /* Get the operands */
1243 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
1244 {
1245 /* Exception occurred */
1246 return FALSE;
1247 }
1248
1249 if (!Soft386ReadModrmByteOperands(State,
1250 &ModRegRm,
1251 &FirstValue,
1252 &SecondValue))
1253 {
1254 /* Exception occurred */
1255 return FALSE;
1256 }
1257
1258 /* Calculate the result */
1259 Result = FirstValue + SecondValue;
1260
1261 /* Update the flags */
1262 State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
1263 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE))
1264 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
1265 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
1266 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1267 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
1268 State->Flags.Pf = Soft386CalculateParity(Result);
1269
1270 /* Write back the result */
1271 return Soft386WriteModrmByteOperands(State,
1272 &ModRegRm,
1273 Opcode & SOFT386_OPCODE_WRITE_REG,
1274 Result);
1275 }
1276
1277 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddModrm)
1278 {
1279 SOFT386_MOD_REG_RM ModRegRm;
1280 BOOLEAN OperandSize, AddressSize;
1281
1282 /* Make sure this is the right instruction */
1283 ASSERT((Opcode & 0xFD) == 0x01);
1284
1285 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
1286
1287 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
1288 {
1289 /* The ADSIZE prefix toggles the address size */
1290 AddressSize = !AddressSize;
1291 }
1292
1293 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
1294 {
1295 /* The OPSIZE prefix toggles the operand size */
1296 OperandSize = !OperandSize;
1297 }
1298
1299 if (State->PrefixFlags
1300 & ~(SOFT386_PREFIX_ADSIZE
1301 | SOFT386_PREFIX_OPSIZE
1302 | SOFT386_PREFIX_SEG
1303 | SOFT386_PREFIX_LOCK))
1304 {
1305 /* Invalid prefix */
1306 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1307 return FALSE;
1308 }
1309
1310 /* Get the operands */
1311 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
1312 {
1313 /* Exception occurred */
1314 return FALSE;
1315 }
1316
1317 /* Check the operand size */
1318 if (OperandSize)
1319 {
1320 ULONG FirstValue, SecondValue, Result;
1321
1322 if (!Soft386ReadModrmDwordOperands(State,
1323 &ModRegRm,
1324 &FirstValue,
1325 &SecondValue))
1326 {
1327 /* Exception occurred */
1328 return FALSE;
1329 }
1330
1331 /* Calculate the result */
1332 Result = FirstValue + SecondValue;
1333
1334 /* Update the flags */
1335 State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
1336 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG))
1337 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
1338 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
1339 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1340 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
1341 State->Flags.Pf = Soft386CalculateParity(Result);
1342
1343 /* Write back the result */
1344 return Soft386WriteModrmDwordOperands(State,
1345 &ModRegRm,
1346 Opcode & SOFT386_OPCODE_WRITE_REG,
1347 Result);
1348 }
1349 else
1350 {
1351 USHORT FirstValue, SecondValue, Result;
1352
1353 if (!Soft386ReadModrmWordOperands(State,
1354 &ModRegRm,
1355 &FirstValue,
1356 &SecondValue))
1357 {
1358 /* Exception occurred */
1359 return FALSE;
1360 }
1361
1362 /* Calculate the result */
1363 Result = FirstValue + SecondValue;
1364
1365 /* Update the flags */
1366 State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
1367 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD))
1368 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
1369 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
1370 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1371 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
1372 State->Flags.Pf = Soft386CalculateParity(Result);
1373
1374 /* Write back the result */
1375 return Soft386WriteModrmWordOperands(State,
1376 &ModRegRm,
1377 Opcode & SOFT386_OPCODE_WRITE_REG,
1378 Result);
1379 }
1380 }
1381
1382 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddAl)
1383 {
1384 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
1385 UCHAR SecondValue, Result;
1386
1387 /* Make sure this is the right instruction */
1388 ASSERT(Opcode == 0x04);
1389
1390 if (State->PrefixFlags)
1391 {
1392 /* This opcode doesn't take any prefixes */
1393 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1394 return FALSE;
1395 }
1396
1397 if (!Soft386FetchByte(State, &SecondValue))
1398 {
1399 /* Exception occurred */
1400 return FALSE;
1401 }
1402
1403 /* Calculate the result */
1404 Result = FirstValue + SecondValue;
1405
1406 /* Update the flags */
1407 State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
1408 State->Flags.Of = ((FirstValue & SIGN_FLAG_BYTE) == (SecondValue & SIGN_FLAG_BYTE))
1409 && ((FirstValue & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
1410 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
1411 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1412 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
1413 State->Flags.Pf = Soft386CalculateParity(Result);
1414
1415 /* Write back the result */
1416 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
1417
1418 return TRUE;
1419 }
1420
1421 SOFT386_OPCODE_HANDLER(Soft386OpcodeAddEax)
1422 {
1423 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
1424
1425 /* Make sure this is the right instruction */
1426 ASSERT(Opcode == 0x05);
1427
1428 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
1429 {
1430 /* The OPSIZE prefix toggles the size */
1431 Size = !Size;
1432 }
1433 else
1434 {
1435 /* Invalid prefix */
1436 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1437 return FALSE;
1438 }
1439
1440 if (Size)
1441 {
1442 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
1443 ULONG SecondValue, Result;
1444
1445 if (!Soft386FetchDword(State, &SecondValue))
1446 {
1447 /* Exception occurred */
1448 return FALSE;
1449 }
1450
1451 /* Calculate the result */
1452 Result = FirstValue + SecondValue;
1453
1454 /* Update the flags */
1455 State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
1456 State->Flags.Of = ((FirstValue & SIGN_FLAG_LONG) == (SecondValue & SIGN_FLAG_LONG))
1457 && ((FirstValue & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
1458 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
1459 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1460 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
1461 State->Flags.Pf = Soft386CalculateParity(Result);
1462
1463 /* Write back the result */
1464 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
1465 }
1466 else
1467 {
1468 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
1469 USHORT SecondValue, Result;
1470
1471 if (!Soft386FetchWord(State, &SecondValue))
1472 {
1473 /* Exception occurred */
1474 return FALSE;
1475 }
1476
1477 /* Calculate the result */
1478 Result = FirstValue + SecondValue;
1479
1480 /* Update the flags */
1481 State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
1482 State->Flags.Of = ((FirstValue & SIGN_FLAG_WORD) == (SecondValue & SIGN_FLAG_WORD))
1483 && ((FirstValue & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
1484 State->Flags.Af = (((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) ? TRUE : FALSE;
1485 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1486 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
1487 State->Flags.Pf = Soft386CalculateParity(Result);
1488
1489 /* Write back the result */
1490 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
1491 }
1492
1493 return TRUE;
1494 }
1495
1496 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrByteModrm)
1497 {
1498 UCHAR FirstValue, SecondValue, Result;
1499 SOFT386_MOD_REG_RM ModRegRm;
1500 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
1501
1502 /* Make sure this is the right instruction */
1503 ASSERT((Opcode & 0xFD) == 0x08);
1504
1505 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
1506 {
1507 /* The ADSIZE prefix toggles the size */
1508 AddressSize = !AddressSize;
1509 }
1510 else if (State->PrefixFlags
1511 & ~(SOFT386_PREFIX_ADSIZE
1512 | SOFT386_PREFIX_SEG
1513 | SOFT386_PREFIX_LOCK))
1514 {
1515 /* Invalid prefix */
1516 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1517 return FALSE;
1518 }
1519
1520 /* Get the operands */
1521 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
1522 {
1523 /* Exception occurred */
1524 return FALSE;
1525 }
1526
1527 if (!Soft386ReadModrmByteOperands(State,
1528 &ModRegRm,
1529 &FirstValue,
1530 &SecondValue))
1531 {
1532 /* Exception occurred */
1533 return FALSE;
1534 }
1535
1536 /* Calculate the result */
1537 Result = FirstValue | SecondValue;
1538
1539 /* Update the flags */
1540 State->Flags.Cf = FALSE;
1541 State->Flags.Of = FALSE;
1542 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1543 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
1544 State->Flags.Pf = Soft386CalculateParity(Result);
1545
1546 /* Write back the result */
1547 return Soft386WriteModrmByteOperands(State,
1548 &ModRegRm,
1549 Opcode & SOFT386_OPCODE_WRITE_REG,
1550 Result);
1551 }
1552
1553 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrModrm)
1554 {
1555 SOFT386_MOD_REG_RM ModRegRm;
1556 BOOLEAN OperandSize, AddressSize;
1557
1558 /* Make sure this is the right instruction */
1559 ASSERT((Opcode & 0xFD) == 0x09);
1560
1561 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
1562
1563 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
1564 {
1565 /* The ADSIZE prefix toggles the address size */
1566 AddressSize = !AddressSize;
1567 }
1568
1569 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
1570 {
1571 /* The OPSIZE prefix toggles the operand size */
1572 OperandSize = !OperandSize;
1573 }
1574
1575 if (State->PrefixFlags
1576 & ~(SOFT386_PREFIX_ADSIZE
1577 | SOFT386_PREFIX_OPSIZE
1578 | SOFT386_PREFIX_SEG
1579 | SOFT386_PREFIX_LOCK))
1580 {
1581 /* Invalid prefix */
1582 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1583 return FALSE;
1584 }
1585
1586 /* Get the operands */
1587 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
1588 {
1589 /* Exception occurred */
1590 return FALSE;
1591 }
1592
1593 /* Check the operand size */
1594 if (OperandSize)
1595 {
1596 ULONG FirstValue, SecondValue, Result;
1597
1598 if (!Soft386ReadModrmDwordOperands(State,
1599 &ModRegRm,
1600 &FirstValue,
1601 &SecondValue))
1602 {
1603 /* Exception occurred */
1604 return FALSE;
1605 }
1606
1607 /* Calculate the result */
1608 Result = FirstValue | SecondValue;
1609
1610 /* Update the flags */
1611 State->Flags.Cf = FALSE;
1612 State->Flags.Of = FALSE;
1613 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1614 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
1615 State->Flags.Pf = Soft386CalculateParity(Result);
1616
1617 /* Write back the result */
1618 return Soft386WriteModrmDwordOperands(State,
1619 &ModRegRm,
1620 Opcode & SOFT386_OPCODE_WRITE_REG,
1621 Result);
1622 }
1623 else
1624 {
1625 USHORT FirstValue, SecondValue, Result;
1626
1627 if (!Soft386ReadModrmWordOperands(State,
1628 &ModRegRm,
1629 &FirstValue,
1630 &SecondValue))
1631 {
1632 /* Exception occurred */
1633 return FALSE;
1634 }
1635
1636 /* Calculate the result */
1637 Result = FirstValue | SecondValue;
1638
1639 /* Update the flags */
1640 State->Flags.Cf = FALSE;
1641 State->Flags.Of = FALSE;
1642 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1643 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
1644 State->Flags.Pf = Soft386CalculateParity(Result);
1645
1646 /* Write back the result */
1647 return Soft386WriteModrmWordOperands(State,
1648 &ModRegRm,
1649 Opcode & SOFT386_OPCODE_WRITE_REG,
1650 Result);
1651 }
1652 }
1653
1654 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrAl)
1655 {
1656 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
1657 UCHAR SecondValue, Result;
1658
1659 /* Make sure this is the right instruction */
1660 ASSERT(Opcode == 0x0C);
1661
1662 if (State->PrefixFlags)
1663 {
1664 /* This opcode doesn't take any prefixes */
1665 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1666 return FALSE;
1667 }
1668
1669 if (!Soft386FetchByte(State, &SecondValue))
1670 {
1671 /* Exception occurred */
1672 return FALSE;
1673 }
1674
1675 /* Calculate the result */
1676 Result = FirstValue | SecondValue;
1677
1678 /* Update the flags */
1679 State->Flags.Cf = FALSE;
1680 State->Flags.Of = FALSE;
1681 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1682 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
1683 State->Flags.Pf = Soft386CalculateParity(Result);
1684
1685 /* Write back the result */
1686 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
1687
1688 return TRUE;
1689 }
1690
1691 SOFT386_OPCODE_HANDLER(Soft386OpcodeOrEax)
1692 {
1693 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
1694
1695 /* Make sure this is the right instruction */
1696 ASSERT(Opcode == 0x0D);
1697
1698 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
1699 {
1700 /* The OPSIZE prefix toggles the size */
1701 Size = !Size;
1702 }
1703 else
1704 {
1705 /* Invalid prefix */
1706 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1707 return FALSE;
1708 }
1709
1710 if (Size)
1711 {
1712 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
1713 ULONG SecondValue, Result;
1714
1715 if (!Soft386FetchDword(State, &SecondValue))
1716 {
1717 /* Exception occurred */
1718 return FALSE;
1719 }
1720
1721 /* Calculate the result */
1722 Result = FirstValue | SecondValue;
1723
1724 /* Update the flags */
1725 State->Flags.Cf = FALSE;
1726 State->Flags.Of = FALSE;
1727 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1728 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
1729 State->Flags.Pf = Soft386CalculateParity(Result);
1730
1731 /* Write back the result */
1732 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
1733 }
1734 else
1735 {
1736 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
1737 USHORT SecondValue, Result;
1738
1739 if (!Soft386FetchWord(State, &SecondValue))
1740 {
1741 /* Exception occurred */
1742 return FALSE;
1743 }
1744
1745 /* Calculate the result */
1746 Result = FirstValue | SecondValue;
1747
1748 /* Update the flags */
1749 State->Flags.Cf = FALSE;
1750 State->Flags.Of = FALSE;
1751 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1752 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
1753 State->Flags.Pf = Soft386CalculateParity(Result);
1754
1755 /* Write back the result */
1756 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
1757 }
1758
1759 return TRUE;
1760 }
1761
1762 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndByteModrm)
1763 {
1764 UCHAR FirstValue, SecondValue, Result;
1765 SOFT386_MOD_REG_RM ModRegRm;
1766 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
1767
1768 /* Make sure this is the right instruction */
1769 ASSERT((Opcode & 0xFD) == 0x20);
1770
1771 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
1772 {
1773 /* The ADSIZE prefix toggles the size */
1774 AddressSize = !AddressSize;
1775 }
1776 else if (State->PrefixFlags
1777 & ~(SOFT386_PREFIX_ADSIZE
1778 | SOFT386_PREFIX_SEG
1779 | SOFT386_PREFIX_LOCK))
1780 {
1781 /* Invalid prefix */
1782 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1783 return FALSE;
1784 }
1785
1786 /* Get the operands */
1787 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
1788 {
1789 /* Exception occurred */
1790 return FALSE;
1791 }
1792
1793 if (!Soft386ReadModrmByteOperands(State,
1794 &ModRegRm,
1795 &FirstValue,
1796 &SecondValue))
1797 {
1798 /* Exception occurred */
1799 return FALSE;
1800 }
1801
1802 /* Calculate the result */
1803 Result = FirstValue & SecondValue;
1804
1805 /* Update the flags */
1806 State->Flags.Cf = FALSE;
1807 State->Flags.Of = FALSE;
1808 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1809 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
1810 State->Flags.Pf = Soft386CalculateParity(Result);
1811
1812 /* Write back the result */
1813 return Soft386WriteModrmByteOperands(State,
1814 &ModRegRm,
1815 Opcode & SOFT386_OPCODE_WRITE_REG,
1816 Result);
1817 }
1818
1819 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndModrm)
1820 {
1821 SOFT386_MOD_REG_RM ModRegRm;
1822 BOOLEAN OperandSize, AddressSize;
1823
1824 /* Make sure this is the right instruction */
1825 ASSERT((Opcode & 0xFD) == 0x21);
1826
1827 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
1828
1829 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
1830 {
1831 /* The ADSIZE prefix toggles the address size */
1832 AddressSize = !AddressSize;
1833 }
1834
1835 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
1836 {
1837 /* The OPSIZE prefix toggles the operand size */
1838 OperandSize = !OperandSize;
1839 }
1840
1841 if (State->PrefixFlags
1842 & ~(SOFT386_PREFIX_ADSIZE
1843 | SOFT386_PREFIX_OPSIZE
1844 | SOFT386_PREFIX_SEG
1845 | SOFT386_PREFIX_LOCK))
1846 {
1847 /* Invalid prefix */
1848 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1849 return FALSE;
1850 }
1851
1852 /* Get the operands */
1853 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
1854 {
1855 /* Exception occurred */
1856 return FALSE;
1857 }
1858
1859 /* Check the operand size */
1860 if (OperandSize)
1861 {
1862 ULONG FirstValue, SecondValue, Result;
1863
1864 if (!Soft386ReadModrmDwordOperands(State,
1865 &ModRegRm,
1866 &FirstValue,
1867 &SecondValue))
1868 {
1869 /* Exception occurred */
1870 return FALSE;
1871 }
1872
1873 /* Calculate the result */
1874 Result = FirstValue & SecondValue;
1875
1876 /* Update the flags */
1877 State->Flags.Cf = FALSE;
1878 State->Flags.Of = FALSE;
1879 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1880 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
1881 State->Flags.Pf = Soft386CalculateParity(Result);
1882
1883 /* Write back the result */
1884 return Soft386WriteModrmDwordOperands(State,
1885 &ModRegRm,
1886 Opcode & SOFT386_OPCODE_WRITE_REG,
1887 Result);
1888 }
1889 else
1890 {
1891 USHORT FirstValue, SecondValue, Result;
1892
1893 if (!Soft386ReadModrmWordOperands(State,
1894 &ModRegRm,
1895 &FirstValue,
1896 &SecondValue))
1897 {
1898 /* Exception occurred */
1899 return FALSE;
1900 }
1901
1902 /* Calculate the result */
1903 Result = FirstValue & SecondValue;
1904
1905 /* Update the flags */
1906 State->Flags.Cf = FALSE;
1907 State->Flags.Of = FALSE;
1908 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1909 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
1910 State->Flags.Pf = Soft386CalculateParity(Result);
1911
1912 /* Write back the result */
1913 return Soft386WriteModrmWordOperands(State,
1914 &ModRegRm,
1915 Opcode & SOFT386_OPCODE_WRITE_REG,
1916 Result);
1917 }
1918 }
1919
1920 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndAl)
1921 {
1922 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
1923 UCHAR SecondValue, Result;
1924
1925 /* Make sure this is the right instruction */
1926 ASSERT(Opcode == 0x24);
1927
1928 if (State->PrefixFlags)
1929 {
1930 /* This opcode doesn't take any prefixes */
1931 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1932 return FALSE;
1933 }
1934
1935 if (!Soft386FetchByte(State, &SecondValue))
1936 {
1937 /* Exception occurred */
1938 return FALSE;
1939 }
1940
1941 /* Calculate the result */
1942 Result = FirstValue & SecondValue;
1943
1944 /* Update the flags */
1945 State->Flags.Cf = FALSE;
1946 State->Flags.Of = FALSE;
1947 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1948 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
1949 State->Flags.Pf = Soft386CalculateParity(Result);
1950
1951 /* Write back the result */
1952 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
1953
1954 return TRUE;
1955 }
1956
1957 SOFT386_OPCODE_HANDLER(Soft386OpcodeAndEax)
1958 {
1959 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
1960
1961 /* Make sure this is the right instruction */
1962 ASSERT(Opcode == 0x25);
1963
1964 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
1965 {
1966 /* The OPSIZE prefix toggles the size */
1967 Size = !Size;
1968 }
1969 else
1970 {
1971 /* Invalid prefix */
1972 Soft386Exception(State, SOFT386_EXCEPTION_UD);
1973 return FALSE;
1974 }
1975
1976 if (Size)
1977 {
1978 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
1979 ULONG SecondValue, Result;
1980
1981 if (!Soft386FetchDword(State, &SecondValue))
1982 {
1983 /* Exception occurred */
1984 return FALSE;
1985 }
1986
1987 /* Calculate the result */
1988 Result = FirstValue & SecondValue;
1989
1990 /* Update the flags */
1991 State->Flags.Cf = FALSE;
1992 State->Flags.Of = FALSE;
1993 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
1994 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
1995 State->Flags.Pf = Soft386CalculateParity(Result);
1996
1997 /* Write back the result */
1998 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
1999 }
2000 else
2001 {
2002 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
2003 USHORT SecondValue, Result;
2004
2005 if (!Soft386FetchWord(State, &SecondValue))
2006 {
2007 /* Exception occurred */
2008 return FALSE;
2009 }
2010
2011 /* Calculate the result */
2012 Result = FirstValue & SecondValue;
2013
2014 /* Update the flags */
2015 State->Flags.Cf = FALSE;
2016 State->Flags.Of = FALSE;
2017 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2018 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
2019 State->Flags.Pf = Soft386CalculateParity(Result);
2020
2021 /* Write back the result */
2022 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
2023 }
2024
2025 return TRUE;
2026 }
2027
2028 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorByteModrm)
2029 {
2030 UCHAR FirstValue, SecondValue, Result;
2031 SOFT386_MOD_REG_RM ModRegRm;
2032 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2033
2034 /* Make sure this is the right instruction */
2035 ASSERT((Opcode & 0xFD) == 0x30);
2036
2037 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2038 {
2039 /* The ADSIZE prefix toggles the size */
2040 AddressSize = !AddressSize;
2041 }
2042 else if (State->PrefixFlags
2043 & ~(SOFT386_PREFIX_ADSIZE
2044 | SOFT386_PREFIX_SEG
2045 | SOFT386_PREFIX_LOCK))
2046 {
2047 /* Invalid prefix */
2048 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2049 return FALSE;
2050 }
2051
2052 /* Get the operands */
2053 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2054 {
2055 /* Exception occurred */
2056 return FALSE;
2057 }
2058
2059 if (!Soft386ReadModrmByteOperands(State,
2060 &ModRegRm,
2061 &FirstValue,
2062 &SecondValue))
2063 {
2064 /* Exception occurred */
2065 return FALSE;
2066 }
2067
2068 /* Calculate the result */
2069 Result = FirstValue ^ SecondValue;
2070
2071 /* Update the flags */
2072 State->Flags.Cf = FALSE;
2073 State->Flags.Of = FALSE;
2074 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2075 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
2076 State->Flags.Pf = Soft386CalculateParity(Result);
2077
2078 /* Write back the result */
2079 return Soft386WriteModrmByteOperands(State,
2080 &ModRegRm,
2081 Opcode & SOFT386_OPCODE_WRITE_REG,
2082 Result);
2083 }
2084
2085 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorModrm)
2086 {
2087 SOFT386_MOD_REG_RM ModRegRm;
2088 BOOLEAN OperandSize, AddressSize;
2089
2090 /* Make sure this is the right instruction */
2091 ASSERT((Opcode & 0xFD) == 0x31);
2092
2093 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2094
2095 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2096 {
2097 /* The ADSIZE prefix toggles the address size */
2098 AddressSize = !AddressSize;
2099 }
2100
2101 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2102 {
2103 /* The OPSIZE prefix toggles the operand size */
2104 OperandSize = !OperandSize;
2105 }
2106
2107 if (State->PrefixFlags
2108 & ~(SOFT386_PREFIX_ADSIZE
2109 | SOFT386_PREFIX_OPSIZE
2110 | SOFT386_PREFIX_SEG
2111 | SOFT386_PREFIX_LOCK))
2112 {
2113 /* Invalid prefix */
2114 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2115 return FALSE;
2116 }
2117
2118 /* Get the operands */
2119 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2120 {
2121 /* Exception occurred */
2122 return FALSE;
2123 }
2124
2125 /* Check the operand size */
2126 if (OperandSize)
2127 {
2128 ULONG FirstValue, SecondValue, Result;
2129
2130 if (!Soft386ReadModrmDwordOperands(State,
2131 &ModRegRm,
2132 &FirstValue,
2133 &SecondValue))
2134 {
2135 /* Exception occurred */
2136 return FALSE;
2137 }
2138
2139 /* Calculate the result */
2140 Result = FirstValue ^ SecondValue;
2141
2142 /* Update the flags */
2143 State->Flags.Cf = FALSE;
2144 State->Flags.Of = FALSE;
2145 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2146 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
2147 State->Flags.Pf = Soft386CalculateParity(Result);
2148
2149 /* Write back the result */
2150 return Soft386WriteModrmDwordOperands(State,
2151 &ModRegRm,
2152 Opcode & SOFT386_OPCODE_WRITE_REG,
2153 Result);
2154 }
2155 else
2156 {
2157 USHORT FirstValue, SecondValue, Result;
2158
2159 if (!Soft386ReadModrmWordOperands(State,
2160 &ModRegRm,
2161 &FirstValue,
2162 &SecondValue))
2163 {
2164 /* Exception occurred */
2165 return FALSE;
2166 }
2167
2168 /* Calculate the result */
2169 Result = FirstValue ^ SecondValue;
2170
2171 /* Update the flags */
2172 State->Flags.Cf = FALSE;
2173 State->Flags.Of = FALSE;
2174 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2175 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
2176 State->Flags.Pf = Soft386CalculateParity(Result);
2177
2178 /* Write back the result */
2179 return Soft386WriteModrmWordOperands(State,
2180 &ModRegRm,
2181 Opcode & SOFT386_OPCODE_WRITE_REG,
2182 Result);
2183 }
2184 }
2185
2186 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorAl)
2187 {
2188 UCHAR FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowByte;
2189 UCHAR SecondValue, Result;
2190
2191 /* Make sure this is the right instruction */
2192 ASSERT(Opcode == 0x34);
2193
2194 if (State->PrefixFlags)
2195 {
2196 /* This opcode doesn't take any prefixes */
2197 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2198 return FALSE;
2199 }
2200
2201 if (!Soft386FetchByte(State, &SecondValue))
2202 {
2203 /* Exception occurred */
2204 return FALSE;
2205 }
2206
2207 /* Calculate the result */
2208 Result = FirstValue ^ SecondValue;
2209
2210 /* Update the flags */
2211 State->Flags.Cf = FALSE;
2212 State->Flags.Of = FALSE;
2213 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2214 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
2215 State->Flags.Pf = Soft386CalculateParity(Result);
2216
2217 /* Write back the result */
2218 State->GeneralRegs[SOFT386_REG_EAX].LowByte = Result;
2219
2220 return TRUE;
2221 }
2222
2223 SOFT386_OPCODE_HANDLER(Soft386OpcodeXorEax)
2224 {
2225 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
2226
2227 /* Make sure this is the right instruction */
2228 ASSERT(Opcode == 0x35);
2229
2230 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
2231 {
2232 /* The OPSIZE prefix toggles the size */
2233 Size = !Size;
2234 }
2235 else
2236 {
2237 /* Invalid prefix */
2238 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2239 return FALSE;
2240 }
2241
2242 if (Size)
2243 {
2244 ULONG FirstValue = State->GeneralRegs[SOFT386_REG_EAX].Long;
2245 ULONG SecondValue, Result;
2246
2247 if (!Soft386FetchDword(State, &SecondValue))
2248 {
2249 /* Exception occurred */
2250 return FALSE;
2251 }
2252
2253 /* Calculate the result */
2254 Result = FirstValue ^ SecondValue;
2255
2256 /* Update the flags */
2257 State->Flags.Cf = FALSE;
2258 State->Flags.Of = FALSE;
2259 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2260 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
2261 State->Flags.Pf = Soft386CalculateParity(Result);
2262
2263 /* Write back the result */
2264 State->GeneralRegs[SOFT386_REG_EAX].Long = Result;
2265 }
2266 else
2267 {
2268 USHORT FirstValue = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
2269 USHORT SecondValue, Result;
2270
2271 if (!Soft386FetchWord(State, &SecondValue))
2272 {
2273 /* Exception occurred */
2274 return FALSE;
2275 }
2276
2277 /* Calculate the result */
2278 Result = FirstValue ^ SecondValue;
2279
2280 /* Update the flags */
2281 State->Flags.Cf = FALSE;
2282 State->Flags.Of = FALSE;
2283 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2284 State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
2285 State->Flags.Pf = Soft386CalculateParity(Result);
2286
2287 /* Write back the result */
2288 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
2289 }
2290
2291 return TRUE;
2292 }
2293
2294 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestByteModrm)
2295 {
2296 UCHAR FirstValue, SecondValue, Result;
2297 SOFT386_MOD_REG_RM ModRegRm;
2298 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2299
2300 /* Make sure this is the right instruction */
2301 ASSERT(Opcode == 0x84);
2302
2303 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2304 {
2305 /* The ADSIZE prefix toggles the size */
2306 AddressSize = !AddressSize;
2307 }
2308 else if (State->PrefixFlags
2309 & ~(SOFT386_PREFIX_ADSIZE
2310 | SOFT386_PREFIX_SEG
2311 | SOFT386_PREFIX_LOCK))
2312 {
2313 /* Invalid prefix */
2314 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2315 return FALSE;
2316 }
2317
2318 /* Get the operands */
2319 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2320 {
2321 /* Exception occurred */
2322 return FALSE;
2323 }
2324
2325 if (!Soft386ReadModrmByteOperands(State,
2326 &ModRegRm,
2327 &FirstValue,
2328 &SecondValue))
2329 {
2330 /* Exception occurred */
2331 return FALSE;
2332 }
2333 /* Calculate the result */
2334 Result = FirstValue & SecondValue;
2335
2336 /* Update the flags */
2337 State->Flags.Cf = FALSE;
2338 State->Flags.Of = FALSE;
2339 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2340 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
2341 State->Flags.Pf = Soft386CalculateParity(Result);
2342
2343 /* The result is discarded */
2344 return TRUE;
2345 }
2346
2347 SOFT386_OPCODE_HANDLER(Soft386OpcodeTestModrm)
2348 {
2349 SOFT386_MOD_REG_RM ModRegRm;
2350 BOOLEAN OperandSize, AddressSize;
2351
2352 /* Make sure this is the right instruction */
2353 ASSERT(Opcode == 0x85);
2354
2355 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2356
2357 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2358 {
2359 /* The ADSIZE prefix toggles the address size */
2360 AddressSize = !AddressSize;
2361 }
2362
2363 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2364 {
2365 /* The OPSIZE prefix toggles the operand size */
2366 OperandSize = !OperandSize;
2367 }
2368
2369 if (State->PrefixFlags
2370 & ~(SOFT386_PREFIX_ADSIZE
2371 | SOFT386_PREFIX_OPSIZE
2372 | SOFT386_PREFIX_SEG
2373 | SOFT386_PREFIX_LOCK))
2374 {
2375 /* Invalid prefix */
2376 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2377 return FALSE;
2378 }
2379
2380 /* Get the operands */
2381 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2382 {
2383 /* Exception occurred */
2384 return FALSE;
2385 }
2386
2387 /* Check the operand size */
2388 if (OperandSize)
2389 {
2390 ULONG FirstValue, SecondValue, Result;
2391
2392 if (!Soft386ReadModrmDwordOperands(State,
2393 &ModRegRm,
2394 &FirstValue,
2395 &SecondValue))
2396 {
2397 /* Exception occurred */
2398 return FALSE;
2399 }
2400
2401 /* Calculate the result */
2402 Result = FirstValue & SecondValue;
2403
2404 /* Update the flags */
2405 State->Flags.Cf = FALSE;
2406 State->Flags.Of = FALSE;
2407 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2408 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
2409 State->Flags.Pf = Soft386CalculateParity(Result);
2410 }
2411 else
2412 {
2413 USHORT FirstValue, SecondValue, Result;
2414
2415 if (!Soft386ReadModrmWordOperands(State,
2416 &ModRegRm,
2417 &FirstValue,
2418 &SecondValue))
2419 {
2420 /* Exception occurred */
2421 return FALSE;
2422 }
2423
2424 /* Calculate the result */
2425 Result = FirstValue & SecondValue;
2426
2427 /* Update the flags */
2428 State->Flags.Cf = FALSE;
2429 State->Flags.Of = FALSE;
2430 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
2431 State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
2432 State->Flags.Pf = Soft386CalculateParity(Result);
2433 }
2434
2435 /* The result is discarded */
2436 return TRUE;
2437 }
2438
2439 SOFT386_OPCODE_HANDLER(Soft386OpcodeXchgByteModrm)
2440 {
2441 UCHAR FirstValue, SecondValue;
2442 SOFT386_MOD_REG_RM ModRegRm;
2443 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2444
2445 /* Make sure this is the right instruction */
2446 ASSERT(Opcode == 0x86);
2447
2448 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2449 {
2450 /* The ADSIZE prefix toggles the size */
2451 AddressSize = !AddressSize;
2452 }
2453 else if (State->PrefixFlags
2454 & ~(SOFT386_PREFIX_ADSIZE
2455 | SOFT386_PREFIX_SEG
2456 | SOFT386_PREFIX_LOCK))
2457 {
2458 /* Invalid prefix */
2459 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2460 return FALSE;
2461 }
2462
2463 /* Get the operands */
2464 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2465 {
2466 /* Exception occurred */
2467 return FALSE;
2468 }
2469
2470 if (!Soft386ReadModrmByteOperands(State,
2471 &ModRegRm,
2472 &FirstValue,
2473 &SecondValue))
2474 {
2475 /* Exception occurred */
2476 return FALSE;
2477 }
2478
2479 /* Write the value from the register to the R/M */
2480 if (!Soft386WriteModrmByteOperands(State,
2481 &ModRegRm,
2482 FALSE,
2483 FirstValue))
2484 {
2485 /* Exception occurred */
2486 return FALSE;
2487 }
2488
2489 /* Write the value from the R/M to the register */
2490 if (!Soft386WriteModrmByteOperands(State,
2491 &ModRegRm,
2492 TRUE,
2493 SecondValue))
2494 {
2495 /* Exception occurred */
2496 return FALSE;
2497 }
2498
2499 return TRUE;
2500 }
2501
2502 SOFT386_OPCODE_HANDLER(Soft386OpcodeXchgModrm)
2503 {
2504 SOFT386_MOD_REG_RM ModRegRm;
2505 BOOLEAN OperandSize, AddressSize;
2506
2507 /* Make sure this is the right instruction */
2508 ASSERT(Opcode == 0x87);
2509
2510 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
2511
2512 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
2513 {
2514 /* The ADSIZE prefix toggles the address size */
2515 AddressSize = !AddressSize;
2516 }
2517
2518 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
2519 {
2520 /* The OPSIZE prefix toggles the operand size */
2521 OperandSize = !OperandSize;
2522 }
2523
2524 if (State->PrefixFlags
2525 & ~(SOFT386_PREFIX_ADSIZE
2526 | SOFT386_PREFIX_OPSIZE
2527 | SOFT386_PREFIX_SEG
2528 | SOFT386_PREFIX_LOCK))
2529 {
2530 /* Invalid prefix */
2531 Soft386Exception(State, SOFT386_EXCEPTION_UD);
2532 return FALSE;
2533 }
2534
2535 /* Get the operands */
2536 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
2537 {
2538 /* Exception occurred */
2539 return FALSE;
2540 }
2541
2542 /* Check the operand size */
2543 if (OperandSize)
2544 {
2545 ULONG FirstValue, SecondValue;
2546
2547 if (!Soft386ReadModrmDwordOperands(State,
2548 &ModRegRm,
2549 &FirstValue,
2550 &SecondValue))
2551 {
2552 /* Exception occurred */
2553 return FALSE;
2554 }
2555
2556 /* Write the value from the register to the R/M */
2557 if (!Soft386WriteModrmDwordOperands(State,
2558 &ModRegRm,
2559 FALSE,
2560 FirstValue))
2561 {
2562 /* Exception occurred */
2563 return FALSE;
2564 }
2565
2566 /* Write the value from the R/M to the register */
2567 if (!Soft386WriteModrmDwordOperands(State,
2568 &ModRegRm,
2569 TRUE,
2570 SecondValue))
2571 {
2572 /* Exception occurred */
2573 return FALSE;
2574 }
2575 }
2576 else
2577 {
2578 USHORT FirstValue, SecondValue;
2579
2580 if (!Soft386ReadModrmWordOperands(State,
2581 &ModRegRm,
2582 &FirstValue,
2583 &SecondValue))
2584 {
2585 /* Exception occurred */
2586 return FALSE;
2587 }
2588
2589 /* Write the value from the register to the R/M */
2590 if (!Soft386WriteModrmWordOperands(State,
2591 &ModRegRm,
2592 FALSE,
2593 FirstValue))
2594 {
2595 /* Exception occurred */
2596 return FALSE;
2597 }
2598
2599 /* Write the value from the R/M to the register */
2600 if (!Soft386WriteModrmWordOperands(State,
2601 &ModRegRm,
2602 TRUE,
2603 SecondValue))
2604 {
2605 /* Exception occurred */
2606 return FALSE;
2607 }
2608 }
2609
2610 /* The result is discarded */
2611 return TRUE;
2612 }