Cleanup: Reduce cpu specific #ifdefs in common masm code
authorSimon Hausmann <simon.hausmann@digia.com>
Tue, 12 Feb 2013 14:55:44 +0000 (15:55 +0100)
committerLars Knoll <lars.knoll@digia.com>
Tue, 12 Feb 2013 21:50:22 +0000 (22:50 +0100)
Centralize the callee save register handling as well as potentially cpu
specific stack frame enter/leave code (like ARM doesn't automatically save the
link register) inside bigger cpu specific #ifdefs instead of sprinkling them
throughout the code. That should make it easier in the future to port to
new calling conventions and architectures.

Change-Id: I92fed7cc3d0f7eb4da86843b7ad59581a64f635f
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
src/v4/qv4isel_masm.cpp
src/v4/qv4isel_masm_p.h

index 0960adf..5098a44 100644 (file)
@@ -59,6 +59,45 @@ using namespace QQmlJS;
 using namespace QQmlJS::MASM;
 using namespace QQmlJS::VM;
 
+/* Platform/Calling convention/Architecture specific section */
+
+#if CPU(X86_64)
+static const Assembler::RegisterID calleeSavedRegisters[] = {
+    // Not used: JSC::X86Registers::rbx,
+    // Not used: JSC::X86Registers::r10,
+    // Not used: JSC::X86Registers::r13,
+    JSC::X86Registers::r14
+    // Not used: JSC::X86Registers::r15,
+};
+#endif
+
+#if CPU(X86)
+static const Assembler::RegisterID calleeSavedRegisters[] = {
+    // Not used: JSC::X86Registers::ebx,
+    JSC::X86Registers::esi
+    // Not used: JSC::X86Registers::edi,
+};
+#endif
+
+#if CPU(ARM)
+static const Assembler::RegisterID calleeSavedRegisters[] = {
+    // ### FIXME: push multi-register push instruction, remove unused registers.
+    JSC::ARMRegisters::r4,
+    JSC::ARMRegisters::r5,
+    JSC::ARMRegisters::r6,
+    JSC::ARMRegisters::r7,
+    JSC::ARMRegisters::r8,
+    JSC::ARMRegisters::r9,
+    JSC::ARMRegisters::r10,
+    JSC::ARMRegisters::r11
+};
+#endif
+
+static const int calleeSavedRegisterCount = sizeof(calleeSavedRegisters) / sizeof(calleeSavedRegisters[0]);
+
+/* End of platform/calling convention/architecture specific section */
+
+
 const Assembler::VoidType Assembler::Void;
 
 Assembler::Assembler(IR::Function* function)
@@ -124,38 +163,32 @@ void Assembler::storeValue(VM::Value value, IR::Temp* destination)
 
 void Assembler::enterStandardStackFrame(int locals)
 {
-#if CPU(ARM)
-    push(JSC::ARMRegisters::lr);
-#endif
+    platformEnterStandardStackFrame();
+
+    // ### FIXME: Handle through calleeSavedRegisters mechanism
+    // or eliminate StackFrameRegister altogether.
     push(StackFrameRegister);
     move(StackPointerRegister, StackFrameRegister);
 
-    // space for the locals and the ContextRegister
-    int32_t frameSize = locals * sizeof(QQmlJS::VM::Value) + sizeof(void*);
+    // space for the locals and callee saved registers
+    int32_t frameSize = locals * sizeof(QQmlJS::VM::Value) + sizeof(void*) * calleeSavedRegisterCount;
 
 #if CPU(X86) || CPU(X86_64)
     frameSize = (frameSize + 15) & ~15; // align on 16 byte boundaries for MMX
 #endif
     subPtr(TrustedImm32(frameSize), StackPointerRegister);
 
-#if CPU(X86) || CPU(ARM)
-    for (int saveReg = CalleeSavedFirstRegister; saveReg <= CalleeSavedLastRegister; ++saveReg)
-        push(static_cast<RegisterID>(saveReg));
-#endif
-    // save the ContextRegister
-    storePtr(ContextRegister, StackPointerRegister);
+    for (int i = 0; i < calleeSavedRegisterCount; ++i)
+        storePtr(calleeSavedRegisters[i], Address(StackPointerRegister, i * sizeof(void*)));
 }
 
 void Assembler::leaveStandardStackFrame(int locals)
 {
-    // restore the ContextRegister
-    loadPtr(StackPointerRegister, ContextRegister);
+    // restore the callee saved registers
+    for (int i = calleeSavedRegisterCount - 1; i >= 0; --i)
+        loadPtr(Address(StackPointerRegister, i * sizeof(void*)), calleeSavedRegisters[i]);
 
-#if CPU(X86) || CPU(ARM)
-    for (int saveReg = CalleeSavedLastRegister; saveReg >= CalleeSavedFirstRegister; --saveReg)
-        pop(static_cast<RegisterID>(saveReg));
-#endif
-    // space for the locals and the ContextRegister
+    // space for the locals and the callee saved registers
     int32_t frameSize = locals * sizeof(QQmlJS::VM::Value) + sizeof(void*);
 #if CPU(X86) || CPU(X86_64)
     frameSize = (frameSize + 15) & ~15; // align on 16 byte boundaries for MMX
@@ -163,9 +196,7 @@ void Assembler::leaveStandardStackFrame(int locals)
     addPtr(TrustedImm32(frameSize), StackPointerRegister);
 
     pop(StackFrameRegister);
-#if CPU(ARM)
-    pop(JSC::ARMRegisters::lr);
-#endif
+    platformLeaveStandardStackFrame();
 }
 
 
