author | Douglas Crosher <dtc-moz@scieneer.com> |
Mon, 17 Feb 2014 22:41:06 +1100 | |
changeset 169344 | e67062995f0b25951d39324622bd908d246d787b |
parent 169343 | 3576a62195ecdef9a289aa0704a2e326b32bb204 |
child 169345 | 0f7f99d0a2f56f0ac3f4c11bc8c636e6e1d4683b |
push id | 26245 |
push user | ryanvm@gmail.com |
push date | Tue, 18 Feb 2014 20:18:17 +0000 |
treeherder | mozilla-central@9019cc90719c [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mjrosenb |
bugs | 966881 |
milestone | 30.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -7998,18 +7998,18 @@ CodeGenerator::visitHaveSameClass(LHaveS return true; } bool CodeGenerator::visitAsmJSCall(LAsmJSCall *ins) { MAsmJSCall *mir = ins->mir(); -#if defined(JS_CODEGEN_ARM) && !defined(JS_CODEGEN_ARM_HARDFP) - if (mir->callee().which() == MAsmJSCall::Callee::Builtin) { +#if defined(JS_CODEGEN_ARM) + if (!useHardFpABI() && mir->callee().which() == MAsmJSCall::Callee::Builtin) { for (unsigned i = 0, e = ins->numOperands(); i < e; i++) { LAllocation *a = ins->getOperand(i); if (a->isFloatReg()) { FloatRegister fr = ToFloatRegister(a); int srcId = fr.code() * 2; masm.ma_vxfer(fr, Register::FromCode(srcId), Register::FromCode(srcId+1)); } }
--- a/js/src/jit/arm/Architecture-arm.cpp +++ b/js/src/jit/arm/Architecture-arm.cpp @@ -10,16 +10,18 @@ #include <elf.h> #endif #include <fcntl.h> #include <unistd.h> #include "jit/arm/Assembler-arm.h" +#define HWCAP_USE_HARDFP_ABI (1 << 28) + #if !(defined(ANDROID) || defined(MOZ_B2G)) && !defined(JS_ARM_SIMULATOR) #define HWCAP_ARMv7 (1 << 29) #include <asm/hwcap.h> #else #define HWCAP_VFP (1<<0) #define HWCAP_VFPv3 (1<<1) #define HWCAP_VFPv3D16 (1<<2) #define HWCAP_VFPv4 (1<<3) @@ -34,16 +36,20 @@ namespace jit { uint32_t GetARMFlags() { static bool isSet = false; static uint32_t flags = 0; if (isSet) return flags; +#ifdef JS_CODEGEN_ARM_HARDFP + flags |= HWCAP_USE_HARDFP_ABI; +#endif + static const char *env = getenv("ARMHWCAP"); if (env && env[0]) { if (strstr(env, "help")) { fflush(NULL); printf( "\n" "usage: ARMHWCAP=option,option,option,... where options can be:\n" @@ -51,16 +57,19 @@ uint32_t GetARMFlags() " armv7 \n" " vfp \n" " neon \n" " vfpv3 \n" " vfpv3d16 \n" " vfpv4 \n" " idiva \n" " idivt \n" +#if defined(JS_ARM_SIMULATOR) + " hardfp \n" +#endif "\n" ); exit(0); /*NOTREACHED*/ } else { // Canonicalize each token to have a leading and trailing space. const char *start = env; // Token start. for (;;) { @@ -93,16 +102,20 @@ uint32_t GetARMFlags() else if (count == 5 && strncmp(start, "idiva", 5) == 0) flags |= HWCAP_IDIVA; else if (count == 5 && strncmp(start, "idivt", 5) == 0) flags |= HWCAP_IDIVT; else if (count == 4 && strncmp(start, "neon", 4) == 0) flags |= HWCAP_NEON; else if (count == 5 && strncmp(start, "armv7", 5) == 0) flags |= HWCAP_ARMv7; +#if defined(JS_ARM_SIMULATOR) + else if (count == 6 && strncmp(start, "hardfp", 6) == 0) + flags |= HWCAP_USE_HARDFP_ABI; +#endif else fprintf(stderr, "Warning: unexpected ARMHWCAP flag at: %s\n", start); start = end; } #ifdef DEBUG IonSpew(IonSpew_Codegen, "ARMHWCAP: '%s'\n flags: 0x%x\n", env, flags); #endif isSet = true; @@ -231,16 +244,24 @@ bool hasIDIV() { #if defined HWCAP_IDIVA return GetARMFlags() & HWCAP_IDIVA; #else return false; #endif } +// This is defined in the header and inlined when not using the simulator. +#if defined(JS_ARM_SIMULATOR) +bool useHardFpABI() +{ + return GetARMFlags() & HWCAP_USE_HARDFP_ABI; +} +#endif + Registers::Code Registers::FromName(const char *name) { // Check for some register aliases first. if (strcmp(name, "ip") == 0) return ip; if (strcmp(name, "r13") == 0) return r13;
--- a/js/src/jit/arm/Architecture-arm.h +++ b/js/src/jit/arm/Architecture-arm.h @@ -8,19 +8,20 @@ #define jit_arm_Architecture_arm_h #include <limits.h> #include <stdint.h> #include "js/Utility.h" // gcc appears to use __ARM_PCS_VFP to denote that the target is a hard-float target. -#ifdef __ARM_PCS_VFP +#if defined(__ARM_PCS_VFP) #define JS_CODEGEN_ARM_HARDFP #endif + namespace js { namespace jit { // In bytes: slots needed for potential memory->memory move spills. // +8 for cycles // +4 for gpr spills // +8 for double spills static const uint32_t ION_FRAME_SLACK_SIZE = 20; @@ -227,12 +228,27 @@ class FloatRegisters uint32_t GetARMFlags(); bool hasMOVWT(); bool hasVFPv3(); bool hasVFP(); bool has16DP(); bool hasIDIV(); +// If the simulator is used then the ABI choice is dynamic. Otherwise the ABI is static +// and useHardFpABI is inlined so that unused branches can be optimized away. +#if defined(JS_ARM_SIMULATOR) +bool useHardFpABI(); +#else +static inline bool useHardFpABI() +{ +#if defined(JS_CODEGEN_ARM_HARDFP) + return true; +#else + return false; +#endif +} +#endif + } // namespace jit } // namespace js #endif /* jit_arm_Architecture_arm_h */
--- a/js/src/jit/arm/Assembler-arm.h +++ b/js/src/jit/arm/Assembler-arm.h @@ -2088,21 +2088,20 @@ class InstructionIterator { Instruction *cur() const { return i; } }; static const uint32_t NumIntArgRegs = 4; static const uint32_t NumFloatArgRegs = 8; -#ifdef JS_CODEGEN_ARM_HARDFP static inline bool GetIntArgReg(uint32_t usedIntArgs, uint32_t usedFloatArgs, Register *out) { - if (usedIntArgs >= NumIntArgRegs) + if (usedIntArgs >= NumIntArgRegs) return false; *out = Register::FromCode(usedIntArgs); return true; } // Get a register in which we plan to put a quantity that will be used as an // integer argument. This differs from GetIntArgReg in that if we have no more // actual argument registers to use we will fall back on using whatever @@ -2118,100 +2117,85 @@ GetTempRegForIntArg(uint32_t usedIntArgs // can allocate. usedIntArgs -= NumIntArgRegs; if (usedIntArgs >= NumCallTempNonArgRegs) return false; *out = CallTempNonArgRegs[usedIntArgs]; return true; } + +#if !defined(JS_CODEGEN_ARM_HARDFP) || defined(JS_ARM_SIMULATOR) + +static inline uint32_t +GetArgStackDisp(uint32_t arg) +{ + JS_ASSERT(!useHardFpABI()); + JS_ASSERT(arg >= NumIntArgRegs); + return (arg - NumIntArgRegs) * sizeof(intptr_t); +} + +#endif + + +#if defined(JS_CODEGEN_ARM_HARDFP) || defined(JS_ARM_SIMULATOR) + static inline bool GetFloatArgReg(uint32_t usedIntArgs, uint32_t usedFloatArgs, FloatRegister *out) { + JS_ASSERT(useHardFpABI()); if (usedFloatArgs >= NumFloatArgRegs) return false; *out = FloatRegister::FromCode(usedFloatArgs); return true; } static inline uint32_t GetIntArgStackDisp(uint32_t usedIntArgs, uint32_t usedFloatArgs, uint32_t *padding) { + JS_ASSERT(useHardFpABI()); JS_ASSERT(usedIntArgs >= NumIntArgRegs); uint32_t doubleSlots = Max(0, (int32_t)usedFloatArgs - (int32_t)NumFloatArgRegs); doubleSlots *= 2; int intSlots = usedIntArgs - NumIntArgRegs; return (intSlots + doubleSlots + *padding) * sizeof(intptr_t); } static inline uint32_t GetFloat32ArgStackDisp(uint32_t usedIntArgs, uint32_t usedFloatArgs, uint32_t *padding) { + JS_ASSERT(useHardFpABI()); JS_ASSERT(usedFloatArgs >= NumFloatArgRegs); uint32_t intSlots = 0; if (usedIntArgs > NumIntArgRegs) intSlots = usedIntArgs - NumIntArgRegs; uint32_t float32Slots = usedFloatArgs - NumFloatArgRegs; return (intSlots + float32Slots + *padding) * sizeof(intptr_t); } static inline uint32_t GetDoubleArgStackDisp(uint32_t usedIntArgs, uint32_t usedFloatArgs, uint32_t *padding) { + JS_ASSERT(useHardFpABI()); JS_ASSERT(usedFloatArgs >= NumFloatArgRegs); uint32_t intSlots = 0; if (usedIntArgs > NumIntArgRegs) { intSlots = usedIntArgs - NumIntArgRegs; // update the amount of padding required. *padding += (*padding + usedIntArgs) % 2; } uint32_t doubleSlots = usedFloatArgs - NumFloatArgRegs; doubleSlots *= 2; return (intSlots + doubleSlots + *padding) * sizeof(intptr_t); } -#else -static inline bool -GetIntArgReg(uint32_t arg, uint32_t floatArg, Register *out) -{ - if (arg < NumIntArgRegs) { - *out = Register::FromCode(arg); - return true; - } - return false; -} - -// Get a register in which we plan to put a quantity that will be used as an -// integer argument. This differs from GetIntArgReg in that if we have no more -// actual argument registers to use we will fall back on using whatever -// CallTempReg* don't overlap the argument registers, and only fail once those -// run out too. -static inline bool -GetTempRegForIntArg(uint32_t usedIntArgs, uint32_t usedFloatArgs, Register *out) -{ - if (GetIntArgReg(usedIntArgs, usedFloatArgs, out)) - return true; - // Unfortunately, we have to assume things about the point at which - // GetIntArgReg returns false, because we need to know how many registers it - // can allocate. - usedIntArgs -= NumIntArgRegs; - if (usedIntArgs >= NumCallTempNonArgRegs) - return false; - *out = CallTempNonArgRegs[usedIntArgs]; - return true; -} - -static inline uint32_t -GetArgStackDisp(uint32_t arg) -{ - JS_ASSERT(arg >= NumIntArgRegs); - return (arg - NumIntArgRegs) * sizeof(intptr_t); -} #endif + + class DoubleEncoder { uint32_t rep(bool b, uint32_t count) { uint32_t ret = 0; for (uint32_t i = 0; i < count; i++) ret = (ret << 1) | b; return ret; }
--- a/js/src/jit/arm/CodeGenerator-arm.h +++ b/js/src/jit/arm/CodeGenerator-arm.h @@ -171,31 +171,29 @@ class CodeGeneratorARM : public CodeGene bool visitAsmJSLoadFuncPtr(LAsmJSLoadFuncPtr *ins); bool visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc *ins); bool visitAsmJSPassStackArg(LAsmJSPassStackArg *ins); bool generateInvalidateEpilogue(); protected: void postAsmJSCall(LAsmJSCall *lir) { -#ifndef JS_CODEGEN_ARM_HARDFP - if (lir->mir()->callee().which() == MAsmJSCall::Callee::Builtin) { + if (!useHardFpABI() && lir->mir()->callee().which() == MAsmJSCall::Callee::Builtin) { switch (lir->mir()->type()) { case MIRType_Double: masm.ma_vxfer(r0, r1, d0); break; case MIRType_Float32: masm.as_vxfer(r0, InvalidReg, VFPRegister(d0).singleOverlay(), Assembler::CoreToFloat); break; default: break; } } -#endif } bool visitEffectiveAddress(LEffectiveAddress *ins); bool visitUDiv(LUDiv *ins); bool visitUMod(LUMod *ins); bool visitSoftUDivOrMod(LSoftUDivOrMod *ins); };
--- a/js/src/jit/arm/MacroAssembler-arm.cpp +++ b/js/src/jit/arm/MacroAssembler-arm.cpp @@ -3485,23 +3485,21 @@ MacroAssemblerARMCompat::breakpoint(Cond void MacroAssemblerARMCompat::setupABICall(uint32_t args) { JS_ASSERT(!inCall_); inCall_ = true; args_ = args; passedArgs_ = 0; passedArgTypes_ = 0; -#ifdef JS_CODEGEN_ARM_HARDFP usedIntSlots_ = 0; +#if defined(JS_CODEGEN_ARM_HARDFP) || defined(JS_ARM_SIMULATOR) usedFloatSlots_ = 0; usedFloat32_ = false; padding_ = 0; -#else - usedSlots_ = 0; #endif floatArgsInGPR[0] = MoveOperand(); floatArgsInGPR[1] = MoveOperand(); floatArgsInGPRValid[0] = false; floatArgsInGPRValid[1] = false; } void @@ -3520,19 +3518,19 @@ MacroAssemblerARMCompat::setupUnalignedA ma_mov(sp, scratch); // Force sp to be aligned ma_and(Imm32(~(StackAlignment - 1)), sp, sp); ma_push(scratch); } -#ifdef JS_CODEGEN_ARM_HARDFP -void -MacroAssemblerARMCompat::passABIArg(const MoveOperand &from, MoveOp::Type type) +#if defined(JS_CODEGEN_ARM_HARDFP) || defined(JS_ARM_SIMULATOR) +void +MacroAssemblerARMCompat::passHardFpABIArg(const MoveOperand &from, MoveOp::Type type) { MoveOperand to; ++passedArgs_; if (!enoughMemory_) return; switch (type) { case MoveOp::FLOAT32: case MoveOp::DOUBLE: { @@ -3591,68 +3589,84 @@ MacroAssemblerARMCompat::passABIArg(cons break; } default: MOZ_ASSUME_UNREACHABLE("Unexpected argument type"); } enoughMemory_ = moveResolver_.addMove(from, to, type); } - -#else -void -MacroAssemblerARMCompat::passABIArg(const MoveOperand &from, MoveOp::Type type) +#endif + +#if !defined(JS_CODEGEN_ARM_HARDFP) || defined(JS_ARM_SIMULATOR) +void +MacroAssemblerARMCompat::passSoftFpABIArg(const MoveOperand &from, MoveOp::Type type) { MoveOperand to; uint32_t increment = 1; bool useResolver = true; ++passedArgs_; switch (type) { case MoveOp::DOUBLE: // Double arguments need to be rounded up to the nearest doubleword // boundary, even if it is in a register! - usedSlots_ = (usedSlots_ + 1) & ~1; + usedIntSlots_ = (usedIntSlots_ + 1) & ~1; increment = 2; passedArgTypes_ = (passedArgTypes_ << ArgType_Shift) | ArgType_Double; break; case MoveOp::FLOAT32: passedArgTypes_ = (passedArgTypes_ << ArgType_Shift) | ArgType_Float32; break; case MoveOp::GENERAL: passedArgTypes_ = (passedArgTypes_ << ArgType_Shift) | ArgType_General; break; default: MOZ_ASSUME_UNREACHABLE("Unexpected argument type"); } Register destReg; MoveOperand dest; - if (GetIntArgReg(usedSlots_, 0, &destReg)) { + if (GetIntArgReg(usedIntSlots_, 0, &destReg)) { if (type == MoveOp::DOUBLE || type == MoveOp::FLOAT32) { floatArgsInGPR[destReg.code() >> 1] = from; floatArgsInGPRValid[destReg.code() >> 1] = true; useResolver = false; } else if (from.isGeneralReg() && from.reg() == destReg) { // No need to move anything useResolver = false; } else { dest = MoveOperand(destReg); } } else { - uint32_t disp = GetArgStackDisp(usedSlots_); + uint32_t disp = GetArgStackDisp(usedIntSlots_); dest = MoveOperand(sp, disp); } if (useResolver) enoughMemory_ = enoughMemory_ && moveResolver_.addMove(from, dest, type); - usedSlots_ += increment; + usedIntSlots_ += increment; } #endif void +MacroAssemblerARMCompat::passABIArg(const MoveOperand &from, MoveOp::Type type) +{ +#if defined(JS_ARM_SIMULATOR) + if (useHardFpABI()) + MacroAssemblerARMCompat::passHardFpABIArg(from, type); + else + MacroAssemblerARMCompat::passSoftFpABIArg(from, type); +#elif defined(JS_CODEGEN_ARM_HARDFP) + MacroAssemblerARMCompat::passHardFpABIArg(from, type); +#else + MacroAssemblerARMCompat::passSoftFpABIArg(from, type); +#endif +} + +void MacroAssemblerARMCompat::passABIArg(const Register ®) { passABIArg(MoveOperand(reg), MoveOp::GENERAL); } void MacroAssemblerARMCompat::passABIArg(const FloatRegister &freg, MoveOp::Type type) { @@ -3666,21 +3680,21 @@ void MacroAssemblerARMCompat::checkStack breakpoint(NonZero); #endif } void MacroAssemblerARMCompat::callWithABIPre(uint32_t *stackAdjust) { JS_ASSERT(inCall_); -#ifdef JS_CODEGEN_ARM_HARDFP + *stackAdjust = ((usedIntSlots_ > NumIntArgRegs) ? usedIntSlots_ - NumIntArgRegs : 0) * sizeof(intptr_t); - *stackAdjust += 2*((usedFloatSlots_ > NumFloatArgRegs) ? usedFloatSlots_ - NumFloatArgRegs : 0) * sizeof(intptr_t); -#else - *stackAdjust = ((usedSlots_ > NumIntArgRegs) ? usedSlots_ - NumIntArgRegs : 0) * sizeof(intptr_t); +#if defined(JS_CODEGEN_ARM_HARDFP) || defined(JS_ARM_SIMULATOR) + if (useHardFpABI()) + *stackAdjust += 2*((usedFloatSlots_ > NumFloatArgRegs) ? usedFloatSlots_ - NumFloatArgRegs : 0) * sizeof(intptr_t); #endif if (!dynamicAlignment_) { *stackAdjust += ComputeByteAlignment(framePushed_ + *stackAdjust, StackAlignment); } else { // sizeof(intptr_t) account for the saved stack pointer pushed by setupUnalignedABICall *stackAdjust += ComputeByteAlignment(*stackAdjust + sizeof(intptr_t), StackAlignment); } @@ -3728,27 +3742,27 @@ MacroAssemblerARMCompat::callWithABIPre( void MacroAssemblerARMCompat::callWithABIPost(uint32_t stackAdjust, MoveOp::Type result) { if (secondScratchReg_ != lr) ma_mov(secondScratchReg_, lr); switch (result) { case MoveOp::DOUBLE: -#ifndef JS_CODEGEN_ARM_HARDFP - // Move double from r0/r1 to ReturnFloatReg. - as_vxfer(r0, r1, ReturnFloatReg, CoreToFloat); - break; -#endif + if (!useHardFpABI()) { + // Move double from r0/r1 to ReturnFloatReg. + as_vxfer(r0, r1, ReturnFloatReg, CoreToFloat); + break; + } case MoveOp::FLOAT32: -#ifndef JS_CODEGEN_ARM_HARDFP - // Move float32 from r0 to ReturnFloatReg. - as_vxfer(r0, InvalidReg, VFPRegister(d0).singleOverlay(), CoreToFloat); - break; -#endif + if (!useHardFpABI()) { + // Move float32 from r0 to ReturnFloatReg. + as_vxfer(r0, InvalidReg, VFPRegister(d0).singleOverlay(), CoreToFloat); + break; + } case MoveOp::GENERAL: break; default: MOZ_ASSUME_UNREACHABLE("unexpected callWithABI result"); } freeStack(stackAdjust);
--- a/js/src/jit/arm/MacroAssembler-arm.h +++ b/js/src/jit/arm/MacroAssembler-arm.h @@ -440,29 +440,27 @@ class MacroAssemblerARMCompat : public M // not be nested. bool inCall_; uint32_t args_; // The actual number of arguments that were passed, used to assert that // the initial number of arguments declared was correct. uint32_t passedArgs_; uint32_t passedArgTypes_; -#ifdef JS_CODEGEN_ARM_HARDFP + // ARM treats arguments as a vector in registers/memory, that looks like: + // { r0, r1, r2, r3, [sp], [sp,+4], [sp,+8] ... } + // usedIntSlots_ keeps track of how many of these have been used. + // It bears a passing resemblance to passedArgs_, but a single argument + // can effectively use between one and three slots depending on its size and + // alignment requirements uint32_t usedIntSlots_; +#if defined(JS_CODEGEN_ARM_HARDFP) || defined(JS_ARM_SIMULATOR) uint32_t usedFloatSlots_; bool usedFloat32_; uint32_t padding_; -#else - // ARM treats arguments as a vector in registers/memory, that looks like: - // { r0, r1, r2, r3, [sp], [sp,+4], [sp,+8] ... } - // usedSlots_ keeps track of how many of these have been used. - // It bears a passing resemblance to passedArgs_, but a single argument - // can effectively use between one and three slots depending on its size and - // alignment requirements - uint32_t usedSlots_; #endif bool dynamicAlignment_; bool enoughMemory_; // Used to work around the move resolver's lack of support for // moving into register pairs, which the softfp ABI needs. mozilla::Array<MoveOperand, 2> floatArgsInGPR; @@ -1406,16 +1404,20 @@ class MacroAssemblerARMCompat : public M // automatically adjusted. It is extremely important that esp-relative // addresses are computed *after* setupABICall(). Furthermore, no // operations should be emitted while setting arguments. void passABIArg(const MoveOperand &from, MoveOp::Type type); void passABIArg(const Register ®); void passABIArg(const FloatRegister ®, MoveOp::Type type); void passABIArg(const ValueOperand ®s); + private: + void passHardFpABIArg(const MoveOperand &from, MoveOp::Type type); + void passSoftFpABIArg(const MoveOperand &from, MoveOp::Type type); + protected: bool buildOOLFakeExitFrame(void *fakeReturnAddr); private: void callWithABIPre(uint32_t *stackAdjust); void callWithABIPost(uint32_t stackAdjust, MoveOp::Type result); public:
--- a/js/src/jit/arm/Simulator-arm.cpp +++ b/js/src/jit/arm/Simulator-arm.cpp @@ -1411,49 +1411,52 @@ ReturnType Simulator::getFromVFPRegister register_size * sizeof(vfp_registers_[0])); memcpy(&value, buffer, register_size * sizeof(vfp_registers_[0])); return value; } void Simulator::getFpArgs(double *x, double *y, int32_t *z) { - if (use_eabi_hardfloat()) { + if (useHardFpABI()) { *x = get_double_from_d_register(0); *y = get_double_from_d_register(1); *z = get_register(0); } else { *x = get_double_from_register_pair(0); *y = get_double_from_register_pair(2); *z = get_register(2); } } void Simulator::setCallResultDouble(double result) { // The return value is either in r0/r1 or d0. - if (use_eabi_hardfloat()) { + if (useHardFpABI()) { char buffer[2 * sizeof(vfp_registers_[0])]; memcpy(buffer, &result, sizeof(buffer)); // Copy result to d0. memcpy(vfp_registers_, buffer, sizeof(buffer)); } else { char buffer[2 * sizeof(registers_[0])]; memcpy(buffer, &result, sizeof(buffer)); // Copy result to r0 and r1. memcpy(registers_, buffer, sizeof(buffer)); } } void Simulator::setCallResultFloat(float result) { - if (use_eabi_hardfloat()) { - MOZ_ASSUME_UNREACHABLE("NYI"); + if (useHardFpABI()) { + char buffer[sizeof(registers_[0])]; + memcpy(buffer, &result, sizeof(buffer)); + // Copy result to s0. + memcpy(vfp_registers_, buffer, sizeof(buffer)); } else { char buffer[sizeof(registers_[0])]; memcpy(buffer, &result, sizeof(buffer)); // Copy result to r0. memcpy(registers_, buffer, sizeof(buffer)); } } @@ -2197,17 +2200,21 @@ Simulator::softwareInterrupt(SimInstruct getFpArgs(&dval0, &dval1, &ival); Prototype_Double_Double target = reinterpret_cast<Prototype_Double_Double>(external); double dresult = target(dval0); scratchVolatileRegisters(/* scratchFloat = true */); setCallResultDouble(dresult); break; } case Args_Float32_Float32: { - float fval0 = mozilla::BitwiseCast<float>(arg0); + float fval0; + if (useHardFpABI()) + fval0 = get_float_from_s_register(0); + else + fval0 = mozilla::BitwiseCast<float>(arg0); Prototype_Float32_Float32 target = reinterpret_cast<Prototype_Float32_Float32>(external); float fresult = target(fval0); scratchVolatileRegisters(/* scratchFloat = true */); setCallResultFloat(fresult); break; } case Args_Double_Int: { Prototype_Double_Int target = reinterpret_cast<Prototype_Double_Int>(external); @@ -2232,29 +2239,35 @@ Simulator::softwareInterrupt(SimInstruct getFpArgs(&dval0, &dval1, &ival); Prototype_Double_DoubleDouble target = reinterpret_cast<Prototype_Double_DoubleDouble>(external); double dresult = target(dval0, dval1); scratchVolatileRegisters(/* scratchFloat = true */); setCallResultDouble(dresult); break; } case Args_Double_IntDouble: { - MOZ_ASSERT(!use_eabi_hardfloat()); // NYI int32_t ival = get_register(0); - double dval0 = get_double_from_register_pair(2); + double dval0; + if (useHardFpABI()) + dval0 = get_double_from_d_register(0); + else + dval0 = get_double_from_register_pair(2); Prototype_Double_IntDouble target = reinterpret_cast<Prototype_Double_IntDouble>(external); double dresult = target(ival, dval0); scratchVolatileRegisters(/* scratchFloat = true */); setCallResultDouble(dresult); break; } case Args_Int_IntDouble: { - MOZ_ASSERT(!use_eabi_hardfloat()); // NYI int32_t ival = get_register(0); - double dval0 = get_double_from_register_pair(2); + double dval0; + if (useHardFpABI()) + dval0 = get_double_from_d_register(0); + else + dval0 = get_double_from_register_pair(2); Prototype_Int_IntDouble target = reinterpret_cast<Prototype_Int_IntDouble>(external); int32_t result = target(ival, dval0); scratchVolatileRegisters(/* scratchFloat = true */); set_register(r0, result); break; } default: MOZ_ASSUME_UNREACHABLE("call");
--- a/js/src/jit/arm/Simulator-arm.h +++ b/js/src/jit/arm/Simulator-arm.h @@ -27,16 +27,17 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef jit_arm_Simulator_arm_h #define jit_arm_Simulator_arm_h #ifdef JS_ARM_SIMULATOR #include "jit/IonTypes.h" +#include "jit/arm/Architecture-arm.h" namespace js { namespace jit { class SimulatorRuntime; SimulatorRuntime *CreateSimulatorRuntime(); void DestroySimulatorRuntime(SimulatorRuntime *srt); @@ -161,25 +162,16 @@ class Simulator // Debugger input. void setLastDebuggerInput(char *input); char *lastDebuggerInput() { return lastDebuggerInput_; } // Returns true if pc register contains one of the 'special_values' defined // below (bad_lr, end_sim_pc). bool has_bad_pc() const; - // EABI variant for double arguments in use. - bool use_eabi_hardfloat() { -#if USE_EABI_HARDFLOAT - return true; -#else - return false; -#endif - } - private: enum special_values { // Known bad pc value to ensure that the simulator does not execute // without being properly setup. bad_lr = -1, // A pc value used to signal the simulator to stop execution. Generally // the lr is set to this value on transition from native C code to // simulated execution, so that the simulator can "return" to the native