b2957650d0709580d7931b9fb6004a27647ac2b4
[reactos.git] / lib / fast486 / opgroups.c
1 /*
2 * Fast486 386/486 CPU Emulation Library
3 * opgroups.c
4 *
5 * Copyright (C) 2013 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 "common.h"
32
33 /* PRIVATE FUNCTIONS **********************************************************/
34
35 inline
36 static
37 ULONG
38 Fast486ArithmeticOperation(PFAST486_STATE State,
39 INT Operation,
40 ULONG FirstValue,
41 ULONG SecondValue,
42 UCHAR Bits)
43 {
44 ULONG Result;
45 ULONG SignFlag = 1 << (Bits - 1);
46 ULONG MaxValue = (1 << Bits) - 1;
47
48 /* Make sure the values don't exceed the maximum for their size */
49 FirstValue &= MaxValue;
50 SecondValue &= MaxValue;
51
52 /* Check which operation is this */
53 switch (Operation)
54 {
55 /* ADD */
56 case 0:
57 {
58 Result = (FirstValue + SecondValue) & MaxValue;
59
60 /* Update CF, OF and AF */
61 State->Flags.Cf = (Result < FirstValue) && (Result < SecondValue);
62 State->Flags.Of = ((FirstValue & SignFlag) == (SecondValue & SignFlag))
63 && ((FirstValue & SignFlag) != (Result & SignFlag));
64 State->Flags.Af = ((((FirstValue & 0x0F) + (SecondValue & 0x0F)) & 0x10) != 0);
65
66 break;
67 }
68
69 /* OR */
70 case 1:
71 {
72 Result = FirstValue | SecondValue;
73 break;
74 }
75
76 /* ADC */
77 case 2:
78 {
79 INT Carry = State->Flags.Cf ? 1 : 0;
80
81 Result = (FirstValue + SecondValue + Carry) & MaxValue;
82
83 /* Update CF, OF and AF */
84 State->Flags.Cf = ((SecondValue == MaxValue) && (Carry == 1))
85 || ((Result < FirstValue) && (Result < (SecondValue + Carry)));
86 State->Flags.Of = ((FirstValue & SignFlag) == (SecondValue & SignFlag))
87 && ((FirstValue & SignFlag) != (Result & SignFlag));
88 State->Flags.Af = ((((FirstValue & 0x0F) + ((SecondValue + Carry) & 0x0F)) & 0x10) != 0);
89
90 break;
91 }
92
93 /* SBB */
94 case 3:
95 {
96 INT Carry = State->Flags.Cf ? 1 : 0;
97
98 Result = (FirstValue - SecondValue - Carry) & MaxValue;
99
100 /* Update CF, OF and AF */
101 State->Flags.Cf = FirstValue < (SecondValue + Carry);
102 State->Flags.Of = ((FirstValue & SignFlag) != (SecondValue & SignFlag))
103 && ((FirstValue & SignFlag) != (Result & SignFlag));
104 State->Flags.Af = (FirstValue & 0x0F) < ((SecondValue + Carry) & 0x0F);
105
106 break;
107 }
108
109 /* AND */
110 case 4:
111 {
112 Result = FirstValue & SecondValue;
113 break;
114 }
115
116 /* SUB or CMP */
117 case 5:
118 case 7:
119 {
120 Result = (FirstValue - SecondValue) & MaxValue;
121
122 /* Update CF, OF and AF */
123 State->Flags.Cf = FirstValue < SecondValue;
124 State->Flags.Of = ((FirstValue & SignFlag) != (SecondValue & SignFlag))
125 && ((FirstValue & SignFlag) != (Result & SignFlag));
126 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F);
127
128 break;
129 }
130
131 /* XOR */
132 case 6:
133 {
134 Result = FirstValue ^ SecondValue;
135 break;
136 }
137
138 default:
139 {
140 /* Shouldn't happen */
141 ASSERT(FALSE);
142 }
143 }
144
145 /* Update ZF, SF and PF */
146 State->Flags.Zf = (Result == 0);
147 State->Flags.Sf = ((Result & SignFlag) != 0);
148 State->Flags.Pf = Fast486CalculateParity(LOBYTE(Result));
149
150 /* Return the result */
151 return Result;
152 }
153
154 static
155 inline
156 ULONG
157 Fast486RotateOperation(PFAST486_STATE State,
158 INT Operation,
159 ULONG Value,
160 UCHAR Bits,
161 UCHAR Count)
162 {
163 ULONG HighestBit = 1 << (Bits - 1);
164 ULONG Result;
165
166 if ((Operation != 2) && (Operation != 3))
167 {
168 /* Mask the count */
169 Count &= Bits - 1;
170 }
171 else
172 {
173 /* For RCL and RCR, the CF is included in the value */
174 Count %= Bits + 1;
175 }
176
177 /* Check which operation is this */
178 switch (Operation)
179 {
180 /* ROL */
181 case 0:
182 {
183 Result = (Value << Count) | (Value >> (Bits - Count));
184
185 /* Update CF and OF */
186 State->Flags.Cf = Result & 1;
187 if (Count == 1) State->Flags.Of = ((Result & HighestBit) != 0)
188 ^ State->Flags.Cf;
189
190 break;
191 }
192
193 /* ROR */
194 case 1:
195 {
196 Result = (Value >> Count) | (Value << (Bits - Count));
197
198 /* Update CF and OF */
199 State->Flags.Cf = ((Result & HighestBit) != 0);
200 if (Count == 1) State->Flags.Of = State->Flags.Cf
201 ^ ((Result & (HighestBit >> 1)) != 0);
202
203 break;
204 }
205
206 /* RCL */
207 case 2:
208 {
209 Result = (Value << Count)
210 | (State->Flags.Cf << (Count - 1))
211 | (Value >> (Bits - Count + 1));
212
213 /* Update CF and OF */
214 State->Flags.Cf = ((Value & (1 << (Bits - Count))) != 0);
215 if (Count == 1) State->Flags.Of = ((Result & HighestBit) != 0)
216 ^ State->Flags.Cf;
217
218 break;
219 }
220
221 /* RCR */
222 case 3:
223 {
224 Result = (Value >> Count)
225 | (State->Flags.Cf << (Bits - Count))
226 | (Value << (Bits - Count + 1));
227
228 /* Update CF and OF */
229 State->Flags.Cf = ((Value & (1 << (Bits - Count))) != 0);
230 if (Count == 1) State->Flags.Of = State->Flags.Cf
231 ^ ((Result & (HighestBit >> 1)) != 0);
232
233 break;
234 }
235
236 /* SHL/SAL */
237 case 4:
238 case 6:
239 {
240 Result = Value << Count;
241
242 /* Update CF and OF */
243 State->Flags.Cf = ((Value & (1 << (Bits - Count))) != 0);
244 if (Count == 1) State->Flags.Of = ((Result & HighestBit) != 0)
245 ^ State->Flags.Cf;
246
247 break;
248 }
249
250 /* SHR */
251 case 5:
252 {
253 Result = Value >> Count;
254
255 /* Update CF and OF */
256 State->Flags.Cf = ((Value & (1 << (Count - 1))) != 0);
257 if (Count == 1) State->Flags.Of = ((Value & HighestBit) != 0);
258
259 break;
260 }
261
262 /* SAR */
263 case 7:
264 {
265 Result = Value >> Count;
266
267 /* Fill the top Count bits with the sign bit */
268 if (Value & HighestBit) Result |= ((1 << Count) - 1) << (Bits - Count);
269
270 /* Update CF and OF */
271 State->Flags.Cf = ((Value & (1 << (Count - 1))) != 0);
272 if (Count == 1) State->Flags.Of = FALSE;
273
274 break;
275 }
276 }
277
278 if (Operation >= 4)
279 {
280 /* Update ZF, SF and PF */
281 State->Flags.Zf = (Result == 0);
282 State->Flags.Sf = ((Result & HighestBit) != 0);
283 State->Flags.Pf = Fast486CalculateParity(Result);
284 }
285
286 /* Return the result */
287 return Result;
288 }
289
290 /* PUBLIC FUNCTIONS ***********************************************************/
291
292 FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8082)
293 {
294 UCHAR Immediate, Dummy, Value;
295 FAST486_MOD_REG_RM ModRegRm;
296 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
297
298 TOGGLE_ADSIZE(AddressSize);
299
300 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
301 {
302 /* Exception occurred */
303 return FALSE;
304 }
305
306 /* Fetch the immediate operand */
307 if (!Fast486FetchByte(State, &Immediate))
308 {
309 /* Exception occurred */
310 return FALSE;
311 }
312
313 /* Read the operands */
314 if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
315 {
316 /* Exception occurred */
317 return FALSE;
318 }
319
320 /* Calculate the result */
321 Value = Fast486ArithmeticOperation(State, ModRegRm.Register, Value, Immediate, 8);
322
323 /* Unless this is CMP, write back the result */
324 if (ModRegRm.Register != 7)
325 {
326 return Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Value);
327 }
328
329 return TRUE;
330 }
331
332 FAST486_OPCODE_HANDLER(Fast486OpcodeGroup81)
333 {
334 FAST486_MOD_REG_RM ModRegRm;
335 BOOLEAN OperandSize, AddressSize;
336
337 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
338
339 TOGGLE_OPSIZE(OperandSize);
340 TOGGLE_ADSIZE(AddressSize);
341
342 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
343 {
344 /* Exception occurred */
345 return FALSE;
346 }
347
348 if (OperandSize)
349 {
350 ULONG Immediate, Value, Dummy;
351
352 /* Fetch the immediate operand */
353 if (!Fast486FetchDword(State, &Immediate))
354 {
355 /* Exception occurred */
356 return FALSE;
357 }
358
359 /* Read the operands */
360 if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value))
361 {
362 /* Exception occurred */
363 return FALSE;
364 }
365
366 /* Calculate the result */
367 Value = Fast486ArithmeticOperation(State, ModRegRm.Register, Value, Immediate, 32);
368
369 /* Unless this is CMP, write back the result */
370 if (ModRegRm.Register != 7)
371 {
372 return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value);
373 }
374 }
375 else
376 {
377 USHORT Immediate, Value, Dummy;
378
379 /* Fetch the immediate operand */
380 if (!Fast486FetchWord(State, &Immediate))
381 {
382 /* Exception occurred */
383 return FALSE;
384 }
385
386 /* Read the operands */
387 if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value))
388 {
389 /* Exception occurred */
390 return FALSE;
391 }
392
393 /* Calculate the result */
394 Value = Fast486ArithmeticOperation(State, ModRegRm.Register, Value, Immediate, 16);
395
396 /* Unless this is CMP, write back the result */
397 if (ModRegRm.Register != 7)
398 {
399 return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value);
400 }
401 }
402
403 return TRUE;
404 }
405
406 FAST486_OPCODE_HANDLER(Fast486OpcodeGroup83)
407 {
408 CHAR ImmByte;
409 FAST486_MOD_REG_RM ModRegRm;
410 BOOLEAN OperandSize, AddressSize;
411
412 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
413
414 TOGGLE_OPSIZE(OperandSize);
415 TOGGLE_ADSIZE(AddressSize);
416
417 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
418 {
419 /* Exception occurred */
420 return FALSE;
421 }
422
423 /* Fetch the immediate operand */
424 if (!Fast486FetchByte(State, (PUCHAR)&ImmByte))
425 {
426 /* Exception occurred */
427 return FALSE;
428 }
429
430 if (OperandSize)
431 {
432 ULONG Immediate = (ULONG)((LONG)ImmByte); // Sign extend
433 ULONG Value, Dummy;
434
435 /* Read the operands */
436 if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value))
437 {
438 /* Exception occurred */
439 return FALSE;
440 }
441
442 /* Calculate the result */
443 Value = Fast486ArithmeticOperation(State, ModRegRm.Register, Value, Immediate, 32);
444
445 /* Unless this is CMP, write back the result */
446 if (ModRegRm.Register != 7)
447 {
448 return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value);
449 }
450 }
451 else
452 {
453 USHORT Immediate = (USHORT)((SHORT)ImmByte); // Sign extend
454 USHORT Value, Dummy;
455
456 /* Read the operands */
457 if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value))
458 {
459 /* Exception occurred */
460 return FALSE;
461 }
462
463 /* Calculate the result */
464 Value = Fast486ArithmeticOperation(State, ModRegRm.Register, Value, Immediate, 16);
465
466 /* Unless this is CMP, write back the result */
467 if (ModRegRm.Register != 7)
468 {
469 return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value);
470 }
471 }
472
473 return TRUE;
474 }
475
476 FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8F)
477 {
478 ULONG Value;
479 FAST486_MOD_REG_RM ModRegRm;
480 BOOLEAN OperandSize, AddressSize;
481
482 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
483
484 TOGGLE_OPSIZE(OperandSize);
485 TOGGLE_ADSIZE(AddressSize);
486
487 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
488 {
489 /* Exception occurred */
490 return FALSE;
491 }
492
493 if (ModRegRm.Register != 0)
494 {
495 /* Invalid */
496 Fast486Exception(State, FAST486_EXCEPTION_UD);
497 return FALSE;
498 }
499
500 /* Pop a value from the stack */
501 if (!Fast486StackPop(State, &Value))
502 {
503 /* Exception occurred */
504 return FALSE;
505 }
506
507 if (OperandSize)
508 {
509 return Fast486WriteModrmDwordOperands(State,
510 &ModRegRm,
511 FALSE,
512 Value);
513 }
514 else
515 {
516 return Fast486WriteModrmWordOperands(State,
517 &ModRegRm,
518 FALSE,
519 LOWORD(Value));
520 }
521 }
522
523 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC0)
524 {
525 UCHAR Dummy, Value, Count;
526 FAST486_MOD_REG_RM ModRegRm;
527 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
528
529 TOGGLE_ADSIZE(AddressSize);
530
531 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
532 {
533 /* Exception occurred */
534 return FALSE;
535 }
536
537 /* Fetch the count */
538 if (!Fast486FetchByte(State, &Count))
539 {
540 /* Exception occurred */
541 return FALSE;
542 }
543
544 /* Read the operands */
545 if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
546 {
547 /* Exception occurred */
548 return FALSE;
549 }
550
551 /* Calculate the result */
552 Value = LOBYTE(Fast486RotateOperation(State,
553 ModRegRm.Register,
554 Value,
555 8,
556 Count));
557
558 /* Write back the result */
559 return Fast486WriteModrmByteOperands(State,
560 &ModRegRm,
561 FALSE,
562 Value);
563 }
564
565 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC1)
566 {
567 UCHAR Count;
568 FAST486_MOD_REG_RM ModRegRm;
569 BOOLEAN OperandSize, AddressSize;
570
571 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
572
573 TOGGLE_OPSIZE(OperandSize);
574 TOGGLE_ADSIZE(AddressSize);
575
576 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
577 {
578 /* Exception occurred */
579 return FALSE;
580 }
581
582 /* Fetch the count */
583 if (!Fast486FetchByte(State, &Count))
584 {
585 /* Exception occurred */
586 return FALSE;
587 }
588
589 if (OperandSize)
590 {
591 ULONG Dummy, Value;
592
593 /* Read the operands */
594 if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value))
595 {
596 /* Exception occurred */
597 return FALSE;
598 }
599
600 /* Calculate the result */
601 Value = Fast486RotateOperation(State,
602 ModRegRm.Register,
603 Value,
604 32,
605 Count);
606
607 /* Write back the result */
608 return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value);
609 }
610 else
611 {
612 USHORT Dummy, Value;
613
614 /* Read the operands */
615 if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value))
616 {
617 /* Exception occurred */
618 return FALSE;
619 }
620
621 /* Calculate the result */
622 Value = LOWORD(Fast486RotateOperation(State,
623 ModRegRm.Register,
624 Value,
625 16,
626 Count));
627
628 /* Write back the result */
629 return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value);
630 }
631 }
632
633 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC6)
634 {
635 UCHAR Immediate;
636 FAST486_MOD_REG_RM ModRegRm;
637 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
638
639 TOGGLE_ADSIZE(AddressSize);
640
641 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
642 {
643 /* Exception occurred */
644 return FALSE;
645 }
646
647 if (ModRegRm.Register != 0)
648 {
649 /* Invalid */
650 Fast486Exception(State, FAST486_EXCEPTION_UD);
651 return FALSE;
652 }
653
654 /* Get the immediate operand */
655 if (!Fast486FetchByte(State, &Immediate))
656 {
657 /* Exception occurred */
658 return FALSE;
659 }
660
661 return Fast486WriteModrmByteOperands(State,
662 &ModRegRm,
663 FALSE,
664 Immediate);
665 }
666
667 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC7)
668 {
669 FAST486_MOD_REG_RM ModRegRm;
670 BOOLEAN OperandSize, AddressSize;
671
672 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
673
674 TOGGLE_OPSIZE(OperandSize);
675 TOGGLE_ADSIZE(AddressSize);
676
677 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
678 {
679 /* Exception occurred */
680 return FALSE;
681 }
682
683 if (ModRegRm.Register != 0)
684 {
685 /* Invalid */
686 Fast486Exception(State, FAST486_EXCEPTION_UD);
687 return FALSE;
688 }
689
690 if (OperandSize)
691 {
692 ULONG Immediate;
693
694 /* Get the immediate operand */
695 if (!Fast486FetchDword(State, &Immediate))
696 {
697 /* Exception occurred */
698 return FALSE;
699 }
700
701 return Fast486WriteModrmDwordOperands(State,
702 &ModRegRm,
703 FALSE,
704 Immediate);
705 }
706 else
707 {
708 USHORT Immediate;
709
710 /* Get the immediate operand */
711 if (!Fast486FetchWord(State, &Immediate))
712 {
713 /* Exception occurred */
714 return FALSE;
715 }
716
717 return Fast486WriteModrmWordOperands(State,
718 &ModRegRm,
719 FALSE,
720 Immediate);
721 }
722 }
723
724 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD0)
725 {
726 UCHAR Dummy, Value;
727 FAST486_MOD_REG_RM ModRegRm;
728 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
729
730 TOGGLE_ADSIZE(AddressSize);
731
732 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
733 {
734 /* Exception occurred */
735 return FALSE;
736 }
737
738 /* Read the operands */
739 if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
740 {
741 /* Exception occurred */
742 return FALSE;
743 }
744
745 /* Calculate the result */
746 Value = LOBYTE(Fast486RotateOperation(State, ModRegRm.Register, Value, 8, 1));
747
748 /* Write back the result */
749 return Fast486WriteModrmByteOperands(State,
750 &ModRegRm,
751 FALSE,
752 Value);
753
754 }
755
756 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD1)
757 {
758 FAST486_MOD_REG_RM ModRegRm;
759 BOOLEAN OperandSize, AddressSize;
760
761 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
762
763 TOGGLE_OPSIZE(OperandSize);
764 TOGGLE_ADSIZE(AddressSize);
765
766 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
767 {
768 /* Exception occurred */
769 return FALSE;
770 }
771
772 if (OperandSize)
773 {
774 ULONG Dummy, Value;
775
776 /* Read the operands */
777 if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value))
778 {
779 /* Exception occurred */
780 return FALSE;
781 }
782
783 /* Calculate the result */
784 Value = Fast486RotateOperation(State, ModRegRm.Register, Value, 32, 1);
785
786 /* Write back the result */
787 return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value);
788 }
789 else
790 {
791 USHORT Dummy, Value;
792
793 /* Read the operands */
794 if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value))
795 {
796 /* Exception occurred */
797 return FALSE;
798 }
799
800 /* Calculate the result */
801 Value = LOWORD(Fast486RotateOperation(State, ModRegRm.Register, Value, 16, 1));
802
803 /* Write back the result */
804 return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value);
805 }
806 }
807
808 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD2)
809 {
810 UCHAR Dummy, Value;
811 FAST486_MOD_REG_RM ModRegRm;
812 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
813
814 TOGGLE_ADSIZE(AddressSize);
815
816 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
817 {
818 /* Exception occurred */
819 return FALSE;
820 }
821
822 /* Read the operands */
823 if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
824 {
825 /* Exception occurred */
826 return FALSE;
827 }
828
829 /* Calculate the result */
830 Value = LOBYTE(Fast486RotateOperation(State,
831 ModRegRm.Register,
832 Value,
833 8,
834 State->GeneralRegs[FAST486_REG_ECX].LowByte));
835
836 /* Write back the result */
837 return Fast486WriteModrmByteOperands(State,
838 &ModRegRm,
839 FALSE,
840 Value);
841 }
842
843 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD3)
844 {
845 FAST486_MOD_REG_RM ModRegRm;
846 BOOLEAN OperandSize, AddressSize;
847
848 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
849
850 TOGGLE_OPSIZE(OperandSize);
851 TOGGLE_ADSIZE(AddressSize);
852
853 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
854 {
855 /* Exception occurred */
856 return FALSE;
857 }
858
859 if (OperandSize)
860 {
861 ULONG Dummy, Value;
862
863 /* Read the operands */
864 if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value))
865 {
866 /* Exception occurred */
867 return FALSE;
868 }
869
870 /* Calculate the result */
871 Value = Fast486RotateOperation(State,
872 ModRegRm.Register,
873 Value,
874 32,
875 State->GeneralRegs[FAST486_REG_ECX].LowByte);
876
877 /* Write back the result */
878 return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value);
879 }
880 else
881 {
882 USHORT Dummy, Value;
883
884 /* Read the operands */
885 if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value))
886 {
887 /* Exception occurred */
888 return FALSE;
889 }
890
891 /* Calculate the result */
892 Value = LOWORD(Fast486RotateOperation(State,
893 ModRegRm.Register,
894 Value,
895 16,
896 State->GeneralRegs[FAST486_REG_ECX].LowByte));
897
898 /* Write back the result */
899 return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value);
900 }
901 }
902
903 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6)
904 {
905 UCHAR Dummy, Value = 0;
906 FAST486_MOD_REG_RM ModRegRm;
907 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
908
909 TOGGLE_ADSIZE(AddressSize);
910
911 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
912 {
913 /* Exception occurred */
914 return FALSE;
915 }
916
917 /* Read the operands */
918 if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
919 {
920 /* Exception occurred */
921 return FALSE;
922 }
923
924 switch (ModRegRm.Register)
925 {
926 /* TEST */
927 case 0:
928 case 1:
929 {
930 UCHAR Immediate, Result;
931
932 /* Fetch the immediate byte */
933 if (!Fast486FetchByte(State, &Immediate))
934 {
935 /* Exception occurred */
936 return FALSE;
937 }
938
939 /* Calculate the result */
940 Result = Value & Immediate;
941
942 /* Update the flags */
943 State->Flags.Cf = FALSE;
944 State->Flags.Of = FALSE;
945 State->Flags.Zf = (Result == 0);
946 State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
947 State->Flags.Pf = Fast486CalculateParity(Result);
948
949 break;
950 }
951
952 /* NOT */
953 case 2:
954 {
955 /* Write back the result */
956 return Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, ~Value);
957 }
958
959 /* NEG */
960 case 3:
961 {
962 /* Calculate the result */
963 UCHAR Result = -Value;
964
965 /* Update the flags */
966 State->Flags.Cf = (Value != 0);
967 State->Flags.Of = (Value & SIGN_FLAG_BYTE) && (Result & SIGN_FLAG_BYTE);
968 State->Flags.Af = ((Value & 0x0F) != 0);
969 State->Flags.Zf = (Result == 0);
970 State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0);
971 State->Flags.Pf = Fast486CalculateParity(Result);
972
973 /* Write back the result */
974 return Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Result);
975 }
976
977 /* MUL */
978 case 4:
979 {
980 USHORT Result = (USHORT)Value * (USHORT)State->GeneralRegs[FAST486_REG_EAX].LowByte;
981
982 /* Update the flags */
983 State->Flags.Cf = State->Flags.Of = (HIBYTE(Result) != 0);
984
985 /* Write back the result */
986 State->GeneralRegs[FAST486_REG_EAX].LowWord = Result;
987
988 break;
989 }
990
991 /* IMUL */
992 case 5:
993 {
994 SHORT Result = (SHORT)((CHAR)Value) * (SHORT)((CHAR)State->GeneralRegs[FAST486_REG_EAX].LowByte);
995
996 /* Update the flags */
997 State->Flags.Cf = State->Flags.Of =
998 ((Result < -128) || (Result > 127));
999
1000 /* Write back the result */
1001 State->GeneralRegs[FAST486_REG_EAX].LowWord = (USHORT)Result;
1002
1003 break;
1004 }
1005
1006 /* DIV */
1007 case 6:
1008 {
1009 UCHAR Quotient = State->GeneralRegs[FAST486_REG_EAX].LowWord / Value;
1010 UCHAR Remainder = State->GeneralRegs[FAST486_REG_EAX].LowWord % Value;
1011
1012 /* Write back the results */
1013 State->GeneralRegs[FAST486_REG_EAX].LowByte = Quotient;
1014 State->GeneralRegs[FAST486_REG_EAX].HighByte = Remainder;
1015
1016 break;
1017 }
1018
1019 /* IDIV */
1020 case 7:
1021 {
1022 CHAR Quotient = (SHORT)State->GeneralRegs[FAST486_REG_EAX].LowWord / (CHAR)Value;
1023 CHAR Remainder = (SHORT)State->GeneralRegs[FAST486_REG_EAX].LowWord % (CHAR)Value;
1024
1025 /* Write back the results */
1026 State->GeneralRegs[FAST486_REG_EAX].LowByte = (UCHAR)Quotient;
1027 State->GeneralRegs[FAST486_REG_EAX].HighByte = (UCHAR)Remainder;
1028
1029 break;
1030 }
1031 }
1032
1033 return TRUE;
1034 }
1035
1036 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7)
1037 {
1038 ULONG Dummy, Value = 0, SignFlag;
1039 FAST486_MOD_REG_RM ModRegRm;
1040 BOOLEAN OperandSize, AddressSize;
1041
1042 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1043
1044 TOGGLE_OPSIZE(OperandSize);
1045 TOGGLE_ADSIZE(AddressSize);
1046
1047 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1048 {
1049 /* Exception occurred */
1050 return FALSE;
1051 }
1052
1053 /* Set the sign flag */
1054 if (OperandSize) SignFlag = SIGN_FLAG_LONG;
1055 else SignFlag = SIGN_FLAG_WORD;
1056
1057 /* Read the operand */
1058 if (OperandSize)
1059 {
1060 /* 32-bit */
1061 if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value))
1062 {
1063 /* Exception occurred */
1064 return FALSE;
1065 }
1066 }
1067 else
1068 {
1069 /* 16-bit */
1070 if (!Fast486ReadModrmWordOperands(State, &ModRegRm, (PUSHORT)&Dummy, (PUSHORT)&Value))
1071 {
1072 /* Exception occurred */
1073 return FALSE;
1074 }
1075 }
1076
1077 switch (ModRegRm.Register)
1078 {
1079 /* TEST */
1080 case 0:
1081 case 1:
1082 {
1083 ULONG Immediate = 0, Result = 0;
1084
1085 if (OperandSize)
1086 {
1087 /* Fetch the immediate dword */
1088 if (!Fast486FetchDword(State, &Immediate))
1089 {
1090 /* Exception occurred */
1091 return FALSE;
1092 }
1093 }
1094 else
1095 {
1096 /* Fetch the immediate word */
1097 if (!Fast486FetchWord(State, (PUSHORT)&Immediate))
1098 {
1099 /* Exception occurred */
1100 return FALSE;
1101 }
1102 }
1103
1104 /* Calculate the result */
1105 Result = Value & Immediate;
1106
1107 /* Update the flags */
1108 State->Flags.Cf = FALSE;
1109 State->Flags.Of = FALSE;
1110 State->Flags.Zf = (Result == 0);
1111 State->Flags.Sf = ((Result & SignFlag) != 0);
1112 State->Flags.Pf = Fast486CalculateParity(Result);
1113
1114 break;
1115 }
1116
1117 /* NOT */
1118 case 2:
1119 {
1120 /* Write back the result */
1121 if (OperandSize)
1122 {
1123 /* 32-bit */
1124 return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, ~Value);
1125 }
1126 else
1127 {
1128 /* 16-bit */
1129 return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, LOWORD(~Value));
1130 }
1131 }
1132
1133 /* NEG */
1134 case 3:
1135 {
1136 /* Calculate the result */
1137 ULONG Result = -Value;
1138 if (!OperandSize) Result &= 0xFFFF;
1139
1140 /* Update the flags */
1141 State->Flags.Cf = (Value != 0);
1142 State->Flags.Of = (Value & SignFlag) && (Result & SignFlag);
1143 State->Flags.Af = ((Value & 0x0F) != 0);
1144 State->Flags.Zf = (Result == 0);
1145 State->Flags.Sf = ((Result & SignFlag) != 0);
1146 State->Flags.Pf = Fast486CalculateParity(Result);
1147
1148 /* Write back the result */
1149 if (OperandSize)
1150 {
1151 /* 32-bit */
1152 return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Result);
1153 }
1154 else
1155 {
1156 /* 16-bit */
1157 return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, LOWORD(Result));
1158 }
1159 }
1160
1161 /* MUL */
1162 case 4:
1163 {
1164 if (OperandSize)
1165 {
1166 ULONGLONG Result = (ULONGLONG)Value * (ULONGLONG)State->GeneralRegs[FAST486_REG_EAX].Long;
1167
1168 /* Update the flags */
1169 State->Flags.Cf = State->Flags.Of =
1170 ((Result & 0xFFFFFFFF00000000ULL) != 0);
1171
1172 /* Write back the result */
1173 State->GeneralRegs[FAST486_REG_EAX].Long = Result & 0xFFFFFFFFULL;
1174 State->GeneralRegs[FAST486_REG_EDX].Long = Result >> 32;
1175 }
1176 else
1177 {
1178 ULONG Result = (ULONG)Value * (ULONG)State->GeneralRegs[FAST486_REG_EAX].LowWord;
1179
1180 /* Update the flags */
1181 State->Flags.Cf = State->Flags.Of = (HIWORD(Result) != 0);
1182
1183 /* Write back the result */
1184 State->GeneralRegs[FAST486_REG_EAX].LowWord = LOWORD(Result);
1185 State->GeneralRegs[FAST486_REG_EDX].LowWord = HIWORD(Result);
1186 }
1187
1188 break;
1189 }
1190
1191 /* IMUL */
1192 case 5:
1193 {
1194 if (OperandSize)
1195 {
1196 LONGLONG Result = (LONGLONG)((LONG)Value) * (LONGLONG)((LONG)State->GeneralRegs[FAST486_REG_EAX].Long);
1197
1198 /* Update the flags */
1199 State->Flags.Cf = State->Flags.Of =
1200 ((Result < -2147483648LL) || (Result > 2147483647LL));
1201
1202 /* Write back the result */
1203 State->GeneralRegs[FAST486_REG_EAX].Long = Result & 0xFFFFFFFFULL;
1204 State->GeneralRegs[FAST486_REG_EDX].Long = Result >> 32;
1205 }
1206 else
1207 {
1208 LONG Result = (LONG)((SHORT)Value) * (LONG)((SHORT)State->GeneralRegs[FAST486_REG_EAX].LowWord);
1209
1210 /* Update the flags */
1211 State->Flags.Cf = State->Flags.Of =
1212 ((Result < -32768) || (Result > 32767));
1213
1214 /* Write back the result */
1215 State->GeneralRegs[FAST486_REG_EAX].LowWord = LOWORD(Result);
1216 State->GeneralRegs[FAST486_REG_EDX].LowWord = HIWORD(Result);
1217 }
1218
1219 break;
1220 }
1221
1222 /* DIV */
1223 case 6:
1224 {
1225 if (OperandSize)
1226 {
1227 ULONGLONG Dividend = (ULONGLONG)State->GeneralRegs[FAST486_REG_EAX].Long
1228 | ((ULONGLONG)State->GeneralRegs[FAST486_REG_EDX].Long << 32);
1229 ULONG Quotient = Dividend / Value;
1230 ULONG Remainder = Dividend % Value;
1231
1232 /* Write back the results */
1233 State->GeneralRegs[FAST486_REG_EAX].Long = Quotient;
1234 State->GeneralRegs[FAST486_REG_EDX].Long = Remainder;
1235 }
1236 else
1237 {
1238 ULONG Dividend = (ULONG)State->GeneralRegs[FAST486_REG_EAX].LowWord
1239 | ((ULONG)State->GeneralRegs[FAST486_REG_EDX].LowWord << 16);
1240 USHORT Quotient = Dividend / Value;
1241 USHORT Remainder = Dividend % Value;
1242
1243 /* Write back the results */
1244 State->GeneralRegs[FAST486_REG_EAX].LowWord = Quotient;
1245 State->GeneralRegs[FAST486_REG_EDX].LowWord = Remainder;
1246 }
1247
1248 break;
1249 }
1250
1251 /* IDIV */
1252 case 7:
1253 {
1254 if (OperandSize)
1255 {
1256 LONGLONG Dividend = (LONGLONG)State->GeneralRegs[FAST486_REG_EAX].Long
1257 | ((LONGLONG)State->GeneralRegs[FAST486_REG_EDX].Long << 32);
1258 LONG Quotient = Dividend / (LONG)Value;
1259 LONG Remainder = Dividend % (LONG)Value;
1260
1261 /* Write back the results */
1262 State->GeneralRegs[FAST486_REG_EAX].Long = (ULONG)Quotient;
1263 State->GeneralRegs[FAST486_REG_EDX].Long = (ULONG)Remainder;
1264 }
1265 else
1266 {
1267 LONG Dividend = (LONG)State->GeneralRegs[FAST486_REG_EAX].LowWord
1268 | ((LONG)State->GeneralRegs[FAST486_REG_EDX].LowWord << 16);
1269 SHORT Quotient = Dividend / (SHORT)LOWORD(Value);
1270 SHORT Remainder = Dividend % (SHORT)LOWORD(Value);
1271
1272 /* Write back the results */
1273 State->GeneralRegs[FAST486_REG_EAX].LowWord = (USHORT)Quotient;
1274 State->GeneralRegs[FAST486_REG_EDX].LowWord = (USHORT)Remainder;
1275 }
1276
1277 break;
1278 }
1279 }
1280
1281 return TRUE;
1282 }
1283
1284 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFE)
1285 {
1286 UCHAR Dummy, Value;
1287 FAST486_MOD_REG_RM ModRegRm;
1288 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1289
1290 TOGGLE_ADSIZE(AddressSize);
1291
1292 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1293 {
1294 /* Exception occurred */
1295 return FALSE;
1296 }
1297
1298 if (ModRegRm.Register > 1)
1299 {
1300 /* Invalid */
1301 Fast486Exception(State, FAST486_EXCEPTION_UD);
1302 return FALSE;
1303 }
1304
1305 /* Read the operands */
1306 if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Dummy, &Value))
1307 {
1308 /* Exception occurred */
1309 return FALSE;
1310 }
1311
1312 if (ModRegRm.Register == 0)
1313 {
1314 /* Increment and update OF and AF */
1315 Value++;
1316 State->Flags.Of = (Value == SIGN_FLAG_BYTE);
1317 State->Flags.Af = ((Value & 0x0F) == 0);
1318 }
1319 else
1320 {
1321 /* Decrement and update OF and AF */
1322 State->Flags.Of = (Value == SIGN_FLAG_BYTE);
1323 Value--;
1324 State->Flags.Af = ((Value & 0x0F) == 0x0F);
1325 }
1326
1327 /* Update flags */
1328 State->Flags.Zf = (Value == 0);
1329 State->Flags.Sf = ((Value & SIGN_FLAG_BYTE) != 0);
1330 State->Flags.Pf = Fast486CalculateParity(Value);
1331
1332 /* Write back the result */
1333 return Fast486WriteModrmByteOperands(State,
1334 &ModRegRm,
1335 FALSE,
1336 Value);
1337 }
1338
1339 FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF)
1340 {
1341 FAST486_MOD_REG_RM ModRegRm;
1342 BOOLEAN OperandSize, AddressSize;
1343
1344 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1345
1346 TOGGLE_OPSIZE(OperandSize);
1347 TOGGLE_ADSIZE(AddressSize);
1348
1349 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1350 {
1351 /* Exception occurred */
1352 return FALSE;
1353 }
1354
1355 if (ModRegRm.Register == 7)
1356 {
1357 /* Invalid */
1358 Fast486Exception(State, FAST486_EXCEPTION_UD);
1359 return FALSE;
1360 }
1361
1362 /* Read the operands */
1363 if (OperandSize)
1364 {
1365 ULONG Dummy, Value;
1366
1367 if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value))
1368 {
1369 /* Exception occurred */
1370 return FALSE;
1371 }
1372
1373 if (ModRegRm.Register == 0)
1374 {
1375 /* Increment and update OF and AF */
1376 Value++;
1377 State->Flags.Of = (Value == SIGN_FLAG_LONG);
1378 State->Flags.Af = ((Value & 0x0F) == 0);
1379 }
1380 else if (ModRegRm.Register == 1)
1381 {
1382 /* Decrement and update OF and AF */
1383 State->Flags.Of = (Value == SIGN_FLAG_LONG);
1384 Value--;
1385 State->Flags.Af = ((Value & 0x0F) == 0x0F);
1386 }
1387 else if (ModRegRm.Register == 2)
1388 {
1389 /* Push the current value of EIP */
1390 if (!Fast486StackPush(State, State->InstPtr.Long))
1391 {
1392 /* Exception occurred */
1393 return FALSE;
1394 }
1395
1396 /* Set the EIP to the address */
1397 State->InstPtr.Long = Value;
1398 }
1399 else if (ModRegRm.Register == 3)
1400 {
1401 USHORT Selector;
1402 INT Segment = FAST486_REG_DS;
1403
1404 /* Check for the segment override */
1405 if (State->PrefixFlags & FAST486_PREFIX_SEG)
1406 {
1407 /* Use the override segment instead */
1408 Segment = State->SegmentOverride;
1409 }
1410
1411 /* Read the selector */
1412 if (!Fast486ReadMemory(State,
1413 Segment,
1414 ModRegRm.MemoryAddress + sizeof(ULONG),
1415 FALSE,
1416 &Selector,
1417 sizeof(USHORT)))
1418 {
1419 /* Exception occurred */
1420 return FALSE;
1421 }
1422
1423 /* Push the current value of CS */
1424 if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_CS].Selector))
1425 {
1426 /* Exception occurred */
1427 return FALSE;
1428 }
1429
1430 /* Push the current value of EIP */
1431 if (!Fast486StackPush(State, State->InstPtr.Long))
1432 {
1433 /* Exception occurred */
1434 return FALSE;
1435 }
1436
1437 /* Load the new code segment */
1438 if (!Fast486LoadSegment(State, FAST486_REG_CS, Selector))
1439 {
1440 /* Exception occurred */
1441 return FALSE;
1442 }
1443
1444 /* Set the EIP to the address */
1445 State->InstPtr.Long = Value;
1446 }
1447 else if (ModRegRm.Register == 4)
1448 {
1449 /* Set the EIP to the address */
1450 State->InstPtr.Long = Value;
1451 }
1452 else if (ModRegRm.Register == 5)
1453 {
1454 USHORT Selector;
1455 INT Segment = FAST486_REG_DS;
1456
1457 /* Check for the segment override */
1458 if (State->PrefixFlags & FAST486_PREFIX_SEG)
1459 {
1460 /* Use the override segment instead */
1461 Segment = State->SegmentOverride;
1462 }
1463
1464 /* Read the selector */
1465 if (!Fast486ReadMemory(State,
1466 Segment,
1467 ModRegRm.MemoryAddress + sizeof(ULONG),
1468 FALSE,
1469 &Selector,
1470 sizeof(USHORT)))
1471 {
1472 /* Exception occurred */
1473 return FALSE;
1474 }
1475
1476 /* Load the new code segment */
1477 if (!Fast486LoadSegment(State, FAST486_REG_CS, Selector))
1478 {
1479 /* Exception occurred */
1480 return FALSE;
1481 }
1482
1483 /* Set the EIP to the address */
1484 State->InstPtr.Long = Value;
1485 }
1486 else if (ModRegRm.Register == 6)
1487 {
1488 /* Push the value on to the stack */
1489 return Fast486StackPush(State, Value);
1490 }
1491
1492 if (ModRegRm.Register <= 1)
1493 {
1494 /* Update flags */
1495 State->Flags.Sf = ((Value & SIGN_FLAG_LONG) != 0);
1496 State->Flags.Zf = (Value == 0);
1497 State->Flags.Pf = Fast486CalculateParity(Value);
1498
1499 /* Write back the result */
1500 return Fast486WriteModrmDwordOperands(State,
1501 &ModRegRm,
1502 FALSE,
1503 Value);
1504 }
1505 }
1506 else
1507 {
1508 USHORT Dummy, Value;
1509
1510 if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value))
1511 {
1512 /* Exception occurred */
1513 return FALSE;
1514 }
1515
1516 if (ModRegRm.Register == 0)
1517 {
1518 /* Increment and update OF */
1519 Value++;
1520 State->Flags.Of = (Value == SIGN_FLAG_WORD);
1521 State->Flags.Af = ((Value & 0x0F) == 0);
1522 }
1523 else if (ModRegRm.Register == 1)
1524 {
1525 /* Decrement and update OF */
1526 State->Flags.Of = (Value == SIGN_FLAG_WORD);
1527 Value--;
1528 State->Flags.Af = ((Value & 0x0F) == 0x0F);
1529 }
1530 else if (ModRegRm.Register == 2)
1531 {
1532 /* Push the current value of IP */
1533 if (!Fast486StackPush(State, State->InstPtr.LowWord))
1534 {
1535 /* Exception occurred */
1536 return FALSE;
1537 }
1538
1539 /* Set the IP to the address */
1540 State->InstPtr.LowWord = Value;
1541 }
1542 else if (ModRegRm.Register == 3)
1543 {
1544 USHORT Selector;
1545 INT Segment = FAST486_REG_DS;
1546
1547 /* Check for the segment override */
1548 if (State->PrefixFlags & FAST486_PREFIX_SEG)
1549 {
1550 /* Use the override segment instead */
1551 Segment = State->SegmentOverride;
1552 }
1553
1554 /* Read the selector */
1555 if (!Fast486ReadMemory(State,
1556 Segment,
1557 ModRegRm.MemoryAddress + sizeof(USHORT),
1558 FALSE,
1559 &Selector,
1560 sizeof(USHORT)))
1561 {
1562 /* Exception occurred */
1563 return FALSE;
1564 }
1565
1566 /* Push the current value of CS */
1567 if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_CS].Selector))
1568 {
1569 /* Exception occurred */
1570 return FALSE;
1571 }
1572
1573 /* Push the current value of IP */
1574 if (!Fast486StackPush(State, State->InstPtr.LowWord))
1575 {
1576 /* Exception occurred */
1577 return FALSE;
1578 }
1579
1580 /* Load the new code segment */
1581 if (!Fast486LoadSegment(State, FAST486_REG_CS, Selector))
1582 {
1583 /* Exception occurred */
1584 return FALSE;
1585 }
1586
1587 /* Set the IP to the address */
1588 State->InstPtr.LowWord = Value;
1589
1590 }
1591 else if (ModRegRm.Register == 4)
1592 {
1593 /* Set the IP to the address */
1594 State->InstPtr.LowWord = Value;
1595 }
1596 else if (ModRegRm.Register == 5)
1597 {
1598 USHORT Selector;
1599 INT Segment = FAST486_REG_DS;
1600
1601 /* Check for the segment override */
1602 if (State->PrefixFlags & FAST486_PREFIX_SEG)
1603 {
1604 /* Use the override segment instead */
1605 Segment = State->SegmentOverride;
1606 }
1607
1608 /* Read the selector */
1609 if (!Fast486ReadMemory(State,
1610 Segment,
1611 ModRegRm.MemoryAddress + sizeof(USHORT),
1612 FALSE,
1613 &Selector,
1614 sizeof(USHORT)))
1615 {
1616 /* Exception occurred */
1617 return FALSE;
1618 }
1619
1620 /* Load the new code segment */
1621 if (!Fast486LoadSegment(State, FAST486_REG_CS, Selector))
1622 {
1623 /* Exception occurred */
1624 return FALSE;
1625 }
1626
1627 /* Set the IP to the address */
1628 State->InstPtr.LowWord = Value;
1629 }
1630 else if (ModRegRm.Register == 6)
1631 {
1632 /* Push the value on to the stack */
1633 return Fast486StackPush(State, Value);
1634 }
1635 else
1636 {
1637 /* Invalid */
1638 Fast486Exception(State, FAST486_EXCEPTION_UD);
1639 return FALSE;
1640 }
1641
1642 if (ModRegRm.Register <= 1)
1643 {
1644 /* Update flags */
1645 State->Flags.Sf = ((Value & SIGN_FLAG_WORD) != 0);
1646 State->Flags.Zf = (Value == 0);
1647 State->Flags.Pf = Fast486CalculateParity(Value);
1648
1649 /* Write back the result */
1650 return Fast486WriteModrmWordOperands(State,
1651 &ModRegRm,
1652 FALSE,
1653 Value);
1654 }
1655 }
1656
1657 return TRUE;
1658 }
1659
1660 FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0F01)
1661 {
1662 UCHAR TableReg[6];
1663 FAST486_MOD_REG_RM ModRegRm;
1664 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1665 FAST486_SEG_REGS Segment = FAST486_REG_DS;
1666
1667 NO_LOCK_PREFIX();
1668 TOGGLE_ADSIZE(AddressSize);
1669
1670 /* Check for the segment override */
1671 if (State->PrefixFlags & FAST486_PREFIX_SEG)
1672 {
1673 /* Use the override segment instead */
1674 Segment = State->SegmentOverride;
1675 }
1676
1677 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1678 {
1679 /* Exception occurred */
1680 return FALSE;
1681 }
1682
1683 /* Check which operation this is */
1684 switch (ModRegRm.Register)
1685 {
1686 /* SGDT */
1687 case 0:
1688 {
1689 if (!ModRegRm.Memory)
1690 {
1691 /* The second operand must be a memory location */
1692 Fast486Exception(State, FAST486_EXCEPTION_UD);
1693 return FALSE;
1694 }
1695
1696 /* Fill the 6-byte table register */
1697 RtlCopyMemory(TableReg, &State->Gdtr.Size, sizeof(USHORT));
1698 RtlCopyMemory(&TableReg[sizeof(USHORT)], &State->Gdtr.Address, sizeof(ULONG));
1699
1700 /* Store the GDTR */
1701 return Fast486WriteMemory(State,
1702 Segment,
1703 ModRegRm.MemoryAddress,
1704 TableReg,
1705 sizeof(TableReg));
1706 }
1707
1708 /* SIDT */
1709 case 1:
1710 {
1711 if (!ModRegRm.Memory)
1712 {
1713 /* The second operand must be a memory location */
1714 Fast486Exception(State, FAST486_EXCEPTION_UD);
1715 return FALSE;
1716 }
1717
1718 /* Fill the 6-byte table register */
1719 RtlCopyMemory(TableReg, &State->Idtr.Size, sizeof(USHORT));
1720 RtlCopyMemory(&TableReg[sizeof(USHORT)], &State->Idtr.Address, sizeof(ULONG));
1721
1722 /* Store the IDTR */
1723 return Fast486WriteMemory(State,
1724 Segment,
1725 ModRegRm.MemoryAddress,
1726 TableReg,
1727 sizeof(TableReg));
1728 }
1729
1730 /* LGDT */
1731 case 2:
1732 {
1733 /* This is a privileged instruction */
1734 if (Fast486GetCurrentPrivLevel(State) != 0)
1735 {
1736 Fast486Exception(State, FAST486_EXCEPTION_GP);
1737 return FALSE;
1738 }
1739
1740 if (!ModRegRm.Memory)
1741 {
1742 /* The second operand must be a memory location */
1743 Fast486Exception(State, FAST486_EXCEPTION_UD);
1744 return FALSE;
1745 }
1746
1747 /* Read the new GDTR */
1748 if (!Fast486ReadMemory(State,
1749 Segment,
1750 ModRegRm.MemoryAddress,
1751 FALSE,
1752 TableReg,
1753 sizeof(TableReg)))
1754 {
1755 /* Exception occurred */
1756 return FALSE;
1757 }
1758
1759 /* Load the new GDT */
1760 State->Gdtr.Size = *((PUSHORT)TableReg);
1761 State->Gdtr.Address = *((PULONG)&TableReg[sizeof(USHORT)]);
1762
1763 return TRUE;
1764 }
1765
1766 /* LIDT */
1767 case 3:
1768 {
1769 /* This is a privileged instruction */
1770 if (Fast486GetCurrentPrivLevel(State) != 0)
1771 {
1772 Fast486Exception(State, FAST486_EXCEPTION_GP);
1773 return FALSE;
1774 }
1775
1776 if (!ModRegRm.Memory)
1777 {
1778 /* The second operand must be a memory location */
1779 Fast486Exception(State, FAST486_EXCEPTION_UD);
1780 return FALSE;
1781 }
1782
1783 /* Read the new IDTR */
1784 if (!Fast486ReadMemory(State,
1785 Segment,
1786 ModRegRm.MemoryAddress,
1787 FALSE,
1788 TableReg,
1789 sizeof(TableReg)))
1790 {
1791 /* Exception occurred */
1792 return FALSE;
1793 }
1794
1795 /* Load the new IDT */
1796 State->Idtr.Size = *((PUSHORT)TableReg);
1797 State->Idtr.Address = *((PULONG)&TableReg[sizeof(USHORT)]);
1798
1799 return TRUE;
1800 }
1801
1802 /* SMSW */
1803 case 4:
1804 {
1805 /* Store the lower 16 bits of CR0 */
1806 return Fast486WriteModrmWordOperands(State,
1807 &ModRegRm,
1808 FALSE,
1809 LOWORD(State->ControlRegisters[FAST486_REG_CR0]));
1810 }
1811
1812 /* LMSW */
1813 case 6:
1814 {
1815 USHORT MasterStatusWord, Dummy;
1816
1817 /* This is a privileged instruction */
1818 if (Fast486GetCurrentPrivLevel(State) != 0)
1819 {
1820 Fast486Exception(State, FAST486_EXCEPTION_GP);
1821 return FALSE;
1822 }
1823
1824 /* Read the new master status word */
1825 if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &MasterStatusWord))
1826 {
1827 /* Exception occurred */
1828 return FALSE;
1829 }
1830
1831 /* This instruction cannot be used to return to real mode */
1832 if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)
1833 && !(MasterStatusWord & FAST486_CR0_PE))
1834 {
1835 Fast486Exception(State, FAST486_EXCEPTION_GP);
1836 return FALSE;
1837 }
1838
1839 /* Set the lowest 4 bits */
1840 State->ControlRegisters[FAST486_REG_CR0] &= 0xFFFFFFF0;
1841 State->ControlRegisters[FAST486_REG_CR0] |= MasterStatusWord & 0x0F;
1842
1843 return TRUE;
1844 }
1845
1846 /* INVLPG */
1847 case 7:
1848 {
1849 UNIMPLEMENTED;
1850 return FALSE;
1851 }
1852
1853 /* Invalid */
1854 default:
1855 {
1856 Fast486Exception(State, FAST486_EXCEPTION_UD);
1857 return FALSE;
1858 }
1859 }
1860 }
1861
1862 FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FB9)
1863 {
1864 FAST486_MOD_REG_RM ModRegRm;
1865 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1866
1867 TOGGLE_ADSIZE(AddressSize);
1868
1869 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1870 {
1871 /* Exception occurred */
1872 return FALSE;
1873 }
1874
1875 /* All of them are reserved (UD2) */
1876 Fast486Exception(State, FAST486_EXCEPTION_UD);
1877 return FALSE;
1878 }
1879
1880 FAST486_OPCODE_HANDLER(Fast486OpcodeGroup0FBA)
1881 {
1882 FAST486_MOD_REG_RM ModRegRm;
1883 BOOLEAN OperandSize, AddressSize;
1884 UINT DataSize;
1885 UCHAR BitNumber;
1886
1887 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
1888
1889 TOGGLE_OPSIZE(OperandSize);
1890 TOGGLE_ADSIZE(AddressSize);
1891
1892 /* Get the number of bits */
1893 if (OperandSize) DataSize = 32;
1894 else DataSize = 16;
1895
1896 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
1897 {
1898 /* Exception occurred */
1899 return FALSE;
1900 }
1901
1902 if (ModRegRm.Register < 4)
1903 {
1904 /* Invalid */
1905 Fast486Exception(State, FAST486_EXCEPTION_UD);
1906 return FALSE;
1907 }
1908
1909 /* Get the bit number */
1910 if (!Fast486FetchByte(State, &BitNumber))
1911 {
1912 /* Exception occurred */
1913 return FALSE;
1914 }
1915
1916 if (ModRegRm.Memory)
1917 {
1918 /*
1919 * For memory operands, add the bit offset divided by
1920 * the data size to the address
1921 */
1922 ModRegRm.MemoryAddress += BitNumber / DataSize;
1923 }
1924
1925 /* Normalize the bit number */
1926 BitNumber &= (1 << DataSize) - 1;
1927
1928 if (OperandSize)
1929 {
1930 ULONG Dummy, Value;
1931
1932 /* Read the value */
1933 if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Dummy, &Value))
1934 {
1935 /* Exception occurred */
1936 return FALSE;
1937 }
1938
1939 /* Set CF to the bit value */
1940 State->Flags.Cf = (Value >> BitNumber) & 1;
1941
1942 if (ModRegRm.Register == 5)
1943 {
1944 /* BTS */
1945 Value |= 1 << BitNumber;
1946 }
1947 else if (ModRegRm.Register == 6)
1948 {
1949 /* BTR */
1950 Value &= ~(1 << BitNumber);
1951 }
1952 else if (ModRegRm.Register == 7)
1953 {
1954 /* BTC */
1955 Value ^= 1 << BitNumber;
1956 }
1957
1958 if (ModRegRm.Register >= 5)
1959 {
1960 /* Write back the result */
1961 if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value))
1962 {
1963 /* Exception occurred */
1964 return FALSE;
1965 }
1966 }
1967 }
1968 else
1969 {
1970 USHORT Dummy, Value;
1971
1972 /* Read the value */
1973 if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Dummy, &Value))
1974 {
1975 /* Exception occurred */
1976 return FALSE;
1977 }
1978
1979 /* Set CF to the bit value */
1980 State->Flags.Cf = (Value >> BitNumber) & 1;
1981
1982 if (ModRegRm.Register == 5)
1983 {
1984 /* BTS */
1985 Value |= 1 << BitNumber;
1986 }
1987 else if (ModRegRm.Register == 6)
1988 {
1989 /* BTR */
1990 Value &= ~(1 << BitNumber);
1991 }
1992 else if (ModRegRm.Register == 7)
1993 {
1994 /* BTC */
1995 Value ^= 1 << BitNumber;
1996 }
1997
1998 if (ModRegRm.Register >= 5)
1999 {
2000 /* Write back the result */
2001 if (!Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value))
2002 {
2003 /* Exception occurred */
2004 return FALSE;
2005 }
2006 }
2007 }
2008
2009 /* Return success */
2010 return TRUE;
2011
2012 return TRUE;
2013 }
2014
2015 /* EOF */
2016