diff options
Diffstat (limited to 'Source/JavaScriptCore/disassembler/ARMv7')
-rw-r--r-- | Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.cpp | 176 | ||||
-rw-r--r-- | Source/JavaScriptCore/disassembler/ARMv7/ARMv7DOpcode.h | 103 |
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; |