summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/disassembler/ARM64
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/disassembler/ARM64
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c.tar.gz
Diffstat (limited to 'Source/JavaScriptCore/disassembler/ARM64')
-rw-r--r--Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.cpp330
-rw-r--r--Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.h94
2 files changed, 343 insertions, 81 deletions
diff --git a/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.cpp b/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.cpp
index 0ea817a46..9584f4953 100644
--- a/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.cpp
+++ b/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if USE(ARM64_DISASSEMBLER)
+
#include "A64DOpcode.h"
#include <stdarg.h>
@@ -62,6 +65,8 @@ struct OpcodeGroupInitializer {
{ 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),
@@ -78,6 +83,7 @@ static OpcodeGroupInitializer opcodeGroupList[] = {
OPCODE_GROUP_ENTRY(0x15, A64DOpcodeConditionalBranchImmediate),
OPCODE_GROUP_ENTRY(0x15, A64DOpcodeCompareAndBranchImmediate),
OPCODE_GROUP_ENTRY(0x15, A64DOpcodeHint),
+ OPCODE_GROUP_ENTRY(0x15, A64DOpcodeDmb),
OPCODE_GROUP_ENTRY(0x16, A64DOpcodeUnconditionalBranchImmediate),
OPCODE_GROUP_ENTRY(0x16, A64DOpcodeUnconditionalBranchRegister),
OPCODE_GROUP_ENTRY(0x16, A64DOpcodeTestAndBranchImmediate),
@@ -88,12 +94,14 @@ static OpcodeGroupInitializer opcodeGroupList[] = {
OPCODE_GROUP_ENTRY(0x18, A64DOpcodeLoadStoreRegisterOffset),
OPCODE_GROUP_ENTRY(0x19, A64DOpcodeLoadStoreUnsignedImmediate),
OPCODE_GROUP_ENTRY(0x1a, A64DOpcodeConditionalSelect),
+ OPCODE_GROUP_ENTRY(0x1a, A64DOpcodeDataProcessing1Source),
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, A64DOpcodeFloatingPointConditionalSelect),
OPCODE_GROUP_ENTRY(0x1e, A64DOpcodeFloatingPointDataProcessing2Source),
OPCODE_GROUP_ENTRY(0x1e, A64DOpcodeFloatingPointDataProcessing1Source),
OPCODE_GROUP_ENTRY(0x1e, A64DOpcodeFloatingFixedPointConversions),
@@ -172,6 +180,11 @@ const char* A64DOpcode::format()
void A64DOpcode::appendRegisterName(unsigned registerNumber, bool is64Bit)
{
+ if (registerNumber == 29) {
+ bufferPrintf(is64Bit ? "fp" : "wfp");
+ return;
+ }
+
if (registerNumber == 30) {
bufferPrintf(is64Bit ? "lr" : "wlr");
return;
@@ -276,7 +289,7 @@ 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* const A64DOpcodeBitfield::s_extractOpNames[3] = { "sbfx", "bfxil", "ubfx" };
const char* A64DOpcodeBitfield::format()
{
@@ -298,7 +311,7 @@ const char* A64DOpcodeBitfield::format()
} else if (immediateS() == 15) {
appendInstructionName(extendPseudoOpNames(1));
isSTXType = true;
- } else if (immediateS() == 31 && is64Bit()) {
+ } else if (immediateS() == 31 && is64Bit() && !opc()) {
appendInstructionName(extendPseudoOpNames(2));
isSTXType = true;
}
@@ -312,19 +325,9 @@ const char* A64DOpcodeBitfield::format()
}
}
- 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))) {
+ if (!(opc() & 0x1) && ((immediateS() & 0x1f) == 0x1f) && (is64Bit() == (immediateS() >> 5))) {
// asr/lsr
- appendInstructionName(!opc() ? "ars" : "lsr");
+ appendInstructionName(!opc() ? "asr" : "lsr");
appendRegisterName(rd(), is64Bit());
appendSeparator();
@@ -333,42 +336,58 @@ const char* A64DOpcodeBitfield::format()
appendUnsignedImmediate(immediateR());
return m_formatBuffer;
- } else if (immediateS() < immediateR()) {
- // bit field insert
- appendInstructionName(insertOpNames());
+ }
+ if (opc() == 0x2 && (immediateS() + 1) == immediateR()) {
+ // lsl
+ appendInstructionName("lsl");
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());
+ }
+
+ if (immediateS() < immediateR()) {
+ if (opc() != 1 || rn() != 0x1f) {
+ // 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;
+ }
+
+ appendInstructionName(opName());
appendRegisterName(rd(), is64Bit());
appendSeparator();
appendRegisterName(rn(), is64Bit());
appendSeparator();
appendUnsignedImmediate(immediateR());
appendSeparator();
- appendUnsignedImmediate(immediateS() - immediateR() + 1);
-
+ appendUnsignedImmediate(immediateS());
+
return m_formatBuffer;
}
+
+ // bit field extract
+ appendInstructionName(extractOpNames());
- appendInstructionName(opName());
appendRegisterName(rd(), is64Bit());
appendSeparator();
appendRegisterName(rn(), is64Bit());
appendSeparator();
appendUnsignedImmediate(immediateR());
appendSeparator();
- appendUnsignedImmediate(immediateS());
+ appendUnsignedImmediate(immediateS() - immediateR() + 1);
return m_formatBuffer;
}
@@ -430,6 +449,38 @@ const char* A64DOpcodeConditionalSelect::format()
}
+const char* const A64DOpcodeDataProcessing1Source::s_opNames[8] = {
+ "rbit", "rev16", "rev32", "rev", "clz", "cls", 0, 0
+};
+
+const char* A64DOpcodeDataProcessing1Source::format()
+{
+ if (sBit())
+ return A64DOpcode::format();
+
+ if (opCode2())
+ return A64DOpcode::format();
+
+ if (opCode() & 0x38)
+ return A64DOpcode::format();
+
+ if ((opCode() & 0x3e) == 0x6)
+ return A64DOpcode::format();
+
+ if (is64Bit() && opCode() == 0x3)
+ return A64DOpcode::format();
+
+ if (!is64Bit() && opCode() == 0x2)
+ appendInstructionName("rev");
+ else
+ appendInstructionName(opName());
+ appendZROrRegisterName(rd(), is64Bit());
+ appendSeparator();
+ appendZROrRegisterName(rn(), is64Bit());
+
+ 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
};
@@ -449,11 +500,11 @@ const char* A64DOpcodeDataProcessing2Source::format()
return A64DOpcode::format();
appendInstructionName(opName());
- appendRegisterName(rd(), is64Bit());
+ appendZROrRegisterName(rd(), is64Bit());
appendSeparator();
- appendRegisterName(rn(), is64Bit());
+ appendZROrRegisterName(rn(), is64Bit());
appendSeparator();
- appendRegisterName(rm(), is64Bit());
+ appendZROrRegisterName(rm(), is64Bit());
return m_formatBuffer;
}
@@ -482,15 +533,18 @@ const char* A64DOpcodeDataProcessing3Source::format()
if (!opName())
return A64DOpcode::format();
+ if ((opNum() & 0x4) && (ra() != 31))
+ return A64DOpcode::format();
+
appendInstructionName(opName());
- appendRegisterName(rd(), is64Bit());
+ appendZROrRegisterName(rd(), is64Bit());
appendSeparator();
bool srcOneAndTwoAre64Bit = is64Bit() & !(opNum() & 0x2);
- appendRegisterName(rn(), srcOneAndTwoAre64Bit);
+ appendZROrRegisterName(rn(), srcOneAndTwoAre64Bit);
appendSeparator();
- appendRegisterName(rm(), srcOneAndTwoAre64Bit);
+ appendZROrRegisterName(rm(), srcOneAndTwoAre64Bit);
- if ((ra() != 31) || !(opNum() & 0x4)) {
+ if (ra() != 31) {
appendSeparator();
appendRegisterName(ra(), is64Bit());
}
@@ -550,23 +604,26 @@ const char* A64OpcodeExceptionGeneration::format()
const char* A64DOpcodeExtract::format()
{
- if (!op21() || !o0Bit())
+ if (op21() || o0Bit())
return A64DOpcode::format();
if (is64Bit() != nBit())
return A64DOpcode::format();
- if (is64Bit() && (immediateS() & 0x20))
+ if (!is64Bit() && (immediateS() & 0x20))
return A64DOpcode::format();
- const char* opName = (rn() == rm()) ? "ror" : "extr";
+ bool isROR = rn() == rm();
+ const char* opName = (isROR) ? "ror" : "extr";
appendInstructionName(opName);
- appendRegisterName(rd(), is64Bit());
+ appendZROrRegisterName(rd(), is64Bit());
appendSeparator();
- appendRegisterName(rn(), is64Bit());
- appendSeparator();
- appendRegisterName(rm(), is64Bit());
+ appendZROrRegisterName(rn(), is64Bit());
+ if (!isROR) {
+ appendSeparator();
+ appendZROrRegisterName(rm(), is64Bit());
+ }
appendSeparator();
appendUnsignedImmediate(immediateS());
@@ -602,6 +659,30 @@ const char* A64DOpcodeFloatingPointCompare::format()
return m_formatBuffer;
}
+const char* A64DOpcodeFloatingPointConditionalSelect::format()
+{
+ if (mBit())
+ return A64DOpcode::format();
+
+ if (sBit())
+ return A64DOpcode::format();
+
+ if (type() & 0x2)
+ return A64DOpcode::format();
+
+ appendInstructionName(opName());
+ unsigned registerSize = type() + 2;
+ appendFPRegisterName(rd(), registerSize);
+ appendSeparator();
+ appendFPRegisterName(rn(), registerSize);
+ appendSeparator();
+ appendFPRegisterName(rm(), registerSize);
+ appendSeparator();
+ appendString(conditionName(condition()));
+
+ 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"
@@ -770,10 +851,10 @@ const char* A64DOpcodeFloatingPointIntegerConversions::format()
// fmov Vd.D[1], Xn
bufferPrintf("V%u.D[1]", rd());
appendSeparator();
- appendRegisterName(rn());
+ appendZROrRegisterName(rn());
} else {
// fmov Xd, Vn.D[1]
- appendRegisterName(rd());
+ appendZROrRegisterName(rd());
appendSeparator();
bufferPrintf("V%u.D[1]", rn());
}
@@ -788,9 +869,9 @@ const char* A64DOpcodeFloatingPointIntegerConversions::format()
if (destIsFP) {
appendFPRegisterName(rd(), FPRegisterSize);
appendSeparator();
- appendRegisterName(rn(), is64Bit());
+ appendZROrRegisterName(rn(), is64Bit());
} else {
- appendRegisterName(rd(), is64Bit());
+ appendZROrRegisterName(rd(), is64Bit());
appendSeparator();
appendFPRegisterName(rn(), FPRegisterSize);
}
@@ -812,6 +893,23 @@ const char* A64DOpcodeHint::format()
return m_formatBuffer;
}
+const char* const A64DOpcodeDmb::s_optionNames[16] = {
+ 0, "oshld", "oshst", "osh", 0, "nshld", "nshst", "nsh",
+ 0, "ishld", "ishst", "ish", 0, "ld", "st", "sy"
+};
+
+const char* A64DOpcodeDmb::format()
+{
+ appendInstructionName(opName());
+ const char* thisOption = option();
+ if (thisOption)
+ appendString(thisOption);
+ else
+ appendUnsignedImmediate(crM());
+
+ 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",
@@ -853,6 +951,8 @@ const char* A64DOpcodeLoadStoreImmediate::format()
appendInstructionName(thisOpName);
if (vBit())
appendFPRegisterName(rt(), size());
+ else if (!opc())
+ appendZROrRegisterName(rt(), is64BitRT());
else
appendRegisterName(rt(), is64BitRT());
appendSeparator();
@@ -910,31 +1010,99 @@ const char* A64DOpcodeLoadStoreRegisterOffset::format()
appendFPRegisterName(rt(), size());
scale = ((opc() & 2)<<1) | size();
} else {
- appendRegisterName(rt(), is64BitRT());
+ if (!opc())
+ appendZROrRegisterName(rt(), is64BitRT());
+ else
+ appendRegisterName(rt(), is64BitRT());
scale = size();
}
appendSeparator();
appendCharacter('[');
appendSPOrRegisterName(rn());
- appendSeparator();
- appendZROrRegisterName(rm(), (option() & 0x3) == 0x3);
+ if (rm() != 31) {
+ appendSeparator();
+ appendRegisterName(rm(), (option() & 0x3) == 0x3);
- unsigned shift = sBit() ? scale : 0;
+ unsigned shift = sBit() ? scale : 0;
- if (option() == 0x3) {
- if (shift) {
+ if (option() == 0x3) {
+ if (shift) {
+ appendSeparator();
+ appendString("lsl ");
+ appendUnsignedImmediate(shift);
+ }
+ } else {
appendSeparator();
- appendString("lsl ");
- appendUnsignedImmediate(shift);
+ 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 {
+ if (!lBit())
+ appendZROrRegisterName(rt(), is64Bit());
+ else
+ appendRegisterName(rt(), is64Bit());
appendSeparator();
- appendString(optionName());
- if (shift)
- appendUnsignedImmediate(shift);
+ if (!lBit())
+ appendZROrRegisterName(rt2(), is64Bit());
+ else
+ appendRegisterName(rt2(), is64Bit());
+ offsetShift = (size() >> 1) + 2;
}
- appendCharacter(']');
+ 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;
}
@@ -952,7 +1120,10 @@ const char* A64DOpcodeLoadStoreUnsignedImmediate::format()
appendFPRegisterName(rt(), size());
scale = ((opc() & 2)<<1) | size();
} else {
- appendRegisterName(rt(), is64BitRT());
+ if (!opc())
+ appendZROrRegisterName(rt(), is64BitRT());
+ else
+ appendRegisterName(rt(), is64BitRT());
scale = size();
}
appendSeparator();
@@ -983,15 +1154,15 @@ const char* A64DOpcodeLogicalShiftedRegister::format()
appendInstructionName("tst");
else {
if (isMov())
- appendInstructionName("mov");
+ appendInstructionName(nBit() ? "mvn" : "mov");
else
appendInstructionName(opName(opNumber()));
- appendSPOrRegisterName(rd(), is64Bit());
+ appendZROrRegisterName(rd(), is64Bit());
appendSeparator();
}
if (!isMov()) {
- appendRegisterName(rn(), is64Bit());
+ appendZROrRegisterName(rn(), is64Bit());
appendSeparator();
}
@@ -1075,22 +1246,39 @@ const char* A64DOpcodeLogicalImmediate::format()
return m_formatBuffer;
}
-const char* const A64DOpcodeMoveWide::s_opNames[4] = { "movn", "", "movz", "movk" };
+const char* const A64DOpcodeMoveWide::s_opNames[4] = { "movn", 0, "movz", "movk" };
const char* A64DOpcodeMoveWide::format()
{
if (opc() == 1)
return A64DOpcode::format();
- if (!size() && hw() >= 2)
+ if (!is64Bit() && hw() >= 2)
return A64DOpcode::format();
- appendInstructionName(opName());
- appendRegisterName(rd(), is64Bit());
- appendSeparator();
- appendUnsignedImmediate(immediate16());
- if (hw()) {
+ if (!opc() && (!immediate16() || !hw()) && (is64Bit() || immediate16() != 0xffff)) {
+ // MOV pseudo op for MOVN
+ appendInstructionName("mov");
+ appendRegisterName(rd(), is64Bit());
appendSeparator();
- appendShiftAmount(hw());
+
+ if (is64Bit()) {
+ int64_t amount = immediate16() << (hw() * 16);
+ amount = ~amount;
+ appendSignedImmediate64(amount);
+ } else {
+ int32_t amount = immediate16() << (hw() * 16);
+ amount = ~amount;
+ appendSignedImmediate(amount);
+ }
+ } else {
+ appendInstructionName(opName());
+ appendRegisterName(rd(), is64Bit());
+ appendSeparator();
+ appendUnsignedHexImmediate(immediate16());
+ if (hw()) {
+ appendSeparator();
+ appendShiftAmount(hw());
+ }
}
return m_formatBuffer;
@@ -1130,3 +1318,5 @@ const char* A64DOpcodeUnconditionalBranchRegister::format()
}
} } // namespace JSC::ARM64Disassembler
+
+#endif // USE(ARM64_DISASSEMBLER)
diff --git a/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.h b/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.h
index ed18d30df..89c00477d 100644
--- a/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.h
+++ b/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,8 +23,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef A64DOpcode_h
-#define A64DOpcode_h
+#pragma once
#include <wtf/Assertions.h>
#include <stdint.h>
@@ -165,19 +164,29 @@ protected:
bufferPrintf("#%d", immediate);
}
+ void appendSignedImmediate64(int64_t immediate)
+ {
+ bufferPrintf("#%" PRIi64, immediate);
+ }
+
void appendUnsignedImmediate(unsigned immediate)
{
bufferPrintf("#%u", immediate);
}
+ void appendUnsignedHexImmediate(unsigned immediate)
+ {
+ bufferPrintf("#0x%x", immediate);
+ }
+
void appendUnsignedImmediate64(uint64_t immediate)
{
- bufferPrintf("#0x%llx", immediate);
+ bufferPrintf("#0x%" PRIx64, immediate);
}
void appendPCRelativeOffset(uint32_t* pc, int32_t immediate)
{
- bufferPrintf("0x%llx", reinterpret_cast<uint64_t>(pc + immediate));
+ bufferPrintf("0x%" PRIx64, reinterpret_cast<uint64_t>(pc + immediate));
}
void appendShiftAmount(unsigned amount)
@@ -313,7 +322,7 @@ private:
static const char* const s_opNames[4];
public:
- static const uint32_t mask = 0x1fe00010;
+ static const uint32_t mask = 0x1fe00000;
static const uint32_t pattern = 0x1a800000;
DEFINE_STATIC_FORMAT(A64DOpcodeConditionalSelect, thisObj);
@@ -328,6 +337,25 @@ public:
unsigned op2() { return (m_opcode >> 10) & 0x3; }
};
+class A64DOpcodeDataProcessing1Source : public A64DOpcode {
+private:
+ static const char* const s_opNames[8];
+
+public:
+ static const uint32_t mask = 0x5fe00000;
+ static const uint32_t pattern = 0x5ac00000;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeDataProcessing1Source, 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 opCode2() { return (m_opcode >> 16) & 0x1f; }
+ unsigned opNameIndex() { return (opCode() & 0x7); }
+};
+
class A64DOpcodeDataProcessing2Source : public A64DOpcode {
private:
static const char* const s_opNames[8];
@@ -359,7 +387,7 @@ public:
const char* format();
- const char* opName() { return ra() == 31 ? s_opNames[opNum() & 0xf] : s_pseudoOpNames[opNum() & 0xf]; }
+ const char* opName() { return ra() == 31 ? s_pseudoOpNames[opNum() & 0xf] : s_opNames[opNum() & 0xf]; }
unsigned ra() { return (m_opcode >> 10) & 0x1f; }
unsigned op54() { return (m_opcode >> 29) & 0x3; }
unsigned op31() { return (m_opcode >> 21) & 0x7; }
@@ -369,7 +397,7 @@ public:
class A64OpcodeExceptionGeneration : public A64DOpcode {
public:
- static const uint32_t mask = 0xff000010;
+ static const uint32_t mask = 0xff000000;
static const uint32_t pattern = 0xd4000000;
DEFINE_STATIC_FORMAT(A64OpcodeExceptionGeneration, thisObj);
@@ -423,6 +451,20 @@ public:
unsigned opNum() { return (m_opcode >> 3) & 0x3; }
};
+class A64DOpcodeFloatingPointConditionalSelect : public A64DOpcodeFloatingPointOps {
+public:
+ static const uint32_t mask = 0x5f200c00;
+ static const uint32_t pattern = 0x1e200c00;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeFloatingPointConditionalSelect, thisObj);
+
+ const char* format();
+
+ const char* opName() { return "fcsel"; }
+
+ unsigned condition() { return (m_opcode >> 12) & 0xf; }
+};
+
class A64DOpcodeFloatingPointDataProcessing1Source : public A64DOpcodeFloatingPointOps {
private:
static const char* const s_opNames[16];
@@ -510,6 +552,22 @@ public:
unsigned immediate7() { return (m_opcode >> 5) & 0x7f; }
};
+class A64DOpcodeDmb : public A64DOpcode {
+ static const char* const s_optionNames[16];
+
+public:
+ static const uint32_t mask = 0xfffff0ff;
+ static const uint32_t pattern = 0xd50330bf;
+
+ DEFINE_STATIC_FORMAT(A64DOpcodeDmb, thisObj);
+
+ const char* format();
+
+ const char* opName() { return "dmb"; }
+ const char* option() { return s_optionNames[crM()]; }
+ unsigned crM() { return (m_opcode >> 8) & 0xf; }
+};
+
class A64DOpcodeLoadStore : public A64DOpcode {
private:
static const char* const s_opNames[32];
@@ -565,6 +623,22 @@ public:
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;
@@ -618,7 +692,7 @@ public:
const char* format();
bool isTst() { return ((opNumber() == 6) && (rd() == 31)); }
- bool isMov() { return ((opNumber() == 2) && (rn() == 31)); }
+ bool isMov() { return ((opc() == 1) && (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; }
@@ -688,5 +762,3 @@ public:
} } // namespace JSC::ARM64Disassembler
using JSC::ARM64Disassembler::A64DOpcode;
-
-#endif // A64DOpcode_h