Title: [161318] branches/jsCStack/Source/_javascript_Core
Revision
161318
Author
[email protected]
Date
2014-01-04 23:29:27 -0800 (Sat, 04 Jan 2014)

Log Message

CStack Branch: ARM64 needs push/pop pair macro assembler instructions
https://bugs.webkit.org/show_bug.cgi?id=126474

Reviewed by Mark Lam.

Added templated ldp() and stp() instruction generators to the ARM64 assembler.
Added popPair() and pushPair() to the ARM64 macro assembler.  Added ARM64
version of emitFunctionPrologue() and emitFunctionEpilogue() to AssemblyHelpers.h
that use the pushPair() and popPair() macro instructions.  Added disassembler support
for the newly added load/store pair instructions.

Verified that we correctly generate the new instructions and that they disassemble
the same as what the debugger shows.

* assembler/ARM64Assembler.h:
(JSC::isInt7):
(JSC::isInt11):
(JSC::PairPostIndex::PairPostIndex):
(JSC::PairPostIndex::operator int):
(JSC::PairPreIndex::PairPreIndex):
(JSC::PairPreIndex::operator int):
(JSC::ARM64Assembler::memPairOffsetShift):
(JSC::ARM64Assembler::ldp):
(JSC::ARM64Assembler::stp):
(JSC::ARM64Assembler::loadStoreRegisterPairPostIndex):
(JSC::ARM64Assembler::loadStoreRegisterPairPreIndex):
* assembler/MacroAssemblerARM64.h:
(JSC::MacroAssemblerARM64::popPair):
(JSC::MacroAssemblerARM64::pushPair):
* disassembler/ARM64/A64DOpcode.cpp:
(JSC::ARM64Disassembler::A64DOpcode::appendRegisterName):
(JSC::ARM64Disassembler::A64DOpcodeLoadStoreRegisterPair::opName):
(JSC::ARM64Disassembler::A64DOpcodeLoadStoreRegisterPair::format):
* disassembler/ARM64/A64DOpcode.h:
(JSC::ARM64Disassembler::A64DOpcodeLoadStoreRegisterPair::rt2):
(JSC::ARM64Disassembler::A64DOpcodeLoadStoreRegisterPair::immediate7):
(JSC::ARM64Disassembler::A64DOpcodeLoadStoreRegisterPair::offsetMode):
(JSC::ARM64Disassembler::A64DOpcodeLoadStoreRegisterPair::lBit):
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::emitFunctionPrologue):
(JSC::AssemblyHelpers::emitFunctionEpilogue):

Modified Paths

Diff

Modified: branches/jsCStack/Source/_javascript_Core/ChangeLog (161317 => 161318)


--- branches/jsCStack/Source/_javascript_Core/ChangeLog	2014-01-05 02:15:25 UTC (rev 161317)
+++ branches/jsCStack/Source/_javascript_Core/ChangeLog	2014-01-05 07:29:27 UTC (rev 161318)
@@ -1,5 +1,49 @@
 2014-01-04  Michael Saboff  <[email protected]>
 
+        CStack Branch: ARM64 needs push/pop pair macro assembler instructions
+        https://bugs.webkit.org/show_bug.cgi?id=126474
+
+        Reviewed by Mark Lam.
+
+        Added templated ldp() and stp() instruction generators to the ARM64 assembler.
+        Added popPair() and pushPair() to the ARM64 macro assembler.  Added ARM64
+        version of emitFunctionPrologue() and emitFunctionEpilogue() to AssemblyHelpers.h
+        that use the pushPair() and popPair() macro instructions.  Added disassembler support
+        for the newly added load/store pair instructions.
+
+        Verified that we correctly generate the new instructions and that they disassemble
+        the same as what the debugger shows.
+
+        * assembler/ARM64Assembler.h:
+        (JSC::isInt7):
+        (JSC::isInt11):
+        (JSC::PairPostIndex::PairPostIndex):
+        (JSC::PairPostIndex::operator int):
+        (JSC::PairPreIndex::PairPreIndex):
+        (JSC::PairPreIndex::operator int):
+        (JSC::ARM64Assembler::memPairOffsetShift):
+        (JSC::ARM64Assembler::ldp):
+        (JSC::ARM64Assembler::stp):
+        (JSC::ARM64Assembler::loadStoreRegisterPairPostIndex):
+        (JSC::ARM64Assembler::loadStoreRegisterPairPreIndex):
+        * assembler/MacroAssemblerARM64.h:
+        (JSC::MacroAssemblerARM64::popPair):
+        (JSC::MacroAssemblerARM64::pushPair):
+        * disassembler/ARM64/A64DOpcode.cpp:
+        (JSC::ARM64Disassembler::A64DOpcode::appendRegisterName):
+        (JSC::ARM64Disassembler::A64DOpcodeLoadStoreRegisterPair::opName):
+        (JSC::ARM64Disassembler::A64DOpcodeLoadStoreRegisterPair::format):
+        * disassembler/ARM64/A64DOpcode.h:
+        (JSC::ARM64Disassembler::A64DOpcodeLoadStoreRegisterPair::rt2):
+        (JSC::ARM64Disassembler::A64DOpcodeLoadStoreRegisterPair::immediate7):
+        (JSC::ARM64Disassembler::A64DOpcodeLoadStoreRegisterPair::offsetMode):
+        (JSC::ARM64Disassembler::A64DOpcodeLoadStoreRegisterPair::lBit):
+        * jit/AssemblyHelpers.h:
+        (JSC::AssemblyHelpers::emitFunctionPrologue):
+        (JSC::AssemblyHelpers::emitFunctionEpilogue):
+
+2014-01-04  Michael Saboff  <[email protected]>
+
         CStack Branch: ARM64 add of stack pointer not valid as second source operand
         https://bugs.webkit.org/show_bug.cgi?id=126486
 

