BYTE CDetourDis::BeginCopy32()

in src/disasm.cpp [3445:3531]


BYTE CDetourDis::BeginCopy32(BYTE* pSource, BYTE* pDest)
{
    ULONG instruction = GetLongInstruction(pSource);

    // Immediate data processing instructions; ADD, SUB, MOV, MOVN, ADR, MOVT, BFC, SSAT16, etc.
    if ((instruction & 0xF8008000) == 0xF0000000) { // 11110xxxxxxxxxxx0xxxxxxxxxxxxxxx
        // Should all be blitt-able
        // ToDo: What about ADR?  Is it safe to do a straight-copy?
        // ToDo: Not handling moves to or from PC
        return PureCopy32(pSource, pDest);
    }

    // Non-Immediate data processing instructions; ADD, EOR, TST, etc.
    if ((instruction & 0xEE000000) == 0xEA000000) { // 111x101xxxxxxxxxxxxxxxxxxxxxxx
        // Should all be blitt-able
        return PureCopy32(pSource, pDest);
    }

    // Load and store single data item, memory hints
    if ((instruction & 0xFE000000) == 0xF8000000) { // 1111100xxxxxxxxxxxxxxxxxxxxxxxxx
        return CopyLoadAndStoreSingle(pSource, pDest);
    }

    // Load and store, double and exclusive, and table branch
    if ((instruction & 0xFE400000) == 0xE8400000) { // 1110100xx1xxxxxxxxxxxxxxxxxxxxxx
        // Load and store double
        if (instruction & 0x1200000) {
            // LDRD, STRD (immediate) : xxxxxxxPxxWxxxxxxxxxxxxxxxxxxxxx where PW != 0b00
            // The source register is PC
            if ((instruction & 0xF0000) == 0xF0000) {
                // ToDo: If the source register is PC, what should we do?
                ASSERT(false);
            }

            // If either target registers are PC
            if (((instruction & 0xF000) == 0xF000) ||
                ((instruction & 0xF00) == 0xF00)) {
                m_pbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_DYNAMIC;
            }

            return PureCopy32(pSource, pDest);
        }

        // Load and store exclusive
        if (!(instruction & 0x800000)) { // LDREX, STREX : xxxxxxxx0xxxxxxxxxxxxxxxxxxxxxxx
            if ((instruction & 0xF000) == 0xF000) { // xxxxxxxxxxxx1111xxxxxxxxxxxx
                m_pbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_DYNAMIC;
            }
            return PureCopy32(pSource, pDest);
        }

        // Table branch
        if ((instruction & 0x1000F0) == 0x100000 ||  // TBB : xxxxxxxxxxx1xxxxxxxxxxxx0000xxxx
            (instruction & 0x1000F0) == 0x100010) { // TBH : xxxxxxxxxxx1xxxxxxxxxxxx0001xxxx
            return CopyTableBranch(pSource, pDest);
        }

        // Load and store exclusive byte, halfword, doubleword (LDREXB, LDREXH, LDREXD, STREXB, STREXH, STREXD, etc.)
        return PureCopy32(pSource, pDest);
    }

    // Load and store multiple, RFE and SRS
    if ((instruction & 0xFE400000) == 0xE8000000) { // 1110100xx0xxxxxxxxxxxxxxxxxxxxxx
        // Return from exception (RFE)
        if ((instruction & 0xE9900000) == 0xE9900000 || // 1110100110x1xxxxxxxxxxxxxxxxxxxx
            (instruction & 0xE8100000) == 0xE8100000) { // 1110100000x1xxxxxxxxxxxxxxxxxxxx
            return PureCopy32(pSource, pDest);
        }

        return CopyLoadAndStoreMultipleAndSRS(pSource, pDest);
    }

    // Branches, miscellaneous control
    if ((instruction & 0xF8008000) == 0xF0008000) { // 11110xxxxxxxxxxx0xxxxxxxxxxxxxxx
        // Branches, miscellaneous control
        return CopyBranchOrMiscellaneous32(pSource, pDest);
    }

    // Coprocessor instructions
    if ((instruction & 0xEC000000) == 0xEC000000) { // 111x11xxxxxxxxxxxxxxxxxxxxxxxxxx
        return PureCopy32(pSource, pDest);
    }

    // Unhandled instruction; should never make it this far
    ASSERT(false);
    return PureCopy32(pSource, pDest);
}