[SOFT386]
[reactos.git] / lib / soft386 / opgroups.c
1 /*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: 386/486 CPU Emulation Library
4 * FILE: opgroups.c
5 * PURPOSE: Opcode group handlers.
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 // #define WIN32_NO_STATUS
12 // #define _INC_WINDOWS
13 #include <windef.h>
14
15 // #define NDEBUG
16 #include <debug.h>
17
18 #include <soft386.h>
19 #include "opcodes.h"
20 #include "common.h"
21
22 /* PRIVATE FUNCTIONS **********************************************************/
23
24 static
25 inline
26 ULONG
27 Soft386RotateOperation(PSOFT386_STATE State,
28 INT Operation,
29 ULONG Value,
30 UCHAR Bits,
31 UCHAR Count)
32 {
33 ULONG HighestBit = 1 << (Bits - 1);
34 ULONG Result;
35
36 if ((Operation != 2) && (Operation != 3))
37 {
38 /* Mask the count */
39 Count &= Bits - 1;
40 }
41 else
42 {
43 /* For RCL and RCR, the CF is included in the value */
44 Count %= Bits + 1;
45 }
46
47 /* Check which operation is this */
48 switch (Operation)
49 {
50 /* ROL */
51 case 0:
52 {
53 Result = (Value << Count) | (Value >> (Bits - Count));
54
55 /* Update CF and OF */
56 State->Flags.Cf = Result & 1;
57 if (Count == 1) State->Flags.Of = ((Result & HighestBit) ? TRUE : FALSE)
58 ^ State->Flags.Cf;
59
60 break;
61 }
62
63 /* ROR */
64 case 1:
65 {
66 Result = (Value >> Count) | (Value << (Bits - Count));
67
68 /* Update CF and OF */
69 State->Flags.Cf = (Result & HighestBit) ? TRUE : FALSE;
70 if (Count == 1) State->Flags.Of = State->Flags.Cf
71 ^ ((Result & (HighestBit >> 1))
72 ? TRUE : FALSE);
73
74 break;
75 }
76
77 /* RCL */
78 case 2:
79 {
80 Result = (Value << Count)
81 | (State->Flags.Cf << (Count - 1))
82 | (Value >> (Bits - Count + 1));
83
84 /* Update CF and OF */
85 State->Flags.Cf = (Value & (1 << (Bits - Count))) ? TRUE : FALSE;
86 if (Count == 1) State->Flags.Of = ((Result & HighestBit) ? TRUE : FALSE)
87 ^ State->Flags.Cf;
88
89 break;
90 }
91
92 /* RCR */
93 case 3:
94 {
95 Result = (Value >> Count)
96 | (State->Flags.Cf << (Bits - Count))
97 | (Value << (Bits - Count + 1));
98
99 /* Update CF and OF */
100 State->Flags.Cf = (Value & (1 << (Bits - Count))) ? TRUE : FALSE;
101 if (Count == 1) State->Flags.Of = State->Flags.Cf
102 ^ ((Result & (HighestBit >> 1))
103 ? TRUE : FALSE);
104
105 break;
106 }
107
108 /* SHL/SAL */
109 case 4:
110 case 6:
111 {
112 Result = Value << Count;
113
114 /* Update CF and OF */
115 State->Flags.Cf = (Value & (1 << (Bits - Count))) ? TRUE : FALSE;
116 if (Count == 1) State->Flags.Of = ((Result & HighestBit) ? TRUE : FALSE)
117 ^ (State->Flags.Cf ? TRUE : FALSE);
118
119 break;
120 }
121
122 /* SHR */
123 case 5:
124 {
125 Result = Value >> Count;
126
127 /* Update CF and OF */
128 State->Flags.Cf = (Value & (1 << (Count - 1))) ? TRUE : FALSE;
129 if (Count == 1) State->Flags.Of = (Value & HighestBit) ? TRUE : FALSE;
130
131 break;
132 }
133
134 /* SAR */
135 case 7:
136 {
137 Result = Value >> Count;
138
139 /* Fill the top Count bits with the sign bit */
140 if (Value & HighestBit) Result |= ((1 << Count) - 1) << (Bits - Count);
141
142 /* Update CF and OF */
143 State->Flags.Cf = Value & 1;
144 if (Count == 1) State->Flags.Of = FALSE;
145
146 break;
147 }
148 }
149
150 /* Update ZF, SF and PF */
151 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
152 State->Flags.Sf = (Result & HighestBit) ? TRUE : FALSE;
153 State->Flags.Pf = Soft386CalculateParity(Result);
154
155 /* Return the result */
156 return Result;
157 }
158
159 /* PUBLIC FUNCTIONS ***********************************************************/
160
161 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroup8082)
162 {
163 UCHAR Immediate, Result, Dummy, Value;
164 SOFT386_MOD_REG_RM ModRegRm;
165 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
166
167 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
168 {
169 /* The ADSIZE prefix toggles the size */
170 AddressSize = !AddressSize;
171 }
172
173 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
174 {
175 /* Exception occurred */
176 return FALSE;
177 }
178
179 /* Fetch the immediate operand */
180 if (!Soft386FetchByte(State, &Immediate))
181 {
182 /* Exception occurred */
183 return FALSE;
184 }
185
186 /* Read the operands */
187 if (!Soft386ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
188 {
189 /* Exception occurred */
190 return FALSE;
191 }
192
193 /* Check which operation is this */
194 switch (ModRegRm.Register)
195 {
196 /* ADD */
197 case 0:
198 {
199 Result = Value + Immediate;
200
201 /* Update CF, OF and AF */
202 State->Flags.Cf = (Result < Value) && (Result < Immediate);
203 State->Flags.Of = ((Value & SIGN_FLAG_BYTE) == (Immediate & SIGN_FLAG_BYTE))
204 && ((Value & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
205 State->Flags.Af = (((Value & 0x0F) + (Immediate & 0x0F)) & 0x10) ? TRUE : FALSE;
206
207 break;
208 }
209
210 /* OR */
211 case 1:
212 {
213 Result = Value | Immediate;
214 break;
215 }
216
217 /* ADC */
218 case 2:
219 {
220 INT Carry = State->Flags.Cf ? 1 : 0;
221
222 Result = Value + Immediate + Carry;
223
224 /* Update CF, OF and AF */
225 State->Flags.Cf = ((Immediate == 0xFF) && (Carry == 1))
226 || ((Result < Value) && (Result < (Immediate + Carry)));
227 State->Flags.Of = ((Value & SIGN_FLAG_BYTE) == (Immediate & SIGN_FLAG_BYTE))
228 && ((Value & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
229 State->Flags.Af = (((Value & 0x0F) + ((Immediate + Carry) & 0x0F)) & 0x10)
230 ? TRUE : FALSE;
231
232 break;
233 }
234
235 /* SBB */
236 case 3:
237 {
238 INT Carry = State->Flags.Cf ? 1 : 0;
239
240 Result = Value - Immediate - Carry;
241
242 /* Update CF, OF and AF */
243 State->Flags.Cf = Value < (Immediate + Carry);
244 State->Flags.Of = ((Value & SIGN_FLAG_BYTE) != (Immediate & SIGN_FLAG_BYTE))
245 && ((Value & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
246 State->Flags.Af = (Value & 0x0F) < ((Immediate + Carry) & 0x0F);
247
248 break;
249 }
250
251 /* AND */
252 case 4:
253 {
254 Result = Value & Immediate;
255 break;
256 }
257
258 /* SUB or CMP */
259 case 5:
260 case 7:
261 {
262 Result = Value - Immediate;
263
264 /* Update CF, OF and AF */
265 State->Flags.Cf = Value < Immediate;
266 State->Flags.Of = ((Value & SIGN_FLAG_BYTE) != (Immediate & SIGN_FLAG_BYTE))
267 && ((Value & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
268 State->Flags.Af = (Value & 0x0F) < (Immediate & 0x0F);
269
270 break;
271 }
272
273 /* XOR */
274 case 6:
275 {
276 Value ^= Immediate;
277 break;
278 }
279
280 default:
281 {
282 /* Shouldn't happen */
283 ASSERT(FALSE);
284 }
285 }
286
287 /* Update ZF, SF and PF */
288 State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
289 State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
290 State->Flags.Pf = Soft386CalculateParity(Result);
291
292 /* Unless this is CMP, write back the result */
293 if (ModRegRm.Register != 7)
294 {
295 return Soft386WriteModrmByteOperands(State, &ModRegRm, FALSE, Result);
296 }
297
298 return TRUE;
299 }
300
301 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroup81)
302 {
303 UNIMPLEMENTED;
304 return FALSE; // TODO: NOT IMPLEMENTED
305 }
306
307 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroup83)
308 {
309 UNIMPLEMENTED;
310 return FALSE; // TODO: NOT IMPLEMENTED
311 }
312
313 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroup8F)
314 {
315 ULONG Value;
316 SOFT386_MOD_REG_RM ModRegRm;
317 BOOLEAN OperandSize, AddressSize;
318
319 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
320
321 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
322 {
323 /* The OPSIZE prefix toggles the size */
324 OperandSize = !OperandSize;
325 }
326
327 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
328 {
329 /* The ADSIZE prefix toggles the size */
330 AddressSize = !AddressSize;
331 }
332
333 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
334 {
335 /* Exception occurred */
336 return FALSE;
337 }
338
339 if (ModRegRm.Register != 0)
340 {
341 /* Invalid */
342 Soft386Exception(State, SOFT386_EXCEPTION_UD);
343 return FALSE;
344 }
345
346 /* Pop a value from the stack */
347 if (!Soft386StackPop(State, &Value))
348 {
349 /* Exception occurred */
350 return FALSE;
351 }
352
353 if (OperandSize)
354 {
355 return Soft386WriteModrmDwordOperands(State,
356 &ModRegRm,
357 FALSE,
358 Value);
359 }
360 else
361 {
362 return Soft386WriteModrmWordOperands(State,
363 &ModRegRm,
364 FALSE,
365 LOWORD(Value));
366 }
367 }
368
369 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupC0)
370 {
371 UCHAR Dummy, Value, Count;
372 SOFT386_MOD_REG_RM ModRegRm;
373 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
374
375 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
376 {
377 /* The ADSIZE prefix toggles the size */
378 AddressSize = !AddressSize;
379 }
380
381 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
382 {
383 /* Exception occurred */
384 return FALSE;
385 }
386
387 /* Read the operands */
388 if (!Soft386ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
389 {
390 /* Exception occurred */
391 return FALSE;
392 }
393
394 /* Fetch the count */
395 if (!Soft386FetchByte(State, &Count))
396 {
397 /* Exception occurred */
398 return FALSE;
399 }
400
401 /* Calculate the result */
402 Value = LOBYTE(Soft386RotateOperation(State,
403 ModRegRm.Register,
404 Value,
405 8,
406 Count));
407
408 /* Write back the result */
409 return Soft386WriteModrmByteOperands(State,
410 &ModRegRm,
411 FALSE,
412 Value);
413 }
414
415 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupC1)
416 {
417 UCHAR Count;
418 SOFT386_MOD_REG_RM ModRegRm;
419 BOOLEAN OperandSize, AddressSize;
420
421 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
422
423 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
424 {
425 /* The OPSIZE prefix toggles the size */
426 OperandSize = !OperandSize;
427 }
428
429 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
430 {
431 /* The ADSIZE prefix toggles the size */
432 AddressSize = !AddressSize;
433 }
434
435 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
436 {
437 /* Exception occurred */
438 return FALSE;
439 }
440
441 /* Fetch the count */
442 if (!Soft386FetchByte(State, &Count))
443 {
444 /* Exception occurred */
445 return FALSE;
446 }
447
448 if (OperandSize)
449 {
450 ULONG Dummy, Value;
451
452 /* Read the operands */
453 if (!Soft386ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value))
454 {
455 /* Exception occurred */
456 return FALSE;
457 }
458
459 /* Calculate the result */
460 Value = Soft386RotateOperation(State,
461 ModRegRm.Register,
462 Value,
463 32,
464 Count);
465
466 /* Write back the result */
467 return Soft386WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value);
468 }
469 else
470 {
471 USHORT Dummy, Value;
472
473 /* Read the operands */
474 if (!Soft386ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value))
475 {
476 /* Exception occurred */
477 return FALSE;
478 }
479
480 /* Calculate the result */
481 Value = LOWORD(Soft386RotateOperation(State,
482 ModRegRm.Register,
483 Value,
484 16,
485 Count));
486
487 /* Write back the result */
488 return Soft386WriteModrmWordOperands(State, &ModRegRm, FALSE, Value);
489 }
490 }
491
492 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupC6)
493 {
494 UCHAR Immediate;
495 SOFT386_MOD_REG_RM ModRegRm;
496 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
497
498 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
499 {
500 /* The ADSIZE prefix toggles the size */
501 AddressSize = !AddressSize;
502 }
503
504 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
505 {
506 /* Exception occurred */
507 return FALSE;
508 }
509
510 if (ModRegRm.Register != 0)
511 {
512 /* Invalid */
513 Soft386Exception(State, SOFT386_EXCEPTION_UD);
514 return FALSE;
515 }
516
517 /* Get the immediate operand */
518 if (!Soft386FetchByte(State, &Immediate))
519 {
520 /* Exception occurred */
521 return FALSE;
522 }
523
524 return Soft386WriteModrmByteOperands(State,
525 &ModRegRm,
526 FALSE,
527 Immediate);
528 }
529
530 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupC7)
531 {
532 SOFT386_MOD_REG_RM ModRegRm;
533 BOOLEAN OperandSize, AddressSize;
534
535 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
536
537 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
538 {
539 /* The OPSIZE prefix toggles the size */
540 OperandSize = !OperandSize;
541 }
542
543 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
544 {
545 /* The ADSIZE prefix toggles the size */
546 AddressSize = !AddressSize;
547 }
548
549 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
550 {
551 /* Exception occurred */
552 return FALSE;
553 }
554
555 if (ModRegRm.Register != 0)
556 {
557 /* Invalid */
558 Soft386Exception(State, SOFT386_EXCEPTION_UD);
559 return FALSE;
560 }
561
562 if (OperandSize)
563 {
564 ULONG Immediate;
565
566 /* Get the immediate operand */
567 if (!Soft386FetchDword(State, &Immediate))
568 {
569 /* Exception occurred */
570 return FALSE;
571 }
572
573 return Soft386WriteModrmDwordOperands(State,
574 &ModRegRm,
575 FALSE,
576 Immediate);
577 }
578 else
579 {
580 USHORT Immediate;
581
582 /* Get the immediate operand */
583 if (!Soft386FetchWord(State, &Immediate))
584 {
585 /* Exception occurred */
586 return FALSE;
587 }
588
589 return Soft386WriteModrmWordOperands(State,
590 &ModRegRm,
591 FALSE,
592 Immediate);
593 }
594 }
595
596 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupD0)
597 {
598 UCHAR Dummy, Value;
599 SOFT386_MOD_REG_RM ModRegRm;
600 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
601
602 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
603 {
604 /* The ADSIZE prefix toggles the size */
605 AddressSize = !AddressSize;
606 }
607
608 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
609 {
610 /* Exception occurred */
611 return FALSE;
612 }
613
614 /* Read the operands */
615 if (!Soft386ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
616 {
617 /* Exception occurred */
618 return FALSE;
619 }
620
621 /* Calculate the result */
622 Value = LOBYTE(Soft386RotateOperation(State, ModRegRm.Register, Value, 8, 1));
623
624 /* Write back the result */
625 return Soft386WriteModrmByteOperands(State,
626 &ModRegRm,
627 FALSE,
628 Value);
629
630 }
631
632 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupD1)
633 {
634 SOFT386_MOD_REG_RM ModRegRm;
635 BOOLEAN OperandSize, AddressSize;
636
637 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
638
639 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
640 {
641 /* The OPSIZE prefix toggles the size */
642 OperandSize = !OperandSize;
643 }
644
645
646 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
647 {
648 /* The ADSIZE prefix toggles the size */
649 AddressSize = !AddressSize;
650 }
651
652 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
653 {
654 /* Exception occurred */
655 return FALSE;
656 }
657
658 if (OperandSize)
659 {
660 ULONG Dummy, Value;
661
662 /* Read the operands */
663 if (!Soft386ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value))
664 {
665 /* Exception occurred */
666 return FALSE;
667 }
668
669 /* Calculate the result */
670 Value = Soft386RotateOperation(State, ModRegRm.Register, Value, 32, 1);
671
672 /* Write back the result */
673 return Soft386WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value);
674 }
675 else
676 {
677 USHORT Dummy, Value;
678
679 /* Read the operands */
680 if (!Soft386ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value))
681 {
682 /* Exception occurred */
683 return FALSE;
684 }
685
686 /* Calculate the result */
687 Value = LOWORD(Soft386RotateOperation(State, ModRegRm.Register, Value, 16, 1));
688
689 /* Write back the result */
690 return Soft386WriteModrmWordOperands(State, &ModRegRm, FALSE, Value);
691 }
692 }
693
694 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupD2)
695 {
696 UCHAR Dummy, Value;
697 SOFT386_MOD_REG_RM ModRegRm;
698 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
699
700 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
701 {
702 /* The ADSIZE prefix toggles the size */
703 AddressSize = !AddressSize;
704 }
705
706 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
707 {
708 /* Exception occurred */
709 return FALSE;
710 }
711
712 /* Read the operands */
713 if (!Soft386ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
714 {
715 /* Exception occurred */
716 return FALSE;
717 }
718
719 /* Calculate the result */
720 Value = LOBYTE(Soft386RotateOperation(State,
721 ModRegRm.Register,
722 Value,
723 8,
724 State->GeneralRegs[SOFT386_REG_ECX].LowByte));
725
726 /* Write back the result */
727 return Soft386WriteModrmByteOperands(State,
728 &ModRegRm,
729 FALSE,
730 Value);
731 }
732
733 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupD3)
734 {
735 SOFT386_MOD_REG_RM ModRegRm;
736 BOOLEAN OperandSize, AddressSize;
737
738 OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
739
740 if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
741 {
742 /* The OPSIZE prefix toggles the size */
743 OperandSize = !OperandSize;
744 }
745
746 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
747 {
748 /* The ADSIZE prefix toggles the size */
749 AddressSize = !AddressSize;
750 }
751
752 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
753 {
754 /* Exception occurred */
755 return FALSE;
756 }
757
758 if (OperandSize)
759 {
760 ULONG Dummy, Value;
761
762 /* Read the operands */
763 if (!Soft386ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value))
764 {
765 /* Exception occurred */
766 return FALSE;
767 }
768
769 /* Calculate the result */
770 Value = Soft386RotateOperation(State,
771 ModRegRm.Register,
772 Value,
773 32,
774 State->GeneralRegs[SOFT386_REG_ECX].LowByte);
775
776 /* Write back the result */
777 return Soft386WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value);
778 }
779 else
780 {
781 USHORT Dummy, Value;
782
783 /* Read the operands */
784 if (!Soft386ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value))
785 {
786 /* Exception occurred */
787 return FALSE;
788 }
789
790 /* Calculate the result */
791 Value = LOWORD(Soft386RotateOperation(State,
792 ModRegRm.Register,
793 Value,
794 16,
795 State->GeneralRegs[SOFT386_REG_ECX].LowByte));
796
797 /* Write back the result */
798 return Soft386WriteModrmWordOperands(State, &ModRegRm, FALSE, Value);
799 }
800 }
801
802 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupF6)
803 {
804 UNIMPLEMENTED;
805 return FALSE; // TODO: NOT IMPLEMENTED
806 }
807
808 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupF7)
809 {
810 UNIMPLEMENTED;
811 return FALSE; // TODO: NOT IMPLEMENTED
812 }
813
814 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupFE)
815 {
816 UCHAR Dummy, Value;
817 SOFT386_MOD_REG_RM ModRegRm;
818 BOOLEAN AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
819
820 if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
821 {
822 /* The ADSIZE prefix toggles the size */
823 AddressSize = !AddressSize;
824 }
825
826 if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
827 {
828 /* Exception occurred */
829 return FALSE;
830 }
831
832 if (ModRegRm.Register > 1)
833 {
834 /* Invalid */
835 Soft386Exception(State, SOFT386_EXCEPTION_UD);
836 return FALSE;
837 }
838
839 /* Read the operands */
840 if (!Soft386ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
841 {
842 /* Exception occurred */
843 return FALSE;
844 }
845
846 if (ModRegRm.Register == 0)
847 {
848 /* Increment and update OF */
849 Value++;
850 State->Flags.Of = (Value == SIGN_FLAG_BYTE) ? TRUE : FALSE;
851 }
852 else
853 {
854 /* Decrement and update OF */
855 State->Flags.Of = (Value == SIGN_FLAG_BYTE) ? TRUE : FALSE;
856 Value--;
857 }
858
859 /* Update flags */
860 State->Flags.Sf = (Value & SIGN_FLAG_BYTE) ? TRUE : FALSE;
861 State->Flags.Zf = (Value == 0) ? TRUE : FALSE;
862 State->Flags.Af = ((Value & 0x0F) == 0) ? TRUE : FALSE;
863 State->Flags.Pf = Soft386CalculateParity(Value);
864
865 /* Write back the result */
866 return Soft386WriteModrmByteOperands(State,
867 &ModRegRm,
868 FALSE,
869 Value);
870 }
871
872 SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupFF)
873 {
874 UNIMPLEMENTED;
875 return FALSE; // TODO: NOT IMPLEMENTED
876 }
877
878 /* EOF */
879