Reactos
at master 2446 lines 71 kB view raw
1/* 2 * Fast486 386/486 CPU Emulation Library 3 * opgroups.c 4 * 5 * Copyright (C) 2015 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 35static 36inline 37ULONG 38Fast486ArithmeticOperation(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 = (SignFlag - 1) | SignFlag; 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 State->Flags.Cf = State->Flags.Of = FALSE; 74 break; 75 } 76 77 /* ADC */ 78 case 2: 79 { 80 INT Carry = State->Flags.Cf ? 1 : 0; 81 82 Result = (FirstValue + SecondValue + Carry) & MaxValue; 83 84 /* Update CF, OF and AF */ 85 State->Flags.Cf = ((SecondValue == MaxValue) && (Carry == 1)) 86 || ((Result < FirstValue) && (Result < (SecondValue + Carry))); 87 State->Flags.Of = ((FirstValue & SignFlag) == (SecondValue & SignFlag)) 88 && ((FirstValue & SignFlag) != (Result & SignFlag)); 89 State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0; 90 91 break; 92 } 93 94 /* SBB */ 95 case 3: 96 { 97 INT Carry = State->Flags.Cf ? 1 : 0; 98 99 Result = (FirstValue - SecondValue - Carry) & MaxValue; 100 101 /* Update CF, OF and AF */ 102 State->Flags.Cf = Carry 103 ? (FirstValue <= SecondValue) 104 : (FirstValue < SecondValue); 105 State->Flags.Of = ((FirstValue & SignFlag) != (SecondValue & SignFlag)) 106 && ((FirstValue & SignFlag) != (Result & SignFlag)); 107 State->Flags.Af = ((FirstValue ^ SecondValue ^ Result) & 0x10) != 0; 108 109 break; 110 } 111 112 /* AND */ 113 case 4: 114 { 115 Result = FirstValue & SecondValue; 116 State->Flags.Cf = State->Flags.Of = FALSE; 117 break; 118 } 119 120 /* SUB or CMP */ 121 case 5: 122 case 7: 123 { 124 Result = (FirstValue - SecondValue) & MaxValue; 125 126 /* Update CF, OF and AF */ 127 State->Flags.Cf = (FirstValue < SecondValue); 128 State->Flags.Of = ((FirstValue & SignFlag) != (SecondValue & SignFlag)) 129 && ((FirstValue & SignFlag) != (Result & SignFlag)); 130 State->Flags.Af = (FirstValue & 0x0F) < (SecondValue & 0x0F); 131 132 break; 133 } 134 135 /* XOR */ 136 case 6: 137 { 138 Result = FirstValue ^ SecondValue; 139 State->Flags.Cf = State->Flags.Of = FALSE; 140 break; 141 } 142 143 default: 144 { 145 /* Shouldn't happen */ 146 ASSERT(FALSE); 147 } 148 } 149 150 /* Update ZF, SF and PF */ 151 State->Flags.Zf = (Result == 0); 152 State->Flags.Sf = ((Result & SignFlag) != 0); 153 State->Flags.Pf = Fast486CalculateParity(LOBYTE(Result)); 154 155 /* Return the result */ 156 return Result; 157} 158 159static 160inline 161ULONG 162Fast486RotateOperation(PFAST486_STATE State, 163 INT Operation, 164 ULONG Value, 165 UCHAR Bits, 166 UCHAR Count) 167{ 168 ULONG HighestBit = 1 << (Bits - 1); 169 ULONG MaxValue = HighestBit | (HighestBit - 1); 170 ULONG Result; 171 172 /* Normalize the count */ 173 Count &= 0x1F; 174 175 if ((Operation == 2) || (Operation == 3)) Count %= Bits + 1; 176 177 /* If the count is zero, do nothing */ 178 if (Count == 0) return Value; 179 180 /* Check which operation is this */ 181 switch (Operation) 182 { 183 /* ROL */ 184 case 0: 185 { 186 Count %= Bits; 187 Result = (Value << Count) | (Value >> (Bits - Count)); 188 189 /* Update CF and OF */ 190 State->Flags.Cf = Result & 1; 191 if (Count == 1) State->Flags.Of = State->Flags.Cf 192 ^ ((Result & HighestBit) != 0); 193 194 break; 195 } 196 197 /* ROR */ 198 case 1: 199 { 200 Count %= Bits; 201 Result = (Value >> Count) | (Value << (Bits - Count)); 202 203 /* Update CF and OF */ 204 State->Flags.Cf = ((Result & HighestBit) != 0); 205 if (Count == 1) State->Flags.Of = State->Flags.Cf 206 ^ ((Result & (HighestBit >> 1)) != 0); 207 208 break; 209 } 210 211 /* RCL */ 212 case 2: 213 { 214 Result = (Value << Count) | (State->Flags.Cf << (Count - 1)); 215 216 /* Complete the calculation, but make sure we don't shift by too much */ 217 if ((Bits - Count) < 31) Result |= Value >> (Bits - Count + 1); 218 219 /* Update CF and OF */ 220 State->Flags.Cf = ((Value & (1 << (Bits - Count))) != 0); 221 if (Count == 1) State->Flags.Of = State->Flags.Cf ^ ((Result & HighestBit) != 0); 222 223 break; 224 } 225 226 /* RCR */ 227 case 3: 228 { 229 /* Update OF */ 230 if (Count == 1) State->Flags.Of = State->Flags.Cf ^ ((Value & HighestBit) != 0); 231 232 Result = (Value >> Count) | (State->Flags.Cf << (Bits - Count)); 233 234 /* Complete the calculation, but make sure we don't shift by too much */ 235 if ((Bits - Count) < 31) Result |= Value << (Bits - Count + 1); 236 237 /* Update CF */ 238 State->Flags.Cf = ((Value & (1 << (Count - 1))) != 0); 239 240 break; 241 } 242 243 /* SHL/SAL */ 244 case 4: 245 case 6: 246 { 247 Result = Value << Count; 248 249 /* Update CF and OF */ 250 State->Flags.Cf = ((Value & (1 << (Bits - Count))) != 0); 251 if (Count == 1) State->Flags.Of = State->Flags.Cf 252 ^ ((Result & HighestBit) != 0); 253 254 break; 255 } 256 257 /* SHR */ 258 case 5: 259 { 260 Result = Value >> Count; 261 262 /* Update CF and OF */ 263 State->Flags.Cf = ((Value & (1 << (Count - 1))) != 0); 264 if (Count == 1) State->Flags.Of = ((Value & HighestBit) != 0); 265 266 break; 267 } 268 269 /* SAR */ 270 case 7: 271 { 272 Result = Value >> Count; 273 274 /* Fill the top Count bits with the sign bit */ 275 if (Value & HighestBit) Result |= ((1 << Count) - 1) << (Bits - Count); 276 277 /* Update CF and OF */ 278 State->Flags.Cf = ((Value & (1 << (Count - 1))) != 0); 279 if (Count == 1) State->Flags.Of = FALSE; 280 281 break; 282 } 283 } 284 285 if (Operation >= 4) 286 { 287 /* Update ZF, SF and PF */ 288 State->Flags.Zf = ((Result & MaxValue) == 0); 289 State->Flags.Sf = ((Result & HighestBit) != 0); 290 State->Flags.Pf = Fast486CalculateParity(Result); 291 } 292 293 /* Return the result */ 294 return Result; 295} 296 297/* PUBLIC FUNCTIONS ***********************************************************/ 298 299FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8082) 300{ 301 UCHAR Immediate, Value; 302 FAST486_MOD_REG_RM ModRegRm; 303 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 304 305 TOGGLE_ADSIZE(AddressSize); 306 307 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 308 { 309 /* Exception occurred */ 310 return; 311 } 312 313 /* Fetch the immediate operand */ 314 if (!Fast486FetchByte(State, &Immediate)) 315 { 316 /* Exception occurred */ 317 return; 318 } 319 320 /* Read the operands */ 321 if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value)) 322 { 323 /* Exception occurred */ 324 return; 325 } 326 327 /* Calculate the result */ 328 Value = Fast486ArithmeticOperation(State, ModRegRm.Register, Value, Immediate, 8); 329 330 /* Unless this is CMP, write back the result */ 331 if (ModRegRm.Register != 7) 332 { 333 Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Value); 334 } 335} 336 337FAST486_OPCODE_HANDLER(Fast486OpcodeGroup81) 338{ 339 FAST486_MOD_REG_RM ModRegRm; 340 BOOLEAN OperandSize, AddressSize; 341 342 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 343 344 TOGGLE_OPSIZE(OperandSize); 345 TOGGLE_ADSIZE(AddressSize); 346 347 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 348 { 349 /* Exception occurred */ 350 return; 351 } 352 353 if (OperandSize) 354 { 355 ULONG Immediate, Value; 356 357 /* Fetch the immediate operand */ 358 if (!Fast486FetchDword(State, &Immediate)) 359 { 360 /* Exception occurred */ 361 return; 362 } 363 364 /* Read the operands */ 365 if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) 366 { 367 /* Exception occurred */ 368 return; 369 } 370 371 /* Calculate the result */ 372 Value = Fast486ArithmeticOperation(State, ModRegRm.Register, Value, Immediate, 32); 373 374 /* Unless this is CMP, write back the result */ 375 if (ModRegRm.Register != 7) 376 { 377 Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value); 378 } 379 } 380 else 381 { 382 USHORT Immediate, Value; 383 384 /* Fetch the immediate operand */ 385 if (!Fast486FetchWord(State, &Immediate)) 386 { 387 /* Exception occurred */ 388 return; 389 } 390 391 /* Read the operands */ 392 if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value)) 393 { 394 /* Exception occurred */ 395 return; 396 } 397 398 /* Calculate the result */ 399 Value = Fast486ArithmeticOperation(State, ModRegRm.Register, Value, Immediate, 16); 400 401 /* Unless this is CMP, write back the result */ 402 if (ModRegRm.Register != 7) 403 { 404 Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value); 405 } 406 } 407} 408 409FAST486_OPCODE_HANDLER(Fast486OpcodeGroup83) 410{ 411 CHAR ImmByte; 412 FAST486_MOD_REG_RM ModRegRm; 413 BOOLEAN OperandSize, AddressSize; 414 415 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 416 417 TOGGLE_OPSIZE(OperandSize); 418 TOGGLE_ADSIZE(AddressSize); 419 420 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 421 { 422 /* Exception occurred */ 423 return; 424 } 425 426 /* Fetch the immediate operand */ 427 if (!Fast486FetchByte(State, (PUCHAR)&ImmByte)) 428 { 429 /* Exception occurred */ 430 return; 431 } 432 433 if (OperandSize) 434 { 435 ULONG Immediate = (ULONG)((LONG)ImmByte); // Sign extend 436 ULONG Value; 437 438 /* Read the operands */ 439 if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) 440 { 441 /* Exception occurred */ 442 return; 443 } 444 445 /* Calculate the result */ 446 Value = Fast486ArithmeticOperation(State, ModRegRm.Register, Value, Immediate, 32); 447 448 /* Unless this is CMP, write back the result */ 449 if (ModRegRm.Register != 7) 450 { 451 Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value); 452 } 453 } 454 else 455 { 456 USHORT Immediate = (USHORT)((SHORT)ImmByte); // Sign extend 457 USHORT Value; 458 459 /* Read the operands */ 460 if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value)) 461 { 462 /* Exception occurred */ 463 return; 464 } 465 466 /* Calculate the result */ 467 Value = Fast486ArithmeticOperation(State, ModRegRm.Register, Value, Immediate, 16); 468 469 /* Unless this is CMP, write back the result */ 470 if (ModRegRm.Register != 7) 471 { 472 Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value); 473 } 474 } 475} 476 477FAST486_OPCODE_HANDLER(Fast486OpcodeGroup8F) 478{ 479 ULONG Value; 480 FAST486_MOD_REG_RM ModRegRm; 481 BOOLEAN OperandSize, AddressSize; 482 483 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 484 485 TOGGLE_OPSIZE(OperandSize); 486 TOGGLE_ADSIZE(AddressSize); 487 488 /* Pop a value from the stack - this must be done first */ 489 if (!Fast486StackPop(State, &Value)) 490 { 491 /* Exception occurred */ 492 return; 493 } 494 495 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 496 { 497 /* Exception occurred */ 498 return; 499 } 500 501 if (ModRegRm.Register != 0) 502 { 503 /* Invalid */ 504 Fast486Exception(State, FAST486_EXCEPTION_UD); 505 return; 506 } 507 508 if (OperandSize) Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value); 509 else Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, LOWORD(Value)); 510} 511 512FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC0) 513{ 514 UCHAR Value, Count; 515 FAST486_MOD_REG_RM ModRegRm; 516 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 517 518 TOGGLE_ADSIZE(AddressSize); 519 520 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 521 { 522 /* Exception occurred */ 523 return; 524 } 525 526 /* Fetch the count */ 527 if (!Fast486FetchByte(State, &Count)) 528 { 529 /* Exception occurred */ 530 return; 531 } 532 533 /* Read the operands */ 534 if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value)) 535 { 536 /* Exception occurred */ 537 return; 538 } 539 540 /* Calculate the result */ 541 Value = LOBYTE(Fast486RotateOperation(State, 542 ModRegRm.Register, 543 Value, 544 8, 545 Count)); 546 547 /* Write back the result */ 548 Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Value); 549} 550 551FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC1) 552{ 553 UCHAR Count; 554 FAST486_MOD_REG_RM ModRegRm; 555 BOOLEAN OperandSize, AddressSize; 556 557 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 558 559 TOGGLE_OPSIZE(OperandSize); 560 TOGGLE_ADSIZE(AddressSize); 561 562 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 563 { 564 /* Exception occurred */ 565 return; 566 } 567 568 /* Fetch the count */ 569 if (!Fast486FetchByte(State, &Count)) 570 { 571 /* Exception occurred */ 572 return; 573 } 574 575 if (OperandSize) 576 { 577 ULONG Value; 578 579 /* Read the operands */ 580 if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) 581 { 582 /* Exception occurred */ 583 return; 584 } 585 586 /* Calculate the result */ 587 Value = Fast486RotateOperation(State, 588 ModRegRm.Register, 589 Value, 590 32, 591 Count); 592 593 /* Write back the result */ 594 Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value); 595 } 596 else 597 { 598 USHORT Value; 599 600 /* Read the operands */ 601 if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value)) 602 { 603 /* Exception occurred */ 604 return; 605 } 606 607 /* Calculate the result */ 608 Value = LOWORD(Fast486RotateOperation(State, 609 ModRegRm.Register, 610 Value, 611 16, 612 Count)); 613 614 /* Write back the result */ 615 Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value); 616 } 617} 618 619FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC6) 620{ 621 UCHAR Immediate; 622 FAST486_MOD_REG_RM ModRegRm; 623 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 624 625 TOGGLE_ADSIZE(AddressSize); 626 627 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 628 { 629 /* Exception occurred */ 630 return; 631 } 632 633 if (ModRegRm.Register != 0) 634 { 635 /* Invalid */ 636 Fast486Exception(State, FAST486_EXCEPTION_UD); 637 return; 638 } 639 640 /* Get the immediate operand */ 641 if (!Fast486FetchByte(State, &Immediate)) 642 { 643 /* Exception occurred */ 644 return; 645 } 646 647 Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Immediate); 648} 649 650FAST486_OPCODE_HANDLER(Fast486OpcodeGroupC7) 651{ 652 FAST486_MOD_REG_RM ModRegRm; 653 BOOLEAN OperandSize, AddressSize; 654 655 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 656 657 TOGGLE_OPSIZE(OperandSize); 658 TOGGLE_ADSIZE(AddressSize); 659 660 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 661 { 662 /* Exception occurred */ 663 return; 664 } 665 666 if (ModRegRm.Register != 0) 667 { 668 /* Invalid */ 669 Fast486Exception(State, FAST486_EXCEPTION_UD); 670 return; 671 } 672 673 if (OperandSize) 674 { 675 ULONG Immediate; 676 677 /* Get the immediate operand */ 678 if (!Fast486FetchDword(State, &Immediate)) 679 { 680 /* Exception occurred */ 681 return; 682 } 683 684 Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Immediate); 685 } 686 else 687 { 688 USHORT Immediate; 689 690 /* Get the immediate operand */ 691 if (!Fast486FetchWord(State, &Immediate)) 692 { 693 /* Exception occurred */ 694 return; 695 } 696 697 Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Immediate); 698 } 699} 700 701FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD0) 702{ 703 UCHAR Value; 704 FAST486_MOD_REG_RM ModRegRm; 705 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 706 707 TOGGLE_ADSIZE(AddressSize); 708 709 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 710 { 711 /* Exception occurred */ 712 return; 713 } 714 715 /* Read the operands */ 716 if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value)) 717 { 718 /* Exception occurred */ 719 return; 720 } 721 722 /* Calculate the result */ 723 Value = LOBYTE(Fast486RotateOperation(State, ModRegRm.Register, Value, 8, 1)); 724 725 /* Write back the result */ 726 Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Value); 727 728} 729 730FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD1) 731{ 732 FAST486_MOD_REG_RM ModRegRm; 733 BOOLEAN OperandSize, AddressSize; 734 735 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 736 737 TOGGLE_OPSIZE(OperandSize); 738 TOGGLE_ADSIZE(AddressSize); 739 740 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 741 { 742 /* Exception occurred */ 743 return; 744 } 745 746 if (OperandSize) 747 { 748 ULONG Value; 749 750 /* Read the operands */ 751 if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) 752 { 753 /* Exception occurred */ 754 return; 755 } 756 757 /* Calculate the result */ 758 Value = Fast486RotateOperation(State, ModRegRm.Register, Value, 32, 1); 759 760 /* Write back the result */ 761 Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value); 762 } 763 else 764 { 765 USHORT Value; 766 767 /* Read the operands */ 768 if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value)) 769 { 770 /* Exception occurred */ 771 return; 772 } 773 774 /* Calculate the result */ 775 Value = LOWORD(Fast486RotateOperation(State, ModRegRm.Register, Value, 16, 1)); 776 777 /* Write back the result */ 778 Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value); 779 } 780} 781 782FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD2) 783{ 784 UCHAR Value; 785 FAST486_MOD_REG_RM ModRegRm; 786 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 787 788 TOGGLE_ADSIZE(AddressSize); 789 790 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 791 { 792 /* Exception occurred */ 793 return; 794 } 795 796 /* Read the operands */ 797 if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value)) 798 { 799 /* Exception occurred */ 800 return; 801 } 802 803 /* Calculate the result */ 804 Value = LOBYTE(Fast486RotateOperation(State, 805 ModRegRm.Register, 806 Value, 807 8, 808 State->GeneralRegs[FAST486_REG_ECX].LowByte)); 809 810 /* Write back the result */ 811 Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Value); 812} 813 814FAST486_OPCODE_HANDLER(Fast486OpcodeGroupD3) 815{ 816 FAST486_MOD_REG_RM ModRegRm; 817 BOOLEAN OperandSize, AddressSize; 818 819 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 820 821 TOGGLE_OPSIZE(OperandSize); 822 TOGGLE_ADSIZE(AddressSize); 823 824 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 825 { 826 /* Exception occurred */ 827 return; 828 } 829 830 if (OperandSize) 831 { 832 ULONG Value; 833 834 /* Read the operands */ 835 if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) 836 { 837 /* Exception occurred */ 838 return; 839 } 840 841 /* Calculate the result */ 842 Value = Fast486RotateOperation(State, 843 ModRegRm.Register, 844 Value, 845 32, 846 State->GeneralRegs[FAST486_REG_ECX].LowByte); 847 848 /* Write back the result */ 849 Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value); 850 } 851 else 852 { 853 USHORT Value; 854 855 /* Read the operands */ 856 if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value)) 857 { 858 /* Exception occurred */ 859 return; 860 } 861 862 /* Calculate the result */ 863 Value = LOWORD(Fast486RotateOperation(State, 864 ModRegRm.Register, 865 Value, 866 16, 867 State->GeneralRegs[FAST486_REG_ECX].LowByte)); 868 869 /* Write back the result */ 870 Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value); 871 } 872} 873 874FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6) 875{ 876 UCHAR Value = 0; 877 FAST486_MOD_REG_RM ModRegRm; 878 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 879 880 TOGGLE_ADSIZE(AddressSize); 881 882 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 883 { 884 /* Exception occurred */ 885 return; 886 } 887 888 /* Read the operands */ 889 if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value)) 890 { 891 /* Exception occurred */ 892 return; 893 } 894 895 switch (ModRegRm.Register) 896 { 897 /* TEST */ 898 case 0: 899 case 1: 900 { 901 UCHAR Immediate, Result; 902 903 /* Fetch the immediate byte */ 904 if (!Fast486FetchByte(State, &Immediate)) 905 { 906 /* Exception occurred */ 907 return; 908 } 909 910 /* Calculate the result */ 911 Result = Value & Immediate; 912 913 /* Update the flags */ 914 State->Flags.Cf = FALSE; 915 State->Flags.Of = FALSE; 916 State->Flags.Zf = (Result == 0); 917 State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0); 918 State->Flags.Pf = Fast486CalculateParity(Result); 919 920 break; 921 } 922 923 /* NOT */ 924 case 2: 925 { 926 /* Write back the result */ 927 Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, ~Value); 928 929 break; 930 } 931 932 /* NEG */ 933 case 3: 934 { 935 /* Calculate the result */ 936 UCHAR Result = -Value; 937 938 /* Update the flags */ 939 State->Flags.Cf = (Value != 0); 940 State->Flags.Of = (Value & SIGN_FLAG_BYTE) && (Result & SIGN_FLAG_BYTE); 941 State->Flags.Af = ((Value & 0x0F) != 0); 942 State->Flags.Zf = (Result == 0); 943 State->Flags.Sf = ((Result & SIGN_FLAG_BYTE) != 0); 944 State->Flags.Pf = Fast486CalculateParity(Result); 945 946 /* Write back the result */ 947 Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Result); 948 949 break; 950 } 951 952 /* MUL */ 953 case 4: 954 { 955 USHORT Result = (USHORT)Value * (USHORT)State->GeneralRegs[FAST486_REG_EAX].LowByte; 956 957 /* Update the flags */ 958 State->Flags.Cf = State->Flags.Of = (HIBYTE(Result) != 0); 959 960 /* Write back the result */ 961 State->GeneralRegs[FAST486_REG_EAX].LowWord = Result; 962 963 break; 964 } 965 966 /* IMUL */ 967 case 5: 968 { 969 SHORT Result = (SHORT)((CHAR)Value) * (SHORT)((CHAR)State->GeneralRegs[FAST486_REG_EAX].LowByte); 970 971 /* Update the flags */ 972 State->Flags.Cf = State->Flags.Of = ((Result < FAST486_CHAR_MIN) || (Result > FAST486_CHAR_MAX)); 973 974 /* Write back the result */ 975 State->GeneralRegs[FAST486_REG_EAX].LowWord = (USHORT)Result; 976 977 break; 978 } 979 980 /* DIV */ 981 case 6: 982 { 983 USHORT Quotient; 984 UCHAR Remainder; 985 986 if (Value == 0) 987 { 988 /* Divide error */ 989 Fast486Exception(State, FAST486_EXCEPTION_DE); 990 return; 991 } 992 993 Quotient = State->GeneralRegs[FAST486_REG_EAX].LowWord / Value; 994 Remainder = State->GeneralRegs[FAST486_REG_EAX].LowWord % Value; 995 996 if (Quotient > 0xFF) 997 { 998 /* Divide error */ 999 Fast486Exception(State, FAST486_EXCEPTION_DE); 1000 return; 1001 } 1002 1003 /* Write back the results */ 1004 State->GeneralRegs[FAST486_REG_EAX].LowByte = (UCHAR)Quotient; 1005 State->GeneralRegs[FAST486_REG_EAX].HighByte = Remainder; 1006 1007 break; 1008 } 1009 1010 /* IDIV */ 1011 case 7: 1012 { 1013 SHORT Quotient; 1014 CHAR Remainder; 1015 1016 if (Value == 0) 1017 { 1018 /* Divide error */ 1019 Fast486Exception(State, FAST486_EXCEPTION_DE); 1020 return; 1021 } 1022 1023 Quotient = (SHORT)State->GeneralRegs[FAST486_REG_EAX].LowWord / (CHAR)Value; 1024 Remainder = (SHORT)State->GeneralRegs[FAST486_REG_EAX].LowWord % (CHAR)Value; 1025 1026 if (Quotient > FAST486_CHAR_MAX || Quotient < FAST486_CHAR_MIN) 1027 { 1028 /* Divide error */ 1029 Fast486Exception(State, FAST486_EXCEPTION_DE); 1030 return; 1031 } 1032 1033 /* Write back the results */ 1034 State->GeneralRegs[FAST486_REG_EAX].LowByte = (UCHAR)((CHAR)Quotient); 1035 State->GeneralRegs[FAST486_REG_EAX].HighByte = (UCHAR)Remainder; 1036 1037 break; 1038 } 1039 } 1040} 1041 1042FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7) 1043{ 1044 ULONG Value = 0, SignFlag; 1045 FAST486_MOD_REG_RM ModRegRm; 1046 BOOLEAN OperandSize, AddressSize; 1047 1048 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 1049 1050 TOGGLE_OPSIZE(OperandSize); 1051 TOGGLE_ADSIZE(AddressSize); 1052 1053 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 1054 { 1055 /* Exception occurred */ 1056 return; 1057 } 1058 1059 /* Set the sign flag */ 1060 if (OperandSize) SignFlag = SIGN_FLAG_LONG; 1061 else SignFlag = SIGN_FLAG_WORD; 1062 1063 /* Read the operand */ 1064 if (OperandSize) 1065 { 1066 /* 32-bit */ 1067 if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) 1068 { 1069 /* Exception occurred */ 1070 return; 1071 } 1072 } 1073 else 1074 { 1075 /* 16-bit */ 1076 if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, (PUSHORT)&Value)) 1077 { 1078 /* Exception occurred */ 1079 return; 1080 } 1081 } 1082 1083 switch (ModRegRm.Register) 1084 { 1085 /* TEST */ 1086 case 0: 1087 case 1: 1088 { 1089 ULONG Immediate = 0, Result = 0; 1090 1091 if (OperandSize) 1092 { 1093 /* Fetch the immediate dword */ 1094 if (!Fast486FetchDword(State, &Immediate)) 1095 { 1096 /* Exception occurred */ 1097 return; 1098 } 1099 } 1100 else 1101 { 1102 /* Fetch the immediate word */ 1103 if (!Fast486FetchWord(State, (PUSHORT)&Immediate)) 1104 { 1105 /* Exception occurred */ 1106 return; 1107 } 1108 } 1109 1110 /* Calculate the result */ 1111 Result = Value & Immediate; 1112 1113 /* Update the flags */ 1114 State->Flags.Cf = FALSE; 1115 State->Flags.Of = FALSE; 1116 State->Flags.Zf = (Result == 0); 1117 State->Flags.Sf = ((Result & SignFlag) != 0); 1118 State->Flags.Pf = Fast486CalculateParity(Result); 1119 1120 break; 1121 } 1122 1123 /* NOT */ 1124 case 2: 1125 { 1126 /* Write back the result */ 1127 if (OperandSize) 1128 { 1129 /* 32-bit */ 1130 Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, ~Value); 1131 } 1132 else 1133 { 1134 /* 16-bit */ 1135 Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, LOWORD(~Value)); 1136 } 1137 1138 break; 1139 } 1140 1141 /* NEG */ 1142 case 3: 1143 { 1144 /* Calculate the result */ 1145 ULONG Result = -(LONG)Value; 1146 if (!OperandSize) Result &= 0xFFFF; 1147 1148 /* Update the flags */ 1149 State->Flags.Cf = (Value != 0); 1150 State->Flags.Of = (Value & SignFlag) && (Result & SignFlag); 1151 State->Flags.Af = ((Value & 0x0F) != 0); 1152 State->Flags.Zf = (Result == 0); 1153 State->Flags.Sf = ((Result & SignFlag) != 0); 1154 State->Flags.Pf = Fast486CalculateParity(Result); 1155 1156 /* Write back the result */ 1157 if (OperandSize) 1158 { 1159 /* 32-bit */ 1160 Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Result); 1161 } 1162 else 1163 { 1164 /* 16-bit */ 1165 Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, LOWORD(Result)); 1166 } 1167 1168 break; 1169 } 1170 1171 /* MUL */ 1172 case 4: 1173 { 1174 if (OperandSize) 1175 { 1176 ULONGLONG Result = (ULONGLONG)Value * (ULONGLONG)State->GeneralRegs[FAST486_REG_EAX].Long; 1177 1178 /* Update the flags */ 1179 State->Flags.Cf = State->Flags.Of = ((Result & 0xFFFFFFFF00000000ULL) != 0); 1180 1181 /* Write back the result */ 1182 State->GeneralRegs[FAST486_REG_EAX].Long = Result & 0xFFFFFFFFULL; 1183 State->GeneralRegs[FAST486_REG_EDX].Long = Result >> 32; 1184 } 1185 else 1186 { 1187 ULONG Result = (ULONG)Value * (ULONG)State->GeneralRegs[FAST486_REG_EAX].LowWord; 1188 1189 /* Update the flags */ 1190 State->Flags.Cf = State->Flags.Of = (HIWORD(Result) != 0); 1191 1192 /* Write back the result */ 1193 State->GeneralRegs[FAST486_REG_EAX].LowWord = LOWORD(Result); 1194 State->GeneralRegs[FAST486_REG_EDX].LowWord = HIWORD(Result); 1195 } 1196 1197 break; 1198 } 1199 1200 /* IMUL */ 1201 case 5: 1202 { 1203 if (OperandSize) 1204 { 1205 LONGLONG Result = (LONGLONG)((LONG)Value) * (LONGLONG)((LONG)State->GeneralRegs[FAST486_REG_EAX].Long); 1206 1207 /* Update the flags */ 1208 State->Flags.Cf = State->Flags.Of = ((Result < FAST486_LONG_MIN) || (Result > FAST486_LONG_MAX)); 1209 1210 /* Write back the result */ 1211 State->GeneralRegs[FAST486_REG_EAX].Long = Result & 0xFFFFFFFFULL; 1212 State->GeneralRegs[FAST486_REG_EDX].Long = Result >> 32; 1213 } 1214 else 1215 { 1216 LONG Result = (LONG)((SHORT)Value) * (LONG)((SHORT)State->GeneralRegs[FAST486_REG_EAX].LowWord); 1217 1218 /* Update the flags */ 1219 State->Flags.Cf = State->Flags.Of = ((Result < FAST486_SHORT_MIN) || (Result > FAST486_SHORT_MAX)); 1220 1221 /* Write back the result */ 1222 State->GeneralRegs[FAST486_REG_EAX].LowWord = LOWORD(Result); 1223 State->GeneralRegs[FAST486_REG_EDX].LowWord = HIWORD(Result); 1224 } 1225 1226 break; 1227 } 1228 1229 /* DIV */ 1230 case 6: 1231 { 1232 if (Value == 0) 1233 { 1234 /* Divide error */ 1235 Fast486Exception(State, FAST486_EXCEPTION_DE); 1236 return; 1237 } 1238 1239 if (OperandSize) 1240 { 1241 ULONGLONG Dividend = (ULONGLONG)State->GeneralRegs[FAST486_REG_EAX].Long 1242 | ((ULONGLONG)State->GeneralRegs[FAST486_REG_EDX].Long << 32); 1243 ULONGLONG Quotient = Dividend / Value; 1244 ULONG Remainder = Dividend % Value; 1245 1246 if (Quotient > 0xFFFFFFFFULL) 1247 { 1248 /* Divide error */ 1249 Fast486Exception(State, FAST486_EXCEPTION_DE); 1250 return; 1251 } 1252 1253 /* Write back the results */ 1254 State->GeneralRegs[FAST486_REG_EAX].Long = (ULONG)Quotient; 1255 State->GeneralRegs[FAST486_REG_EDX].Long = Remainder; 1256 } 1257 else 1258 { 1259 ULONG Dividend = (ULONG)State->GeneralRegs[FAST486_REG_EAX].LowWord 1260 | ((ULONG)State->GeneralRegs[FAST486_REG_EDX].LowWord << 16); 1261 ULONG Quotient = Dividend / Value; 1262 USHORT Remainder = Dividend % Value; 1263 1264 if (Quotient > 0xFFFF) 1265 { 1266 /* Divide error */ 1267 Fast486Exception(State, FAST486_EXCEPTION_DE); 1268 return; 1269 } 1270 1271 /* Write back the results */ 1272 State->GeneralRegs[FAST486_REG_EAX].LowWord = (USHORT)Quotient; 1273 State->GeneralRegs[FAST486_REG_EDX].LowWord = Remainder; 1274 } 1275 1276 break; 1277 } 1278 1279 /* IDIV */ 1280 case 7: 1281 { 1282 if (Value == 0) 1283 { 1284 /* Divide error */ 1285 Fast486Exception(State, FAST486_EXCEPTION_DE); 1286 return; 1287 } 1288 1289 if (OperandSize) 1290 { 1291 LONGLONG Dividend = (LONGLONG)State->GeneralRegs[FAST486_REG_EAX].Long 1292 | ((LONGLONG)State->GeneralRegs[FAST486_REG_EDX].Long << 32); 1293 LONGLONG Quotient = Dividend / (LONG)Value; 1294 LONG Remainder = Dividend % (LONG)Value; 1295 1296 if (Quotient > FAST486_LONG_MAX || Quotient < FAST486_LONG_MIN) 1297 { 1298 /* Divide error */ 1299 Fast486Exception(State, FAST486_EXCEPTION_DE); 1300 return; 1301 } 1302 1303 /* Write back the results */ 1304 State->GeneralRegs[FAST486_REG_EAX].Long = (ULONG)((LONG)Quotient); 1305 State->GeneralRegs[FAST486_REG_EDX].Long = (ULONG)Remainder; 1306 } 1307 else 1308 { 1309 LONG Dividend = (LONG)State->GeneralRegs[FAST486_REG_EAX].LowWord 1310 | ((LONG)State->GeneralRegs[FAST486_REG_EDX].LowWord << 16); 1311 LONG Quotient = Dividend / (SHORT)LOWORD(Value); 1312 SHORT Remainder = Dividend % (SHORT)LOWORD(Value); 1313 1314 if (Quotient > FAST486_SHORT_MAX || Quotient < FAST486_SHORT_MIN) 1315 { 1316 /* Divide error */ 1317 Fast486Exception(State, FAST486_EXCEPTION_DE); 1318 return; 1319 } 1320 1321 /* Write back the results */ 1322 State->GeneralRegs[FAST486_REG_EAX].LowWord = (USHORT)((SHORT)Quotient); 1323 State->GeneralRegs[FAST486_REG_EDX].LowWord = (USHORT)Remainder; 1324 } 1325 1326 break; 1327 } 1328 } 1329} 1330 1331FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFE) 1332{ 1333 UCHAR Value; 1334 FAST486_MOD_REG_RM ModRegRm; 1335 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 1336 1337 TOGGLE_ADSIZE(AddressSize); 1338 1339 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 1340 { 1341 /* Exception occurred */ 1342 return; 1343 } 1344 1345 if (ModRegRm.Register > 1) 1346 { 1347 /* Invalid */ 1348 Fast486Exception(State, FAST486_EXCEPTION_UD); 1349 return; 1350 } 1351 1352 /* Read the operands */ 1353 if (!Fast486ReadModrmByteOperands(State, &ModRegRm, NULL, &Value)) 1354 { 1355 /* Exception occurred */ 1356 return; 1357 } 1358 1359 if (ModRegRm.Register == 0) 1360 { 1361 /* Increment and update OF and AF */ 1362 Value++; 1363 State->Flags.Of = (Value == SIGN_FLAG_BYTE); 1364 State->Flags.Af = ((Value & 0x0F) == 0); 1365 } 1366 else 1367 { 1368 /* Decrement and update OF and AF */ 1369 State->Flags.Of = (Value == SIGN_FLAG_BYTE); 1370 Value--; 1371 State->Flags.Af = ((Value & 0x0F) == 0x0F); 1372 } 1373 1374 /* Update flags */ 1375 State->Flags.Zf = (Value == 0); 1376 State->Flags.Sf = ((Value & SIGN_FLAG_BYTE) != 0); 1377 State->Flags.Pf = Fast486CalculateParity(Value); 1378 1379 /* Write back the result */ 1380 Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Value); 1381} 1382 1383FAST486_OPCODE_HANDLER(Fast486OpcodeGroupFF) 1384{ 1385 FAST486_MOD_REG_RM ModRegRm; 1386 BOOLEAN OperandSize, AddressSize; 1387 1388 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 1389 1390 TOGGLE_OPSIZE(OperandSize); 1391 TOGGLE_ADSIZE(AddressSize); 1392 1393 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 1394 { 1395 /* Exception occurred */ 1396 return; 1397 } 1398 1399 if (ModRegRm.Register == 7) 1400 { 1401 /* Invalid */ 1402 Fast486Exception(State, FAST486_EXCEPTION_UD); 1403 return; 1404 } 1405 1406 /* Read the operands */ 1407 if (OperandSize) 1408 { 1409 ULONG Value; 1410 1411 if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) 1412 { 1413 /* Exception occurred */ 1414 return; 1415 } 1416 1417 if (ModRegRm.Register == 0) 1418 { 1419 /* Increment and update OF and AF */ 1420 Value++; 1421 State->Flags.Of = (Value == SIGN_FLAG_LONG); 1422 State->Flags.Af = ((Value & 0x0F) == 0); 1423 } 1424 else if (ModRegRm.Register == 1) 1425 { 1426 /* Decrement and update OF and AF */ 1427 State->Flags.Of = (Value == SIGN_FLAG_LONG); 1428 Value--; 1429 State->Flags.Af = ((Value & 0x0F) == 0x0F); 1430 } 1431 else if (ModRegRm.Register == 2) 1432 { 1433 /* Push the current value of EIP */ 1434 if (!Fast486StackPush(State, State->InstPtr.Long)) 1435 { 1436 /* Exception occurred */ 1437 return; 1438 } 1439 1440 /* Set the EIP to the address */ 1441 State->InstPtr.Long = Value; 1442 } 1443 else if (ModRegRm.Register == 3) 1444 { 1445 USHORT Selector; 1446 FAST486_SEG_REGS Segment = FAST486_REG_DS; 1447 1448 /* Check for the segment override */ 1449 if (State->PrefixFlags & FAST486_PREFIX_SEG) 1450 { 1451 /* Use the override segment instead */ 1452 Segment = State->SegmentOverride; 1453 } 1454 1455 /* Read the selector */ 1456 if (!Fast486ReadMemory(State, 1457 Segment, 1458 ModRegRm.MemoryAddress + sizeof(ULONG), 1459 FALSE, 1460 &Selector, 1461 sizeof(USHORT))) 1462 { 1463 /* Exception occurred */ 1464 return; 1465 } 1466 1467 if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) 1468 && !State->Flags.Vm) 1469 { 1470 if (!Fast486ProcessGate(State, Selector, Value, TRUE)) 1471 { 1472 /* Gate processed or exception occurred */ 1473 return; 1474 } 1475 } 1476 1477 /* Push the current value of CS */ 1478 if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_CS].Selector)) 1479 { 1480 /* Exception occurred */ 1481 return; 1482 } 1483 1484 /* Push the current value of EIP */ 1485 if (!Fast486StackPush(State, State->InstPtr.Long)) 1486 { 1487 /* Exception occurred */ 1488 return; 1489 } 1490 1491 /* Load the new code segment */ 1492 if (!Fast486LoadSegment(State, FAST486_REG_CS, Selector)) 1493 { 1494 /* Exception occurred */ 1495 return; 1496 } 1497 1498 /* Set the EIP to the address */ 1499 State->InstPtr.Long = Value; 1500 } 1501 else if (ModRegRm.Register == 4) 1502 { 1503 /* Set the EIP to the address */ 1504 State->InstPtr.Long = Value; 1505 } 1506 else if (ModRegRm.Register == 5) 1507 { 1508 USHORT Selector; 1509 FAST486_SEG_REGS Segment = FAST486_REG_DS; 1510 1511 /* Check for the segment override */ 1512 if (State->PrefixFlags & FAST486_PREFIX_SEG) 1513 { 1514 /* Use the override segment instead */ 1515 Segment = State->SegmentOverride; 1516 } 1517 1518 /* Read the selector */ 1519 if (!Fast486ReadMemory(State, 1520 Segment, 1521 ModRegRm.MemoryAddress + sizeof(ULONG), 1522 FALSE, 1523 &Selector, 1524 sizeof(USHORT))) 1525 { 1526 /* Exception occurred */ 1527 return; 1528 } 1529 1530 if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) 1531 && !State->Flags.Vm) 1532 { 1533 if (!Fast486ProcessGate(State, Selector, Value, FALSE)) 1534 { 1535 /* Gate processed or exception occurred */ 1536 return; 1537 } 1538 } 1539 1540 /* Load the new code segment */ 1541 if (!Fast486LoadSegment(State, FAST486_REG_CS, Selector)) 1542 { 1543 /* Exception occurred */ 1544 return; 1545 } 1546 1547 /* Set the EIP to the address */ 1548 State->InstPtr.Long = Value; 1549 } 1550 else if (ModRegRm.Register == 6) 1551 { 1552 /* Push the value on to the stack */ 1553 Fast486StackPush(State, Value); 1554 return; 1555 } 1556 1557 if (ModRegRm.Register <= 1) 1558 { 1559 /* Update flags */ 1560 State->Flags.Sf = ((Value & SIGN_FLAG_LONG) != 0); 1561 State->Flags.Zf = (Value == 0); 1562 State->Flags.Pf = Fast486CalculateParity(Value); 1563 1564 /* Write back the result */ 1565 Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value); 1566 } 1567 } 1568 else 1569 { 1570 USHORT Value; 1571 1572 if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value)) 1573 { 1574 /* Exception occurred */ 1575 return; 1576 } 1577 1578 if (ModRegRm.Register == 0) 1579 { 1580 /* Increment and update OF */ 1581 Value++; 1582 State->Flags.Of = (Value == SIGN_FLAG_WORD); 1583 State->Flags.Af = ((Value & 0x0F) == 0); 1584 } 1585 else if (ModRegRm.Register == 1) 1586 { 1587 /* Decrement and update OF */ 1588 State->Flags.Of = (Value == SIGN_FLAG_WORD); 1589 Value--; 1590 State->Flags.Af = ((Value & 0x0F) == 0x0F); 1591 } 1592 else if (ModRegRm.Register == 2) 1593 { 1594 /* Push the current value of IP */ 1595 if (!Fast486StackPush(State, State->InstPtr.LowWord)) 1596 { 1597 /* Exception occurred */ 1598 return; 1599 } 1600 1601 /* Set the IP to the address */ 1602 State->InstPtr.LowWord = Value; 1603 1604 /* Clear the top half of EIP */ 1605 State->InstPtr.Long &= 0xFFFF; 1606 } 1607 else if (ModRegRm.Register == 3) 1608 { 1609 USHORT Selector; 1610 FAST486_SEG_REGS Segment = FAST486_REG_DS; 1611 1612 /* Check for the segment override */ 1613 if (State->PrefixFlags & FAST486_PREFIX_SEG) 1614 { 1615 /* Use the override segment instead */ 1616 Segment = State->SegmentOverride; 1617 } 1618 1619 /* Read the selector */ 1620 if (!Fast486ReadMemory(State, 1621 Segment, 1622 ModRegRm.MemoryAddress + sizeof(USHORT), 1623 FALSE, 1624 &Selector, 1625 sizeof(USHORT))) 1626 { 1627 /* Exception occurred */ 1628 return; 1629 } 1630 1631 if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) 1632 && !State->Flags.Vm) 1633 { 1634 if (!Fast486ProcessGate(State, Selector, Value, TRUE)) 1635 { 1636 /* Gate processed or exception occurred */ 1637 return; 1638 } 1639 } 1640 1641 /* Push the current value of CS */ 1642 if (!Fast486StackPush(State, State->SegmentRegs[FAST486_REG_CS].Selector)) 1643 { 1644 /* Exception occurred */ 1645 return; 1646 } 1647 1648 /* Push the current value of IP */ 1649 if (!Fast486StackPush(State, State->InstPtr.LowWord)) 1650 { 1651 /* Exception occurred */ 1652 return; 1653 } 1654 1655 /* Load the new code segment */ 1656 if (!Fast486LoadSegment(State, FAST486_REG_CS, Selector)) 1657 { 1658 /* Exception occurred */ 1659 return; 1660 } 1661 1662 /* Set the IP to the address */ 1663 State->InstPtr.LowWord = Value; 1664 1665 /* Clear the top half of EIP */ 1666 State->InstPtr.Long &= 0xFFFF; 1667 } 1668 else if (ModRegRm.Register == 4) 1669 { 1670 /* Set the IP to the address */ 1671 State->InstPtr.LowWord = Value; 1672 1673 /* Clear the top half of EIP */ 1674 State->InstPtr.Long &= 0xFFFF; 1675 } 1676 else if (ModRegRm.Register == 5) 1677 { 1678 USHORT Selector; 1679 FAST486_SEG_REGS Segment = FAST486_REG_DS; 1680 1681 /* Check for the segment override */ 1682 if (State->PrefixFlags & FAST486_PREFIX_SEG) 1683 { 1684 /* Use the override segment instead */ 1685 Segment = State->SegmentOverride; 1686 } 1687 1688 /* Read the selector */ 1689 if (!Fast486ReadMemory(State, 1690 Segment, 1691 ModRegRm.MemoryAddress + sizeof(USHORT), 1692 FALSE, 1693 &Selector, 1694 sizeof(USHORT))) 1695 { 1696 /* Exception occurred */ 1697 return; 1698 } 1699 1700 if ((State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) 1701 && !State->Flags.Vm) 1702 { 1703 if (!Fast486ProcessGate(State, Selector, Value, FALSE)) 1704 { 1705 /* Gate processed or exception occurred */ 1706 return; 1707 } 1708 } 1709 1710 /* Load the new code segment */ 1711 if (!Fast486LoadSegment(State, FAST486_REG_CS, Selector)) 1712 { 1713 /* Exception occurred */ 1714 return; 1715 } 1716 1717 /* Set the IP to the address */ 1718 State->InstPtr.LowWord = Value; 1719 1720 /* Clear the top half of EIP */ 1721 State->InstPtr.Long &= 0xFFFF; 1722 } 1723 else if (ModRegRm.Register == 6) 1724 { 1725 /* Push the value on to the stack */ 1726 Fast486StackPush(State, Value); 1727 return; 1728 } 1729 else 1730 { 1731 /* Invalid */ 1732 Fast486Exception(State, FAST486_EXCEPTION_UD); 1733 return; 1734 } 1735 1736 if (ModRegRm.Register <= 1) 1737 { 1738 /* Update flags */ 1739 State->Flags.Sf = ((Value & SIGN_FLAG_WORD) != 0); 1740 State->Flags.Zf = (Value == 0); 1741 State->Flags.Pf = Fast486CalculateParity(Value); 1742 1743 /* Write back the result */ 1744 Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value); 1745 } 1746 } 1747} 1748 1749FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0F00) 1750{ 1751 FAST486_MOD_REG_RM ModRegRm; 1752 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 1753 1754 NO_LOCK_PREFIX(); 1755 TOGGLE_ADSIZE(AddressSize); 1756 1757 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 1758 { 1759 /* Exception occurred */ 1760 return; 1761 } 1762 1763 /* Check which operation this is */ 1764 switch (ModRegRm.Register) 1765 { 1766 /* SLDT */ 1767 case 0: 1768 { 1769 /* Not recognized in real mode or virtual 8086 mode */ 1770 if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) 1771 || State->Flags.Vm) 1772 { 1773 Fast486Exception(State, FAST486_EXCEPTION_UD); 1774 return; 1775 } 1776 1777 Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, State->Ldtr.Selector); 1778 break; 1779 } 1780 1781 /* STR */ 1782 case 1: 1783 { 1784 /* Not recognized in real mode or virtual 8086 mode */ 1785 if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) 1786 || State->Flags.Vm) 1787 { 1788 Fast486Exception(State, FAST486_EXCEPTION_UD); 1789 return; 1790 } 1791 1792 Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, State->TaskReg.Selector); 1793 break; 1794 } 1795 1796 /* LLDT */ 1797 case 2: 1798 { 1799 BOOLEAN Valid; 1800 USHORT Selector; 1801 FAST486_SYSTEM_DESCRIPTOR GdtEntry; 1802 1803 /* Not recognized in real mode or virtual 8086 mode */ 1804 if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) 1805 || State->Flags.Vm) 1806 { 1807 Fast486Exception(State, FAST486_EXCEPTION_UD); 1808 return; 1809 } 1810 1811 /* This is a privileged instruction */ 1812 if (Fast486GetCurrentPrivLevel(State) != 0) 1813 { 1814 Fast486Exception(State, FAST486_EXCEPTION_GP); 1815 return; 1816 } 1817 1818 if (!Fast486ReadModrmWordOperands(State, 1819 &ModRegRm, 1820 NULL, 1821 &Selector)) 1822 { 1823 /* Exception occurred */ 1824 return; 1825 } 1826 1827 if (Selector & SEGMENT_TABLE_INDICATOR) 1828 { 1829 /* This selector doesn't point to the GDT */ 1830 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector); 1831 return; 1832 } 1833 1834 if (!Fast486ReadDescriptorEntry(State, 1835 Selector, 1836 &Valid, 1837 (PFAST486_GDT_ENTRY)&GdtEntry)) 1838 { 1839 /* Exception occurred */ 1840 return; 1841 } 1842 1843 if (!Valid) 1844 { 1845 /* Invalid selector */ 1846 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector); 1847 return; 1848 } 1849 1850 if (GET_SEGMENT_INDEX(Selector) == 0) 1851 { 1852 RtlZeroMemory(&State->Ldtr, sizeof(State->Ldtr)); 1853 return; 1854 } 1855 1856 if (!GdtEntry.Present) 1857 { 1858 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_NP, Selector); 1859 return; 1860 } 1861 1862 if (GdtEntry.Signature != FAST486_LDT_SIGNATURE) 1863 { 1864 /* This is not a LDT descriptor */ 1865 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector); 1866 return; 1867 } 1868 1869 /* Update the LDTR */ 1870 State->Ldtr.Selector = Selector; 1871 State->Ldtr.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24); 1872 State->Ldtr.Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16); 1873 1874 if (GdtEntry.Granularity) 1875 { 1876 State->Ldtr.Limit <<= 12; 1877 State->Ldtr.Limit |= 0x00000FFF; 1878 } 1879 1880 break; 1881 } 1882 1883 /* LTR */ 1884 case 3: 1885 { 1886 BOOLEAN Valid; 1887 USHORT Selector; 1888 FAST486_SYSTEM_DESCRIPTOR GdtEntry; 1889 1890 /* Not recognized in real mode or virtual 8086 mode */ 1891 if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) 1892 || State->Flags.Vm) 1893 { 1894 Fast486Exception(State, FAST486_EXCEPTION_UD); 1895 return; 1896 } 1897 1898 /* This is a privileged instruction */ 1899 if (Fast486GetCurrentPrivLevel(State) != 0) 1900 { 1901 Fast486Exception(State, FAST486_EXCEPTION_GP); 1902 return; 1903 } 1904 1905 if (!Fast486ReadModrmWordOperands(State, 1906 &ModRegRm, 1907 NULL, 1908 &Selector)) 1909 { 1910 /* Exception occurred */ 1911 return; 1912 } 1913 1914 if (Selector & SEGMENT_TABLE_INDICATOR) 1915 { 1916 /* This selector doesn't point to the GDT */ 1917 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector); 1918 return; 1919 } 1920 1921 if (!Fast486ReadDescriptorEntry(State, 1922 Selector, 1923 &Valid, 1924 (PFAST486_GDT_ENTRY)&GdtEntry)) 1925 { 1926 /* Exception occurred */ 1927 return; 1928 } 1929 1930 if (!Valid) 1931 { 1932 /* Invalid selector */ 1933 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector); 1934 return; 1935 } 1936 1937 if (GET_SEGMENT_INDEX(Selector) == 0) 1938 { 1939 Fast486Exception(State, FAST486_EXCEPTION_GP); 1940 return; 1941 } 1942 1943 if (!GdtEntry.Present) 1944 { 1945 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_NP, Selector); 1946 return; 1947 } 1948 1949 if (GdtEntry.Signature != FAST486_TSS_SIGNATURE 1950 && GdtEntry.Signature != FAST486_BUSY_TSS_SIGNATURE 1951 && GdtEntry.Signature != FAST486_TSS_16_SIGNATURE 1952 && GdtEntry.Signature != FAST486_BUSY_TSS_16_SIGNATURE) 1953 { 1954 /* This is not a TSS descriptor */ 1955 Fast486ExceptionWithErrorCode(State, FAST486_EXCEPTION_GP, Selector); 1956 return; 1957 } 1958 1959 /* Update the TR */ 1960 State->TaskReg.Selector = Selector; 1961 State->TaskReg.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24); 1962 State->TaskReg.Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16); 1963 State->TaskReg.Modern = GdtEntry.Signature == FAST486_TSS_SIGNATURE 1964 || GdtEntry.Signature == FAST486_BUSY_TSS_SIGNATURE; 1965 1966 if (GdtEntry.Granularity) 1967 { 1968 State->TaskReg.Limit <<= 12; 1969 State->TaskReg.Limit |= 0x00000FFF; 1970 } 1971 1972 if (GdtEntry.Signature != FAST486_BUSY_TSS_SIGNATURE 1973 && GdtEntry.Signature != FAST486_BUSY_TSS_16_SIGNATURE) 1974 { 1975 /* Set the busy bit of this TSS descriptor and write it back */ 1976 GdtEntry.Signature |= 2; 1977 1978 Fast486WriteLinearMemory(State, 1979 State->Gdtr.Address + GET_SEGMENT_INDEX(Selector), 1980 &GdtEntry, 1981 sizeof(GdtEntry), 1982 FALSE /* We already made sure CPL is 0 */); 1983 } 1984 1985 break; 1986 } 1987 1988 /* VERR/VERW */ 1989 case 4: 1990 case 5: 1991 { 1992 USHORT Selector; 1993 BOOLEAN Valid; 1994 FAST486_GDT_ENTRY GdtEntry; 1995 1996 /* Not recognized in real mode or virtual 8086 mode */ 1997 if (!(State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) 1998 || State->Flags.Vm) 1999 { 2000 Fast486Exception(State, FAST486_EXCEPTION_UD); 2001 return; 2002 } 2003 2004 if (!Fast486ReadModrmWordOperands(State, 2005 &ModRegRm, 2006 NULL, 2007 &Selector)) 2008 { 2009 /* Exception occurred */ 2010 return; 2011 } 2012 2013 if (!Fast486ReadDescriptorEntry(State, Selector, &Valid, &GdtEntry)) 2014 { 2015 /* Exception occurred */ 2016 return; 2017 } 2018 2019 if (!Valid) 2020 { 2021 /* Clear ZF */ 2022 State->Flags.Zf = FALSE; 2023 return; 2024 } 2025 2026 /* Set ZF if it is valid and accessible */ 2027 State->Flags.Zf = GdtEntry.Present // must be present 2028 && GdtEntry.SystemType // must be a segment 2029 && (((ModRegRm.Register == 4) 2030 /* code segments are only readable if the RW bit is set */ 2031 && (!GdtEntry.Executable || GdtEntry.ReadWrite)) 2032 || ((ModRegRm.Register == 5) 2033 /* code segments are never writable, data segments are writable when RW is set */ 2034 && (!GdtEntry.Executable && GdtEntry.ReadWrite))) 2035 /* 2036 * for segments other than conforming code segments, 2037 * both RPL and CPL must be less than or equal to DPL 2038 */ 2039 && (((!GdtEntry.Executable || !GdtEntry.DirConf) 2040 && (GET_SEGMENT_RPL(Selector) <= GdtEntry.Dpl) 2041 && (Fast486GetCurrentPrivLevel(State) <= GdtEntry.Dpl)) 2042 /* for conforming code segments, DPL must be less than or equal to CPL */ 2043 || ((GdtEntry.Executable && GdtEntry.DirConf) 2044 && (GdtEntry.Dpl <= Fast486GetCurrentPrivLevel(State)))); 2045 2046 2047 break; 2048 } 2049 2050 /* Invalid */ 2051 default: 2052 { 2053 Fast486Exception(State, FAST486_EXCEPTION_UD); 2054 } 2055 } 2056} 2057 2058FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0F01) 2059{ 2060 // FAST486_TABLE_REG TableReg; 2061 UCHAR TableReg[6]; 2062 FAST486_MOD_REG_RM ModRegRm; 2063 BOOLEAN OperandSize, AddressSize; 2064 FAST486_SEG_REGS Segment = FAST486_REG_DS; 2065 2066 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 2067 2068 NO_LOCK_PREFIX(); 2069 TOGGLE_OPSIZE(OperandSize); 2070 TOGGLE_ADSIZE(AddressSize); 2071 2072 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 2073 { 2074 /* Exception occurred */ 2075 return; 2076 } 2077 2078 /* Check for the segment override */ 2079 if (State->PrefixFlags & FAST486_PREFIX_SEG) 2080 { 2081 /* Use the override segment instead */ 2082 Segment = State->SegmentOverride; 2083 } 2084 2085 /* Check which operation this is */ 2086 switch (ModRegRm.Register) 2087 { 2088 /* SGDT */ 2089 case 0: 2090 { 2091 if (!ModRegRm.Memory) 2092 { 2093 /* The second operand must be a memory location */ 2094 Fast486Exception(State, FAST486_EXCEPTION_UD); 2095 return; 2096 } 2097 2098 /* Fill the 6-byte table register */ 2099 // TableReg = State->Gdtr; 2100 *((PUSHORT)&TableReg) = State->Gdtr.Size; 2101 *((PULONG)&TableReg[sizeof(USHORT)]) = State->Gdtr.Address; 2102 2103 /* Store the GDTR */ 2104 Fast486WriteMemory(State, 2105 Segment, 2106 ModRegRm.MemoryAddress, 2107 TableReg, 2108 sizeof(TableReg)); 2109 2110 break; 2111 } 2112 2113 /* SIDT */ 2114 case 1: 2115 { 2116 if (!ModRegRm.Memory) 2117 { 2118 /* The second operand must be a memory location */ 2119 Fast486Exception(State, FAST486_EXCEPTION_UD); 2120 return; 2121 } 2122 2123 /* Fill the 6-byte table register */ 2124 // TableReg = State->Idtr; 2125 *((PUSHORT)&TableReg) = State->Idtr.Size; 2126 *((PULONG)&TableReg[sizeof(USHORT)]) = State->Idtr.Address; 2127 2128 /* Store the IDTR */ 2129 Fast486WriteMemory(State, 2130 Segment, 2131 ModRegRm.MemoryAddress, 2132 TableReg, 2133 sizeof(TableReg)); 2134 2135 break; 2136 } 2137 2138 /* LGDT */ 2139 case 2: 2140 { 2141 /* This is a privileged instruction */ 2142 if (Fast486GetCurrentPrivLevel(State) != 0) 2143 { 2144 Fast486Exception(State, FAST486_EXCEPTION_GP); 2145 return; 2146 } 2147 2148 if (!ModRegRm.Memory) 2149 { 2150 /* The second operand must be a memory location */ 2151 Fast486Exception(State, FAST486_EXCEPTION_UD); 2152 return; 2153 } 2154 2155 /* Read the new GDTR */ 2156 if (!Fast486ReadMemory(State, 2157 Segment, 2158 ModRegRm.MemoryAddress, 2159 FALSE, 2160 TableReg, 2161 sizeof(TableReg))) 2162 { 2163 /* Exception occurred */ 2164 return; 2165 } 2166 2167 /* Load the new GDT */ 2168 // State->Gdtr = TableReg; 2169 State->Gdtr.Size = *((PUSHORT)&TableReg); 2170 State->Gdtr.Address = *((PULONG)&TableReg[sizeof(USHORT)]); 2171 2172 /* In 16-bit mode the highest byte is masked out */ 2173 if (!OperandSize) State->Gdtr.Address &= 0x00FFFFFF; 2174 2175 break; 2176 } 2177 2178 /* LIDT */ 2179 case 3: 2180 { 2181 /* This is a privileged instruction */ 2182 if (Fast486GetCurrentPrivLevel(State) != 0) 2183 { 2184 Fast486Exception(State, FAST486_EXCEPTION_GP); 2185 return; 2186 } 2187 2188 if (!ModRegRm.Memory) 2189 { 2190 /* The second operand must be a memory location */ 2191 Fast486Exception(State, FAST486_EXCEPTION_UD); 2192 return; 2193 } 2194 2195 /* Read the new IDTR */ 2196 if (!Fast486ReadMemory(State, 2197 Segment, 2198 ModRegRm.MemoryAddress, 2199 FALSE, 2200 TableReg, 2201 sizeof(TableReg))) 2202 { 2203 /* Exception occurred */ 2204 return; 2205 } 2206 2207 /* Load the new IDT */ 2208 // State->Idtr = TableReg; 2209 State->Idtr.Size = *((PUSHORT)&TableReg); 2210 State->Idtr.Address = *((PULONG)&TableReg[sizeof(USHORT)]); 2211 2212 /* In 16-bit mode the highest byte is masked out */ 2213 if (!OperandSize) State->Idtr.Address &= 0x00FFFFFF; 2214 2215 break; 2216 } 2217 2218 /* SMSW */ 2219 case 4: 2220 { 2221 /* Store the lower 16 bits (Machine Status Word) of CR0 */ 2222 Fast486WriteModrmWordOperands(State, 2223 &ModRegRm, 2224 FALSE, 2225 LOWORD(State->ControlRegisters[FAST486_REG_CR0])); 2226 2227 break; 2228 } 2229 2230 /* LMSW */ 2231 case 6: 2232 { 2233 USHORT MachineStatusWord; 2234 2235 if (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE) 2236 { 2237 /* This is a privileged instruction */ 2238 if (Fast486GetCurrentPrivLevel(State) != 0) 2239 { 2240 Fast486Exception(State, FAST486_EXCEPTION_GP); 2241 return; 2242 } 2243 } 2244 2245 /* Read the new Machine Status Word */ 2246 if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &MachineStatusWord)) 2247 { 2248 /* Exception occurred */ 2249 return; 2250 } 2251 2252 /* Set the lowest 4 bits, but never clear bit 0 */ 2253 State->ControlRegisters[FAST486_REG_CR0] &= 0xFFFFFFF1; 2254 State->ControlRegisters[FAST486_REG_CR0] |= MachineStatusWord & 0x0F; 2255 2256 break; 2257 } 2258 2259 /* INVLPG */ 2260 case 7: 2261 { 2262#ifndef FAST486_NO_PREFETCH 2263 /* Invalidate the prefetch */ 2264 State->PrefetchValid = FALSE; 2265#endif 2266 2267 /* This is a privileged instruction */ 2268 if (Fast486GetCurrentPrivLevel(State) != 0) 2269 { 2270 Fast486Exception(State, FAST486_EXCEPTION_GP); 2271 return; 2272 } 2273 2274 if (!ModRegRm.Memory) 2275 { 2276 /* The second operand must be a memory location */ 2277 Fast486Exception(State, FAST486_EXCEPTION_UD); 2278 return; 2279 } 2280 2281 if (State->Tlb != NULL) 2282 { 2283 /* Clear the TLB entry */ 2284 State->Tlb[ModRegRm.MemoryAddress >> 12] = INVALID_TLB_FIELD; 2285 } 2286 2287 break; 2288 } 2289 2290 /* Invalid */ 2291 default: 2292 { 2293 Fast486Exception(State, FAST486_EXCEPTION_UD); 2294 } 2295 } 2296} 2297 2298FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0FB9) 2299{ 2300 FAST486_MOD_REG_RM ModRegRm; 2301 BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 2302 2303 TOGGLE_ADSIZE(AddressSize); 2304 2305 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 2306 { 2307 /* Exception occurred */ 2308 return; 2309 } 2310 2311 /* All of them are reserved (UD2) */ 2312 Fast486Exception(State, FAST486_EXCEPTION_UD); 2313 return; 2314} 2315 2316FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0FBA) 2317{ 2318 FAST486_MOD_REG_RM ModRegRm; 2319 BOOLEAN OperandSize, AddressSize; 2320 UINT DataSize; 2321 UCHAR BitNumber; 2322 2323 OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size; 2324 2325 TOGGLE_OPSIZE(OperandSize); 2326 TOGGLE_ADSIZE(AddressSize); 2327 2328 /* Get the number of bits */ 2329 if (OperandSize) DataSize = 32; 2330 else DataSize = 16; 2331 2332 if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm)) 2333 { 2334 /* Exception occurred */ 2335 return; 2336 } 2337 2338 if (ModRegRm.Register < 4) 2339 { 2340 /* Invalid */ 2341 Fast486Exception(State, FAST486_EXCEPTION_UD); 2342 return; 2343 } 2344 2345 /* Get the bit number */ 2346 if (!Fast486FetchByte(State, &BitNumber)) 2347 { 2348 /* Exception occurred */ 2349 return; 2350 } 2351 2352 if (ModRegRm.Memory) 2353 { 2354 /* 2355 * For memory operands, add the bit offset divided by 2356 * the data size to the address 2357 */ 2358 ModRegRm.MemoryAddress += BitNumber / DataSize; 2359 } 2360 2361 /* Normalize the bit number */ 2362 BitNumber %= DataSize; 2363 2364 if (OperandSize) 2365 { 2366 ULONG Value; 2367 2368 /* Read the value */ 2369 if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, NULL, &Value)) 2370 { 2371 /* Exception occurred */ 2372 return; 2373 } 2374 2375 /* Set CF to the bit value */ 2376 State->Flags.Cf = (Value >> BitNumber) & 1; 2377 2378 if (ModRegRm.Register == 5) 2379 { 2380 /* BTS */ 2381 Value |= 1 << BitNumber; 2382 } 2383 else if (ModRegRm.Register == 6) 2384 { 2385 /* BTR */ 2386 Value &= ~(1 << BitNumber); 2387 } 2388 else if (ModRegRm.Register == 7) 2389 { 2390 /* BTC */ 2391 Value ^= 1 << BitNumber; 2392 } 2393 2394 if (ModRegRm.Register >= 5) 2395 { 2396 /* Write back the result */ 2397 if (!Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Value)) 2398 { 2399 /* Exception occurred */ 2400 return; 2401 } 2402 } 2403 } 2404 else 2405 { 2406 USHORT Value; 2407 2408 /* Read the value */ 2409 if (!Fast486ReadModrmWordOperands(State, &ModRegRm, NULL, &Value)) 2410 { 2411 /* Exception occurred */ 2412 return; 2413 } 2414 2415 /* Set CF to the bit value */ 2416 State->Flags.Cf = (Value >> BitNumber) & 1; 2417 2418 if (ModRegRm.Register == 5) 2419 { 2420 /* BTS */ 2421 Value |= 1 << BitNumber; 2422 } 2423 else if (ModRegRm.Register == 6) 2424 { 2425 /* BTR */ 2426 Value &= ~(1 << BitNumber); 2427 } 2428 else if (ModRegRm.Register == 7) 2429 { 2430 /* BTC */ 2431 Value ^= 1 << BitNumber; 2432 } 2433 2434 if (ModRegRm.Register >= 5) 2435 { 2436 /* Write back the result */ 2437 if (!Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Value)) 2438 { 2439 /* Exception occurred */ 2440 return; 2441 } 2442 } 2443 } 2444} 2445 2446/* EOF */