Add support for showing disassembled ARM JIT code
authorSimon Hausmann <simon.hausmann@digia.com>
Thu, 3 Oct 2013 11:03:18 +0000 (13:03 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Thu, 10 Oct 2013 19:50:45 +0000 (21:50 +0200)
Ported the ARM disassembler from upstream trunk. QtQml needs to be configured
with qmake CONFIG+=disassembler and QV4_SHOW_ASM=1 enables the dump at
run-time.

Change-Id: Ia13a98835829fde0d3c5a795cb8f6ef9de951807
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
src/3rdparty/masm/disassembler/ARMv7/ARMv7DOpcode.cpp [new file with mode: 0644]
src/3rdparty/masm/disassembler/ARMv7/ARMv7DOpcode.h [new file with mode: 0644]
src/3rdparty/masm/disassembler/ARMv7Disassembler.cpp [new file with mode: 0644]
src/3rdparty/masm/masm-defs.pri
src/3rdparty/masm/masm.pri
src/3rdparty/masm/wtf/Platform.h
src/qml/compiler/qv4isel_masm.cpp

diff --git a/src/3rdparty/masm/disassembler/ARMv7/ARMv7DOpcode.cpp b/src/3rdparty/masm/disassembler/ARMv7/ARMv7DOpcode.cpp
new file mode 100644 (file)
index 0000000..0494873
--- /dev/null
@@ -0,0 +1,1566 @@
+/*
+ * 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", "asl", "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, ARMv7DOpcodeLoadStoreRegisterImmediateHalfWord),
+    OPCODE_GROUP_ENTRY(0x11, ARMv7DOpcodeLoadStoreRegisterImmediateHalfWord),
+    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(0x5, ARMv7DOpcodeDataProcessingShiftedReg),
+    OPCODE_GROUP_ENTRY(0x6, ARMv7DOpcodeVMOVSinglePrecision),
+    OPCODE_GROUP_ENTRY(0x6, ARMv7DOpcodeVMOVDoublePrecision),
+    OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeFPTransfer),
+    OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeVMSR),
+    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, 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),
+};
+
+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 & 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;
+}
+
+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;
+}
+
+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* 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/src/3rdparty/masm/disassembler/ARMv7/ARMv7DOpcode.h b/src/3rdparty/masm/disassembler/ARMv7/ARMv7DOpcode.h
new file mode 100644 (file)
index 0000000..0b84842
--- /dev/null
@@ -0,0 +1,1142 @@
+/*
+ * 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:
+    static const unsigned RegSP = 0xd;
+    static const unsigned RegLR = 0xe;
+    static 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) & 0x3; }
+    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() { return 2 - (op() >> 1); }
+};
+
+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 ARMv7DOpcodeLoadStoreRegisterImmediateHalfWord : public ARMv7DOpcodeLoadStoreRegisterImmediate {
+public:
+    static const uint16_t s_mask = 0xf800;
+    static const uint16_t s_pattern = 0x8000;
+
+    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 & 0x7f); }
+};
+
+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 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 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
diff --git a/src/3rdparty/masm/disassembler/ARMv7Disassembler.cpp b/src/3rdparty/masm/disassembler/ARMv7Disassembler.cpp
new file mode 100644 (file)
index 0000000..bfb4895
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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"
+#include "Disassembler.h"
+
+#if USE(ARMV7_DISASSEMBLER)
+
+#include "ARMv7/ARMv7DOpcode.h"
+#include "MacroAssemblerCodeRef.h"
+
+namespace JSC {
+
+bool tryToDisassemble(const MacroAssemblerCodePtr& codePtr, size_t size, const char* prefix, PrintStream& out)
+{
+    ARMv7DOpcode armOpcode;
+
+    uint16_t* currentPC = reinterpret_cast<uint16_t*>(reinterpret_cast<uintptr_t>(codePtr.executableAddress())&~1);
+    uint16_t* endPC = currentPC + (size / sizeof(uint16_t));
+
+    while (currentPC < endPC) {
+        char pcString[12];
+        snprintf(pcString, sizeof(pcString), "0x%x", reinterpret_cast<unsigned>(currentPC));
+        out.printf("%s%10s: %s\n", prefix, pcString, armOpcode.disassemble(currentPC));
+    }
+
+    return true;
+}
+
+} // namespace JSC
+
+#endif // USE(ARMV7_DISASSEMBLER)
+
index ef9f79a..aa6acc9 100644 (file)
@@ -35,8 +35,12 @@ INCLUDEPATH += $$PWD/stubs
 INCLUDEPATH += $$PWD/stubs/wtf
 INCLUDEPATH += $$PWD
 
-disassembler:if(isEqual(QT_ARCH, "i386")|isEqual(QT_ARCH, "x86_64")):!win*: DEFINES += WTF_USE_UDIS86=1
-else: DEFINES += WTF_USE_UDIS86=0
+disassembler {
+    if(isEqual(QT_ARCH, "i386")|isEqual(QT_ARCH, "x86_64")):!win*: DEFINES += WTF_USE_UDIS86=1
+    if(isEqual(QT_ARCH, "arm")):contains(DEFINES, V4_ENABLE_JIT): DEFINES += WTF_USE_ARMV7_DISASSEMBLER=1
+} else {
+    DEFINES += WTF_USE_UDIS86=0
+}
 
 INCLUDEPATH += $$PWD/disassembler
 INCLUDEPATH += $$PWD/disassembler/udis86
index 99c364e..63537f2 100644 (file)
@@ -59,6 +59,11 @@ contains(DEFINES, WTF_USE_UDIS86=1) {
     QMAKE_EXTRA_TARGETS += udis86_tab_cfile
 }
 
+# We can always compile these, they have ifdef guards inside
+SOURCES += $$PWD/disassembler/ARMv7Disassembler.cpp
+SOURCES += $$PWD/disassembler/ARMv7/ARMv7DOpcode.cpp
+HEADERS += $$PWD/disassembler/ARMv7/ARMv7DOpcode.h
+
 SOURCES += $$PWD/yarr/*.cpp
 HEADERS += $$PWD/yarr/*.h
 
index 68f6f66..b8402a9 100644 (file)
 #define WTF_USE_UDIS86 1
 #endif
 
-#if !defined(ENABLE_DISASSEMBLER) && USE(UDIS86)
+#if !defined(ENABLE_DISASSEMBLER) && (USE(UDIS86) || USE(ARMV7_DISASSEMBLER))
 #define ENABLE_DISASSEMBLER 1
 #endif
 
index 2665356..7df64b3 100644 (file)
@@ -611,7 +611,7 @@ JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize)
 #  if OS(MAC_OS_X)
         char *disasmOutput = memStream.buf.data();
 #  endif
-#  if CPU(X86) || CPU(X86_64)
+#  if CPU(X86) || CPU(X86_64) || CPU(ARM)
         QHash<void*, String*> idents;
         printDisassembledOutputWithCalls(disasmOutput, functions);
 #  endif