| 611 | } |
| 612 | |
| 613 | bool CMipsInstruction::Validate() |
| 614 | { |
| 615 | if (RamPos % 4) |
| 616 | { |
| 617 | Logger::queueError(Logger::Error,L"opcode not aligned to word boundary"); |
| 618 | return false; |
| 619 | } |
| 620 | |
| 621 | // check immediates |
| 622 | if (immediateType != MIPS_NOIMMEDIATE) |
| 623 | { |
| 624 | immediate.originalValue = immediate.value; |
| 625 | |
| 626 | if (Opcode.flags & MO_IMMALIGNED) // immediate must be aligned |
| 627 | { |
| 628 | if (immediate.value % 4) |
| 629 | { |
| 630 | Logger::queueError(Logger::Error,L"Immediate must be word aligned",immediate.value); |
| 631 | return false; |
| 632 | } |
| 633 | } |
| 634 | |
| 635 | if (Opcode.flags & MO_IPCA) // absolute value >> 2) |
| 636 | { |
| 637 | immediate.value = (immediate.value >> 2) & 0x3FFFFFF; |
| 638 | } else if (Opcode.flags & MO_IPCR) // relative 16 bit value |
| 639 | { |
| 640 | const int num = (immediate.value-RamPos-4) >> 2; |
| 641 | |
| 642 | if (num > std::numeric_limits<short>::max() || num < std::numeric_limits<short>::min()) |
| 643 | { |
| 644 | Logger::queueError(Logger::Error,L"Branch target %08X out of range",immediate.value); |
| 645 | return false; |
| 646 | } |
| 647 | immediate.value = num; |
| 648 | } |
| 649 | |
| 650 | int immediateBits = getImmediateBits(immediateType); |
| 651 | unsigned int mask = (0xFFFFFFFF << (32-immediateBits)) >> (32-immediateBits); |
| 652 | int digits = (immediateBits+3) / 4; |
| 653 | |
| 654 | if ((unsigned int)std::abs(immediate.value) > mask) |
| 655 | { |
| 656 | Logger::queueError(Logger::Error,L"Immediate value %0*X out of range",digits,immediate.value); |
| 657 | return false; |
| 658 | } |
| 659 | |
| 660 | immediate.value &= mask; |
| 661 | } |
| 662 | |
| 663 | return true; |
| 664 | } |
| 665 | |
| 666 | void CMipsInstruction::encodeNormal() |
| 667 | { |
no test coverage detected