summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/disassembler/ARMv7
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/disassembler/ARMv7')
-rw-r--r--Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.cpp176
-rw-r--r--Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.h103
2 files changed, 271 insertions, 8 deletions
diff --git a/Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.cpp b/Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.cpp
index fb6e0db83..3175cccbd 100644
--- a/Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.cpp
+++ b/Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.cpp
@@ -32,6 +32,7 @@
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
+#include <string.h>
namespace JSC { namespace ARMv7Disassembler {
@@ -48,7 +49,7 @@ const char* const ARMv7DOpcode::s_optionName[8] = {
};
const char* const ARMv7DOpcode::s_shiftNames[4] = {
- "lsl", "lsr", "asl", "ror"
+ "lsl", "lsr", "asr", "ror"
};
const char* const ARMv7DOpcode::s_specialRegisterNames[3] = { "sp", "lr", "pc" };
@@ -90,8 +91,8 @@ static Opcode16GroupInitializer opcode16BitGroupList[] = {
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(0x10, ARMv7DOpcodeStoreRegisterImmediateHalfWord),
+ OPCODE_GROUP_ENTRY(0x11, ARMv7DOpcodeLoadRegisterImmediateHalfWord),
OPCODE_GROUP_ENTRY(0x12, ARMv7DOpcodeLoadStoreRegisterSPRelative),
OPCODE_GROUP_ENTRY(0x13, ARMv7DOpcodeLoadStoreRegisterSPRelative),
OPCODE_GROUP_ENTRY(0x14, ARMv7DOpcodeGeneratePCRelativeAddress),
@@ -112,11 +113,16 @@ static Opcode16GroupInitializer opcode16BitGroupList[] = {
};
static Opcode32GroupInitializer opcode32BitGroupList[] = {
+ OPCODE_GROUP_ENTRY(0x4, ARMv7DOpcodeDataPopMultiple),
+ OPCODE_GROUP_ENTRY(0x4, ARMv7DOpcodeDataPushMultiple),
OPCODE_GROUP_ENTRY(0x5, ARMv7DOpcodeDataProcessingShiftedReg),
+ OPCODE_GROUP_ENTRY(0x6, ARMv7DOpcodeVLDR),
OPCODE_GROUP_ENTRY(0x6, ARMv7DOpcodeVMOVSinglePrecision),
OPCODE_GROUP_ENTRY(0x6, ARMv7DOpcodeVMOVDoublePrecision),
OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeFPTransfer),
OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeVMSR),
+ OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeVCMP),
+ OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeVCVTBetweenFPAndInt),
OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeDataProcessingModifiedImmediate),
OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeConditionalBranchT3),
OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeBranchOrBranchLink),
@@ -132,6 +138,8 @@ static Opcode32GroupInitializer opcode32BitGroupList[] = {
OPCODE_GROUP_ENTRY(0xb, ARMv7DOpcodeBranchOrBranchLink),
OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeLoadRegister),
OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeDataPushPopSingle), // Should be before StoreSingle*
+ OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeDataPopMultiple),
+ OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeDataPushMultiple),
OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeStoreSingleRegister),
OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeStoreSingleImmediate12),
OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeStoreSingleImmediate8),
@@ -142,6 +150,9 @@ static Opcode32GroupInitializer opcode32BitGroupList[] = {
OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeDataProcessingRegExtend),
OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeDataProcessingRegParallel),
OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeDataProcessingRegMisc),
+ OPCODE_GROUP_ENTRY(0xe, ARMv7DOpcodeVLDR),
+ OPCODE_GROUP_ENTRY(0xf, ARMv7DOpcodeVCMP),
+ OPCODE_GROUP_ENTRY(0xf, ARMv7DOpcodeVCVTBetweenFPAndInt),
};
bool ARMv7DOpcode::s_initialized = false;
@@ -269,7 +280,7 @@ void ARMv7DOpcode::appendRegisterList(unsigned registers)
appendCharacter('{');
for (unsigned i = 0; i < 16; i++) {
- if (registers & i) {
+ if (registers & (1 << i)) {
if (numberPrinted++)
appendSeparator();
appendRegisterName(i);
@@ -513,6 +524,25 @@ const char* ARMv7DOpcodeLoadStoreRegisterImmediate::format()
return m_formatBuffer;
}
+unsigned ARMv7DOpcodeLoadStoreRegisterImmediate::scale()
+{
+ switch (op()) {
+ case 0:
+ case 1:
+ return 2;
+ case 2:
+ case 3:
+ return 0;
+ case 4:
+ case 5:
+ return 1;
+ default:
+ break;
+ }
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
const char* const ARMv7DOpcodeLoadStoreRegisterOffsetT1::s_opNames[8] = {
"str", "strh", "strb", "ldrsb", "ldr", "ldrh", "ldrb", "ldrsh"
};
@@ -1424,6 +1454,46 @@ const char* ARMv7DOpcodeDataPushPopSingle::format()
return m_formatBuffer;
}
+void ARMv7DOpcodeDataPushPopMultiple::appendRegisterList()
+{
+ unsigned registers = registerList();
+
+ appendCharacter('{');
+ bool needSeparator = false;
+
+ for (unsigned i = 0; i < 16; i++) {
+ if (registers & (1 << i)) {
+ if (needSeparator)
+ appendSeparator();
+ appendRegisterName(i);
+ needSeparator = true;
+ }
+ }
+ appendCharacter('}');
+}
+
+const char* ARMv7DOpcodeDataPopMultiple::format()
+{
+ if (condition() != 0xe)
+ bufferPrintf(" pop%-4.4s", conditionName(condition()));
+ else
+ appendInstructionName("pop");
+ appendRegisterList();
+
+ return m_formatBuffer;
+}
+
+const char* ARMv7DOpcodeDataPushMultiple::format()
+{
+ if (condition() != 0xe)
+ bufferPrintf(" push%-3.3s", conditionName(condition()));
+ else
+ appendInstructionName("push");
+ appendRegisterList();
+
+ return m_formatBuffer;
+}
+
const char* ARMv7DOpcodeStoreSingleImmediate12::format()
{
appendInstructionName(opName());
@@ -1493,6 +1563,104 @@ const char* ARMv7DOpcodeStoreSingleRegister::format()
return m_formatBuffer;
}
+const char* ARMv7DOpcodeVCMP::format()
+{
+ bufferPrintf(" vcmp");
+
+ if (eBit())
+ appendCharacter('e'); // Raise exception on qNaN
+
+ if (condition() != 0xe)
+ appendString(conditionName(condition()));
+
+ appendCharacter('.');
+ appendString(szBit() ? "f64" : "f32");
+ appendCharacter(' ');
+ if (szBit()) {
+ appendFPRegisterName('d', (dBit() << 4) | vd());
+ appendSeparator();
+ appendFPRegisterName('d', (mBit() << 4) | vm());
+ } else {
+ appendFPRegisterName('s', (vd() << 1) | dBit());
+ appendSeparator();
+ appendFPRegisterName('s', (vm() << 1) | mBit());
+ }
+
+ return m_formatBuffer;
+}
+
+const char* ARMv7DOpcodeVCVTBetweenFPAndInt::format()
+{
+ bufferPrintf(" vcvt");
+ bool convertToInteger = op2() & 0x4;
+
+ if (convertToInteger) {
+ if (!op())
+ appendCharacter('r'); // Round using mode in FPSCR
+ if (condition() != 0xe)
+ appendString(conditionName(condition()));
+ appendCharacter('.');
+ appendCharacter((op2() & 1) ? 's' : 'u');
+ appendString("32.f");
+ appendString(szBit() ? "64" : "32");
+ appendCharacter(' ');
+ appendFPRegisterName('s', (vd() << 1) | dBit());
+ appendSeparator();
+ if (szBit())
+ appendFPRegisterName('d', (mBit() << 4) | vm());
+ else
+ appendFPRegisterName('s', (vm() << 1) | mBit());
+ } else {
+ if (condition() != 0xe)
+ appendString(conditionName(condition()));
+ appendCharacter('.');
+ appendString(szBit() ? "f64." : "f32.");
+ appendString(op() ? "s32" : "u32");
+ appendCharacter(' ');
+ if (szBit())
+ appendFPRegisterName('d', (dBit() << 4) | vd());
+ else
+ appendFPRegisterName('s', (vd() << 1) | dBit());
+ appendSeparator();
+ appendFPRegisterName('s', (vm() << 1) | mBit());
+ }
+
+ return m_formatBuffer;
+}
+
+const char* ARMv7DOpcodeVLDR::format()
+{
+ if (condition() != 0xe)
+ bufferPrintf(" vldr%-3.3s", conditionName(condition()));
+ else
+ appendInstructionName("vldr");
+
+ appendFPRegisterName(doubleReg() ? 'd' : 's', vd());
+ appendSeparator();
+
+ int immediate = immediate8() * 4;
+
+ if (!uBit())
+ immediate = -immediate;
+
+ appendCharacter('[');
+
+ if (rn() == RegPC)
+ appendPCRelativeOffset(immediate);
+ else {
+ appendRegisterName(rn());
+
+ if (immediate) {
+ appendSeparator();
+ appendSignedImmediate(immediate);
+ }
+ }
+
+ appendCharacter(']');
+
+ return m_formatBuffer;
+}
+
const char* ARMv7DOpcodeVMOVDoublePrecision::format()
{
appendInstructionName("vmov");
diff --git a/Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.h b/Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.h
index 28bddd53e..13e209db7 100644
--- a/Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.h
+++ b/Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.h
@@ -275,7 +275,7 @@ protected:
const char* opName() { return s_opNames[op()]; }
unsigned op() { return (m_opcode >> 9) & 0x1; }
- unsigned immediate3() { return (m_opcode >> 6) & 0x3; }
+ unsigned immediate3() { return (m_opcode >> 6) & 0x7; }
unsigned rn() { return (m_opcode >> 3) & 0x7; }
};
@@ -441,7 +441,7 @@ protected:
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); }
+ unsigned scale();
};
class ARMv7DOpcodeLoadStoreRegisterImmediateWordAndByte : public ARMv7DOpcodeLoadStoreRegisterImmediate {
@@ -452,7 +452,7 @@ public:
DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadStoreRegisterImmediate, thisObj);
};
-class ARMv7DOpcodeLoadStoreRegisterImmediateHalfWord : public ARMv7DOpcodeLoadStoreRegisterImmediate {
+class ARMv7DOpcodeStoreRegisterImmediateHalfWord : public ARMv7DOpcodeLoadStoreRegisterImmediate {
public:
static const uint16_t s_mask = 0xf800;
static const uint16_t s_pattern = 0x8000;
@@ -460,6 +460,14 @@ public:
DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadStoreRegisterImmediate, thisObj);
};
+class ARMv7DOpcodeLoadRegisterImmediateHalfWord : public ARMv7DOpcodeLoadStoreRegisterImmediate {
+public:
+ static const uint16_t s_mask = 0xf800;
+ static const uint16_t s_pattern = 0x8800;
+
+ DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadStoreRegisterImmediate, thisObj);
+};
+
class ARMv7DOpcodeLoadStoreRegisterOffsetT1 : public ARMv7D16BitOpcode {
private:
static const char* const s_opNames[8];
@@ -621,7 +629,7 @@ protected:
const char* opName() { return op() ? "pop" : "push"; }
unsigned op() { return (m_opcode >> 11) & 0x1; }
- unsigned registerMask() { return ((m_opcode << 6) & 0x4000) | (m_opcode & 0x7f); }
+ unsigned registerMask() { return ((m_opcode << 6) & 0x4000) | (m_opcode & 0xff); }
};
class ARMv7DOpcodeMoveImmediateT1 : public ARMv7D16BitOpcode {
@@ -1011,6 +1019,36 @@ protected:
unsigned op() { return (m_opcode >> 20) & 0x1; }
};
+class ARMv7DOpcodeDataPushPopMultiple : public ARMv7D32BitOpcode {
+protected:
+ void appendRegisterList();
+
+ unsigned registerList() { return m_opcode & 0xffff; }
+ unsigned condition() { return m_opcode >> 28; }
+};
+
+class ARMv7DOpcodeDataPopMultiple : public ARMv7DOpcodeDataPushPopMultiple {
+public:
+ static const uint32_t s_mask = 0x0fff0000;
+ static const uint32_t s_pattern = 0x08bd0000;
+
+ DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataPopMultiple, thisObj);
+
+protected:
+ const char* format();
+};
+
+class ARMv7DOpcodeDataPushMultiple : public ARMv7DOpcodeDataPushPopMultiple {
+public:
+ static const uint32_t s_mask = 0xfe7f0000;
+ static const uint32_t s_pattern = 0xe82d0000;
+
+ DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataPushMultiple, thisObj);
+
+protected:
+ const char* format();
+};
+
class ARMv7DOpcodeDataStoreSingle : public ARMv7D32BitOpcode {
protected:
static const char* const s_opNames[4];
@@ -1086,6 +1124,63 @@ protected:
unsigned immediate16() { return ((m_opcode >> 4) & 0xf000) | ((m_opcode >> 15) & 0x0800) | ((m_opcode >> 4) & 0x0700) | (m_opcode & 0x00ff); }
};
+class ARMv7DOpcodeVCMP : public ARMv7D32BitOpcode {
+public:
+ static const uint32_t s_mask = 0x0fbf0e50;
+ static const uint32_t s_pattern = 0x0eb40a40;
+
+ DEFINE_STATIC_FORMAT32(ARMv7DOpcodeVCMP, thisObj);
+
+protected:
+ const char* format();
+
+ unsigned condition() { return m_opcode >> 28; }
+ unsigned dBit() { return (m_opcode >> 22) & 0x1; }
+ unsigned vd() { return (m_opcode >> 12) & 0xf; }
+ unsigned szBit() { return (m_opcode >> 8) & 0x1; }
+ unsigned eBit() { return (m_opcode >> 7) & 0x1; }
+ unsigned mBit() { return (m_opcode >> 5) & 0x1; }
+ unsigned vm() { return m_opcode & 0xf; }
+};
+
+class ARMv7DOpcodeVCVTBetweenFPAndInt : public ARMv7D32BitOpcode {
+public:
+ static const uint32_t s_mask = 0x0fb80e50;
+ static const uint32_t s_pattern = 0x0eb80a40;
+
+ DEFINE_STATIC_FORMAT32(ARMv7DOpcodeVCVTBetweenFPAndInt, thisObj);
+
+protected:
+ const char* format();
+
+ unsigned condition() { return m_opcode >> 28; }
+ unsigned dBit() { return (m_opcode >> 22) & 0x1; }
+ unsigned op2() { return (m_opcode >> 16) & 0x7; }
+ unsigned vd() { return (m_opcode >> 12) & 0xf; }
+ unsigned szBit() { return (m_opcode >> 8) & 0x1; }
+ unsigned op() { return (m_opcode >> 7) & 0x1; }
+ unsigned mBit() { return (m_opcode >> 5) & 0x1; }
+ unsigned vm() { return m_opcode & 0xf; }
+};
+
+class ARMv7DOpcodeVLDR : public ARMv7D32BitOpcode {
+public:
+ static const uint32_t s_mask = 0x0f300e00;
+ static const uint32_t s_pattern = 0x0d100a00;
+
+ DEFINE_STATIC_FORMAT32(ARMv7DOpcodeVLDR, thisObj);
+
+protected:
+ const char* format();
+
+ unsigned condition() { return m_opcode >> 28; }
+ unsigned uBit() { return (m_opcode >> 23) & 0x1; }
+ unsigned rn() { return (m_opcode >> 16) & 0xf; }
+ unsigned vd() { return ((m_opcode >> 18) & 0x10) | ((m_opcode >> 12) & 0xf); }
+ bool doubleReg() { return !!(m_opcode & 0x100); }
+ unsigned immediate8() { return m_opcode & 0xff; }
+};
+
class ARMv7DOpcodeVMOVDoublePrecision : public ARMv7D32BitOpcode {
public:
static const uint32_t s_mask = 0xffe00fd0;