From ff5a76e229a024ff44414f7523d4dba8a1d6862f Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 12 Feb 2013 15:55:44 +0100 Subject: [PATCH] Cleanup: Reduce cpu specific #ifdefs in common masm code 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 --- src/v4/qv4isel_masm.cpp | 80 +++++++++++++++++++++++++++++++++---------------- src/v4/qv4isel_masm_p.h | 20 ++++++++++--- 2 files changed, 71 insertions(+), 29 deletions(-) diff --git a/src/v4/qv4isel_masm.cpp b/src/v4/qv4isel_masm.cpp index 0960adf..5098a44 100644 --- a/src/v4/qv4isel_masm.cpp +++ b/src/v4/qv4isel_masm.cpp @@ -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(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(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) { diff --git a/src/v4/qv4isel_masm_p.h b/src/v4/qv4isel_masm_p.h index f20ffd9..3662268 100644 --- a/src/v4/qv4isel_masm_p.h +++ b/src/v4/qv4isel_masm_p.h @@ -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(JSC::ARMRegisters::r0 + index); }; + inline void platformEnterStandardStackFrame() + { + push(JSC::ARMRegisters::lr); + } + inline void platformLeaveStandardStackFrame() + { + pop(JSC::ARMRegisters::lr); + } #else #error Argh. #endif -- 2.7.4