Modified: branches/jsCStack/Source/_javascript_Core/assembler/ARM64Assembler.h (161317 => 161318)


--- branches/jsCStack/Source/_javascript_Core/assembler/ARM64Assembler.h	2014-01-05 02:15:25 UTC (rev 161317)
+++ branches/jsCStack/Source/_javascript_Core/assembler/ARM64Assembler.h	2014-01-05 07:29:27 UTC (rev 161318)
@@ -40,14 +40,26 @@
 #define DATASIZE DATASIZE_OF(datasize)
 #define MEMOPSIZE MEMOPSIZE_OF(datasize)
 #define CHECK_FP_MEMOP_DATASIZE() ASSERT(datasize == 8 || datasize == 16 || datasize == 32 || datasize == 64 || datasize == 128)
+#define MEMPAIROPSIZE_INT(datasize) ((datasize == 64) ? MemPairOp_64 : MemPairOp_32)
+#define MEMPAIROPSIZE_FP(datasize) ((datasize == 128) ? MemPairOp_V128 : (datasize == 64) ? MemPairOp_V64 : MemPairOp_32)
 
 namespace JSC {
 
+ALWAYS_INLINE bool isInt7(int32_t value)
+{
+    return value == ((value << 25) >> 25);
+}
+
 ALWAYS_INLINE bool isInt9(int32_t value)
 {
     return value == ((value << 23) >> 23);
 }
 
+ALWAYS_INLINE bool isInt11(int32_t value)
+{
+    return value == ((value << 21) >> 21);
+}
+
 ALWAYS_INLINE bool isUInt5(int32_t value)
 {
     return !(value & ~0x1f);
@@ -119,6 +131,34 @@
     int m_value;
 };
 
+class PairPostIndex {
+public:
+    explicit PairPostIndex(int value)
+        : m_value(value)
+    {
+        ASSERT(isInt11(value));
+    }
+
+    operator int() { return m_value; }
+
+private:
+    int m_value;
+};
+
+class PairPreIndex {
+public:
+    explicit PairPreIndex(int value)
+        : m_value(value)
+    {
+        ASSERT(isInt11(value));
+    }
+
+    operator int() { return m_value; }
+
+private:
+    int m_value;
+};
+
 class LogicalImmediate {
 public:
     static LogicalImmediate create32(uint32_t value)
@@ -823,6 +863,16 @@
         MemOp_LOAD_signed32 = 3 // size may be 0 or 1
     };
 
+    enum MemPairOpSize {
+        MemPairOp_32 = 0,
+        MemPairOp_LoadSigned_32 = 1,
+        MemPairOp_64 = 2,
+
+        MemPairOp_V32 = MemPairOp_32,
+        MemPairOp_V64 = 1,
+        MemPairOp_V128 = 2
+    };
+
     enum MoveWideOp {
         MoveWideOp_N = 0,
         MoveWideOp_Z = 2,
@@ -836,6 +886,14 @@
         LdrLiteralOp_128BIT = 2
     };
 
+    static unsigned memPairOffsetShift(bool V, MemPairOpSize size)
+    {
+        // return the log2 of the size in bytes, e.g. 64 bit size returns 3
+        if (V)
+            return size + 2;
+        return (size >> 1) + 2;
+    }
+
 public:
     // Integer Instructions:
 
@@ -1216,6 +1274,20 @@
     }
 
     template<int datasize>
