aboutsummaryrefslogtreecommitdiffstats
path: root/src/3rdparty/masm/disassembler
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@digia.com>2016-01-14 15:39:17 +0100
committerErik Verbruggen <erik.verbruggen@theqtcompany.com>2016-01-19 11:19:38 +0000
commitf8bcf723ce920981705c6913fffb1f4d3de6793d (patch)
treed0bced1e1e422c32d3f148c1ded7846063fb25f6 /src/3rdparty/masm/disassembler
parent9876f7ac8bd3679a9ed0e617aaadad032403a88f (diff)
V4: add Aarch64/ARM64 support.
This uses the JavaScriptCore assembler rev. 195098. It is tested on iOS (for which it is disabled, as it only allows marking pages as executable when running from Xcode). Testing on Linux will be done when hardware arrives. Change-Id: I650e15fec03c27d4b326a2d70863a89b85cfc5c3 Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
Diffstat (limited to 'src/3rdparty/masm/disassembler')
-rw-r--r--src/3rdparty/masm/disassembler/ARM64/A64DOpcode.cpp1202
-rw-r--r--src/3rdparty/masm/disassembler/ARM64/A64DOpcode.h708
-rw-r--r--src/3rdparty/masm/disassembler/ARM64Disassembler.cpp72
-rw-r--r--src/3rdparty/masm/disassembler/ARMv7/ARMv7DOpcode.cpp2
-rw-r--r--src/3rdparty/masm/disassembler/ARMv7/ARMv7DOpcode.h2
-rw-r--r--src/3rdparty/masm/disassembler/ARMv7Disassembler.cpp2
6 files changed, 1986 insertions, 2 deletions
diff --git a/src/3rdparty/masm/disassembler/ARM64/A64DOpcode.cpp b/src/3rdparty/masm/disassembler/ARM64/A64DOpcode.cpp
new file mode 100644
index 0000000000..52a92c669c
--- /dev/null
+++ b/src/3rdparty/masm/disassembler/ARM64/A64DOpcode.cpp
@@ -0,0 +1,1202 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#define __STDC_FORMAT_MACROS
+#include "config.h"
+
+#if USE(ARM64_DISASSEMBLER)
+
+#include "A64DOpcode.h"
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+
+namespace JSC { namespace ARM64Disassembler {
+
+A64DOpcode::OpcodeGroup* A64DOpcode::opcodeTable[32];
+
+const char* const A64DOpcode::s_conditionNames[16] = {
+ "eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
+ "hi", "ls", "ge", "lt", "gt", "le", "al", "ne"
+};
+
+const char* const A64DOpcode::s_optionName[8] = {
+ "uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx"
+};
+
+const char* const A64DOpcode::s_shiftNames[4] = {
+ "lsl", "lsr", "asl", "ror"
+};
+
+const char A64DOpcode::s_FPRegisterPrefix[5] = {
+ 'b', 'h', 's', 'd', 'q'
+};
+
+struct OpcodeGroupInitializer {
+ unsigned m_opcodeGroupNumber;
+ uint32_t m_mask;
+ uint32_t m_pattern;
+ const char* (*m_format)(A64DOpcode*);
+};
+
+#define OPCODE_GROUP_ENTRY(groupIndex, groupClass) \
+{ groupIndex, groupClass::mask, groupClass::pattern, groupClass::format }
+
+static OpcodeGroupInitializer opcodeGroupList[] = {
+ OPCODE_GROUP_ENTRY(0x08, A64DOpcodeLoadStoreRegisterPair),
+ OPCODE_GROUP_ENTRY(0x09, A64DOpcodeLoadStoreRegisterPair),
+ OPCODE_GROUP_ENTRY(0x0a, A64DOpcodeLogicalShiftedRegister),
+ OPCODE_GROUP_ENTRY(0x0b, A64DOpcodeAddSubtractExtendedRegister),
+ OPCODE_GROUP_ENTRY(0x0b, A64DOpcodeAddSubtractShiftedRegister),
+ OPCODE_GROUP_ENTRY(0x11, A64DOpcodeAddSubtractImmediate),
+ OPCODE_GROUP_ENTRY(0x12, A64DOpcodeMoveWide),
+ OPCODE_GROUP_ENTRY(0x12, A64DOpcodeLogicalImmediate),
+ OPCODE_GROUP_ENTRY(0x13, A64DOpcodeBitfield),
+ OPCODE_GROUP_ENTRY(0x13, A64DOpcodeExtract),
+ OPCODE_GROUP_ENTRY(0x14, A64DOpcodeUnconditionalBranchImmediate),
+ OPCODE_GROUP_ENTRY(0x14, A64DOpcodeConditionalBranchImmediate),
+ OPCODE_GROUP_ENTRY(0x14, A64DOpcodeCompareAndBranchImmediate),
+ OPCODE_GROUP_ENTRY(0x14, A64OpcodeExceptionGeneration),
+ OPCODE_GROUP_ENTRY(0x15, A64DOpcodeUnconditionalBranchImmediate),
+ OPCODE_GROUP_ENTRY(0x15, A64DOpcodeConditionalBranchImmediate),
+ OPCODE_GROUP_ENTRY(0x15, A64DOpcodeCompareAndBranchImmediate),
+ OPCODE_GROUP_ENTRY(0x15, A64DOpcodeHint),
+ OPCODE_GROUP_ENTRY(0x16, A64DOpcodeUnconditionalBranchImmediate),
+ OPCODE_GROUP_ENTRY(0x16, A64DOpcodeUnconditionalBranchRegister),
+ OPCODE_GROUP_ENTRY(0x16, A64DOpcodeTestAndBranchImmediate),
+ OPCODE_GROUP_ENTRY(0x17, A64DOpcodeUnconditionalBranchImmediate),
+ OPCODE_GROUP_ENTRY(0x17, A64DOpcodeUnconditionalBranchRegister),
+ OPCODE_GROUP_ENTRY(0x17, A64DOpcodeTestAndBranchImmediate),
+ OPCODE_GROUP_ENTRY(0x18, A64DOpcodeLoadStoreImmediate),
+ OPCODE_GROUP_ENTRY(0x18, A64DOpcodeLoadStoreRegisterOffset),
+ OPCODE_GROUP_ENTRY(0x19, A64DOpcodeLoadStoreUnsignedImmediate),
+ OPCODE_GROUP_ENTRY(0x1a, A64DOpcodeConditionalSelect),
+ OPCODE_GROUP_ENTRY(0x1a, A64DOpcodeDataProcessing2Source),
+ OPCODE_GROUP_ENTRY(0x1b, A64DOpcodeDataProcessing3Source),
+ OPCODE_GROUP_ENTRY(0x1c, A64DOpcodeLoadStoreImmediate),
+ OPCODE_GROUP_ENTRY(0x1c, A64DOpcodeLoadStoreRegisterOffset),
+ OPCODE_GROUP_ENTRY(0x1d, A64DOpcodeLoadStoreUnsignedImmediate),
+ OPCODE_GROUP_ENTRY(0x1e, A64DOpcodeFloatingPointCompare),
+ OPCODE_GROUP_ENTRY(0x1e, A64DOpcodeFloatingPointDataProcessing2Source),
+ OPCODE_GROUP_ENTRY(0x1e, A64DOpcodeFloatingPointDataProcessing1Source),
+ OPCODE_GROUP_ENTRY(0x1e, A64DOpcodeFloatingFixedPointConversions),
+ OPCODE_GROUP_ENTRY(0x1e, A64DOpcodeFloatingPointIntegerConversions),
+};
+
+bool A64DOpcode::s_initialized = false;
+
+void A64DOpcode::init()
+{
+ if (s_initialized)
+ return;
+
+ OpcodeGroup* lastGroups[32];
+
+ for (unsigned i = 0; i < 32; i++) {
+ opcodeTable[i] = 0;
+ lastGroups[i] = 0;
+ }
+
+ for (unsigned i = 0; i < sizeof(opcodeGroupList) / sizeof(struct OpcodeGroupInitializer); i++) {
+ OpcodeGroup* newOpcodeGroup = new OpcodeGroup(opcodeGroupList[i].m_mask, opcodeGroupList[i].m_pattern, opcodeGroupList[i].m_format);
+ uint32_t opcodeGroupNumber = opcodeGroupList[i].m_opcodeGroupNumber;
+
+ if (!opcodeTable[opcodeGroupNumber])
+ opcodeTable[opcodeGroupNumber] = newOpcodeGroup;
+ else
+ lastGroups[opcodeGroupNumber]->setNext(newOpcodeGroup);
+ lastGroups[opcodeGroupNumber] = newOpcodeGroup;
+ }
+
+ s_initialized = true;
+}
+
+void A64DOpcode::setPCAndOpcode(uint32_t* newPC, uint32_t newOpcode)
+{
+ m_currentPC = newPC;
+ m_opcode = newOpcode;
+ m_bufferOffset = 0;
+ m_formatBuffer[0] = '\0';
+}
+
+const char* A64DOpcode::disassemble(uint32_t* currentPC)
+{
+ setPCAndOpcode(currentPC, *currentPC);
+
+ OpcodeGroup* opGroup = opcodeTable[opcodeGroupNumber(m_opcode)];
+
+ while (opGroup) {
+ if (opGroup->matches(m_opcode))
+ return opGroup->format(this);
+ opGroup = opGroup->next();
+ }
+
+ return A64DOpcode::format();
+}
+
+void A64DOpcode::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);
+}
+
+const char* A64DOpcode::format()
+{
+ bufferPrintf(" .long %08x", m_opcode);
+ return m_formatBuffer;
+}
+
+void A64DOpcode::appendRegisterName(unsigned registerNumber, bool is64Bit)
+{
+ if (registerNumber == 29) {
+ bufferPrintf(is64Bit ? "fp" : "wfp");
+ return;
+ }
+
+ if (registerNumber == 30) {
+ bufferPrintf(is64Bit ? "lr" : "wlr");
+ return;
+ }
+
+ bufferPrintf("%c%u", is64Bit ? 'x' : 'w', registerNumber);
+}
+
+void A64DOpcode::appendFPRegisterName(unsigned registerNumber, unsigned registerSize)
+{
+ bufferPrintf("%c%u", FPRegisterPrefix(registerSize), registerNumber);
+}
+
+const char* const A64DOpcodeAddSubtract::s_opNames[4] = { "add", "adds", "sub", "subs" };
+
+const char* A64DOpcodeAddSubtractImmediate::format()
+{
+ if (isCMP())
+ appendInstructionName(cmpName());
+ else {
+ if (isMovSP())
+ appendInstructionName("mov");
+ else
+ appendInstructionName(opName());
+ appendSPOrRegisterName(rd(), is64Bit());
+ appendSeparator();
+ }
+ appendSPOrRegisterName(rn(), is64Bit());
+
+ if (!isMovSP()) {
+ appendSeparator();
+ appendUnsignedImmediate(immed12());
+ if (shift()) {
+ appendSeparator();
+ appendString(shift() == 1 ? "lsl" : "reserved");
+ }
+ }
+ return m_formatBuffer;
+}
+
+const char* A64DOpcodeAddSubtractExtendedRegister::format()
+{
+ if (immediate3() > 4)
+ return A64DOpcode::format();
+
+ if (isCMP())
+ appendInstructionName(cmpName());
+ else {
+ appendInstructionName(opName());
+ appendSPOrRegisterName(rd(), is64Bit());
+ appendSeparator();
+ }
+ appendSPOrRegisterName(rn(), is64Bit());
+ appendSeparator();
+ appendZROrRegisterName(rm(), is64Bit() && ((option() & 0x3) == 0x3));
+ appendSeparator();
+ if (option() == 0x2 && ((rd() == 31) || (rn() == 31)))
+ appendString("lsl");
+ else
+ appendString(optionName());
+ if (immediate3()) {
+ appendCharacter(' ');
+ appendUnsignedImmediate(immediate3());
+ }
+
+ return m_formatBuffer;
+}
+
+const char* A64DOpcodeAddSubtractShiftedRegister::format()
+{
+ if (!is64Bit() && immediate6() & 0x20)
+ return A64DOpcode::format();
+
+ if (shift() == 0x3)
+ return A64DOpcode::format();
+
+ if (isCMP())
+ appendInstructionName(cmpName());
+ else {
+ if (isNeg())
+ appendInstructionName(cmpName());
+ else
+ appendInstructionName(opName());
+ appendSPOrRegisterName(rd(), is64Bit());
+ appendSeparator();
+ }
+ if (!isNeg()) {
+ appendRegisterName(rn(), is64Bit());
+ appendSeparator();
+ }
+ appendZROrRegisterName(rm(), is64Bit());
+ if (immediate6()) {
+ appendSeparator();
+ appendShiftType(shift());
+ appendUnsignedImmediate(immediate6());
+ }
+
+ return m_formatBuffer;
+}
+
+const char* const A64DOpcodeBitfield::s_opNames[3] = { "sbfm", "bfm", "ubfm" };
+const char* const A64DOpcodeBitfield::s_extendPseudoOpNames[3][3] = {
+ { "sxtb", "sxth", "sxtw" }, { 0, 0, 0} , { "uxtb", "uxth", "uxtw" } };
+const char* const A64DOpcodeBitfield::s_insertOpNames[3] = { "sbfiz", "bfi", "ubfiz" };
+const char* const A64DOpcodeBitfield::s_extractOpNames[3] = { "sbfx", "bf", "ubfx" };
+
+const char* A64DOpcodeBitfield::format()
+{
+ if (opc() == 0x3)
+ return A64DOpcode::format();
+
+ if (is64Bit() != nBit())
+ return A64DOpcode::format();
+
+ if (!is64Bit() && ((immediateR() & 0x20) || (immediateS() & 0x20)))
+ return A64DOpcode::format();
+
+ if (!(opc() & 0x1) && !immediateR()) {
+ // [un]signed {btye,half-word,word} extend
+ bool isSTXType = false;
+ if (immediateS() == 7) {
+ appendInstructionName(extendPseudoOpNames(0));
+ isSTXType = true;
+ } else if (immediateS() == 15) {
+ appendInstructionName(extendPseudoOpNames(1));
+ isSTXType = true;
+ } else if (immediateS() == 31 && is64Bit()) {
+ appendInstructionName(extendPseudoOpNames(2));
+ isSTXType = true;
+ }
+
+ if (isSTXType) {
+ appendRegisterName(rd(), is64Bit());
+ appendSeparator();
+ appendRegisterName(rn(), false);
+
+ return m_formatBuffer;
+ }
+ }
+
+ if (opc() == 0x2 && immediateS() == (immediateR() + 1)) {
+ // lsl
+ appendInstructionName("lsl");
+ appendRegisterName(rd(), is64Bit());
+ appendSeparator();
+ appendRegisterName(rn(), is64Bit());
+ appendSeparator();
+ appendUnsignedImmediate((is64Bit() ? 63u : 31u) - immediateR());
+
+ return m_formatBuffer;
+ } else if (!(opc() & 0x1) && ((immediateS() & 0x1f) == 0x1f) && (is64Bit() == (immediateS() >> 5))) {
+ // asr/lsr
+ appendInstructionName(!opc() ? "ars" : "lsr");
+
+ appendRegisterName(rd(), is64Bit());
+ appendSeparator();
+ appendRegisterName(rn(), is64Bit());
+ appendSeparator();
+ appendUnsignedImmediate(immediateR());
+
+ return m_formatBuffer;
+ } else if (immediateS() < immediateR()) {
+ // bit field insert
+ appendInstructionName(insertOpNames());
+
+ appendRegisterName(rd(), is64Bit());
+ appendSeparator();
+ appendRegisterName(rn(), is64Bit());
+ appendSeparator();
+ appendUnsignedImmediate((is64Bit() ? 64u : 32u) - immediateR());
+ appendSeparator();
+ appendUnsignedImmediate(immediateS() + 1);
+
+ return m_formatBuffer;
+ } else {
+ // bit field extract
+ appendInstructionName(extractOpNames());
+
+ appendRegisterName(rd(), is64Bit());
+ appendSeparator();
+ appendRegisterName(rn(), is64Bit());
+ appendSeparator();
+ appendUnsignedImmediate(immediateR());
+ appendSeparator();
+ appendUnsignedImmediate(immediateS() - immediateR() + 1);
+
+ return m_formatBuffer;
+ }
+
+ appendInstructionName(opName());
+ appendRegisterName(rd(), is64Bit());
+ appendSeparator();
+ appendRegisterName(rn(), is64Bit());
+ appendSeparator();
+ appendUnsignedImmediate(immediateR());
+ appendSeparator();
+ appendUnsignedImmediate(immediateS());
+
+ return m_formatBuffer;
+}
+
+const char* A64DOpcodeCompareAndBranchImmediate::format()
+{
+ appendInstructionName(opBit() ? "cbnz" : "cbz");
+ appendRegisterName(rt(), is64Bit());
+ appendSeparator();
+ appendPCRelativeOffset(m_currentPC, static_cast<int32_t>(immediate19()));
+ return m_formatBuffer;
+}
+
+const char* A64DOpcodeConditionalBranchImmediate::format()
+{
+ bufferPrintf(" b.%-5.5s", conditionName(condition()));
+ appendPCRelativeOffset(m_currentPC, static_cast<int32_t>(immediate19()));
+ return m_formatBuffer;
+}
+
+const char* const A64DOpcodeConditionalSelect::s_opNames[4] = {
+ "csel", "csinc", "csinv", "csneg"
+};
+
+const char* A64DOpcodeConditionalSelect::format()
+{
+ if (sBit())
+ return A64DOpcode::format();
+
+ if (op2() & 0x2)
+ return A64DOpcode::format();
+
+ if (rn() == rm() && (opNum() == 1 || opNum() == 2)) {
+ if (rn() == 31) {
+ appendInstructionName((opNum() == 1) ? "cset" : "csetm");
+ appendRegisterName(rd(), is64Bit());
+ } else {
+ appendInstructionName((opNum() == 1) ? "cinc" : "cinv");
+ appendRegisterName(rd(), is64Bit());
+ appendSeparator();
+ appendZROrRegisterName(rn(), is64Bit());
+ }
+ appendSeparator();
+ appendString(conditionName(condition() ^ 0x1));
+
+ return m_formatBuffer;
+ }
+
+ appendInstructionName(opName());
+ appendRegisterName(rd(), is64Bit());
+ appendSeparator();
+ appendZROrRegisterName(rn(), is64Bit());
+ appendSeparator();
+ appendZROrRegisterName(rm(), is64Bit());
+ appendSeparator();
+ appendString(conditionName(condition()));
+
+ return m_formatBuffer;
+
+}
+
+const char* const A64DOpcodeDataProcessing2Source::s_opNames[8] = {
+ 0, 0, "udiv", "sdiv", "lsl", "lsr", "asr", "ror" // We use the pseudo-op names for the shift/rotate instructions
+};
+
+const char* A64DOpcodeDataProcessing2Source::format()
+{
+ if (sBit())
+ return A64DOpcode::format();
+
+ if (!(opCode() & 0x3e))
+ return A64DOpcode::format();
+
+ if (opCode() & 0x30)
+ return A64DOpcode::format();
+
+ if ((opCode() & 0x34) == 0x4)
+ return A64DOpcode::format();
+
+ appendInstructionName(opName());
+ appendRegisterName(rd(), is64Bit());
+ appendSeparator();
+ appendRegisterName(rn(), is64Bit());
+ appendSeparator();
+ appendRegisterName(rm(), is64Bit());
+
+ return m_formatBuffer;
+}
+
+const char* const A64DOpcodeDataProcessing3Source::s_opNames[16] = {
+ "madd", "msub", "smaddl", "smsubl", "smulh", 0, 0, 0,
+ 0, 0, "umaddl", "umsubl", "umulh", 0, 0, 0
+};
+
+const char* const A64DOpcodeDataProcessing3Source::s_pseudoOpNames[16] = {
+ "mul", "mneg", "smull", "smnegl", "smulh", 0, 0, 0,
+ 0, 0, "umull", "umnegl", "umulh", 0, 0, 0
+};
+
+const char* A64DOpcodeDataProcessing3Source::format()
+{
+ if (op54())
+ return A64DOpcode::format();
+
+ if (opNum() > 12)
+ return A64DOpcode::format();
+
+ if (!is64Bit() && opNum() > 1)
+ return A64DOpcode::format();
+
+ if (!opName())
+ return A64DOpcode::format();
+
+ appendInstructionName(opName());
+ appendRegisterName(rd(), is64Bit());
+ appendSeparator();
+ bool srcOneAndTwoAre64Bit = is64Bit() & !(opNum() & 0x2);
+ appendRegisterName(rn(), srcOneAndTwoAre64Bit);
+ appendSeparator();
+ appendRegisterName(rm(), srcOneAndTwoAre64Bit);
+
+ if ((ra() != 31) || !(opNum() & 0x4)) {
+ appendSeparator();
+ appendRegisterName(ra(), is64Bit());
+ }
+
+ return m_formatBuffer;
+}
+
+const char* A64OpcodeExceptionGeneration::format()
+{
+ const char* opname = 0;
+ if (!op2()) {
+ switch (opc()) {
+ case 0x0: // SVC, HVC & SMC
+ switch (ll()) {
+ case 0x1:
+ opname = "svc";
+ break;
+ case 0x2:
+ opname = "hvc";
+ break;
+ case 0x3:
+ opname = "smc";
+ break;
+ }
+ break;
+ case 0x1: // BRK
+ if (!ll())
+ opname = "brk";
+ break;
+ case 0x2: // HLT
+ if (!ll())
+ opname = "hlt";
+ break;
+ case 0x5: // DPCS1-3
+ switch (ll()) {
+ case 0x1:
+ opname = "dpcs1";
+ break;
+ case 0x2:
+ opname = "dpcs2";
+ break;
+ case 0x3:
+ opname = "dpcs3";
+ break;
+ }
+ break;
+ }
+ }
+
+ if (!opname)
+ return A64DOpcode::format();
+
+ appendInstructionName(opname);
+ appendUnsignedImmediate(immediate16());
+ return m_formatBuffer;
+}
+
+const char* A64DOpcodeExtract::format()
+{
+ if (!op21() || !o0Bit())
+ return A64DOpcode::format();
+
+ if (is64Bit() != nBit())
+ return A64DOpcode::format();
+
+ if (is64Bit() && (immediateS() & 0x20))
+ return A64DOpcode::format();
+
+ const char* opName = (rn() == rm()) ? "ror" : "extr";
+
+ appendInstructionName(opName);
+ appendRegisterName(rd(), is64Bit());
+ appendSeparator();
+ appendRegisterName(rn(), is64Bit());
+ appendSeparator();
+ appendRegisterName(rm(), is64Bit());
+ appendSeparator();
+ appendUnsignedImmediate(immediateS());
+
+ return m_formatBuffer;
+}
+
+const char* A64DOpcodeFloatingPointCompare::format()
+{
+ if (mBit())
+ return A64DOpcode::format();
+
+ if (sBit())
+ return A64DOpcode::format();
+
+ if (type() & 0x2)
+ return A64DOpcode::format();
+
+ if (op())
+ return A64DOpcode::format();
+
+ if (opCode2() & 0x7)
+ return A64DOpcode::format();
+
+ appendInstructionName(opName());
+ unsigned registerSize = type() + 2;
+ appendFPRegisterName(rn(), registerSize);
+ appendSeparator();
+ if (opCode2() & 0x8)
+ bufferPrintf("#0.0");
+ else
+ appendFPRegisterName(rm(), registerSize);
+
+ return m_formatBuffer;
+}
+
+const char* const A64DOpcodeFloatingPointDataProcessing1Source::s_opNames[16] = {
+ "fmov", "fabs", "fneg", "fsqrt", "fcvt", "fcvt", 0, "fcvt",
+ "frintn", "frintp", "frintm", "frintz", "frinta", 0, "frintx", "frinti"
+};
+
+const char* A64DOpcodeFloatingPointDataProcessing1Source::format()
+{
+ if (mBit())
+ return A64DOpcode::format();
+
+ if (sBit())
+ return A64DOpcode::format();
+
+ if (opNum() > 16)
+ return A64DOpcode::format();
+
+ switch (type()) {
+ case 0:
+ if ((opNum() == 0x4) || (opNum() == 0x6) || (opNum() == 0xd))
+ return A64DOpcode::format();
+ break;
+ case 1:
+ if ((opNum() == 0x5) || (opNum() == 0x6) || (opNum() == 0xd))
+ return A64DOpcode::format();
+ break;
+ case 2:
+ return A64DOpcode::format();
+ case 3:
+ if ((opNum() < 0x4) || (opNum() > 0x5))
+ return A64DOpcode::format();
+ break;
+ }
+
+ appendInstructionName(opName());
+ if ((opNum() >= 0x4) && (opNum() <= 0x7)) {
+ unsigned srcRegisterSize = type() ^ 0x2; // 0:s, 1:d & 3:h
+ unsigned destRegisterSize = (opNum() & 0x3) ^ 0x2;
+ appendFPRegisterName(rd(), destRegisterSize);
+ appendSeparator();
+ appendFPRegisterName(rn(), srcRegisterSize);
+ } else {
+ unsigned registerSize = type() + 2;
+ appendFPRegisterName(rd(), registerSize);
+ appendSeparator();
+ appendFPRegisterName(rn(), registerSize);
+ }
+
+ return m_formatBuffer;
+}
+
+const char* const A64DOpcodeFloatingPointDataProcessing2Source::s_opNames[16] = {
+ "fmul", "fdiv", "fadd", "fsub", "fmax", "fmin", "fmaxnm", "fminnm", "fnmul"
+};
+
+const char* A64DOpcodeFloatingPointDataProcessing2Source::format()
+{
+ if (mBit())
+ return A64DOpcode::format();
+
+ if (sBit())
+ return A64DOpcode::format();
+
+ if (type() & 0x2)
+ return A64DOpcode::format();
+
+ if (opNum() > 8)
+ return A64DOpcode::format();
+
+ appendInstructionName(opName());
+ unsigned registerSize = type() + 2;
+ appendFPRegisterName(rd(), registerSize);
+ appendSeparator();
+ appendFPRegisterName(rn(), registerSize);
+ appendSeparator();
+ appendFPRegisterName(rm(), registerSize);
+
+ return m_formatBuffer;
+}
+
+const char* const A64DOpcodeFloatingFixedPointConversions::s_opNames[4] = {
+ "fcvtzs", "fcvtzu", "scvtf", "ucvtf"
+};
+
+const char* A64DOpcodeFloatingFixedPointConversions::format()
+{
+ if (sBit())
+ return A64DOpcode::format();
+
+ if (type() & 0x2)
+ return A64DOpcode::format();
+
+ if (opcode() & 0x4)
+ return A64DOpcode::format();
+
+ if (!(rmode() & 0x1) && !(opcode() & 0x6))
+ return A64DOpcode::format();
+
+ if ((rmode() & 0x1) && (opcode() & 0x6) == 0x2)
+ return A64DOpcode::format();
+
+ if (!(rmode() & 0x2) && !(opcode() & 0x6))
+ return A64DOpcode::format();
+
+ if ((rmode() & 0x2) && (opcode() & 0x6) == 0x2)
+ return A64DOpcode::format();
+
+ if (!is64Bit() && scale() >= 32)
+ return A64DOpcode::format();
+
+ appendInstructionName(opName());
+ unsigned FPRegisterSize = type() + 2;
+ bool destIsFP = !rmode();
+
+ if (destIsFP) {
+ appendFPRegisterName(rd(), FPRegisterSize);
+ appendSeparator();
+ appendRegisterName(rn(), is64Bit());
+ } else {
+ appendRegisterName(rd(), is64Bit());
+ appendSeparator();
+ appendFPRegisterName(rn(), FPRegisterSize);
+ }
+ appendSeparator();
+ appendUnsignedImmediate(64 - scale());
+
+ return m_formatBuffer;
+}
+
+const char* const A64DOpcodeFloatingPointIntegerConversions::s_opNames[32] = {
+ "fcvtns", "fcvtnu", "scvtf", "ucvtf", "fcvtas", "fcvtau", "fmov", "fmov",
+ "fcvtps", "fcvtpu", 0, 0, 0, 0, "fmov", "fmov",
+ "fcvtms", "fcvtmu", 0, 0, 0, 0, 0, 0,
+ "fcvtzs", "fcvtzu", 0, 0, 0, 0, 0, 0
+};
+
+const char* A64DOpcodeFloatingPointIntegerConversions::format()
+{
+ if (sBit())
+ return A64DOpcode::format();
+
+ if (type() == 0x3)
+ return A64DOpcode::format();
+
+ if (((rmode() & 0x1) || (rmode() & 0x2)) && (((opcode() & 0x6) == 0x2) || ((opcode() & 0x6) == 0x4)))
+ return A64DOpcode::format();
+
+ if ((type() == 0x2) && (!(opcode() & 0x4) || ((opcode() & 0x6) == 0x4)))
+ return A64DOpcode::format();
+
+ if (!type() && (rmode() & 0x1) && ((opcode() & 0x6) == 0x6))
+ return A64DOpcode::format();
+
+ if (is64Bit() && type() == 0x2 && ((opNum() & 0xe) == 0x6))
+ return A64DOpcode::format();
+
+ if (!opName())
+ return A64DOpcode::format();
+
+ if ((opNum() & 0x1e) == 0xe) {
+ // Handle fmov to/from upper half of quad separately
+ if (!is64Bit() || (type() != 0x2))
+ return A64DOpcode::format();
+
+ appendInstructionName(opName());
+ if (opcode() & 0x1) {
+ // fmov Vd.D[1], Xn
+ bufferPrintf("V%u.D[1]", rd());
+ appendSeparator();
+ appendRegisterName(rn());
+ } else {
+ // fmov Xd, Vn.D[1]
+ appendRegisterName(rd());
+ appendSeparator();
+ bufferPrintf("V%u.D[1]", rn());
+ }
+
+ return m_formatBuffer;
+ }
+
+ appendInstructionName(opName());
+ unsigned FPRegisterSize = type() + 2;
+ bool destIsFP = ((opNum() == 2) || (opNum() == 3) || (opNum() == 7));
+
+ if (destIsFP) {
+ appendFPRegisterName(rd(), FPRegisterSize);
+ appendSeparator();
+ appendRegisterName(rn(), is64Bit());
+ } else {
+ appendRegisterName(rd(), is64Bit());
+ appendSeparator();
+ appendFPRegisterName(rn(), FPRegisterSize);
+ }
+
+ return m_formatBuffer;
+}
+
+const char* const A64DOpcodeHint::s_opNames[6] = {
+ "nop", "yield", "wfe", "wfi", "sev", "sevl"
+};
+
+const char* A64DOpcodeHint::format()
+{
+ appendInstructionName(opName());
+
+ if (immediate7() > 5)
+ appendUnsignedImmediate(immediate7());
+
+ return m_formatBuffer;
+}
+
+// A zero in an entry of the table means the instruction is Unallocated
+const char* const A64DOpcodeLoadStore::s_opNames[32] = {
+ "strb", "ldrb", "ldrsb", "ldrsb", "str", "ldr", "str", "ldr",
+ "strh", "ldrh", "ldrsh", "ldrsh", "str", "ldr", 0, 0,
+ "str", "ldr", "ldrsw", 0, "str", "ldr", 0, 0,
+ "str", "ldr", 0, 0, "str", "ldr", 0, 0
+};
+
+// A zero in an entry of the table means the instruction is Unallocated
+const char* const A64DOpcodeLoadStoreImmediate::s_unprivilegedOpNames[32] = {
+ "sttrb", "ldtrb", "ldtrsb", "ldtrsb", 0, 0, 0, 0,
+ "sttrh", "ldtrh", "ldtrsh", "ldtrsh", 0, 0, 0, 0,
+ "sttr", "ldtr", "ldtrsw", 0, 0, 0, 0, 0,
+ "sttr", "ldtr", 0, 0, 0, 0, 0, 0
+};
+
+// A zero in an entry of the table means the instruction is Unallocated
+const char* const A64DOpcodeLoadStoreImmediate::s_unscaledOpNames[32] = {
+ "sturb", "ldurb", "ldursb", "ldursb", "stur", "ldur", "stur", "ldur",
+ "sturh", "ldurh", "ldursh", "ldursh", "stur", "ldur", 0, 0,
+ "stur", "ldur", "ldursw", 0, "stur", "ldur", 0, 0,
+ "stur", "ldur", "prfum", 0, "stur", "ldur", 0, 0
+};
+
+const char* A64DOpcodeLoadStoreImmediate::format()
+{
+ const char* thisOpName;
+
+ if (type() & 0x1)
+ thisOpName = opName();
+ else if (!type())
+ thisOpName = unscaledOpName();
+ else
+ thisOpName = unprivilegedOpName();
+
+ if (!thisOpName)
+ return A64DOpcode::format();
+
+ appendInstructionName(thisOpName);
+ if (vBit())
+ appendFPRegisterName(rt(), size());
+ else
+ appendRegisterName(rt(), is64BitRT());
+ appendSeparator();
+ appendCharacter('[');
+ appendSPOrRegisterName(rn());
+
+ switch (type()) {
+ case 0: // Unscaled Immediate
+ if (immediate9()) {
+ appendSeparator();
+ appendSignedImmediate(immediate9());
+ }
+ appendCharacter(']');
+ break;
+ case 1: // Immediate Post-Indexed
+ appendCharacter(']');
+ if (immediate9()) {
+ appendSeparator();
+ appendSignedImmediate(immediate9());
+ }
+ break;
+ case 2: // Unprivileged
+ if (immediate9()) {
+ appendSeparator();
+ appendSignedImmediate(immediate9());
+ }
+ appendCharacter(']');
+ break;
+ case 3: // Immediate Pre-Indexed
+ if (immediate9()) {
+ appendSeparator();
+ appendSignedImmediate(immediate9());
+ }
+ appendCharacter(']');
+ appendCharacter('!');
+ break;
+ }
+
+ return m_formatBuffer;
+}
+
+const char* A64DOpcodeLoadStoreRegisterOffset::format()
+{
+ const char* thisOpName = opName();
+
+ if (!thisOpName)
+ return A64DOpcode::format();
+
+ if (!(option() & 0x2))
+ return A64DOpcode::format();
+
+ appendInstructionName(thisOpName);
+ unsigned scale;
+ if (vBit()) {
+ appendFPRegisterName(rt(), size());
+ scale = ((opc() & 2)<<1) | size();
+ } else {
+ appendRegisterName(rt(), is64BitRT());
+ scale = size();
+ }
+ appendSeparator();
+ appendCharacter('[');
+ appendSPOrRegisterName(rn());
+ appendSeparator();
+ appendZROrRegisterName(rm(), (option() & 0x3) == 0x3);
+
+ unsigned shift = sBit() ? scale : 0;
+
+ if (option() == 0x3) {
+ if (shift) {
+ appendSeparator();
+ appendString("lsl ");
+ appendUnsignedImmediate(shift);
+ }
+ } else {
+ appendSeparator();
+ appendString(optionName());
+ if (shift)
+ appendUnsignedImmediate(shift);
+ }
+
+ appendCharacter(']');
+
+ return m_formatBuffer;
+}
+
+const char* A64DOpcodeLoadStoreRegisterPair::opName()
+{
+ if (!vBit() && lBit() && size() == 0x1)
+ return "ldpsw";
+ if (lBit())
+ return "ldp";
+ return "stp";
+}
+
+const char* A64DOpcodeLoadStoreRegisterPair::format()
+{
+ const char* thisOpName = opName();
+
+ if (size() == 0x3)
+ return A64DOpcode::format();
+
+ if ((offsetMode() < 0x1) || (offsetMode() > 0x3))
+ return A64DOpcode::format();
+
+ if ((offsetMode() == 0x1) && !vBit() && !lBit())
+ return A64DOpcode::format();
+
+ appendInstructionName(thisOpName);
+ unsigned offsetShift;
+ if (vBit()) {
+ appendFPRegisterName(rt(), size());
+ appendSeparator();
+ appendFPRegisterName(rt2(), size());
+ offsetShift = size() + 2;
+ } else {
+ appendRegisterName(rt(), is64Bit());
+ appendSeparator();
+ appendRegisterName(rt2(), is64Bit());
+ offsetShift = (size() >> 1) + 2;
+ }
+
+ appendSeparator();
+ appendCharacter('[');
+ appendSPOrRegisterName(rn());
+
+ int offset = immediate7() << offsetShift;
+
+ if (offsetMode() == 1) {
+ appendCharacter(']');
+ appendSeparator();
+ appendSignedImmediate(offset);
+ } else {
+ appendSeparator();
+ appendSignedImmediate(offset);
+ appendCharacter(']');
+ if (offsetMode() == 0x3)
+ appendCharacter('!');
+ }
+
+ return m_formatBuffer;
+}
+
+const char* A64DOpcodeLoadStoreUnsignedImmediate::format()
+{
+ const char* thisOpName = opName();
+
+ if (!thisOpName)
+ return A64DOpcode::format();
+
+ appendInstructionName(thisOpName);
+ unsigned scale;
+ if (vBit()) {
+ appendFPRegisterName(rt(), size());
+ scale = ((opc() & 2)<<1) | size();
+ } else {
+ appendRegisterName(rt(), is64BitRT());
+ scale = size();
+ }
+ appendSeparator();
+ appendCharacter('[');
+ appendSPOrRegisterName(rn());
+
+ if (immediate12()) {
+ appendSeparator();
+ appendUnsignedImmediate(immediate12() << scale);
+ }
+
+ appendCharacter(']');
+
+ return m_formatBuffer;
+}
+
+// A zero in an entry of the table means the instruction is Unallocated
+const char* const A64DOpcodeLogical::s_opNames[8] = {
+ "and", "bic", "orr", "orn", "eor", "eon", "ands", "bics"
+};
+
+const char* A64DOpcodeLogicalShiftedRegister::format()
+{
+ if (!is64Bit() && immediate6() & 0x20)
+ return A64DOpcode::format();
+
+ if (isTst())
+ appendInstructionName("tst");
+ else {
+ if (isMov())
+ appendInstructionName("mov");
+ else
+ appendInstructionName(opName(opNumber()));
+ appendSPOrRegisterName(rd(), is64Bit());
+ appendSeparator();
+ }
+
+ if (!isMov()) {
+ appendRegisterName(rn(), is64Bit());
+ appendSeparator();
+ }
+
+ appendZROrRegisterName(rm(), is64Bit());
+ if (immediate6()) {
+ appendSeparator();
+ appendShiftType(shift());
+ appendUnsignedImmediate(immediate6());
+ }
+
+ return m_formatBuffer;
+}
+
+static unsigned highestBitSet(unsigned value)
+{
+ unsigned result = 0;
+
+ while (value >>= 1)
+ result++;
+
+ return result;
+}
+
+static uint64_t rotateRight(uint64_t value, unsigned width, unsigned shift)
+{
+ uint64_t result = value;
+
+ if (shift)
+ result = (value >> (shift % width)) | (value << (width - shift));
+
+ return result;
+}
+
+static uint64_t replicate(uint64_t value, unsigned width)
+{
+ uint64_t result = 0;
+
+ for (unsigned totalBits = 0; totalBits < 64; totalBits += width)
+ result = (result << width) | value;
+
+ return result;
+}
+
+const char* A64DOpcodeLogicalImmediate::format()
+{
+ if (!is64Bit() && nBit())
+ return A64DOpcode::format();
+
+ unsigned len = highestBitSet(nBit() << 6 | (immediateS() ^ 0x3f));
+ unsigned levels = (1 << len) - 1; // len number of 1 bits starting at LSB
+
+ if ((immediateS() & levels) == levels)
+ return A64DOpcode::format();
+
+ unsigned r = immediateR() & levels;
+ unsigned s = immediateS() & levels;
+ unsigned eSize = 1 << len;
+ uint64_t pattern = rotateRight((1ull << (s + 1)) - 1, eSize, r);
+
+ uint64_t immediate = replicate(pattern, eSize);
+
+ if (!is64Bit())
+ immediate &= 0xffffffffull;
+
+ if (isTst())
+ appendInstructionName("tst");
+ else {
+ if (isMov())
+ appendInstructionName("mov");
+ else
+ appendInstructionName(opName(opNumber()));
+ appendRegisterName(rd(), is64Bit());
+ appendSeparator();
+ }
+ if (!isMov()) {
+ appendRegisterName(rn(), is64Bit());
+ appendSeparator();
+ }
+ appendUnsignedImmediate64(immediate);
+
+ return m_formatBuffer;
+}
+
+const char* const A64DOpcodeMoveWide::s_opNames[4] = { "movn", "", "movz", "movk" };
+
+const char* A64DOpcodeMoveWide::format()
+{
+ if (opc() == 1)
+ return A64DOpcode::format();
+ if (!size() && hw() >= 2)
+ return A64DOpcode::format();
+
+ appendInstructionName(opName());
+ appendRegisterName(rd(), is64Bit());
+ appendSeparator();
+ appendUnsignedImmediate(immediate16());
+ if (hw()) {
+ appendSeparator();
+ appendShiftAmount(hw());
+ }
+
+ return m_formatBuffer;
+}
+
+const char* A64DOpcodeTestAndBranchImmediate::format()
+{
+ appendInstructionName(opBit() ? "tbnz" : "tbz");
+ appendRegisterName(rt());
+ appendSeparator();
+ appendUnsignedImmediate(bitNumber());
+ appendSeparator();
+ appendPCRelativeOffset(m_currentPC, static_cast<int32_t>(immediate14()));
+ return m_formatBuffer;
+}
+
+const char* A64DOpcodeUnconditionalBranchImmediate::format()
+{
+ appendInstructionName(op() ? "bl" : "b");
+ appendPCRelativeOffset(m_currentPC, static_cast<int32_t>(immediate26()));
+ return m_formatBuffer;
+}
+
+const char* const A64DOpcodeUnconditionalBranchRegister::s_opNames[8] = { "br", "blr", "ret", "", "eret", "drps", "", "" };
+
+const char* A64DOpcodeUnconditionalBranchRegister::format()
+{
+ unsigned opcValue = opc();
+ if (opcValue == 3 || opcValue > 5)
+ return A64DOpcode::format();
+ if (((opcValue & 0xe) == 0x4) && rn() != 0x1f)
+ return A64DOpcode::format();
+ appendInstructionName(opName());
+ if (opcValue <= 2)
+ appendRegisterName(rn());
+ return m_formatBuffer;
+}
+
+} } // namespace JSC::ARM64Disassembler
+
+#endif // USE(ARM64_DISASSEMBLER)
diff --git a/src/3rdparty/masm/disassembler/ARM64/A64DOpcode.h b/src/3rdparty/masm/disassembler/ARM64/A64DOpcode.h
new file mode 100644
index 0000000000..5bb7db9f12
--- /dev/null
+++ b/src/3rdparty/masm/disassembler/ARM64/A64DOpcode.h
@@ -0,0 +1,708 @@
+/*
+ * Copyright (C) 2012 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 A64DOpcode_h
+#define A64DOpcode_h
+
+#include <wtf/Assertions.h>
+#include <stdint.h>
+
+namespace JSC { namespace ARM64Disassembler {
+
+class A64DOpcode {
+private:
+ class OpcodeGroup {
+ public:
+ OpcodeGroup(uint32_t opcodeMask, uint32_t opcodePattern, const char* (*format)(A64DOpcode*))
+ : 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(A64DOpcode* thisObj)
+ {
+ return m_format(thisObj);
+ }
+
+ private:
+ uint32_t m_opcodeMask;
+ uint32_t m_opcodePattern;
+ const char* (*m_format)(A64DOpcode*);
+ OpcodeGroup* m_next;
+ };
+
+public:
+ static void init();
+
+ A64DOpcode()
+ : m_opcode(0)
+ , m_bufferOffset(0)
+ {
+ init();
+ m_formatBuffer[0] = '\0';
+ }
+
+ const char* disassemble(uint32_t* currentPC);
+
+protected:
+ void setPCAndOpcode(uint32_t*, uint32_t);
+ const char* format();
+
+ static const char* const s_conditionNames[16];
+ static const char* const s_shiftNames[4];
+ static const char* const s_optionName[8];
+ static const char s_FPRegisterPrefix[5];
+
+ static const char* conditionName(unsigned condition) { return s_conditionNames[condition & 0xf]; }
+ static const char* shiftName(unsigned shiftValue) { return s_shiftNames[shiftValue & 0x3]; }
+ const char* optionName() { return s_optionName[option()]; }
+ static char FPRegisterPrefix(unsigned FPRegisterSize)
+ {
+ if (FPRegisterSize > 4)
+ FPRegisterSize = 4;
+ return s_FPRegisterPrefix[FPRegisterSize];
+ }
+
+ unsigned opcodeGroupNumber(uint32_t opcode) { return (opcode >> 24) & 0x1f; }
+
+ bool is64Bit() { return m_opcode & 0x80000000; }
+ unsigned size() { return m_opcode >> 30; }
+ unsigned option() { return (m_opcode >> 13) & 0x7; }
+ unsigned rd() { return m_opcode & 0x1f; }
+ unsigned rt() { return m_opcode & 0x1f; }
+ unsigned rn() { return (m_opcode >> 5) & 0x1f; }
+ unsigned rm() { return (m_opcode >> 16) & 0x1f; }
+
+ void bufferPrintf(const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
+
+ void appendInstructionName(const char* instructionName)
+ {
+ bufferPrintf(" %-7.7s", instructionName);
+ }
+
+ void appendRegisterName(unsigned registerNumber, bool is64Bit = true);
+ void appendSPOrRegisterName(unsigned registerNumber, bool is64Bit = true)
+ {
+ if (registerNumber == 31) {
+ bufferPrintf(is64Bit ? "sp" : "wsp");
+ return;
+ }
+ appendRegisterName(registerNumber, is64Bit);
+ }
+
+ void appendZROrRegisterName(unsigned registerNumber, bool is64Bit = true)
+ {
+ if (registerNumber == 31) {
+ bufferPrintf(is64Bit ? "xzr" : "wzr");
+ return;
+ }
+ appendRegisterName(registerNumber, is64Bit);
+ }
+
+ void appendFPRegisterName(unsigned registerNumber, unsigned registerSize);
+
+ 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 appendUnsignedImmediate64(uint64_t immediate)
+ {
+ bufferPrintf("#0x%" PRIx64, immediate);
+ }
+
+ void appendPCRelativeOffset(uint32_t* pc, int32_t immediate)
+ {
+ bufferPrintf("0x%" PRIx64, reinterpret_cast<uint64_t>(pc + immediate));
+ }
+
+ void appendShiftAmount(unsigned amount)
+ {
+ bufferPrintf("lsl #%u", 16 * amount);
+ }
+
+ static const int bufferSize = 81;
+
+ char m_formatBuffer[bufferSize];
+ uint32_t* m_currentPC;
+ uint32_t m_opcode;
+ int m_bufferOffset;
+
+private:
+ static OpcodeGroup* opcodeTable[32];
+
+ static bool s_initialized;
+};
+
+#define DEFINE_STATIC_FORMAT(klass, thisObj) \
+ static const char* format(A64DOpcode* thisObj) { return reinterpret_cast< klass *>(thisObj)->format(); }
+
+class A64DOpcodeAddSubtract : public A64DOpcode {
+private:
+ static const char* const s_opNames[4];
+
+public:
+ const char* opName() { return s_opNames[opAndS()]; }
+ const char* cmpName() { return op() ? "cmp" : "cmn"; }
+
+ bool isCMP() { return (sBit() && rd() == 31); }
+ unsigned op() { return (m_opcode >> 30) & 0x1; }
+ unsigned sBit() { return (m_opcode >> 29) & 0x1; }
+ unsigned opAndS() { return (m_opcode >> 29) & 0x3; }
+};
+
+class A64DOpcodeAddSubtractImmediate : public A64DOpcodeAddSubtract {
+public:
+ static const uint32_t mask = 0x1f000000;
+ static const uint32_t pattern = 0x11000000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeAddSubtractImmediate, thisObj);
+
+ const char* format();
+
+ bool isMovSP() { return (!opAndS() && !immed12() && ((rd() == 31) || rn() == 31)); }
+ unsigned shift() { return (m_opcode >> 22) & 0x3; }
+ unsigned immed12() { return (m_opcode >> 10) & 0xfff; }
+};
+
+class A64DOpcodeAddSubtractExtendedRegister : public A64DOpcodeAddSubtract {
+public:
+ static const uint32_t mask = 0x1fe00000;
+ static const uint32_t pattern = 0x0b200000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeAddSubtractExtendedRegister, thisObj);
+
+ const char* format();
+
+ unsigned immediate3() { return (m_opcode >> 10) & 0x7; }
+};
+
+class A64DOpcodeAddSubtractShiftedRegister : public A64DOpcodeAddSubtract {
+public:
+ static const uint32_t mask = 0x1f200000;
+ static const uint32_t pattern = 0x0b000000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeAddSubtractShiftedRegister, thisObj);
+
+ const char* format();
+
+ bool isNeg() { return (op() && rn() == 31); }
+ const char* negName() { return sBit() ? "negs" : "neg"; }
+ unsigned shift() { return (m_opcode >> 22) & 0x3; }
+ int immediate6() { return (static_cast<int>((m_opcode >> 10) & 0x3f) << 26) >> 26; }
+};
+
+class A64DOpcodeBitfield : public A64DOpcode {
+private:
+ static const char* const s_opNames[3];
+ static const char* const s_extendPseudoOpNames[3][3];
+ static const char* const s_insertOpNames[3];
+ static const char* const s_extractOpNames[3];
+
+public:
+ static const uint32_t mask = 0x1f800000;
+ static const uint32_t pattern = 0x13000000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeBitfield, thisObj);
+
+ const char* format();
+
+ const char* opName() { return s_opNames[opc()]; }
+ const char* extendPseudoOpNames(unsigned opSize) { return s_extendPseudoOpNames[opc()][opSize]; }
+ const char* insertOpNames() { return s_insertOpNames[opc()]; }
+ const char* extractOpNames() { return s_extractOpNames[opc()]; }
+
+ unsigned opc() { return (m_opcode >> 29) & 0x3; }
+ unsigned nBit() { return (m_opcode >> 22) & 0x1; }
+ unsigned immediateR() { return (m_opcode >> 16) & 0x3f; }
+ unsigned immediateS() { return (m_opcode >> 10) & 0x3f; }
+};
+
+class A64DOpcodeCompareAndBranchImmediate : public A64DOpcode {
+public:
+ static const uint32_t mask = 0x7e000000;
+ static const uint32_t pattern = 0x34000000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeCompareAndBranchImmediate, thisObj);
+
+ const char* format();
+
+ unsigned opBit() { return (m_opcode >> 24) & 0x1; }
+ int immediate19() { return (static_cast<int>((m_opcode >> 5) & 0x7ffff) << 13) >> 13; }
+};
+
+class A64DOpcodeConditionalBranchImmediate : public A64DOpcode {
+public:
+ static const uint32_t mask = 0xff000010;
+ static const uint32_t pattern = 0x54000000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeConditionalBranchImmediate, thisObj);
+
+ const char* format();
+
+ unsigned condition() { return m_opcode & 0xf; }
+ int immediate19() { return (static_cast<int>((m_opcode >> 5) & 0x7ffff) << 13) >> 13; }
+};
+
+class A64DOpcodeConditionalSelect : public A64DOpcode {
+private:
+ static const char* const s_opNames[4];
+
+public:
+ static const uint32_t mask = 0x1fe00010;
+ static const uint32_t pattern = 0x1a800000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeConditionalSelect, thisObj);
+
+ const char* format();
+
+ const char* opName() { return s_opNames[opNum()]; }
+ unsigned opNum() { return (op() << 1 | (op2() & 0x1)); }
+ unsigned op() { return (m_opcode >> 30) & 0x1; }
+ unsigned sBit() { return (m_opcode >> 29) & 0x1; }
+ unsigned condition() { return (m_opcode >> 12) & 0xf; }
+ unsigned op2() { return (m_opcode >> 10) & 0x3; }
+};
+
+class A64DOpcodeDataProcessing2Source : public A64DOpcode {
+private:
+ static const char* const s_opNames[8];
+
+public:
+ static const uint32_t mask = 0x5fe00000;
+ static const uint32_t pattern = 0x1ac00000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeDataProcessing2Source, thisObj);
+
+ const char* format();
+
+ const char* opName() { return s_opNames[opNameIndex()]; }
+ unsigned sBit() { return (m_opcode >> 29) & 0x1; }
+ unsigned opCode() { return (m_opcode >> 10) & 0x3f; }
+ unsigned opNameIndex() { return ((m_opcode >> 11) & 0x4) | ((m_opcode >> 10) & 0x3); }
+};
+
+class A64DOpcodeDataProcessing3Source : public A64DOpcode {
+private:
+ static const char* const s_opNames[16];
+ static const char* const s_pseudoOpNames[16];
+
+public:
+ static const uint32_t mask = 0x1f000000;
+ static const uint32_t pattern = 0x1b000000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeDataProcessing3Source, thisObj);
+
+ const char* format();
+
+ const char* opName() { return ra() == 31 ? s_opNames[opNum() & 0xf] : s_pseudoOpNames[opNum() & 0xf]; }
+ unsigned ra() { return (m_opcode >> 10) & 0x1f; }
+ unsigned op54() { return (m_opcode >> 29) & 0x3; }
+ unsigned op31() { return (m_opcode >> 21) & 0x7; }
+ unsigned op0() { return (m_opcode >> 15) & 0x1; }
+ unsigned opNum() { return ((m_opcode >> 25) & 0x30) | ((m_opcode >> 20) & 0xe) | ((m_opcode >> 15) & 0x1); }
+};
+
+class A64OpcodeExceptionGeneration : public A64DOpcode {
+public:
+ static const uint32_t mask = 0xff000010;
+ static const uint32_t pattern = 0xd4000000;
+
+ DEFINE_STATIC_FORMAT(A64OpcodeExceptionGeneration, thisObj);
+
+ const char* format();
+
+ unsigned opc() { return (m_opcode>>21) & 0x7; }
+ unsigned op2() { return (m_opcode>>2) & 0x7; }
+ unsigned ll() { return m_opcode & 0x3; }
+ int immediate16() { return (static_cast<int>((m_opcode >> 5) & 0xffff) << 16) >> 16; }
+};
+
+class A64DOpcodeExtract : public A64DOpcode {
+public:
+ static const uint32_t mask = 0x1f800000;
+ static const uint32_t pattern = 0x13800000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeExtract, thisObj);
+
+ const char* format();
+
+ unsigned op21() { return (m_opcode >> 29) & 0x3; }
+ unsigned nBit() { return (m_opcode >> 22) & 0x1; }
+ unsigned o0Bit() { return (m_opcode >> 21) & 0x1; }
+ unsigned immediateS() { return (m_opcode >> 10) & 0x3f; }
+};
+
+class A64DOpcodeFloatingPointOps : public A64DOpcode {
+public:
+ unsigned mBit() { return (m_opcode >> 31) & 0x1; }
+ unsigned sBit() { return (m_opcode >> 29) & 0x1; }
+ unsigned type() { return (m_opcode >> 22) & 0x3; }
+};
+
+class A64DOpcodeFloatingPointCompare : public A64DOpcodeFloatingPointOps {
+private:
+ static const char* const s_opNames[16];
+
+public:
+ static const uint32_t mask = 0x5f203c00;
+ static const uint32_t pattern = 0x1e202000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeFloatingPointCompare, thisObj);
+
+ const char* format();
+
+ const char* opName() { return (opNum() & 0x2) ? "fcmpe" : "fcmp"; }
+
+ unsigned op() { return (m_opcode >> 14) & 0x3; }
+ unsigned opCode2() { return m_opcode & 0x1f; }
+ unsigned opNum() { return (m_opcode >> 3) & 0x3; }
+};
+
+class A64DOpcodeFloatingPointDataProcessing1Source : public A64DOpcodeFloatingPointOps {
+private:
+ static const char* const s_opNames[16];
+
+public:
+ static const uint32_t mask = 0x5f207c00;
+ static const uint32_t pattern = 0x1e204000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeFloatingPointDataProcessing1Source, thisObj);
+
+ const char* format();
+
+ const char* opName() { return s_opNames[opNum()]; }
+
+ unsigned opNum() { return (m_opcode >> 15) & 0x3f; }
+};
+
+class A64DOpcodeFloatingPointDataProcessing2Source : public A64DOpcodeFloatingPointOps {
+private:
+ static const char* const s_opNames[16];
+
+public:
+ static const uint32_t mask = 0x5f200800;
+ static const uint32_t pattern = 0x1e200800;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeFloatingPointDataProcessing2Source, thisObj);
+
+ const char* format();
+
+ const char* opName() { return s_opNames[opNum()]; }
+
+ unsigned opNum() { return (m_opcode >> 12) & 0xf; }
+};
+
+class A64DOpcodeFloatingFixedPointConversions : public A64DOpcodeFloatingPointOps {
+private:
+ static const char* const s_opNames[4];
+
+public:
+ static const uint32_t mask = 0x5f200000;
+ static const uint32_t pattern = 0x1e000000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeFloatingFixedPointConversions, thisObj);
+
+ const char* format();
+
+ const char* opName() { return s_opNames[opNum()]; }
+ unsigned rmode() { return (m_opcode >> 19) & 0x3; }
+ unsigned opcode() { return (m_opcode >> 16) & 0x7; }
+ unsigned scale() { return (m_opcode >> 10) & 0x3f; }
+ unsigned opNum() { return (m_opcode >> 16) & 0x3; }
+};
+
+class A64DOpcodeFloatingPointIntegerConversions : public A64DOpcodeFloatingPointOps {
+private:
+ static const char* const s_opNames[32];
+
+public:
+ static const uint32_t mask = 0x5f20fc00;
+ static const uint32_t pattern = 0x1e200000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeFloatingPointIntegerConversions, thisObj);
+
+ const char* format();
+
+ const char* opName() { return s_opNames[opNum()]; }
+ unsigned rmode() { return (m_opcode >> 19) & 0x3; }
+ unsigned opcode() { return (m_opcode >> 16) & 0x7; }
+ unsigned opNum() { return (m_opcode >> 16) & 0x1f; }
+};
+
+class A64DOpcodeHint : public A64DOpcode {
+private:
+ static const char* const s_opNames[6];
+
+public:
+ static const uint32_t mask = 0xfffff01f;
+ static const uint32_t pattern = 0xd503201f;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeHint, thisObj);
+
+ const char* format();
+
+ const char* opName() { return immediate7() <= 5 ? s_opNames[immediate7()] : "hint"; }
+ unsigned immediate7() { return (m_opcode >> 5) & 0x7f; }
+};
+
+class A64DOpcodeLoadStore : public A64DOpcode {
+private:
+ static const char* const s_opNames[32];
+
+protected:
+ const char* opName()
+ {
+ return s_opNames[opNumber()];
+ }
+
+ unsigned size() { return (m_opcode >> 30) & 0x3; }
+ unsigned vBit() { return (m_opcode >> 26) & 0x1; }
+ unsigned opc() { return (m_opcode >> 22) & 0x3; }
+ unsigned opNumber() { return (size() <<3 ) | (vBit() << 2) | opc(); }
+ bool is64BitRT() { return ((opNumber() & 0x17) == 0x02) || ((opNumber() & 0x1e) == 0x18); }
+};
+
+class A64DOpcodeLoadStoreImmediate : public A64DOpcodeLoadStore {
+private:
+ static const char* const s_unprivilegedOpNames[32];
+ static const char* const s_unscaledOpNames[32];
+
+public:
+ static const uint32_t mask = 0x3b200000;
+ static const uint32_t pattern = 0x38000000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeLoadStoreImmediate, thisObj);
+
+ const char* format();
+
+ const char* unprivilegedOpName()
+ {
+ return s_unprivilegedOpNames[opNumber()];
+ }
+ const char* unscaledOpName()
+ {
+ return s_unscaledOpNames[opNumber()];
+ }
+ unsigned type() { return (m_opcode >> 10) & 0x3; }
+ int immediate9() { return (static_cast<int>((m_opcode >> 12) & 0x1ff) << 23) >> 23; }
+};
+
+class A64DOpcodeLoadStoreRegisterOffset : public A64DOpcodeLoadStore {
+public:
+ static const uint32_t mask = 0x3b200c00;
+ static const uint32_t pattern = 0x38200800;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeLoadStoreRegisterOffset, thisObj);
+
+ const char* format();
+
+ unsigned option() { return (m_opcode >> 13) & 0x7; }
+ int sBit() { return (m_opcode >> 12) & 0x1; }
+};
+
+class A64DOpcodeLoadStoreRegisterPair : public A64DOpcodeLoadStore {
+public:
+ static const uint32_t mask = 0x3a000000;
+ static const uint32_t pattern = 0x28000000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeLoadStoreRegisterPair, thisObj);
+
+ const char* format();
+ const char* opName();
+
+ unsigned rt2() { return (m_opcode >> 10) & 0x1f; }
+ int immediate7() { return (static_cast<int>((m_opcode >> 15) & 0x7f) << 25) >> 25; }
+ unsigned offsetMode() { return (m_opcode >> 23) & 0x7; }
+ int lBit() { return (m_opcode >> 22) & 0x1; }
+};
+
+class A64DOpcodeLoadStoreUnsignedImmediate : public A64DOpcodeLoadStore {
+public:
+ static const uint32_t mask = 0x3b000000;
+ static const uint32_t pattern = 0x39000000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeLoadStoreUnsignedImmediate, thisObj);
+
+ const char* format();
+
+ unsigned immediate12() { return (m_opcode >> 10) & 0xfff; }
+};
+
+class A64DOpcodeLogical : public A64DOpcode {
+private:
+ static const char* const s_opNames[8];
+
+public:
+ const char* opName(unsigned opNumber)
+ {
+ return s_opNames[opNumber & 0x7];
+ }
+
+ unsigned opc() { return (m_opcode >> 29) & 0x3; }
+ unsigned nBit() { return (m_opcode >> 21) & 0x1; }
+};
+
+class A64DOpcodeLogicalImmediate : public A64DOpcodeLogical {
+public:
+ static const uint32_t mask = 0x1f800000;
+ static const uint32_t pattern = 0x12000000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeLogicalImmediate, thisObj);
+
+ const char* format();
+
+ bool isTst() { return ((opNumber() == 6) && (rd() == 31)); }
+ bool isMov() { return ((opNumber() == 2) && (rn() == 31)); }
+ unsigned opNumber() { return opc() << 1; }
+ unsigned nBit() { return (m_opcode >> 22) & 0x1; }
+ unsigned immediateR() { return (m_opcode >> 16) & 0x3f; }
+ unsigned immediateS() { return (m_opcode >> 10) & 0x3f; }
+};
+
+class A64DOpcodeLogicalShiftedRegister : public A64DOpcodeLogical {
+public:
+ static const uint32_t mask = 0x1f000000;
+ static const uint32_t pattern = 0x0a000000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeLogicalShiftedRegister, thisObj);
+
+ const char* format();
+
+ bool isTst() { return ((opNumber() == 6) && (rd() == 31)); }
+ bool isMov() { return ((opNumber() == 2) && (rn() == 31)); }
+ unsigned opNumber() { return (opc() << 1) | nBit(); }
+ unsigned shift() { return (m_opcode >> 22) & 0x3; }
+ int immediate6() { return (static_cast<int>((m_opcode >> 10) & 0x3f) << 26) >> 26; }
+};
+
+class A64DOpcodeMoveWide : public A64DOpcode {
+private:
+ static const char* const s_opNames[4];
+
+public:
+ static const uint32_t mask = 0x1f800000;
+ static const uint32_t pattern = 0x12800000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeMoveWide, thisObj);
+
+ const char* format();
+
+ const char* opName() { return s_opNames[opc()]; }
+ unsigned opc() { return (m_opcode >> 29) & 0x3; }
+ unsigned hw() { return (m_opcode >> 21) & 0x3; }
+ unsigned immediate16() { return (m_opcode >> 5) & 0xffff; }
+};
+
+class A64DOpcodeTestAndBranchImmediate : public A64DOpcode {
+public:
+ static const uint32_t mask = 0x7e000000;
+ static const uint32_t pattern = 0x36000000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeTestAndBranchImmediate, thisObj);
+
+ const char* format();
+
+ unsigned bitNumber() { return ((m_opcode >> 26) & 0x20) | ((m_opcode >> 19) & 0x1f); }
+ unsigned opBit() { return (m_opcode >> 24) & 0x1; }
+ int immediate14() { return (static_cast<int>((m_opcode >> 5) & 0x3fff) << 18) >> 18; }
+};
+
+class A64DOpcodeUnconditionalBranchImmediate : public A64DOpcode {
+public:
+ static const uint32_t mask = 0x7c000000;
+ static const uint32_t pattern = 0x14000000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeUnconditionalBranchImmediate, thisObj);
+
+ const char* format();
+
+ unsigned op() { return (m_opcode >> 31) & 0x1; }
+ int immediate26() { return (static_cast<int>(m_opcode & 0x3ffffff) << 6) >> 6; }
+};
+
+class A64DOpcodeUnconditionalBranchRegister : public A64DOpcode {
+private:
+ static const char* const s_opNames[8];
+
+public:
+ static const uint32_t mask = 0xfe1ffc1f;
+ static const uint32_t pattern = 0xd61f0000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeUnconditionalBranchRegister, thisObj);
+
+ const char* format();
+
+ const char* opName() { return s_opNames[opc()]; }
+ unsigned opc() { return (m_opcode >> 21) & 0xf; }
+};
+
+} } // namespace JSC::ARM64Disassembler
+
+using JSC::ARM64Disassembler::A64DOpcode;
+
+#endif // A64DOpcode_h
diff --git a/src/3rdparty/masm/disassembler/ARM64Disassembler.cpp b/src/3rdparty/masm/disassembler/ARM64Disassembler.cpp
new file mode 100644
index 0000000000..27ae4b96d0
--- /dev/null
+++ b/src/3rdparty/masm/disassembler/ARM64Disassembler.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2012, 2014 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.
+ */
+
+#define __STDC_FORMAT_MACROS
+#include "config.h"
+#include "Disassembler.h"
+
+#if USE(ARM64_DISASSEMBLER) && CPU(ARM64)
+
+#include "ARM64/A64DOpcode.h"
+#include "MacroAssemblerCodeRef.h"
+
+namespace JSC {
+
+bool tryToDisassemble(const MacroAssemblerCodePtr& codePtr, size_t size, const char* prefix, PrintStream& out)
+{
+ A64DOpcode arm64Opcode;
+
+ uint32_t* currentPC = reinterpret_cast<uint32_t*>(codePtr.executableAddress());
+ size_t byteCount = size;
+
+ while (byteCount) {
+ char pcString[20];
+ snprintf(pcString, sizeof(pcString), "0x%lx", reinterpret_cast<unsigned long>(currentPC));
+ out.printf("%s%16s: %s\n", prefix, pcString, arm64Opcode.disassemble(currentPC));
+ currentPC++;
+ byteCount -= sizeof(uint32_t);
+ }
+
+ return true;
+}
+
+} // namespace JSC
+
+#endif // USE(ARM64_DISASSEMBLER)
+
+#if USE(LLVM_DISASSEMBLER) && CPU(ARM64)
+
+#include "LLVMDisassembler.h"
+
+namespace JSC {
+
+bool tryToDisassemble(const MacroAssemblerCodePtr& codePtr, size_t size, const char* prefix, PrintStream& out, InstructionSubsetHint hint)
+{
+ return tryToDisassembleWithLLVM(codePtr, size, prefix, out, hint);
+}
+
+} // namespace JSC
+
+#endif // USE(LLVM_DISASSEMBLER) && CPU(ARM64)
diff --git a/src/3rdparty/masm/disassembler/ARMv7/ARMv7DOpcode.cpp b/src/3rdparty/masm/disassembler/ARMv7/ARMv7DOpcode.cpp
index d9afdd447a..6af71e523b 100644
--- a/src/3rdparty/masm/disassembler/ARMv7/ARMv7DOpcode.cpp
+++ b/src/3rdparty/masm/disassembler/ARMv7/ARMv7DOpcode.cpp
@@ -1623,6 +1623,8 @@ const char* ARMv7DOpcodeVCVT::format()
default:
n1 = "vcvt.?";
n2 = ".?";
+ dregPrefix = '?';
+ mregPrefix = '?';
break;
}
diff --git a/src/3rdparty/masm/disassembler/ARMv7/ARMv7DOpcode.h b/src/3rdparty/masm/disassembler/ARMv7/ARMv7DOpcode.h
index 051d05525a..03e0ba21c4 100644
--- a/src/3rdparty/masm/disassembler/ARMv7/ARMv7DOpcode.h
+++ b/src/3rdparty/masm/disassembler/ARMv7/ARMv7DOpcode.h
@@ -127,7 +127,7 @@ protected:
void appendPCRelativeOffset(int32_t immediate)
{
- bufferPrintf("0x%x", reinterpret_cast<uint32_t>(m_currentPC + immediate));
+ bufferPrintf("%p", m_currentPC + immediate);
}
void appendShiftAmount(unsigned amount)
diff --git a/src/3rdparty/masm/disassembler/ARMv7Disassembler.cpp b/src/3rdparty/masm/disassembler/ARMv7Disassembler.cpp
index bfb48953c0..dee017525d 100644
--- a/src/3rdparty/masm/disassembler/ARMv7Disassembler.cpp
+++ b/src/3rdparty/masm/disassembler/ARMv7Disassembler.cpp
@@ -26,7 +26,7 @@
#include "config.h"
#include "Disassembler.h"
-#if USE(ARMV7_DISASSEMBLER)
+#if USE(ARMV7_DISASSEMBLER) && CPU(ARM_THUMB2)
#include "ARMv7/ARMv7DOpcode.h"
#include "MacroAssemblerCodeRef.h"