diff options
Diffstat (limited to 'Source/JavaScriptCore/disassembler/ARMv7')
-rw-r--r-- | Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.cpp | 1733 | ||||
-rw-r--r-- | Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.h | 1237 |
2 files changed, 0 insertions, 2970 deletions
diff --git a/Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.cpp b/Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.cpp deleted file mode 100644 index 3175cccbd..000000000 --- a/Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.cpp +++ /dev/null @@ -1,1733 +0,0 @@ -/* - * Copyright (C) 2013 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if USE(ARMV7_DISASSEMBLER) - -#include "ARMv7DOpcode.h" - -#include <stdarg.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> - -namespace JSC { namespace ARMv7Disassembler { - -ARMv7D16BitOpcode::OpcodeGroup* ARMv7D16BitOpcode::opcodeTable[32]; -ARMv7D32BitOpcode::OpcodeGroup* ARMv7D32BitOpcode::opcodeTable[16]; - -const char* const ARMv7DOpcode::s_conditionNames[16] = { - "eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc", - "hi", "ls", "ge", "lt", "gt", "le", "al", "al" -}; - -const char* const ARMv7DOpcode::s_optionName[8] = { - "uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx" -}; - -const char* const ARMv7DOpcode::s_shiftNames[4] = { - "lsl", "lsr", "asr", "ror" -}; - -const char* const ARMv7DOpcode::s_specialRegisterNames[3] = { "sp", "lr", "pc" }; - -template <typename OpcodeType, typename InstructionType> -struct OpcodeGroupInitializer { - unsigned m_opcodeGroupNumber; - InstructionType m_mask; - InstructionType m_pattern; - const char* (*m_format)(OpcodeType*); -}; - -#define OPCODE_GROUP_ENTRY(groupIndex, groupClass) \ -{ groupIndex, groupClass::s_mask, groupClass::s_pattern, groupClass::format } - -typedef OpcodeGroupInitializer<ARMv7D16BitOpcode, uint16_t> Opcode16GroupInitializer; -typedef OpcodeGroupInitializer<ARMv7D32BitOpcode, uint32_t> Opcode32GroupInitializer; - -static Opcode16GroupInitializer opcode16BitGroupList[] = { - OPCODE_GROUP_ENTRY(0x0, ARMv7DOpcodeLogicalImmediateT1), - OPCODE_GROUP_ENTRY(0x1, ARMv7DOpcodeLogicalImmediateT1), - OPCODE_GROUP_ENTRY(0x2, ARMv7DOpcodeLogicalImmediateT1), - OPCODE_GROUP_ENTRY(0x3, ARMv7DOpcodeAddSubtractT1), - OPCODE_GROUP_ENTRY(0x3, ARMv7DOpcodeAddSubtractImmediate3), - OPCODE_GROUP_ENTRY(0x4, ARMv7DOpcodeMoveImmediateT1), - OPCODE_GROUP_ENTRY(0x5, ARMv7DOpcodeCompareImmediateT1), - OPCODE_GROUP_ENTRY(0x6, ARMv7DOpcodeAddSubtractImmediate8), - OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeAddSubtractImmediate8), - OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeDataProcessingRegisterT1), - OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeAddRegisterT2), - OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeCompareRegisterT2), - OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeCompareRegisterT1), - OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeMoveRegisterT1), - OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeBranchExchangeT1), - OPCODE_GROUP_ENTRY(0x9, ARMv7DOpcodeLoadFromLiteralPool), - OPCODE_GROUP_ENTRY(0xa, ARMv7DOpcodeLoadStoreRegisterOffsetT1), - OPCODE_GROUP_ENTRY(0xb, ARMv7DOpcodeLoadStoreRegisterOffsetT1), - OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeLoadStoreRegisterImmediateWordAndByte), - OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeLoadStoreRegisterImmediateWordAndByte), - OPCODE_GROUP_ENTRY(0xe, ARMv7DOpcodeLoadStoreRegisterImmediateWordAndByte), - OPCODE_GROUP_ENTRY(0xf, ARMv7DOpcodeLoadStoreRegisterImmediateWordAndByte), - OPCODE_GROUP_ENTRY(0x10, ARMv7DOpcodeStoreRegisterImmediateHalfWord), - OPCODE_GROUP_ENTRY(0x11, ARMv7DOpcodeLoadRegisterImmediateHalfWord), - OPCODE_GROUP_ENTRY(0x12, ARMv7DOpcodeLoadStoreRegisterSPRelative), - OPCODE_GROUP_ENTRY(0x13, ARMv7DOpcodeLoadStoreRegisterSPRelative), - OPCODE_GROUP_ENTRY(0x14, ARMv7DOpcodeGeneratePCRelativeAddress), - OPCODE_GROUP_ENTRY(0x15, ARMv7DOpcodeAddSPPlusImmediate), - OPCODE_GROUP_ENTRY(0x16, ARMv7DOpcodeMiscCompareAndBranch), - OPCODE_GROUP_ENTRY(0x16, ARMv7DOpcodeMiscByteHalfwordOps), - OPCODE_GROUP_ENTRY(0x16, ARMv7DOpcodeMiscPushPop), - OPCODE_GROUP_ENTRY(0x16, ARMv7DOpcodeMiscAddSubSP), - OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscHint16), // Needs to be before IfThenT1 - OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscIfThenT1), - OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscByteHalfwordOps), - OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscCompareAndBranch), - OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscPushPop), - OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscBreakpointT1), - OPCODE_GROUP_ENTRY(0x1a, ARMv7DOpcodeBranchConditionalT1), - OPCODE_GROUP_ENTRY(0x1b, ARMv7DOpcodeBranchConditionalT1), - OPCODE_GROUP_ENTRY(0x1c, ARMv7DOpcodeBranchT2) -}; - -static Opcode32GroupInitializer opcode32BitGroupList[] = { - OPCODE_GROUP_ENTRY(0x4, ARMv7DOpcodeDataPopMultiple), - OPCODE_GROUP_ENTRY(0x4, ARMv7DOpcodeDataPushMultiple), - OPCODE_GROUP_ENTRY(0x5, ARMv7DOpcodeDataProcessingShiftedReg), - OPCODE_GROUP_ENTRY(0x6, ARMv7DOpcodeVLDR), - OPCODE_GROUP_ENTRY(0x6, ARMv7DOpcodeVMOVSinglePrecision), - OPCODE_GROUP_ENTRY(0x6, ARMv7DOpcodeVMOVDoublePrecision), - OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeFPTransfer), - OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeVMSR), - OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeVCMP), - OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeVCVTBetweenFPAndInt), - OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeDataProcessingModifiedImmediate), - OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeConditionalBranchT3), - OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeBranchOrBranchLink), - OPCODE_GROUP_ENTRY(0x9, ARMv7DOpcodeUnmodifiedImmediate), - OPCODE_GROUP_ENTRY(0x9, ARMv7DOpcodeHint32), - OPCODE_GROUP_ENTRY(0x9, ARMv7DOpcodeConditionalBranchT3), - OPCODE_GROUP_ENTRY(0x9, ARMv7DOpcodeBranchOrBranchLink), - OPCODE_GROUP_ENTRY(0xa, ARMv7DOpcodeDataProcessingModifiedImmediate), - OPCODE_GROUP_ENTRY(0xa, ARMv7DOpcodeConditionalBranchT3), - OPCODE_GROUP_ENTRY(0xa, ARMv7DOpcodeBranchOrBranchLink), - OPCODE_GROUP_ENTRY(0xb, ARMv7DOpcodeUnmodifiedImmediate), - OPCODE_GROUP_ENTRY(0xb, ARMv7DOpcodeConditionalBranchT3), - OPCODE_GROUP_ENTRY(0xb, ARMv7DOpcodeBranchOrBranchLink), - OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeLoadRegister), - OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeDataPushPopSingle), // Should be before StoreSingle* - OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeDataPopMultiple), - OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeDataPushMultiple), - OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeStoreSingleRegister), - OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeStoreSingleImmediate12), - OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeStoreSingleImmediate8), - OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeLoadSignedImmediate), - OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeLoadUnsignedImmediate), - OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeLongMultipleDivide), - OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeDataProcessingRegShift), - OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeDataProcessingRegExtend), - OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeDataProcessingRegParallel), - OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeDataProcessingRegMisc), - OPCODE_GROUP_ENTRY(0xe, ARMv7DOpcodeVLDR), - OPCODE_GROUP_ENTRY(0xf, ARMv7DOpcodeVCMP), - OPCODE_GROUP_ENTRY(0xf, ARMv7DOpcodeVCVTBetweenFPAndInt), -}; - -bool ARMv7DOpcode::s_initialized = false; - -void ARMv7DOpcode::init() -{ - if (s_initialized) - return; - - ARMv7D16BitOpcode::init(); - ARMv7D32BitOpcode::init(); - - s_initialized = true; -} - -void ARMv7DOpcode::startITBlock(unsigned blocksize, unsigned firstCondition) -{ - ASSERT(blocksize > 0 && blocksize <= MaxITBlockSize); - m_ITBlocksize = blocksize; - m_ITConditionIndex = m_ITBlocksize + 1; - m_currentITCondition = 0; - m_ifThenConditions[0] = firstCondition; -} - -void ARMv7DOpcode::saveITConditionAt(unsigned blockPosition, unsigned condition) -{ - if (blockPosition < m_ITBlocksize) - m_ifThenConditions[blockPosition] = static_cast<unsigned char>(condition); -} - -void ARMv7DOpcode::fetchOpcode(uint16_t*& newPC) -{ - m_bufferOffset = 0; - m_formatBuffer[0] = '\0'; - m_currentPC = newPC; - - m_opcode = *newPC++; - - if (is32BitInstruction()) { - m_opcode <<= 16; - m_opcode |= *newPC++; - } - - if (m_ITConditionIndex < m_ITBlocksize) - m_currentITCondition = m_ifThenConditions[m_ITConditionIndex]; - else - m_currentITCondition = CondNone; -} - -const char* ARMv7DOpcode::disassemble(uint16_t*& currentPC) -{ - const char* result; - fetchOpcode(currentPC); - - if (is32BitInstruction()) - result = reinterpret_cast<ARMv7D32BitOpcode*>(this)->doDisassemble(); - else - result = reinterpret_cast<ARMv7D16BitOpcode*>(this)->doDisassemble(); - - if (startingITBlock()) - m_ITConditionIndex = 0; - else if (inITBlock() && (++m_ITConditionIndex >= m_ITBlocksize)) - endITBlock(); - - return result; -} - -void ARMv7DOpcode::bufferPrintf(const char* format, ...) -{ - if (m_bufferOffset >= bufferSize) - return; - - va_list argList; - va_start(argList, format); - - m_bufferOffset += vsnprintf(m_formatBuffer + m_bufferOffset, bufferSize - m_bufferOffset, format, argList); - - va_end(argList); -} - -void ARMv7DOpcode::appendInstructionName(const char* instructionName, bool addS) -{ - if (!inITBlock() && !addS) { - appendInstructionNameNoITBlock(instructionName); - - return; - } - - const char sevenSpaces[8] = " "; - - unsigned length = strlen(instructionName); - - bufferPrintf(" %s", instructionName); - if (inITBlock()) { - const char* condition = conditionName(m_currentITCondition); - length += strlen(condition); - appendString(condition); - } else if (addS) { - length++; - appendCharacter('s'); - } - - if (length >= 7) - length = 6; - - appendString(sevenSpaces + length); -} - -void ARMv7DOpcode::appendRegisterName(unsigned registerNumber) -{ - registerNumber &= 0xf; - - if (registerNumber > 12) { - appendString(s_specialRegisterNames[registerNumber - 13]); - return; - } - - bufferPrintf("r%u", registerNumber); -} - -void ARMv7DOpcode::appendRegisterList(unsigned registers) -{ - unsigned numberPrinted = 0; - - appendCharacter('{'); - - for (unsigned i = 0; i < 16; i++) { - if (registers & (1 << i)) { - if (numberPrinted++) - appendSeparator(); - appendRegisterName(i); - } - } - - appendCharacter('}'); -} - -void ARMv7DOpcode::appendFPRegisterName(char registerPrefix, unsigned registerNumber) -{ - bufferPrintf("%c%u", registerPrefix, registerNumber); -} - -// 16 Bit Instructions - -void ARMv7D16BitOpcode::init() -{ - OpcodeGroup* lastGroups[OpcodeGroup::opcodeTableSize]; - - for (unsigned i = 0; i < OpcodeGroup::opcodeTableSize; i++) { - opcodeTable[i] = 0; - lastGroups[i] = 0; - } - - for (unsigned i = 0; i < sizeof(opcode16BitGroupList) / sizeof(Opcode16GroupInitializer); i++) { - OpcodeGroup* newOpcodeGroup = new OpcodeGroup(opcode16BitGroupList[i].m_mask, opcode16BitGroupList[i].m_pattern, opcode16BitGroupList[i].m_format); - uint16_t opcodeGroupNumber = opcode16BitGroupList[i].m_opcodeGroupNumber; - - if (!opcodeTable[opcodeGroupNumber]) - opcodeTable[opcodeGroupNumber] = newOpcodeGroup; - else - lastGroups[opcodeGroupNumber]->setNext(newOpcodeGroup); - lastGroups[opcodeGroupNumber] = newOpcodeGroup; - } -} - -const char* ARMv7D16BitOpcode::doDisassemble() -{ - OpcodeGroup* opGroup = opcodeTable[opcodeGroupNumber(m_opcode)]; - - while (opGroup) { - if (opGroup->matches(static_cast<uint16_t>(m_opcode))) - return opGroup->format(this); - opGroup = opGroup->next(); - } - - return defaultFormat(); -} - -const char* ARMv7D16BitOpcode::defaultFormat() -{ - bufferPrintf(" .word %04x", m_opcode); - return m_formatBuffer; -} - -const char* ARMv7DOpcodeAddRegisterT2::format() -{ - appendInstructionName("add"); - appendRegisterName(rdn()); - appendSeparator(); - appendRegisterName(rm()); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeAddSPPlusImmediate::format() -{ - appendInstructionName("add"); - appendRegisterName(rd()); - appendSeparator(); - appendRegisterName(RegSP); - appendSeparator(); - appendUnsignedImmediate(immediate8()); - - return m_formatBuffer; -} - -const char* const ARMv7DOpcodeAddSubtract::s_opNames[2] = { "add", "sub" }; - -const char* ARMv7DOpcodeAddSubtractT1::format() -{ - appendInstructionName(opName(), !inITBlock()); - appendRegisterName(rd()); - appendSeparator(); - appendRegisterName(rn()); - appendSeparator(); - appendRegisterName(rm()); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeAddSubtractImmediate3::format() -{ - appendInstructionName(opName(), !inITBlock()); - appendRegisterName(rd()); - appendSeparator(); - appendRegisterName(rn()); - appendSeparator(); - appendUnsignedImmediate(immediate3()); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeAddSubtractImmediate8::format() -{ - appendInstructionName(opName(), !inITBlock()); - appendRegisterName(rdn()); - appendSeparator(); - appendUnsignedImmediate(immediate8()); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeBranchConditionalT1::format() -{ - if (condition() == 0xe) - return defaultFormat(); - - if (condition() == 0xf) { - appendInstructionName("svc"); - appendUnsignedImmediate(offset()); - - return m_formatBuffer; - } - - bufferPrintf(" b%-6.6s", conditionName(condition())); - appendPCRelativeOffset(static_cast<int32_t>(offset()) + 2); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeBranchExchangeT1::format() -{ - appendInstructionName(opName()); - appendRegisterName(rm()); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeBranchT2::format() -{ - appendInstructionName("b"); - appendPCRelativeOffset(static_cast<int32_t>(immediate11()) + 2); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeCompareImmediateT1::format() -{ - appendInstructionName("cmp"); - appendRegisterName(rn()); - appendSeparator(); - appendUnsignedImmediate(immediate8()); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeCompareRegisterT1::format() -{ - appendInstructionName("cmp"); - appendRegisterName(rn()); - appendSeparator(); - appendRegisterName(rm()); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeCompareRegisterT2::format() -{ - appendInstructionName("compare"); - appendRegisterName(rn()); - appendSeparator(); - appendRegisterName(rm()); - - return m_formatBuffer; -} - -const char* const ARMv7DOpcodeDataProcessingRegisterT1::s_opNames[16] = { - "and", "eor", "lsl", "lsr", "asr", "adc", "sbc", "ror", "tst", "rsb", "cmp", "cmn", "orr", "mul", "bic", "mvn" -}; - -const char* ARMv7DOpcodeDataProcessingRegisterT1::format() -{ - appendInstructionName(opName(), inITBlock() && (!(op() == 0x8) || (op() == 0xa) || (op() == 0xb))); - appendRegisterName(rdn()); - appendSeparator(); - appendRegisterName(rm()); - if (op() == 0x9) // rsb T1 - appendString(", #0"); - else if (op() == 0xd) { // mul T1 - appendSeparator(); - appendRegisterName(rdn()); - } - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeGeneratePCRelativeAddress::format() -{ - appendInstructionName("adr"); - appendRegisterName(rd()); - appendSeparator(); - appendPCRelativeOffset(static_cast<int32_t>(immediate8())); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeLoadFromLiteralPool::format() -{ - appendInstructionName("ldr"); - appendRegisterName(rt()); - appendSeparator(); - appendPCRelativeOffset(static_cast<int32_t>(immediate8())); - - return m_formatBuffer; -} - -const char* const ARMv7DOpcodeLoadStoreRegisterImmediate::s_opNames[6] = { - "str", "ldr", "strb", "ldrb", "strh", "ldrh" -}; - -const char* ARMv7DOpcodeLoadStoreRegisterImmediate::format() -{ - const char* instructionName = opName(); - - if (!instructionName) - return defaultFormat(); - - appendInstructionName(opName()); - appendRegisterName(rt()); - appendSeparator(); - appendCharacter('['); - appendRegisterName(rn()); - if (immediate5()) { - appendSeparator(); - appendUnsignedImmediate(immediate5() << scale()); - } - appendCharacter(']'); - - return m_formatBuffer; -} - -unsigned ARMv7DOpcodeLoadStoreRegisterImmediate::scale() -{ - switch (op()) { - case 0: - case 1: - return 2; - case 2: - case 3: - return 0; - case 4: - case 5: - return 1; - default: - break; - } - ASSERT_NOT_REACHED(); - return 0; -} - -const char* const ARMv7DOpcodeLoadStoreRegisterOffsetT1::s_opNames[8] = { - "str", "strh", "strb", "ldrsb", "ldr", "ldrh", "ldrb", "ldrsh" -}; - -const char* ARMv7DOpcodeLoadStoreRegisterOffsetT1::format() -{ - appendInstructionName(opName()); - appendRegisterName(rt()); - appendSeparator(); - appendCharacter('['); - appendRegisterName(rn()); - appendSeparator(); - appendRegisterName(rm()); - appendCharacter(']'); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeLoadStoreRegisterSPRelative::format() -{ - appendInstructionName(opName()); - appendRegisterName(rt()); - appendSeparator(); - appendCharacter('['); - appendRegisterName(RegSP); - if (immediate8()) { - appendSeparator(); - appendUnsignedImmediate(immediate8() << 2); - } - appendCharacter(']'); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeLogicalImmediateT1::format() -{ - if (!op() && !immediate5()) { - // mov T2 - appendInstructionName("movs"); - appendRegisterName(rd()); - appendSeparator(); - appendRegisterName(rm()); - - return m_formatBuffer; - } - - appendInstructionName(opName(), !inITBlock()); - appendRegisterName(rd()); - appendSeparator(); - appendRegisterName(rm()); - appendSeparator(); - appendUnsignedImmediate((op() && !immediate5()) ? 32 : immediate5()); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeMiscAddSubSP::format() -{ - appendInstructionName(opName()); - appendRegisterName(RegSP); - appendSeparator(); - appendRegisterName(RegSP); - appendSeparator(); - appendUnsignedImmediate(immediate7()); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeMiscBreakpointT1::format() -{ - appendInstructionNameNoITBlock("bkpt"); - appendUnsignedImmediate(immediate8()); - - return m_formatBuffer; -} - -const char* const ARMv7DOpcodeMiscByteHalfwordOps::s_opNames[8] = { - "sxth", "sxb", "uxth", "uxtb", "rev", "rev16", "revsh" -}; - -const char* ARMv7DOpcodeMiscByteHalfwordOps::format() -{ - const char* instructionName = opName(); - - if (!instructionName) - return defaultFormat(); - - appendInstructionName(instructionName); - appendRegisterName(rd()); - appendSeparator(); - appendRegisterName(rm()); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeMiscCompareAndBranch::format() -{ - appendInstructionName(opName()); - appendPCRelativeOffset(immediate6() + 2); - - return m_formatBuffer; -} - -const char* const ARMv7DOpcodeMiscHint16::s_opNames[16] = { - "nop", "yield", "wfe", "wfi", "sev" -}; - -const char* ARMv7DOpcodeMiscHint16::format() -{ - if (opA() > 4) - return defaultFormat(); - - appendInstructionName(opName()); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeMiscIfThenT1::format() -{ - char opName[6]; - opName[0] = 'i'; - opName[1] = 't'; - - unsigned condition = firstCondition(); - unsigned maskBits = mask(); - unsigned blockLength = 0; - - for (unsigned i = 0; i < 4; ++i) { - if (maskBits & (1 << i)) { - blockLength = 4 - i; - break; - } - } - - startITBlock(blockLength, condition); - - for (unsigned i = 1; i < blockLength; ++i) { - unsigned currMaskBit = (maskBits >> (4-i)) & 0x1; - opName[i + 1] = (currMaskBit ^ (condition & 1)) ? 'e' : 't'; - saveITConditionAt(i, (condition & ~1) | currMaskBit); - } - opName[blockLength + 1] = '\0'; - - appendInstructionNameNoITBlock(opName); - appendString(conditionName(condition)); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeMiscPushPop::format() -{ - appendInstructionName(opName()); - appendRegisterList(registerMask()); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeMoveImmediateT1::format() -{ - appendInstructionName("mov", !inITBlock()); - appendRegisterName(rd()); - appendSeparator(); - appendUnsignedImmediate(immediate8()); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeMoveRegisterT1::format() -{ - appendInstructionName("mov"); - appendRegisterName(rd()); - appendSeparator(); - appendRegisterName(rm()); - - return m_formatBuffer; -} - -// 32 bit Intructions - -void ARMv7D32BitOpcode::init() -{ - OpcodeGroup* lastGroups[OpcodeGroup::opcodeTableSize]; - - for (unsigned i = 0; i < OpcodeGroup::opcodeTableSize; i++) { - opcodeTable[i] = 0; - lastGroups[i] = 0; - } - - for (unsigned i = 0; i < sizeof(opcode32BitGroupList) / sizeof(Opcode32GroupInitializer); i++) { - OpcodeGroup* newOpcodeGroup = new OpcodeGroup(opcode32BitGroupList[i].m_mask, opcode32BitGroupList[i].m_pattern, opcode32BitGroupList[i].m_format); - uint16_t opcodeGroupNumber = opcode32BitGroupList[i].m_opcodeGroupNumber; - - if (!opcodeTable[opcodeGroupNumber]) - opcodeTable[opcodeGroupNumber] = newOpcodeGroup; - else - lastGroups[opcodeGroupNumber]->setNext(newOpcodeGroup); - lastGroups[opcodeGroupNumber] = newOpcodeGroup; - } -} - -const char* ARMv7D32BitOpcode::doDisassemble() -{ - OpcodeGroup* opGroup = opcodeTable[opcodeGroupNumber(m_opcode)]; - - while (opGroup) { - if (opGroup->matches(m_opcode)) - return opGroup->format(this); - opGroup = opGroup->next(); - } - - return defaultFormat(); -} - -const char* ARMv7D32BitOpcode::defaultFormat() -{ - bufferPrintf(" .long %08x", m_opcode); - return m_formatBuffer; -} - -const char* ARMv7DOpcodeConditionalBranchT3::format() -{ - if (condition() < 0xe) - bufferPrintf(" b%-6.6s", conditionName(condition())); - else - appendInstructionName("b"); - appendPCRelativeOffset(offset() + 2); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeBranchOrBranchLink::format() -{ - appendInstructionName(isBL() ? "bl" : "b"); - appendPCRelativeOffset(offset() + 2); - - return m_formatBuffer; -} - -const char* const ARMv7DOpcodeDataProcessingLogicalAndRithmetic::s_opNames[16] = { - "and", "bic", "orr", "orn", "eor", 0, "pkh", 0, "add", 0, "adc", "sbc", 0, "sub", "rsb", 0 -}; - -void ARMv7DOpcodeDataProcessingModifiedImmediate::appendModifiedImmediate(unsigned immediate12) -{ - if (!(immediate12 & 0xc00)) { - unsigned immediate = 0; - unsigned lower8Bits = immediate12 & 0xff; - - switch ((immediate12 >> 8) & 3) { - case 0: - immediate = lower8Bits; - break; - case 1: - immediate = (lower8Bits << 16) | lower8Bits; - break; - case 2: - immediate = (lower8Bits << 24) | (lower8Bits << 8); - break; - case 3: - immediate = (lower8Bits << 24) | (lower8Bits << 16) | (lower8Bits << 8) | lower8Bits; - break; - } - appendUnsignedImmediate(immediate); - return; - } - - unsigned immediate8 = 0x80 | (immediate12 & 0x7f); - unsigned shiftAmount = 32 - ((immediate12 >> 7) & 0x1f); - - appendUnsignedImmediate(immediate8 << shiftAmount); -} - -const char* ARMv7DOpcodeDataProcessingModifiedImmediate::format() -{ - if ((op() == 0x5) || (op() == 0x6) || (op() == 0x7) || (op() == 0x9) || (op() == 0xc) || (op() == 0xf)) - return defaultFormat(); - - const char* instructionName = opName(); - - if (rn() == 15) { - if (op() == 2) { - // MOV T2 - instructionName = sBit() ? "movs" : "mov"; - appendInstructionName(instructionName); - appendRegisterName(rd()); - appendSeparator(); - appendModifiedImmediate(immediate12()); - - return m_formatBuffer; - } - - if (op() == 3) { - // MVN T1 - instructionName = sBit() ? "mvns" : "mvn"; - appendInstructionName(instructionName); - appendRegisterName(rd()); - appendSeparator(); - appendModifiedImmediate(immediate12()); - - return m_formatBuffer; - } - } - - if (rd() == 15) { - if (sBit()) { - bool testOrCmpInstruction = false; - - switch (op()) { - case 0x0: - instructionName = "tst"; - testOrCmpInstruction = true; - break; - case 0x4: - instructionName = "teq"; - testOrCmpInstruction = true; - break; - case 0x8: - instructionName = "cmn"; - testOrCmpInstruction = true; - break; - case 0xd: - instructionName = "cmp"; - testOrCmpInstruction = true; - break; - } - - if (testOrCmpInstruction) { - appendInstructionName(instructionName); - appendRegisterName(rn()); - appendSeparator(); - appendModifiedImmediate(immediate12()); - - return m_formatBuffer; - } - } - } - - appendInstructionName(instructionName); - appendRegisterName(rd()); - appendSeparator(); - appendRegisterName(rn()); - appendSeparator(); - appendModifiedImmediate(immediate12()); - - return m_formatBuffer; -} - -void ARMv7DOpcodeDataProcessingShiftedReg::appendImmShift(unsigned type, unsigned immediate) -{ - if (type || immediate) { - appendSeparator(); - - if (!immediate) { - switch (type) { - case 1: - case 2: - immediate = 32; - break; - case 3: - appendString("rrx"); - return; - } - } - - appendShiftType(type); - appendUnsignedImmediate(immediate); - } -} - -const char* ARMv7DOpcodeDataProcessingShiftedReg::format() -{ - if ((op() == 0x5) || (op() == 0x7) || (op() == 0x9) || (op() == 0xc) || (op() == 0xf)) - return defaultFormat(); - - if (op() == 6) { - // pkhbt or pkhtb - if (sBit() || tBit()) - return defaultFormat(); - - if (tbBit()) - appendInstructionName("pkhtb"); - else - appendInstructionName("pkhbt"); - appendRegisterName(rd()); - appendSeparator(); - appendRegisterName(rn()); - appendSeparator(); - appendRegisterName(rm()); - appendImmShift(tbBit() << 1, immediate5()); - - return m_formatBuffer; - } - - const char* instructionName = opName(); - - if (rn() == 15) { - if (op() == 2) { - if (!type() && !immediate5()) { - // MOV T3 - instructionName = sBit() ? "movs" : "mov"; - appendInstructionName(instructionName); - appendRegisterName(rd()); - appendSeparator(); - appendRegisterName(rm()); - - return m_formatBuffer; - } - - if (type() == 3 && !immediate5()) { - // RRX T1 - instructionName = sBit() ? "rrx" : "rrx"; - appendInstructionName(instructionName); - appendRegisterName(rd()); - appendSeparator(); - appendRegisterName(rm()); - - return m_formatBuffer; - } - - // Logical - if (sBit()) - bufferPrintf("%ss ", shiftName(type())); - else - appendInstructionName(shiftName(type())); - appendRegisterName(rd()); - appendSeparator(); - appendRegisterName(rm()); - appendSeparator(); - appendUnsignedImmediate(immediate5()); - - return m_formatBuffer; - } - - if (op() == 3) { - // MVN T2 - instructionName = sBit() ? "mvns" : "mvn"; - appendInstructionName(instructionName); - appendRegisterName(rd()); - appendSeparator(); - appendRegisterName(rm()); - appendImmShift(type(), immediate5()); - - return m_formatBuffer; - } - } - - if (rd() == 15) { - if (sBit()) { - bool testOrCmpInstruction = false; - - switch (op()) { - case 0x0: - instructionName = "tst"; - testOrCmpInstruction = true; - break; - case 0x4: - instructionName = "teq"; - testOrCmpInstruction = true; - break; - case 0x8: - instructionName = "cmn"; - testOrCmpInstruction = true; - break; - case 0xd: - instructionName = "cmp"; - testOrCmpInstruction = true; - break; - } - - if (testOrCmpInstruction) { - appendInstructionName(instructionName); - appendRegisterName(rn()); - appendSeparator(); - appendRegisterName(rm()); - appendImmShift(type(), immediate5()); - - return m_formatBuffer; - } - } - } - - appendInstructionName(instructionName); - appendRegisterName(rd()); - appendSeparator(); - appendRegisterName(rn()); - appendSeparator(); - appendRegisterName(rm()); - appendImmShift(type(), immediate5()); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeFPTransfer::format() -{ - appendInstructionName("vmov"); - - if (opL()) { - appendFPRegister(); - appendSeparator(); - } - - appendRegisterName(rt()); - - if (!opL()) { - appendSeparator(); - appendFPRegister(); - } - - return m_formatBuffer; -} - -void ARMv7DOpcodeFPTransfer::appendFPRegister() -{ - if (opC()) { - appendFPRegisterName('d', vd()); - bufferPrintf("[%u]", opH()); - } else - appendFPRegisterName('s', vn()); -} - -const char* ARMv7DOpcodeDataProcessingRegShift::format() -{ - appendInstructionName(opName()); - appendRegisterName(rd()); - appendSeparator(); - appendRegisterName(rn()); - appendSeparator(); - appendRegisterName(rm()); - - return m_formatBuffer; -} - -const char* const ARMv7DOpcodeDataProcessingRegExtend::s_opExtendNames[8] = { - "sxth", "uxth", "sxtb16", "uxtb16", "sxtb", "uxtb" -}; - -const char* const ARMv7DOpcodeDataProcessingRegExtend::s_opExtendAndAddNames[8] = { - "sxtah", "uxtah", "sxtab16", "uxtab16", "sxtab", "uxtab" -}; - -const char* ARMv7DOpcodeDataProcessingRegExtend::format() -{ - const char* instructionName; - - if (rn() == 0xf) - instructionName = opExtendName(); - else - instructionName = opExtendAndAddName(); - - if (!instructionName) - return defaultFormat(); - - appendInstructionName(instructionName); - appendRegisterName(rd()); - appendSeparator(); - appendRegisterName(rn()); - appendSeparator(); - appendRegisterName(rm()); - - if (rotate()) { - appendSeparator(); - appendString("ror "); - appendUnsignedImmediate(rotate() * 8); - } - - return m_formatBuffer; -} - -const char* const ARMv7DOpcodeDataProcessingRegParallel::s_opNames[16] = { - "sadd8", "sadd16", "sasx", 0, "ssub8", "ssub16", "ssax", 0, - "qadd8", "qadd16", "qasx", 0, "qsub8", "qsub16", "qsax", 0 -}; - -const char* ARMv7DOpcodeDataProcessingRegParallel::format() -{ - const char* instructionName; - - instructionName = opName(); - - if (!instructionName) - return defaultFormat(); - - appendInstructionName(instructionName); - appendRegisterName(rd()); - appendSeparator(); - appendRegisterName(rn()); - appendSeparator(); - appendRegisterName(rm()); - - return m_formatBuffer; -} - -const char* const ARMv7DOpcodeDataProcessingRegMisc::s_opNames[16] = { - "qadd", "qdadd", "qsub", "qdsub", "rev", "rev16", "rbit", "revsh", - "sel", 0, 0, 0, "clz" -}; - -const char* ARMv7DOpcodeDataProcessingRegMisc::format() -{ - const char* instructionName; - - instructionName = opName(); - - if (!instructionName) - return defaultFormat(); - - if ((op1() & 0x1) && (rn() != rm())) - return defaultFormat(); - - appendInstructionName(instructionName); - appendRegisterName(rd()); - appendSeparator(); - - if (op1() == 0x2) { // sel - appendRegisterName(rn()); - appendSeparator(); - appendRegisterName(rm()); - - return m_formatBuffer; - } - - appendRegisterName(rm()); - - if (!(op1() & 0x1)) { - appendSeparator(); - appendRegisterName(rn()); - } - - return m_formatBuffer; -} - -const char* const ARMv7DOpcodeHint32::s_opNames[8] = { - "nop", "yield", "wfe", "wfi", "sev" -}; - -const char* ARMv7DOpcodeHint32::format() -{ - if (isDebugHint()) { - appendInstructionName("debug"); - appendUnsignedImmediate(debugOption()); - - return m_formatBuffer; - } - - if (op() > 0x4) - return defaultFormat(); - - appendInstructionName(opName()); - - return m_formatBuffer; -} - -const char* const ARMv7DOpcodeDataLoad::s_opNames[8] = { - "ldrb", "ldrh", "ldr", 0, "ldrsb", "ldrsh" -}; - -const char* ARMv7DOpcodeLoadRegister::format() -{ - appendInstructionName(opName()); - appendRegisterName(rt()); - appendSeparator(); - appendCharacter('['); - appendRegisterName(rn()); - appendSeparator(); - appendRegisterName(rm()); - if (immediate2()) { - appendSeparator(); - appendUnsignedImmediate(immediate2()); - } - appendCharacter(']'); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeLoadSignedImmediate::format() -{ - appendInstructionName(opName()); - appendRegisterName(rt()); - appendSeparator(); - appendCharacter('['); - appendRegisterName(rn()); - if (pBit()) { - if (wBit() || immediate8()) { - appendSeparator(); - if (uBit()) - appendUnsignedImmediate(immediate8()); - else - appendSignedImmediate(0 - static_cast<int>(immediate8())); - } - appendCharacter(']'); - if (wBit()) - appendCharacter('!'); - } else { - appendCharacter(']'); - appendSeparator(); - if (uBit()) - appendUnsignedImmediate(immediate8()); - else - appendSignedImmediate(0 - static_cast<int>(immediate8())); - } - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeLoadUnsignedImmediate::format() -{ - appendInstructionName(opName()); - appendRegisterName(rt()); - appendSeparator(); - appendCharacter('['); - appendRegisterName(rn()); - if (immediate12()) { - appendSeparator(); - appendUnsignedImmediate(immediate12()); - } - appendCharacter(']'); - - return m_formatBuffer; -} - -const char* const ARMv7DOpcodeLongMultipleDivide::s_opNames[8] = { - "smull", "sdiv", "umull", "udiv", "smlal", "smlsld", "umlal", 0 -}; - -const char* const ARMv7DOpcodeLongMultipleDivide::s_smlalOpNames[4] = { - "smlalbb", "smlalbt", "smlaltb", "smlaltt" -}; - -const char* const ARMv7DOpcodeLongMultipleDivide::s_smlaldOpNames[2] = { - "smlald", "smlaldx" -}; - -const char* const ARMv7DOpcodeLongMultipleDivide::s_smlsldOpNames[2] = { - "smlsld", "smlsldx" -}; - -const char* ARMv7DOpcodeLongMultipleDivide::format() -{ - const char* instructionName = opName(); - - switch (op1()) { - case 0x0: - case 0x2: - if (op2()) - return defaultFormat(); - break; - case 0x1: - case 0x3: - if (op2() != 0xf) - return defaultFormat(); - break; - case 0x4: - if ((op2() & 0xc) == 0x8) - instructionName = smlalOpName(); - else if ((op2() & 0xe) == 0xc) - instructionName = smlaldOpName(); - else if (op2()) - return defaultFormat(); - break; - case 0x5: - if ((op2() & 0xe) == 0xc) - instructionName = smlaldOpName(); - else - return defaultFormat(); - break; - case 0x6: - if (op2() == 0x5) - instructionName = "umaal"; - else if (op2()) - return defaultFormat(); - break; - case 0x7: - return defaultFormat(); - break; - } - - appendInstructionName(instructionName); - if ((op1() & 0x5) == 0x1) { // sdiv and udiv - if (rt() != 0xf) - return defaultFormat(); - } else { - appendRegisterName(rdLo()); - appendSeparator(); - } - appendRegisterName(rdHi()); - appendSeparator(); - appendRegisterName(rn()); - appendSeparator(); - appendRegisterName(rm()); - - return m_formatBuffer; -} - -const char* const ARMv7DOpcodeUnmodifiedImmediate::s_opNames[16] = { - "addw", 0, "movw", 0, 0, "subw", "movt", 0, - "ssat", "ssat16", "sbfx", "bfi", "usat" , "usat16", "ubfx", 0 -}; - -const char* ARMv7DOpcodeUnmodifiedImmediate::format() -{ - const char* instructionName = opName(); - - switch (op() >> 1) { - case 0x0: - case 0x5: - if (rn() == 0xf) - instructionName = "adr"; - break; - case 0x9: - if (immediate5()) - instructionName = "ssat"; - break; - case 0xb: - if (rn() == 0xf) - instructionName = "bfc"; - break; - case 0xd: - if (immediate5()) - instructionName = "usat"; - break; - } - - if (!instructionName) - return defaultFormat(); - - appendInstructionName(instructionName); - appendRegisterName(rd()); - appendSeparator(); - - if ((op() & 0x17) == 0x4) { // movw or movt - appendUnsignedImmediate(immediate16()); - - return m_formatBuffer; - } - - if (!op() || (op() == 0xa)) { // addw, subw and adr - if (rn() == 0xf) { - int32_t offset; - - if ((op() == 0xa) && (rn() == 0xf)) - offset = 0 - static_cast<int32_t>(immediate12()); - else - offset = static_cast<int32_t>(immediate12()); - - appendPCRelativeOffset(offset); - - return m_formatBuffer; - } - - appendRegisterName(rn()); - appendSeparator(); - appendUnsignedImmediate(immediate12()); - - return m_formatBuffer; - } - - if (((op() & 0x15) == 0x10) || (((op() & 0x17) == 0x12) && immediate5())) { // ssat, usat, ssat16 & usat16 - appendSeparator(); - appendUnsignedImmediate(bitNumOrSatImmediate() + 1); - appendSeparator(); - appendRegisterName(rn()); - if (shBit() || immediate5()) { - appendSeparator(); - appendShiftType(shBit() << 1); - appendUnsignedImmediate(immediate5()); - } - - return m_formatBuffer; - } - - if (op() == 0x16) { // bfi or bfc - int width = static_cast<int>(bitNumOrSatImmediate()) - static_cast<int>(immediate5()) + 1; - - if (width < 0) - return defaultFormat(); - - if (rn() != 0xf) { - appendSeparator(); - appendRegisterName(rn()); - } - appendSeparator(); - appendUnsignedImmediate(immediate5()); - appendSeparator(); - appendSignedImmediate(width); - - return m_formatBuffer; - } - - // Must be sbfx or ubfx - appendSeparator(); - appendRegisterName(rn()); - appendSeparator(); - appendUnsignedImmediate(immediate5()); - appendSeparator(); - appendUnsignedImmediate(bitNumOrSatImmediate() + 1); - - return m_formatBuffer; -} - -const char* const ARMv7DOpcodeDataStoreSingle::s_opNames[4] = { - "strb", "strh", "str", 0 -}; - -const char* ARMv7DOpcodeDataPushPopSingle::format() -{ - appendInstructionName(opName()); - appendRegisterName(rt()); - - return m_formatBuffer; -} - -void ARMv7DOpcodeDataPushPopMultiple::appendRegisterList() -{ - unsigned registers = registerList(); - - appendCharacter('{'); - bool needSeparator = false; - - for (unsigned i = 0; i < 16; i++) { - if (registers & (1 << i)) { - if (needSeparator) - appendSeparator(); - appendRegisterName(i); - needSeparator = true; - } - } - appendCharacter('}'); -} - -const char* ARMv7DOpcodeDataPopMultiple::format() -{ - if (condition() != 0xe) - bufferPrintf(" pop%-4.4s", conditionName(condition())); - else - appendInstructionName("pop"); - appendRegisterList(); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeDataPushMultiple::format() -{ - if (condition() != 0xe) - bufferPrintf(" push%-3.3s", conditionName(condition())); - else - appendInstructionName("push"); - appendRegisterList(); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeStoreSingleImmediate12::format() -{ - appendInstructionName(opName()); - appendRegisterName(rt()); - appendSeparator(); - appendCharacter('['); - appendRegisterName(rn()); - if (immediate12()) { - appendSeparator(); - appendUnsignedImmediate(immediate12()); - } - appendCharacter(']'); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeStoreSingleImmediate8::format() -{ - if (pBit() && uBit() && !wBit()) // Really undecoded strt - return defaultFormat(); - - if ((rn() == 0xf) || (!pBit() && !wBit())) - return defaultFormat(); - - appendInstructionName(opName()); - appendRegisterName(rt()); - appendSeparator(); - appendCharacter('['); - appendRegisterName(rn()); - - if (!pBit()) { - appendCharacter(']'); - appendSeparator(); - appendSignedImmediate(uBit() ? static_cast<int32_t>(immediate8()) : (0 - static_cast<int32_t>(immediate8()))); - - return m_formatBuffer; - } - - if (immediate8()) { - appendSeparator(); - appendSignedImmediate(uBit() ? static_cast<int32_t>(immediate8()) : (0 - static_cast<int32_t>(immediate8()))); - } - appendCharacter(']'); - - if (wBit()) - appendCharacter('!'); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeStoreSingleRegister::format() -{ - appendInstructionName(opName()); - appendRegisterName(rt()); - appendSeparator(); - appendCharacter('['); - appendRegisterName(rn()); - appendSeparator(); - appendRegisterName(rm()); - if (immediate2()) { - appendSeparator(); - appendString("lsl "); - appendUnsignedImmediate(immediate2()); - } - appendCharacter(']'); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeVCMP::format() -{ - bufferPrintf(" vcmp"); - - if (eBit()) - appendCharacter('e'); // Raise exception on qNaN - - if (condition() != 0xe) - appendString(conditionName(condition())); - - appendCharacter('.'); - appendString(szBit() ? "f64" : "f32"); - appendCharacter(' '); - if (szBit()) { - appendFPRegisterName('d', (dBit() << 4) | vd()); - appendSeparator(); - appendFPRegisterName('d', (mBit() << 4) | vm()); - } else { - appendFPRegisterName('s', (vd() << 1) | dBit()); - appendSeparator(); - appendFPRegisterName('s', (vm() << 1) | mBit()); - } - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeVCVTBetweenFPAndInt::format() -{ - bufferPrintf(" vcvt"); - bool convertToInteger = op2() & 0x4; - - if (convertToInteger) { - if (!op()) - appendCharacter('r'); // Round using mode in FPSCR - if (condition() != 0xe) - appendString(conditionName(condition())); - appendCharacter('.'); - appendCharacter((op2() & 1) ? 's' : 'u'); - appendString("32.f"); - appendString(szBit() ? "64" : "32"); - appendCharacter(' '); - appendFPRegisterName('s', (vd() << 1) | dBit()); - appendSeparator(); - if (szBit()) - appendFPRegisterName('d', (mBit() << 4) | vm()); - else - appendFPRegisterName('s', (vm() << 1) | mBit()); - } else { - if (condition() != 0xe) - appendString(conditionName(condition())); - appendCharacter('.'); - appendString(szBit() ? "f64." : "f32."); - appendString(op() ? "s32" : "u32"); - appendCharacter(' '); - if (szBit()) - appendFPRegisterName('d', (dBit() << 4) | vd()); - else - appendFPRegisterName('s', (vd() << 1) | dBit()); - appendSeparator(); - appendFPRegisterName('s', (vm() << 1) | mBit()); - } - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeVLDR::format() -{ - if (condition() != 0xe) - bufferPrintf(" vldr%-3.3s", conditionName(condition())); - else - appendInstructionName("vldr"); - - appendFPRegisterName(doubleReg() ? 'd' : 's', vd()); - appendSeparator(); - - int immediate = immediate8() * 4; - - if (!uBit()) - immediate = -immediate; - - appendCharacter('['); - - if (rn() == RegPC) - appendPCRelativeOffset(immediate); - else { - appendRegisterName(rn()); - - if (immediate) { - appendSeparator(); - appendSignedImmediate(immediate); - } - } - - appendCharacter(']'); - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeVMOVDoublePrecision::format() -{ - appendInstructionName("vmov"); - if (op()) { - appendRegisterName(rt()); - appendSeparator(); - appendRegisterName(rt2()); - appendSeparator(); - } - - appendFPRegisterName('d', vm()); - - if (!op()) { - appendSeparator(); - appendRegisterName(rt()); - appendSeparator(); - appendRegisterName(rt2()); - } - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeVMOVSinglePrecision::format() -{ - appendInstructionName("vmov"); - if (op()) { - appendRegisterName(rt()); - appendSeparator(); - appendRegisterName(rt2()); - appendSeparator(); - } - - appendFPRegisterName('s', vm()); - appendSeparator(); - appendFPRegisterName('s', (vm() + 1) % 32); - - if (!op()) { - appendSeparator(); - appendRegisterName(rt()); - appendSeparator(); - appendRegisterName(rt2()); - } - - return m_formatBuffer; -} - -const char* ARMv7DOpcodeVMSR::format() -{ - appendInstructionName("vmrs"); - if (opL()) { - if (rt() == 0xf) - appendString("apsr_nzcv"); - else - appendRegisterName(rt()); - appendSeparator(); - } - - appendString("fpscr"); - - if (!opL()) { - appendSeparator(); - appendRegisterName(rt()); - } - - return m_formatBuffer; -} - -} } // namespace JSC::ARMv7Disassembler - -#endif // #if USE(ARMV7_DISASSEMBLER) diff --git a/Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.h b/Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.h deleted file mode 100644 index 13e209db7..000000000 --- a/Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.h +++ /dev/null @@ -1,1237 +0,0 @@ -/* - * Copyright (C) 2013 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ARMv7DOpcode_h -#define ARMv7DOpcode_h - -#if USE(ARMV7_DISASSEMBLER) - -#include <stdint.h> -#include <wtf/Assertions.h> - -namespace JSC { namespace ARMv7Disassembler { - -class ARMv7DOpcode { -public: - static void init(); - - ARMv7DOpcode() - : m_opcode(0) - , m_bufferOffset(0) - { - init(); - - for (unsigned i = 0; i < 4; i++) - m_ifThenConditions[i] = CondNone; - - endITBlock(); - - m_formatBuffer[0] = '\0'; - } - - const char* disassemble(uint16_t*& currentPC); - -protected: - const unsigned RegSP = 0xd; - const unsigned RegLR = 0xe; - const unsigned RegPC = 0xf; - - void fetchOpcode(uint16_t*&); - bool is32BitInstruction() { return (m_opcode & 0xfffff800) > 0xe000; } - bool isFPInstruction() { return (m_opcode & 0xfc000e00) == 0xec000a00; } - - static const char* const s_conditionNames[16]; - static const char* const s_shiftNames[4]; - static const char* const s_optionName[8]; - static const char* const s_specialRegisterNames[3]; - - static const char* conditionName(unsigned condition) { return s_conditionNames[condition & 0xf]; } - static const char* shiftName(unsigned shiftValue) { return s_shiftNames[shiftValue & 0x3]; } - - bool inITBlock() { return m_ITConditionIndex < m_ITBlocksize; } - bool startingITBlock() { return m_ITConditionIndex == m_ITBlocksize + 1; } - - void startITBlock(unsigned, unsigned); - void saveITConditionAt(unsigned, unsigned); - void endITBlock() - { - m_currentITCondition = CondNone; - m_ITConditionIndex = 0; - m_ITBlocksize = 0; - } - - void bufferPrintf(const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3); - void appendInstructionName(const char*, bool addS = false); - - void appendInstructionNameNoITBlock(const char* instructionName) - { - bufferPrintf(" %-7.7s", instructionName); - } - - void appendRegisterName(unsigned); - void appendRegisterList(unsigned); - void appendFPRegisterName(char, unsigned); - - void appendSeparator() - { - bufferPrintf(", "); - } - - void appendCharacter(const char c) - { - bufferPrintf("%c", c); - } - - void appendString(const char* string) - { - bufferPrintf("%s", string); - } - - void appendShiftType(unsigned shiftValue) - { - bufferPrintf("%s ", shiftName(shiftValue)); - } - - void appendSignedImmediate(int immediate) - { - bufferPrintf("#%d", immediate); - } - - void appendUnsignedImmediate(unsigned immediate) - { - bufferPrintf("#%u", immediate); - } - - void appendPCRelativeOffset(int32_t immediate) - { - bufferPrintf("0x%x", reinterpret_cast<uint32_t>(m_currentPC + immediate)); - } - - void appendShiftAmount(unsigned amount) - { - bufferPrintf("lsl #%u", 16 * amount); - } - - static const int bufferSize = 81; - static const unsigned char CondNone = 0xe; - static const unsigned MaxITBlockSize = 4; - - char m_formatBuffer[bufferSize]; - unsigned char m_ifThenConditions[MaxITBlockSize]; - uint16_t* m_currentPC; - uint32_t m_opcode; - int m_bufferOffset; - int m_currentITCondition; - unsigned m_ITConditionIndex; - unsigned m_ITBlocksize; - -private: - static bool s_initialized; -}; - -#define DEFINE_STATIC_FORMAT16(klass, thisObj) \ - static const char* format(ARMv7D16BitOpcode* thisObj) { return reinterpret_cast< klass *>(thisObj)->format(); } - -class ARMv7D16BitOpcode : public ARMv7DOpcode { -private: - class OpcodeGroup { - public: - OpcodeGroup(uint16_t opcodeMask, uint16_t opcodePattern, const char* (*format)(ARMv7D16BitOpcode*)) - : m_opcodeMask(opcodeMask) - , m_opcodePattern(opcodePattern) - , m_format(format) - , m_next(0) - { - } - - void setNext(OpcodeGroup* next) - { - m_next = next; - } - - OpcodeGroup* next() - { - return m_next; - } - - bool matches(uint16_t opcode) - { - return (opcode & m_opcodeMask) == m_opcodePattern; - } - - const char* format(ARMv7D16BitOpcode* thisObj) - { - return m_format(thisObj); - } - - public: - static const unsigned opcodeTableSize = 32; - static const unsigned opcodeTableMask = opcodeTableSize-1; - - // private: - uint16_t m_opcodeMask; - uint16_t m_opcodePattern; - const char* (*m_format)(ARMv7D16BitOpcode*); - OpcodeGroup* m_next; - }; - -public: - static void init(); - - const char* defaultFormat(); - const char* doDisassemble(); - -protected: - unsigned rm() { return (m_opcode >> 3) & 0x7; } - unsigned rd() { return m_opcode & 0x7; } - unsigned opcodeGroupNumber(unsigned opcode) { return (opcode >> 11) & OpcodeGroup::opcodeTableMask; } - -private: - static OpcodeGroup* opcodeTable[OpcodeGroup::opcodeTableSize]; -}; - -class ARMv7DOpcodeAddRegisterT2 : public ARMv7D16BitOpcode { -public: - static const uint16_t s_mask = 0xff00; - static const uint16_t s_pattern = 0x4400; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeAddRegisterT2, thisObj); - -protected: - const char* format(); - - unsigned rdn() { return ((m_opcode >> 4) & 0x8) | (m_opcode & 0x7); } - unsigned rm() { return ((m_opcode >> 3) & 0xf); } -}; - -class ARMv7DOpcodeAddSPPlusImmediate : public ARMv7D16BitOpcode { -public: - static const uint16_t s_mask = 0xf800; - static const uint16_t s_pattern = 0xc800; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeAddSPPlusImmediate, thisObj); - -protected: - const char* format(); - - unsigned rd() { return (m_opcode >> 8) & 0x7; } - unsigned immediate8() { return m_opcode & 0x0ff; } -}; - -class ARMv7DOpcodeAddSubtract : public ARMv7D16BitOpcode { -protected: - static const char* const s_opNames[2]; -}; - -class ARMv7DOpcodeAddSubtractT1 : public ARMv7DOpcodeAddSubtract { -public: - static const uint16_t s_mask = 0xfc00; - static const uint16_t s_pattern = 0x1800; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeAddSubtractT1, thisObj); - -protected: - const char* format(); - - const char* opName() { return s_opNames[op()]; } - - unsigned op() { return (m_opcode >> 9) & 0x1; } - unsigned rm() { return (m_opcode >> 6) & 0x7; } - unsigned rn() { return (m_opcode >> 3) & 0x7; } -}; - -class ARMv7DOpcodeAddSubtractImmediate3 : public ARMv7DOpcodeAddSubtract { -public: - static const uint16_t s_mask = 0xfc00; - static const uint16_t s_pattern = 0x1c00; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeAddSubtractImmediate3, thisObj); - -protected: - const char* format(); - - const char* opName() { return s_opNames[op()]; } - - unsigned op() { return (m_opcode >> 9) & 0x1; } - unsigned immediate3() { return (m_opcode >> 6) & 0x7; } - unsigned rn() { return (m_opcode >> 3) & 0x7; } -}; - -class ARMv7DOpcodeAddSubtractImmediate8 : public ARMv7DOpcodeAddSubtract { -public: - static const uint16_t s_mask = 0xf000; - static const uint16_t s_pattern = 0x3000; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeAddSubtractImmediate8, thisObj); - -protected: - const char* format(); - - const char* opName() { return s_opNames[op()]; } - - unsigned op() { return (m_opcode >> 11) & 0x1; } - unsigned rdn() { return (m_opcode >> 8) & 0x7; } - unsigned immediate8() { return m_opcode & 0xff; } -}; - -class ARMv7DOpcodeBranchConditionalT1 : public ARMv7D16BitOpcode { -public: - static const uint16_t s_mask = 0xf000; - static const uint16_t s_pattern = 0xd000; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeBranchConditionalT1, thisObj); - -protected: - const char* format(); - - unsigned condition() { return (m_opcode >> 8) & 0xf; } - int offset() { return static_cast<int>(m_opcode & 0xff); } -}; - -class ARMv7DOpcodeBranchExchangeT1 : public ARMv7D16BitOpcode { -public: - static const uint16_t s_mask = 0xff00; - static const uint16_t s_pattern = 0x4700; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeBranchExchangeT1, thisObj); - -protected: - const char* format(); - - const char* opName() { return (m_opcode & 0x80) ? "blx" : "bx"; } - unsigned rm() { return ((m_opcode >> 3) & 0xf); } -}; - -class ARMv7DOpcodeBranchT2 : public ARMv7D16BitOpcode { -public: - static const uint16_t s_mask = 0xf800; - static const uint16_t s_pattern = 0xe000; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeBranchT2, thisObj); - -protected: - const char* format(); - - int immediate11() { return static_cast<int>(m_opcode & 0x7ff); } -}; - -class ARMv7DOpcodeCompareImmediateT1 : public ARMv7D16BitOpcode { -public: - static const uint16_t s_mask = 0xf800; - static const uint16_t s_pattern = 0x2800; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeCompareImmediateT1, thisObj); - -protected: - const char* format(); - - unsigned rn() { return (m_opcode >> 8) & 0x3; } - unsigned immediate8() { return m_opcode & 0xff; } -}; - -class ARMv7DOpcodeCompareRegisterT1 : public ARMv7D16BitOpcode { -public: - static const uint16_t s_mask = 0xffc0; - static const uint16_t s_pattern = 0x4280; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeCompareRegisterT1, thisObj); - -protected: - const char* format(); - - unsigned rn() { return m_opcode & 0x7; } -}; - -class ARMv7DOpcodeCompareRegisterT2 : public ARMv7D16BitOpcode { -public: - static const uint16_t s_mask = 0xff00; - static const uint16_t s_pattern = 0x4500; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeCompareRegisterT2, thisObj); - -protected: - const char* format(); - - unsigned rn() { return ((m_opcode >> 4) & 0x8) | (m_opcode & 0x7); } - unsigned rm() { return ((m_opcode >> 3) & 0xf); } -}; - -class ARMv7DOpcodeDataProcessingRegisterT1 : public ARMv7D16BitOpcode { -private: - static const char* const s_opNames[16]; - -public: - static const uint16_t s_mask = 0xfc00; - static const uint16_t s_pattern = 0x4000; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeDataProcessingRegisterT1, thisObj); - -protected: - const char* format(); - - const char* opName() { return s_opNames[op()]; } - - unsigned op() { return (m_opcode >> 6) & 0xf; } - - unsigned rm() { return (m_opcode >> 3) & 0x7; } - unsigned rdn() { return m_opcode & 0x7; } -}; - -class ARMv7DOpcodeGeneratePCRelativeAddress : public ARMv7D16BitOpcode { -public: - static const uint16_t s_mask = 0xf800; - static const uint16_t s_pattern = 0xa000; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeGeneratePCRelativeAddress, thisObj); - -protected: - const char* format(); - - unsigned rd() { return (m_opcode >> 8) & 0x7; } - unsigned immediate8() { return m_opcode & 0x0ff; } -}; - -class ARMv7DOpcodeLoadFromLiteralPool : public ARMv7D16BitOpcode { -public: - static const uint16_t s_mask = 0xf800; - static const uint16_t s_pattern = 0x4800; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadFromLiteralPool, thisObj); - -protected: - const char* format(); - - unsigned rt() { return (m_opcode >> 8) & 0x7; } - unsigned immediate8() { return m_opcode & 0x0ff; } -}; - -class ARMv7DOpcodeLoadStoreRegisterImmediate : public ARMv7D16BitOpcode { -private: - static const char* const s_opNames[6]; - -public: - const char* format(); - -protected: - const char* opName() { return s_opNames[op()]; } - - unsigned op() { return ((m_opcode >> 11) & 0x1f) - 0xc; } - unsigned immediate5() { return (m_opcode >> 6) & 0x01f; } - unsigned rn() { return (m_opcode >> 3) & 0x7; } - unsigned rt() { return m_opcode & 0x7; } - unsigned scale(); -}; - -class ARMv7DOpcodeLoadStoreRegisterImmediateWordAndByte : public ARMv7DOpcodeLoadStoreRegisterImmediate { -public: - static const uint16_t s_mask = 0xe000; - static const uint16_t s_pattern = 0x6000; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadStoreRegisterImmediate, thisObj); -}; - -class ARMv7DOpcodeStoreRegisterImmediateHalfWord : public ARMv7DOpcodeLoadStoreRegisterImmediate { -public: - static const uint16_t s_mask = 0xf800; - static const uint16_t s_pattern = 0x8000; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadStoreRegisterImmediate, thisObj); -}; - -class ARMv7DOpcodeLoadRegisterImmediateHalfWord : public ARMv7DOpcodeLoadStoreRegisterImmediate { -public: - static const uint16_t s_mask = 0xf800; - static const uint16_t s_pattern = 0x8800; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadStoreRegisterImmediate, thisObj); -}; - -class ARMv7DOpcodeLoadStoreRegisterOffsetT1 : public ARMv7D16BitOpcode { -private: - static const char* const s_opNames[8]; - -public: - static const uint16_t s_mask = 0xf000; - static const uint16_t s_pattern = 0x5000; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadStoreRegisterOffsetT1, thisObj); - -protected: - const char* format(); - - const char* opName() { return s_opNames[opB()]; } - - unsigned opB() { return (m_opcode >> 9) & 0x7; } - unsigned rm() { return (m_opcode >> 6) & 0x7; } - unsigned rn() { return (m_opcode >> 3) & 0x7; } - unsigned rt() { return m_opcode & 0x7; } -}; - -class ARMv7DOpcodeLoadStoreRegisterSPRelative : public ARMv7D16BitOpcode { -private: - static const char* const s_opNames[8]; - -public: - static const uint16_t s_mask = 0xf000; - static const uint16_t s_pattern = 0x9000; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadStoreRegisterSPRelative, thisObj); - -protected: - const char* format(); - - const char* opName() { return op() ? "ldr" : "str"; } - - unsigned op() { return (m_opcode >> 11) & 0x1; } - unsigned rt() { return (m_opcode >> 8) & 0x7; } - unsigned immediate8() { return m_opcode & 0xff; } -}; - -class ARMv7DOpcodeLogicalImmediateT1 : public ARMv7D16BitOpcode { -public: - static const uint16_t s_mask = 0xe000; - static const uint16_t s_pattern = 0x0000; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLogicalImmediateT1, thisObj); - -protected: - const char* format(); - - const char* opName() { return shiftName(op()); } - - unsigned op() { return (m_opcode >> 12) & 0x3; } - unsigned immediate5() { return (m_opcode >> 6) & 0x1f; } -}; - -class ARMv7DOpcodeMiscAddSubSP : public ARMv7D16BitOpcode { -public: - static const uint16_t s_mask = 0xff00; - static const uint16_t s_pattern = 0xb000; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscAddSubSP, thisObj); - -protected: - const char* format(); - - const char* opName() { return op() ? "sub" : "add"; } - unsigned op() { return (m_opcode >> 7) & 0x1; } - unsigned immediate7() { return m_opcode & 0x7f; } -}; - -class ARMv7DOpcodeMiscByteHalfwordOps : public ARMv7D16BitOpcode { -private: - static const char* const s_opNames[8]; - -public: - static const uint16_t s_mask = 0xf700; - static const uint16_t s_pattern = 0xb200; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscByteHalfwordOps, thisObj); - -protected: - const char* format(); - - const char* opName() { return s_opNames[op()]; } - unsigned op() { return ((m_opcode >> 9) & 0x4) || ((m_opcode >> 6) & 0x3); } -}; - -class ARMv7DOpcodeMiscBreakpointT1 : public ARMv7D16BitOpcode { -public: - static const uint16_t s_mask = 0xff00; - static const uint16_t s_pattern = 0xbe00; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscBreakpointT1, thisObj); - -protected: - const char* format(); - - unsigned immediate8() { return m_opcode & 0xff; } -}; - -class ARMv7DOpcodeMiscCompareAndBranch : public ARMv7D16BitOpcode { -public: - static const uint16_t s_mask = 0xf500; - static const uint16_t s_pattern = 0xb100; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscCompareAndBranch, thisObj); - -protected: - const char* format(); - - const char* opName() { return op() ? "cbnz" : "cbz"; } - unsigned op() { return (m_opcode >> 11) & 0x1; } - int32_t immediate6() { return ((m_opcode >> 4) & 0x20) | ((m_opcode >> 3) & 0x1f); } - unsigned rn() { return m_opcode & 0x7; } -}; - -class ARMv7DOpcodeMiscHint16 : public ARMv7D16BitOpcode { -private: - static const char* const s_opNames[16]; - -public: - static const uint16_t s_mask = 0xff0f; - static const uint16_t s_pattern = 0xbf00; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscHint16, thisObj); - -protected: - const char* format(); - - const char* opName() { return s_opNames[opA()]; } - unsigned opA() { return (m_opcode >> 4) & 0xf; } -}; - -class ARMv7DOpcodeMiscIfThenT1 : public ARMv7D16BitOpcode { -public: - static const uint16_t s_mask = 0xff00; - static const uint16_t s_pattern = 0xbf00; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscIfThenT1, thisObj); - -protected: - const char* format(); - - unsigned firstCondition() { return (m_opcode >> 4) & 0xf; } - unsigned mask() { return m_opcode & 0xf; } -}; - -class ARMv7DOpcodeMiscPushPop : public ARMv7D16BitOpcode { -public: - static const uint16_t s_mask = 0xf600; - static const uint16_t s_pattern = 0xb400; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscPushPop, thisObj); - -protected: - const char* format(); - - const char* opName() { return op() ? "pop" : "push"; } - unsigned op() { return (m_opcode >> 11) & 0x1; } - unsigned registerMask() { return ((m_opcode << 6) & 0x4000) | (m_opcode & 0xff); } -}; - -class ARMv7DOpcodeMoveImmediateT1 : public ARMv7D16BitOpcode { -public: - static const uint16_t s_mask = 0xf800; - static const uint16_t s_pattern = 0x2000; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMoveImmediateT1, thisObj); - -protected: - const char* format(); - - unsigned rd() { return (m_opcode >> 8) & 0x3; } - unsigned immediate8() { return m_opcode & 0xff; } -}; - -class ARMv7DOpcodeMoveRegisterT1 : public ARMv7D16BitOpcode { -public: - static const uint16_t s_mask = 0xff00; - static const uint16_t s_pattern = 0x4600; - - DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMoveRegisterT1, thisObj); - -protected: - const char* format(); - - unsigned rd() { return ((m_opcode >> 4) & 0x8) | (m_opcode & 0x7); } - unsigned rm() { return ((m_opcode >> 3) & 0xf); } -}; - -// 32 Bit instructions - -#define DEFINE_STATIC_FORMAT32(klass, thisObj) \ - static const char* format(ARMv7D32BitOpcode* thisObj) { return reinterpret_cast< klass *>(thisObj)->format(); } - -class ARMv7D32BitOpcode : public ARMv7DOpcode { -private: - class OpcodeGroup { - public: - OpcodeGroup(uint32_t opcodeMask, uint32_t opcodePattern, const char* (*format)(ARMv7D32BitOpcode*)) - : m_opcodeMask(opcodeMask) - , m_opcodePattern(opcodePattern) - , m_format(format) - , m_next(0) - { - } - - void setNext(OpcodeGroup* next) - { - m_next = next; - } - - OpcodeGroup* next() - { - return m_next; - } - - bool matches(uint32_t opcode) - { - return (opcode & m_opcodeMask) == m_opcodePattern; - } - - const char* format(ARMv7D32BitOpcode* thisObj) - { - return m_format(thisObj); - } - - public: - static const unsigned opcodeTableSize = 16; - static const unsigned opcodeTableMask = opcodeTableSize-1; - - private: - uint32_t m_opcodeMask; - uint32_t m_opcodePattern; - const char* (*m_format)(ARMv7D32BitOpcode*); - OpcodeGroup* m_next; - }; - -public: - static void init(); - - const char* defaultFormat(); - const char* doDisassemble(); - -protected: - unsigned rd() { return (m_opcode >> 8) & 0xf; } - unsigned rm() { return m_opcode & 0xf; } - unsigned rn() { return (m_opcode >> 16) & 0xf; } - unsigned rt() { return (m_opcode >> 12) & 0xf; } - - unsigned opcodeGroupNumber(unsigned opcode) { return (opcode >> 25) & OpcodeGroup::opcodeTableMask; } - -private: - static OpcodeGroup* opcodeTable[OpcodeGroup::opcodeTableSize]; -}; - -class ARMv7DOpcodeBranchRelative : public ARMv7D32BitOpcode { -protected: - unsigned sBit() { return (m_opcode >> 26) & 0x1; } - unsigned j1() { return (m_opcode >> 13) & 0x1; } - unsigned j2() { return (m_opcode >> 11) & 0x1; } - unsigned immediate11() { return m_opcode & 0x7ff; } -}; - -class ARMv7DOpcodeConditionalBranchT3 : public ARMv7DOpcodeBranchRelative { -public: - static const uint32_t s_mask = 0xf800d000; - static const uint32_t s_pattern = 0xf0008000; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeConditionalBranchT3, thisObj); - -protected: - const char* format(); - - int32_t offset() { return ((static_cast<int32_t>(sBit() << 31)) >> 12) | static_cast<int32_t>((j1() << 18) | (j2() << 17) | (immediate6() << 11) | immediate11()); } - unsigned condition() { return (m_opcode >> 22) & 0xf; } - unsigned immediate6() { return (m_opcode >> 16) & 0x3f; } -}; - -class ARMv7DOpcodeBranchOrBranchLink : public ARMv7DOpcodeBranchRelative { -public: - static const uint32_t s_mask = 0xf8009000; - static const uint32_t s_pattern = 0xf0009000; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeBranchOrBranchLink, thisObj); - -protected: - const char* format(); - - int32_t offset() { return ((static_cast<int32_t>(sBit() << 31)) >> 8) | static_cast<int32_t>((~(j1() ^ sBit()) << 22) | (~(j2() ^ sBit()) << 21) | (immediate10() << 11) | immediate11()); } - unsigned immediate10() { return (m_opcode >> 16) & 0x3ff; } - bool isBL() { return !!((m_opcode >> 14) & 0x1); } -}; - -class ARMv7DOpcodeDataProcessingLogicalAndRithmetic : public ARMv7D32BitOpcode { -protected: - static const char* const s_opNames[16]; -}; - -class ARMv7DOpcodeDataProcessingModifiedImmediate : public ARMv7DOpcodeDataProcessingLogicalAndRithmetic { -private: - void appendImmShift(unsigned, unsigned); - -public: - static const uint32_t s_mask = 0xfa008000; - static const uint32_t s_pattern = 0xf0000000; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingModifiedImmediate, thisObj); - -protected: - const char* format(); - void appendModifiedImmediate(unsigned); - - const char* opName() { return s_opNames[op()]; } - - unsigned op() { return (m_opcode >> 21) & 0xf; } - unsigned sBit() { return (m_opcode >> 20) & 0x1; } - unsigned immediate12() { return ((m_opcode >> 15) & 0x0800) | ((m_opcode >> 4) & 0x0700) | (m_opcode & 0x00ff); } -}; - -class ARMv7DOpcodeDataProcessingShiftedReg : public ARMv7DOpcodeDataProcessingLogicalAndRithmetic { -private: - void appendImmShift(unsigned, unsigned); - -public: - static const uint32_t s_mask = 0xfe000000; - static const uint32_t s_pattern = 0xea000000; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingShiftedReg, thisObj); - -protected: - const char* format(); - - const char* opName() { return s_opNames[op()]; } - - unsigned sBit() { return (m_opcode >> 20) & 0x1; } - unsigned op() { return (m_opcode >> 21) & 0xf; } - unsigned immediate5() { return ((m_opcode >> 10) & 0x1c) | ((m_opcode >> 6) & 0x3); } - unsigned type() { return (m_opcode >> 4) & 0x3; } - unsigned tbBit() { return (m_opcode >> 5) & 0x1; } - unsigned tBit() { return (m_opcode >> 4) & 0x1; } -}; - -class ARMv7DOpcodeDataProcessingReg : public ARMv7D32BitOpcode { -protected: - unsigned op1() { return (m_opcode >> 20) & 0xf; } - unsigned op2() { return (m_opcode >> 4) & 0xf; } -}; - -class ARMv7DOpcodeDataProcessingRegShift : public ARMv7DOpcodeDataProcessingReg { -public: - static const uint32_t s_mask = 0xffe0f0f0; - static const uint32_t s_pattern = 0xfa00f000; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingRegShift, thisObj); - -protected: - const char* format(); - - const char* opName() { return shiftName((op1() >> 1) & 0x3); } -}; - -class ARMv7DOpcodeDataProcessingRegExtend : public ARMv7DOpcodeDataProcessingReg { -private: - static const char* const s_opExtendNames[8]; - static const char* const s_opExtendAndAddNames[8]; - -public: - static const uint32_t s_mask = 0xff80f0c0; - static const uint32_t s_pattern = 0xfa00f080; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingRegExtend, thisObj); - -protected: - const char* format(); - - const char* opExtendName() { return s_opExtendNames[op1()]; } - const char* opExtendAndAddName() { return s_opExtendAndAddNames[op1()]; } - unsigned rotate() { return (m_opcode >> 4) & 0x3; } -}; - -class ARMv7DOpcodeDataProcessingRegParallel : public ARMv7DOpcodeDataProcessingReg { -private: - static const char* const s_opNames[16]; - -public: - static const uint32_t s_mask = 0xff80f0e0; - static const uint32_t s_pattern = 0xfa00f000; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingRegParallel, thisObj); - -protected: - const char* format(); - - const char* opName() { return s_opNames[((op1() & 0x7) << 1) | (op2() & 0x1)]; } -}; - -class ARMv7DOpcodeDataProcessingRegMisc : public ARMv7DOpcodeDataProcessingReg { -private: - static const char* const s_opNames[16]; - -public: - static const uint32_t s_mask = 0xffc0f0c0; - static const uint32_t s_pattern = 0xfa80f080; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingRegMisc, thisObj); - -protected: - const char* format(); - - const char* opName() { return s_opNames[((op1() & 0x3) << 2) | (op2() & 0x3)]; } -}; - -class ARMv7DOpcodeHint32 : public ARMv7D32BitOpcode { -private: - static const char* const s_opNames[8]; - -public: - static const uint32_t s_mask = 0xfff0d000; - static const uint32_t s_pattern = 0xf3a08000; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeHint32, thisObj); - -protected: - const char* format(); - - const char* opName() { return s_opNames[op()]; } - - bool isDebugHint() { return (m_opcode & 0xf0) == 0xf0; } - unsigned debugOption() { return m_opcode & 0xf; } - unsigned op() { return m_opcode & 0x7; } -}; - -class ARMv7DOpcodeFPTransfer : public ARMv7D32BitOpcode { -public: - static const uint32_t s_mask = 0xffc00e7f; - static const uint32_t s_pattern = 0xee000a10; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeFPTransfer, thisObj); - -protected: - const char* format(); - - void appendFPRegister(); - - unsigned opH() { return (m_opcode >> 21) & 0x1; } - unsigned opL() { return (m_opcode >> 20) & 0x1; } - unsigned rt() { return (m_opcode >> 12) & 0xf; } - unsigned opC() { return (m_opcode >> 8) & 0x1; } - unsigned opB() { return (m_opcode >> 5) & 0x3; } - unsigned vd() { return ((m_opcode >> 3) & 0x10) | ((m_opcode >> 16) & 0xf); } - unsigned vn() { return ((m_opcode >> 7) & 0x1) | ((m_opcode >> 15) & 0x1e); } -}; - -class ARMv7DOpcodeDataLoad : public ARMv7D32BitOpcode { -protected: - static const char* const s_opNames[8]; - -protected: - const char* opName() { return s_opNames[op()]; } - - unsigned op() { return ((m_opcode >> 22) & 0x4) | ((m_opcode >> 21) & 0x3); } -}; - -class ARMv7DOpcodeLoadRegister : public ARMv7DOpcodeDataLoad { -public: - static const uint32_t s_mask = 0xfe900800; - static const uint32_t s_pattern = 0xf8100000; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeLoadRegister, thisObj); - -protected: - const char* format(); - - unsigned immediate2() { return (m_opcode >> 4) & 0x3; } -}; - -class ARMv7DOpcodeLoadSignedImmediate : public ARMv7DOpcodeDataLoad { -public: - static const uint32_t s_mask = 0xfe900800; - static const uint32_t s_pattern = 0xf8100800; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeLoadSignedImmediate, thisObj); - -protected: - const char* format(); - - unsigned pBit() { return (m_opcode >> 10) & 0x1; } - unsigned uBit() { return (m_opcode >> 9) & 0x1; } - unsigned wBit() { return (m_opcode >> 8) & 0x1; } - unsigned immediate8() { return m_opcode & 0xff; } -}; - -class ARMv7DOpcodeLoadUnsignedImmediate : public ARMv7DOpcodeDataLoad { -public: - static const uint32_t s_mask = 0xfe900000; - static const uint32_t s_pattern = 0xf8900000; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeLoadUnsignedImmediate, thisObj); - -protected: - const char* format(); - - unsigned immediate12() { return m_opcode & 0xfff; } -}; - -class ARMv7DOpcodeLongMultipleDivide : public ARMv7D32BitOpcode { -protected: - static const char* const s_opNames[8]; - static const char* const s_smlalOpNames[4]; - static const char* const s_smlaldOpNames[2]; - static const char* const s_smlsldOpNames[2]; - -public: - static const uint32_t s_mask = 0xff800000; - static const uint32_t s_pattern = 0xfb800000; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeLongMultipleDivide, thisObj); - -protected: - const char* format(); - - const char* opName() { return s_opNames[op1()]; } - const char* smlalOpName() { return s_smlalOpNames[(nBit() << 1) | mBit()]; } - const char* smlaldOpName() { return s_smlaldOpNames[mBit()]; } - const char* smlsldOpName() { return s_smlsldOpNames[mBit()]; } - - unsigned rdLo() { return rt(); } - unsigned rdHi() { return rd(); } - unsigned op1() { return (m_opcode >> 20) & 0x7; } - unsigned op2() { return (m_opcode >> 4) & 0xf; } - unsigned nBit() { return (m_opcode >> 5) & 0x1; } - unsigned mBit() { return (m_opcode >> 4) & 0x1; } -}; - -class ARMv7DOpcodeDataPushPopSingle : public ARMv7D32BitOpcode { -public: - static const uint32_t s_mask = 0xffef0fff; - static const uint32_t s_pattern = 0xf84d0d04; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataPushPopSingle, thisObj); - -protected: - const char* format(); - - const char* opName() { return op() ? "pop" : "push"; } - unsigned op() { return (m_opcode >> 20) & 0x1; } -}; - -class ARMv7DOpcodeDataPushPopMultiple : public ARMv7D32BitOpcode { -protected: - void appendRegisterList(); - - unsigned registerList() { return m_opcode & 0xffff; } - unsigned condition() { return m_opcode >> 28; } -}; - -class ARMv7DOpcodeDataPopMultiple : public ARMv7DOpcodeDataPushPopMultiple { -public: - static const uint32_t s_mask = 0x0fff0000; - static const uint32_t s_pattern = 0x08bd0000; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataPopMultiple, thisObj); - -protected: - const char* format(); -}; - -class ARMv7DOpcodeDataPushMultiple : public ARMv7DOpcodeDataPushPopMultiple { -public: - static const uint32_t s_mask = 0xfe7f0000; - static const uint32_t s_pattern = 0xe82d0000; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataPushMultiple, thisObj); - -protected: - const char* format(); -}; - -class ARMv7DOpcodeDataStoreSingle : public ARMv7D32BitOpcode { -protected: - static const char* const s_opNames[4]; - -protected: - const char* opName() { return s_opNames[op()]; } - - unsigned op() { return (m_opcode >> 21) & 0x3; } -}; - -class ARMv7DOpcodeStoreSingleImmediate12 : public ARMv7DOpcodeDataStoreSingle { -public: - static const uint32_t s_mask = 0xfff00000; - static const uint32_t s_pattern = 0xf8c00000; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeStoreSingleImmediate12, thisObj); - - const char* format(); - -protected: - unsigned immediate12() { return m_opcode & 0xfff; } -}; - -class ARMv7DOpcodeStoreSingleImmediate8 : public ARMv7DOpcodeDataStoreSingle { -public: - static const uint32_t s_mask = 0xfff00800; - static const uint32_t s_pattern = 0xf8400800; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeStoreSingleImmediate8, thisObj); - - const char* format(); - -protected: - unsigned pBit() { return (m_opcode >> 10) & 0x1; } - unsigned uBit() { return (m_opcode >> 9) & 0x1; } - unsigned wBit() { return (m_opcode >> 8) & 0x1; } - unsigned immediate8() { return m_opcode & 0xff; } -}; - -class ARMv7DOpcodeStoreSingleRegister : public ARMv7DOpcodeDataStoreSingle { -public: - static const uint32_t s_mask = 0xfff00fc0; - static const uint32_t s_pattern = 0xf8400000; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeStoreSingleRegister, thisObj); - -protected: - const char* format(); - - unsigned immediate2() { return (m_opcode >> 4) & 0x3; } -}; - -class ARMv7DOpcodeUnmodifiedImmediate : public ARMv7D32BitOpcode { -protected: - static const char* const s_opNames[16]; - -public: - static const uint32_t s_mask = 0xfa008000; - static const uint32_t s_pattern = 0xf2000000; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeUnmodifiedImmediate, thisObj); - -protected: - const char* format(); - - const char* opName() { return s_opNames[op() >> 1]; } - - unsigned op() { return (m_opcode >> 20) & 0x1f; } - unsigned shBit() { return (m_opcode >> 21) & 0x1; } - unsigned bitNumOrSatImmediate() { return m_opcode & 0x1f; } - unsigned immediate5() { return ((m_opcode >> 9) & 0x1c) | ((m_opcode >> 6) & 0x3); } - unsigned immediate12() { return ((m_opcode >> 15) & 0x0800) | ((m_opcode >> 4) & 0x0700) | (m_opcode & 0x00ff); } - unsigned immediate16() { return ((m_opcode >> 4) & 0xf000) | ((m_opcode >> 15) & 0x0800) | ((m_opcode >> 4) & 0x0700) | (m_opcode & 0x00ff); } -}; - -class ARMv7DOpcodeVCMP : public ARMv7D32BitOpcode { -public: - static const uint32_t s_mask = 0x0fbf0e50; - static const uint32_t s_pattern = 0x0eb40a40; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeVCMP, thisObj); - -protected: - const char* format(); - - unsigned condition() { return m_opcode >> 28; } - unsigned dBit() { return (m_opcode >> 22) & 0x1; } - unsigned vd() { return (m_opcode >> 12) & 0xf; } - unsigned szBit() { return (m_opcode >> 8) & 0x1; } - unsigned eBit() { return (m_opcode >> 7) & 0x1; } - unsigned mBit() { return (m_opcode >> 5) & 0x1; } - unsigned vm() { return m_opcode & 0xf; } -}; - -class ARMv7DOpcodeVCVTBetweenFPAndInt : public ARMv7D32BitOpcode { -public: - static const uint32_t s_mask = 0x0fb80e50; - static const uint32_t s_pattern = 0x0eb80a40; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeVCVTBetweenFPAndInt, thisObj); - -protected: - const char* format(); - - unsigned condition() { return m_opcode >> 28; } - unsigned dBit() { return (m_opcode >> 22) & 0x1; } - unsigned op2() { return (m_opcode >> 16) & 0x7; } - unsigned vd() { return (m_opcode >> 12) & 0xf; } - unsigned szBit() { return (m_opcode >> 8) & 0x1; } - unsigned op() { return (m_opcode >> 7) & 0x1; } - unsigned mBit() { return (m_opcode >> 5) & 0x1; } - unsigned vm() { return m_opcode & 0xf; } -}; - -class ARMv7DOpcodeVLDR : public ARMv7D32BitOpcode { -public: - static const uint32_t s_mask = 0x0f300e00; - static const uint32_t s_pattern = 0x0d100a00; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeVLDR, thisObj); - -protected: - const char* format(); - - unsigned condition() { return m_opcode >> 28; } - unsigned uBit() { return (m_opcode >> 23) & 0x1; } - unsigned rn() { return (m_opcode >> 16) & 0xf; } - unsigned vd() { return ((m_opcode >> 18) & 0x10) | ((m_opcode >> 12) & 0xf); } - bool doubleReg() { return !!(m_opcode & 0x100); } - unsigned immediate8() { return m_opcode & 0xff; } -}; - -class ARMv7DOpcodeVMOVDoublePrecision : public ARMv7D32BitOpcode { -public: - static const uint32_t s_mask = 0xffe00fd0; - static const uint32_t s_pattern = 0xec400b10; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeVMOVDoublePrecision, thisObj); - -protected: - const char* format(); - - unsigned op() { return (m_opcode >> 20) & 0x1; } - unsigned rt2() { return (m_opcode >> 16) & 0xf; } - unsigned rt() { return (m_opcode >> 16) & 0xf; } - unsigned vm() { return (m_opcode & 0xf) | ((m_opcode >> 1) & 0x10); } -}; - -class ARMv7DOpcodeVMOVSinglePrecision : public ARMv7D32BitOpcode { -public: - static const uint32_t s_mask = 0xffe00fd0; - static const uint32_t s_pattern = 0xec400a10; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeVMOVSinglePrecision, thisObj); - -protected: - const char* format(); - - unsigned op() { return (m_opcode >> 20) & 0x1; } - unsigned rt2() { return (m_opcode >> 16) & 0xf; } - unsigned rt() { return (m_opcode >> 16) & 0xf; } - unsigned vm() { return ((m_opcode << 1) & 0x1e) | ((m_opcode >> 5) & 0x1); } -}; - -class ARMv7DOpcodeVMSR : public ARMv7D32BitOpcode { -public: - static const uint32_t s_mask = 0xffef0fff; - static const uint32_t s_pattern = 0xeee10a10; - - DEFINE_STATIC_FORMAT32(ARMv7DOpcodeVMSR, thisObj); - -protected: - const char* format(); - - unsigned opL() { return (m_opcode >> 20) & 0x1; } - unsigned rt() { return (m_opcode >> 12) & 0xf; } -}; - - -} } // namespace JSC::ARMv7Disassembler - -using JSC::ARMv7Disassembler::ARMv7DOpcode; - -#endif // #if USE(ARMV7_DISASSEMBLER) - -#endif // ARMv7DOpcode_h |