+    ALWAYS_INLINE void ldp(RegisterID rt, RegisterID rt2, RegisterID rn, PairPostIndex simm)
+    {
+        CHECK_DATASIZE();
+        insn(loadStoreRegisterPairPostIndex(MEMPAIROPSIZE_INT(datasize), false, MemOp_LOAD, simm, rn, rt, rt2));
+    }
+
+    template<int datasize>
+    ALWAYS_INLINE void ldp(RegisterID rt, RegisterID rt2, RegisterID rn, PairPreIndex simm)
+    {
+        CHECK_DATASIZE();
+        insn(loadStoreRegisterPairPreIndex(MEMPAIROPSIZE_INT(datasize), false, MemOp_LOAD, simm, rn, rt, rt2));
+    }
+
+    template<int datasize>
     ALWAYS_INLINE void ldr(RegisterID rt, RegisterID rn, RegisterID rm)
     {
         ldr<datasize>(rt, rn, rm, UXTX, 0);
@@ -1748,6 +1820,20 @@
     }
 
     template<int datasize>
+    ALWAYS_INLINE void stp(RegisterID rt, RegisterID rt2, RegisterID rn, PairPostIndex simm)
+    {
+        CHECK_DATASIZE();
+        insn(loadStoreRegisterPairPostIndex(MEMPAIROPSIZE_INT(datasize), false, MemOp_STORE, simm, rn, rt, rt2));
+    }
+
+    template<int datasize>
+    ALWAYS_INLINE void stp(RegisterID rt, RegisterID rt2, RegisterID rn, PairPreIndex simm)
+    {
+        CHECK_DATASIZE();
+        insn(loadStoreRegisterPairPreIndex(MEMPAIROPSIZE_INT(datasize), false, MemOp_STORE, simm, rn, rt, rt2));
+    }
+
+    template<int datasize>
     ALWAYS_INLINE void str(RegisterID rt, RegisterID rn, RegisterID rm)
     {
         str<datasize>(rt, rn, rm, UXTX, 0);
@@ -3361,6 +3447,23 @@
     }
 
     // 'V' means vector
+    ALWAYS_INLINE static int loadStoreRegisterPairPostIndex(MemPairOpSize size, bool V, MemOp opc, int immediate, RegisterID rn, FPRegisterID rt, FPRegisterID rt2)
+    {
+        ASSERT(size < 3);
+        ASSERT(opc == (opc & 1)); // Only load or store, load signed 64 is handled via size.
+        ASSERT(V || (size != MemPairOp_LoadSigned_32) || (opc == MemOp_LOAD)); // There isn't an integer store signed.
+        unsigned immedShiftAmount = memPairOffsetShift(V, size);
+        int imm7 = immediate >> immedShiftAmount;
+        ASSERT((imm7 << immedShiftAmount) == immediate && isInt7(imm7));
+        return (0x28800000 | size << 30 | V << 26 | opc << 22 | (imm7 & 0x7f) << 15 | rt2 << 10 | xOrSp(rn) << 5 | rt);
+    }
+
+    ALWAYS_INLINE static int loadStoreRegisterPairPostIndex(MemPairOpSize size, bool V, MemOp opc, int immediate, RegisterID rn, RegisterID rt, RegisterID rt2)
+    {
+        return loadStoreRegisterPairPostIndex(size, V, opc, immediate, rn, xOrZrAsFPR(rt), xOrZrAsFPR(rt2));
+    }
+
+    // 'V' means vector
     ALWAYS_INLINE static int loadStoreRegisterPreIndex(MemOpSize size, bool V, MemOp opc, int imm9, RegisterID rn, FPRegisterID rt)
     {
         ASSERT(!(size && V && (opc & 2))); // Maximum vector size is 128 bits.
@@ -3375,6 +3478,23 @@
     }
 
     // 'V' means vector