@@ -401,12 +432,11 @@ void InstructionSelection::run(VM::Function *vmFunction, IR::Function *function)
     // That shifts the index the context pointer argument by one.
     contextPointer++;
 #endif
-#if CPU(X86)
-    _as->loadPtr(addressForArgument(contextPointer), Assembler::ContextRegister);
-#elif CPU(X86_64) || CPU(ARM)
+
+#ifdef ARGUMENTS_IN_REGISTERS
     _as->move(_as->registerForArgument(contextPointer), Assembler::ContextRegister);
 #else
-    assert(!"TODO");
+    _as->loadPtr(addressForArgument(contextPointer), Assembler::ContextRegister);
 #endif
 
     foreach (IR::BasicBlock *block, _function->basicBlocks) {
index f20ffd9..3662268 100644 (file)
@@ -63,14 +63,13 @@ public:
 #if CPU(X86)
 
 #undef VALUE_FITS_IN_REGISTER
+#undef ARGUMENTS_IN_REGISTERS
 
     static const RegisterID StackFrameRegister = JSC::X86Registers::ebp;
     static const RegisterID StackPointerRegister = JSC::X86Registers::esp;
     static const RegisterID ContextRegister = JSC::X86Registers::esi;
     static const RegisterID ReturnValueRegister = JSC::X86Registers::eax;
     static const RegisterID ScratchRegister = JSC::X86Registers::ecx;
-    static const RegisterID CalleeSavedFirstRegister = ScratchRegister;
-    static const RegisterID CalleeSavedLastRegister = ScratchRegister;
     static const RegisterID IntegerOpRegister = JSC::X86Registers::eax;
     static const FPRegisterID FPGpr0 = JSC::X86Registers::xmm0;
 
@@ -83,9 +82,13 @@ public:
         // Not reached.
         return JSC::X86Registers::eax;
     }
+
+    inline void platformEnterStandardStackFrame() {}
+    inline void platformLeaveStandardStackFrame() {}
 #elif CPU(X86_64)
 
 #define VALUE_FITS_IN_REGISTER
+#define ARGUMENTS_IN_REGISTERS
 
     static const RegisterID StackFrameRegister = JSC::X86Registers::ebp;
     static const RegisterID StackPointerRegister = JSC::X86Registers::esp;
@@ -111,17 +114,18 @@ public:
         assert(index >= 0 && index < RegisterArgumentCount);
         return regs[index];
     };
+    inline void platformEnterStandardStackFrame() {}
+    inline void platformLeaveStandardStackFrame() {}
 #elif CPU(ARM)
 
 #undef VALUE_FITS_IN_REGISTER
+#define ARGUMENTS_IN_REGISTERS
 
     static const RegisterID StackFrameRegister = JSC::ARMRegisters::r4;
     static const RegisterID StackPointerRegister = JSC::ARMRegisters::sp;
     static const RegisterID ContextRegister = JSC::ARMRegisters::r5;
     static const RegisterID ReturnValueRegister = JSC::ARMRegisters::r0;
     static const RegisterID ScratchRegister = JSC::ARMRegisters::r6;
-    static const RegisterID CalleeSavedFirstRegister = JSC::ARMRegisters::r4;
-    static const RegisterID CalleeSavedLastRegister = JSC::ARMRegisters::r11;
     static const RegisterID IntegerOpRegister = JSC::X86Registers::r0;
     static const FPRegisterID FPGpr0 = JSC::ARMRegisters::d0;
 
@@ -138,6 +142,14 @@ public:
         assert(index >= 0 && index < RegisterArgumentCount);
         return static_cast<RegisterID>(JSC::ARMRegisters::r0 + index);
     };
+    inline void platformEnterStandardStackFrame()
+    {
+        push(JSC::ARMRegisters::lr);
+    }
+    inline void platformLeaveStandardStackFrame()
+    {
+        pop(JSC::ARMRegisters::lr);
+    }
 #else
 #error Argh.
 #endif