From 01058d2707027613f6740ae824a3007a4aa57527 Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Wed, 3 Jul 2013 09:21:50 -0400 Subject: [PATCH] Bug 888578 - Extend ARM masm's floatArgsInGPR workaround to memory loads. r=mjrosenb The move resolver doesn't understand using a pair of registers, which we have to do on ARM softfp to pass doubles in the integer registers, if they occur early enough in the argument list. We had a workaround (see uses of floatArgsInGPR) for when the argument is moved from a float register; this change extends it to handle loading from memory. --- js/src/ion/arm/MacroAssembler-arm.cpp | 31 ++++++++++++++++++++++----- js/src/ion/arm/MacroAssembler-arm.h | 7 +++++- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/js/src/ion/arm/MacroAssembler-arm.cpp b/js/src/ion/arm/MacroAssembler-arm.cpp index d7084b3be535..12590a86e8dd 100644 --- a/js/src/ion/arm/MacroAssembler-arm.cpp +++ b/js/src/ion/arm/MacroAssembler-arm.cpp @@ -2995,8 +2995,10 @@ MacroAssemblerARMCompat::setupABICall(uint32_t args) #else usedSlots_ = 0; #endif - floatArgsInGPR[0] = VFPRegister(); - floatArgsInGPR[1] = VFPRegister(); + floatArgsInGPR[0] = MoveOperand(); + floatArgsInGPR[1] = MoveOperand(); + floatArgsInGPRValid[0] = false; + floatArgsInGPRValid[1] = false; } void @@ -3081,7 +3083,8 @@ MacroAssemblerARMCompat::passABIArg(const MoveOperand &from) MoveOperand dest; if (GetIntArgReg(usedSlots_, 0, &destReg)) { if (from.isDouble()) { - floatArgsInGPR[destReg.code() >> 1] = VFPRegister(from.floatReg()); + floatArgsInGPR[destReg.code() >> 1] = from; + floatArgsInGPRValid[destReg.code() >> 1] = true; useResolver = false; } else if (from.isGeneralReg() && from.reg() == destReg) { // No need to move anything @@ -3150,8 +3153,26 @@ MacroAssemblerARMCompat::callWithABIPre(uint32_t *stackAdjust) emitter.finish(); } for (int i = 0; i < 2; i++) { - if (!floatArgsInGPR[i].isInvalid()) - ma_vxfer(floatArgsInGPR[i], Register::FromCode(i*2), Register::FromCode(i*2+1)); + if (floatArgsInGPRValid[i]) { + MoveOperand from = floatArgsInGPR[i]; + Register to0 = Register::FromCode(i * 2), to1 = Register::FromCode(i * 2 + 1); + + if (from.isFloatReg()) { + ma_vxfer(VFPRegister(from.floatReg()), to0, to1); + } else { + JS_ASSERT(from.isFloatAddress()); + // Note: We can safely use the MoveOperand's displacement here, + // even if the base is SP: MoveEmitter::toOperand adjusts + // SP-relative operands by the difference between the current + // stack usage and stackAdjust, which emitter.finish() resets + // to 0. + // + // Warning: if the offset isn't within [-255,+255] then this + // will assert-fail (or, if non-debug, load the wrong words). + // Nothing uses such an offset at the time of this writing. + ma_ldrd(EDtrAddr(from.base(), EDtrOffImm(from.disp())), to0, to1); + } + } } checkStackAlignment(); diff --git a/js/src/ion/arm/MacroAssembler-arm.h b/js/src/ion/arm/MacroAssembler-arm.h index 7b8dcafca6ec..7035f3684cd6 100644 --- a/js/src/ion/arm/MacroAssembler-arm.h +++ b/js/src/ion/arm/MacroAssembler-arm.h @@ -420,7 +420,12 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM bool dynamicAlignment_; bool enoughMemory_; - VFPRegister floatArgsInGPR[2]; + + // Used to work around the move resolver's lack of support for + // moving into register pairs, which the softfp ABI needs. + MoveResolver::MoveOperand floatArgsInGPR[2]; + bool floatArgsInGPRValid[2]; + // Compute space needed for the function call and set the properties of the // callee. It returns the space which has to be allocated for calling the // function.