+    ALWAYS_INLINE static int loadStoreRegisterPairPreIndex(MemPairOpSize size, bool V, MemOp opc, int immediate, RegisterID rn, FPRegisterID rt, FPRegisterID rt2)
+    {
+        ASSERT(size < 3);
+        ASSERT(opc == (opc & 1)); // Only load or store, load signed 64 is handled via size.
+        ASSERT(V || (size != MemPairOp_LoadSigned_32) || (opc == MemOp_LOAD)); // There isn't an integer store signed.
+        unsigned immedShiftAmount = memPairOffsetShift(V, size);
+        int imm7 = immediate >> immedShiftAmount;
+        ASSERT((imm7 << immedShiftAmount) == immediate && isInt7(imm7));
+        return (0x29800000 | size << 30 | V << 26 | opc << 22 | (imm7 & 0x7f) << 15 | rt2 << 10 | xOrSp(rn) << 5 | rt);
+    }
+
+    ALWAYS_INLINE static int loadStoreRegisterPairPreIndex(MemPairOpSize size, bool V, MemOp opc, int immediate, RegisterID rn, RegisterID rt, RegisterID rt2)
+    {
+        return loadStoreRegisterPairPreIndex(size, V, opc, immediate, rn, xOrZrAsFPR(rt), xOrZrAsFPR(rt2));
+    }
+
+    // 'V' means vector
     // 'S' means shift rm
     ALWAYS_INLINE static int loadStoreRegisterRegisterOffset(MemOpSize size, bool V, MemOp opc, RegisterID rm, ExtendType option, bool S, RegisterID rn, FPRegisterID rt)
     {

Modified: branches/jsCStack/Source/_javascript_Core/assembler/MacroAssemblerARM64.h (161317 => 161318)


--- branches/jsCStack/Source/_javascript_Core/assembler/MacroAssemblerARM64.h	2014-01-05 02:15:25 UTC (rev 161317)
+++ branches/jsCStack/Source/_javascript_Core/assembler/MacroAssemblerARM64.h	2014-01-05 07:29:27 UTC (rev 161318)
@@ -1427,6 +1427,16 @@
         CRASH();
     }
 
+    void popPair(RegisterID dest1, RegisterID dest2)
+    {
+        m_assembler.ldp<64>(dest1, dest2, ARM64Registers::sp, PairPostIndex(16));
+    }
+
+    void pushPair(RegisterID src1, RegisterID src2)
+    {
+        m_assembler.stp<64>(src1, src2, ARM64Registers::sp, PairPreIndex(-16));
+    }
+
     void popToRestore(RegisterID dest)
     {
         m_assembler.ldr<64>(dest, ARM64Registers::sp, PostIndex(16));

Modified: branches/jsCStack/Source/_javascript_Core/disassembler/ARM64/A64DOpcode.cpp (161317 => 161318)


--- branches/jsCStack/Source/_javascript_Core/disassembler/ARM64/A64DOpcode.cpp	2014-01-05 02:15:25 UTC (rev 161317)
+++ branches/jsCStack/Source/_javascript_Core/disassembler/ARM64/A64DOpcode.cpp	2014-01-05 07:29:27 UTC (rev 161318)
@@ -62,6 +62,8 @@
 { 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),
@@ -172,6 +174,11 @@
 
 void A64DOpcode::appendRegisterName(unsigned registerNumber, bool is64Bit)
 {
+    if (registerNumber == 29) {
+        bufferPrintf(is64Bit ? "fp" : "wfp");
+        return;
+    }
+
     if (registerNumber == 30) {
         bufferPrintf(is64Bit ? "lr" : "wlr");
         return;
@@ -939,6 +946,63 @@
     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();

Modified: branches/jsCStack/Source/_javascript_Core/disassembler/ARM64/A64DOpcode.h (161317 => 161318)


--- branches/jsCStack/Source/_javascript_Core/disassembler/ARM64/A64DOpcode.h	2014-01-05 02:15:25 UTC (rev 161317)
+++ branches/jsCStack/Source/_javascript_Core/disassembler/ARM64/A64DOpcode.h	2014-01-05 07:29:27 UTC (rev 161318)
@@ -565,6 +565,22 @@
     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;

Modified: branches/jsCStack/Source/_javascript_Core/jit/AssemblyHelpers.h (161317 => 161318)


--- branches/jsCStack/Source/_javascript_Core/jit/AssemblyHelpers.h	2014-01-05 02:15:25 UTC (rev 161317)
+++ branches/jsCStack/Source/_javascript_Core/jit/AssemblyHelpers.h	2014-01-05 07:29:27 UTC (rev 161318)
@@ -110,6 +110,18 @@
         return 2 * sizeof(void*);
     }
 
+    void emitFunctionPrologue()
+    {
+        pushPair(framePointerRegister, linkRegister);
+        move(stackPointerRegister, framePointerRegister);
+    }
+
+    void emitFunctionEpilogue()
+    {
+        move(framePointerRegister, stackPointerRegister);
+        popPair(framePointerRegister, linkRegister);
+    }
+
     ALWAYS_INLINE void preserveReturnAddressAfterCall(RegisterID reg)
     {
         move(linkRegister, reg);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to