Bug 1289054 - Part 19: Implement the 64bit variant of Int64ToFloatingPoint on arm, r=bbouvier
authorHannes Verschore <hv1989@gmail.com>
Fri, 29 Jul 2016 16:53:50 +0200
changeset 347368 ce45ee774edb69d4e94d3f834b558776782bfac0
parent 347367 48d273fefe73d63673d7a0497864e5ac0701a8f7
child 347369 7edcd686d163c090b31e812db074a345284a07a2
push id6389
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:38:22 +0000
treeherdermozilla-beta@01d67bfe6c81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbbouvier
bugs1289054
milestone50.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
Bug 1289054 - Part 19: Implement the 64bit variant of Int64ToFloatingPoint on arm, r=bbouvier
js/src/asmjs/WasmTypes.cpp
js/src/asmjs/WasmTypes.h
js/src/jit/IonTypes.h
js/src/jit/arm/CodeGenerator-arm.cpp
js/src/jit/arm/CodeGenerator-arm.h
js/src/jit/arm/LIR-arm.h
js/src/jit/arm/LOpcodes-arm.h
js/src/jit/arm/Lowering-arm.cpp
js/src/jit/arm/Simulator-arm.cpp
--- a/js/src/asmjs/WasmTypes.cpp
+++ b/js/src/asmjs/WasmTypes.cpp
@@ -219,16 +219,30 @@ TruncateDoubleToUint64(double input)
     // Therefore also sending the failure value.
     if (input >= double(UINT64_MAX))
         return 0x8000000000000000;
     if (input <= -1.0)
         return 0x8000000000000000;
     return uint64_t(input);
 }
 
+static double
+Int64ToFloatingPoint(int32_t x_hi, uint32_t x_lo)
+{
+    int64_t x = int64_t((uint64_t(x_hi) << 32)) + int64_t(x_lo);
+    return double(x);
+}
+
+static double
+Uint64ToFloatingPoint(int32_t x_hi, uint32_t x_lo)
+{
+    uint64_t x = (uint64_t(x_hi) << 32) + uint64_t(x_lo);
+    return double(x);
+}
+
 template <class F>
 static inline void*
 FuncCast(F* pf, ABIFunctionType type)
 {
     void *pv = JS_FUNC_TO_DATA_PTR(void*, pf);
 #ifdef JS_SIMULATOR
     pv = Simulator::RedirectNativeFunction(pv, type);
 #endif
@@ -270,16 +284,20 @@ wasm::AddressOf(SymbolicAddress imm, Exc
       case SymbolicAddress::ModI64:
         return FuncCast(ModI64, Args_General4);
       case SymbolicAddress::UModI64:
         return FuncCast(UModI64, Args_General4);
       case SymbolicAddress::TruncateDoubleToUint64:
         return FuncCast(TruncateDoubleToUint64, Args_Int64_Double);
       case SymbolicAddress::TruncateDoubleToInt64:
         return FuncCast(TruncateDoubleToInt64, Args_Int64_Double);
+      case SymbolicAddress::Uint64ToFloatingPoint:
+        return FuncCast(Uint64ToFloatingPoint, Args_Double_IntInt);
+      case SymbolicAddress::Int64ToFloatingPoint:
+        return FuncCast(Int64ToFloatingPoint, Args_Double_IntInt);
 #if defined(JS_CODEGEN_ARM)
       case SymbolicAddress::aeabi_idivmod:
         return FuncCast(__aeabi_idivmod, Args_General2);
       case SymbolicAddress::aeabi_uidivmod:
         return FuncCast(__aeabi_uidivmod, Args_General2);
       case SymbolicAddress::AtomicCmpXchg:
         return FuncCast<int32_t (int32_t, int32_t, int32_t, int32_t)>(js::atomics_cmpxchg_asm_callout, Args_General4);
       case SymbolicAddress::AtomicXchg:
--- a/js/src/asmjs/WasmTypes.h
+++ b/js/src/asmjs/WasmTypes.h
@@ -898,16 +898,18 @@ enum class SymbolicAddress
     CoerceInPlace_ToInt32,
     CoerceInPlace_ToNumber,
     DivI64,
     UDivI64,
     ModI64,
     UModI64,
     TruncateDoubleToInt64,
     TruncateDoubleToUint64,
+    Uint64ToFloatingPoint,
+    Int64ToFloatingPoint,
     Limit
 };
 
 void*
 AddressOf(SymbolicAddress imm, ExclusiveContext* cx);
 
 // A wasm::Trap is a reason for why we reached a trap in executed code. Each
 // different trap is mapped to a different error message.
--- a/js/src/jit/IonTypes.h
+++ b/js/src/jit/IonTypes.h
@@ -796,16 +796,19 @@ enum ABIFunctionType
     Args_Float32_Float32 = (ArgType_Float32 << RetType_Shift) | (ArgType_Float32 << ArgType_Shift),
 
     // double f(double)
     Args_Double_Double = Args_Double_None | (ArgType_Double << ArgType_Shift),
 
     // double f(int)
     Args_Double_Int = Args_Double_None | (ArgType_General << ArgType_Shift),
 
+    // double f(int, int)
+    Args_Double_IntInt = Args_Double_Int | (ArgType_General << (ArgType_Shift * 2)),
+
     // double f(double, int)
     Args_Double_DoubleInt = Args_Double_None |
         (ArgType_General << (ArgType_Shift * 1)) |
         (ArgType_Double << (ArgType_Shift * 2)),
 
     // double f(double, double)
     Args_Double_DoubleDouble = Args_Double_Double | (ArgType_Double << (ArgType_Shift * 2)),
 
--- a/js/src/jit/arm/CodeGenerator-arm.cpp
+++ b/js/src/jit/arm/CodeGenerator-arm.cpp
@@ -3088,16 +3088,46 @@ CodeGeneratorARM::visitOutOfLineWasmTrun
     masm.bind(&fail);
     masm.jump(wasm::JumpTarget::IntegerOverflow);
 
     masm.bind(&inputIsNaN);
     masm.jump(wasm::JumpTarget::InvalidConversionToInteger);
 }
 
 void
+CodeGeneratorARM::visitInt64ToFloatingPointCall(LInt64ToFloatingPointCall* lir)
+{
+    Register64 input = ToRegister64(lir->getInt64Operand(0));
+    FloatRegister output = ToFloatRegister(lir->output());
+
+    MInt64ToFloatingPoint* mir = lir->mir();
+    MIRType toType = mir->type();
+
+    // We are free to clobber all registers, since this is a call instruction.
+    AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
+    regs.take(input.low);
+    regs.take(input.high);
+    Register temp = regs.takeAny();
+
+    masm.setupUnalignedABICall(temp);
+    masm.passABIArg(input.high);
+    masm.passABIArg(input.low);
+    if (lir->mir()->isUnsigned())
+        masm.callWithABI(wasm::SymbolicAddress::Uint64ToFloatingPoint, MoveOp::DOUBLE);
+    else
+        masm.callWithABI(wasm::SymbolicAddress::Int64ToFloatingPoint, MoveOp::DOUBLE);
+
+    MOZ_ASSERT_IF(toType == MIRType::Double, output == ReturnDoubleReg);
+    if (toType == MIRType::Float32) {
+        MOZ_ASSERT(output == ReturnFloat32Reg);
+        masm.convertDoubleToFloat32(ReturnDoubleReg, output);
+    }
+}
+
+void
 CodeGeneratorARM::visitCopySignF(LCopySignF* ins)
 {
     FloatRegister lhs = ToFloatRegister(ins->getOperand(0));
     FloatRegister rhs = ToFloatRegister(ins->getOperand(1));
     FloatRegister output = ToFloatRegister(ins->getDef(0));
 
     Register lhsi = ToRegister(ins->getTemp(0));
     Register rhsi = ToRegister(ins->getTemp(1));
--- a/js/src/jit/arm/CodeGenerator-arm.h
+++ b/js/src/jit/arm/CodeGenerator-arm.h
@@ -173,16 +173,17 @@ class CodeGeneratorARM : public CodeGene
     virtual void visitAsmSelectI64(LAsmSelectI64* lir);
     virtual void visitAsmReinterpretFromI64(LAsmReinterpretFromI64* lir);
     virtual void visitAsmReinterpretToI64(LAsmReinterpretToI64* lir);
     virtual void visitPopcntI64(LPopcntI64* ins);
     virtual void visitClzI64(LClzI64* ins);
     virtual void visitCtzI64(LCtzI64* ins);
     virtual void visitNotI64(LNotI64* ins);
     virtual void visitWasmTruncateToInt64(LWasmTruncateToInt64* ins);
+    virtual void visitInt64ToFloatingPointCall(LInt64ToFloatingPointCall* lir);
 
     // Out of line visitors.
     void visitOutOfLineBailout(OutOfLineBailout* ool);
     void visitOutOfLineTableSwitch(OutOfLineTableSwitch* ool);
 
   protected:
     ValueOperand ToValue(LInstruction* ins, size_t pos);
     ValueOperand ToOutValue(LInstruction* ins);
--- a/js/src/jit/arm/LIR-arm.h
+++ b/js/src/jit/arm/LIR-arm.h
@@ -551,12 +551,22 @@ class LWasmTruncateToInt64 : public LCal
         setOperand(0, in);
     }
 
     MWasmTruncateToInt64* mir() const {
         return mir_->toWasmTruncateToInt64();
     }
 };
 
+class LInt64ToFloatingPointCall: public LCallInstructionHelper<1, INT64_PIECES, 0>
+{
+  public:
+    LIR_HEADER(Int64ToFloatingPointCall);
+
+    MInt64ToFloatingPoint* mir() const {
+        return mir_->toInt64ToFloatingPoint();
+    }
+};
+
 } // namespace jit
 } // namespace js
 
 #endif /* jit_arm_LIR_arm_h */
--- a/js/src/jit/arm/LOpcodes-arm.h
+++ b/js/src/jit/arm/LOpcodes-arm.h
@@ -17,11 +17,12 @@
     _(UDiv)                     \
     _(UMod)                     \
     _(SoftUDivOrMod)            \
     _(AsmJSCompareExchangeCallout) \
     _(AsmJSAtomicExchangeCallout) \
     _(AsmJSAtomicBinopCallout)  \
     _(DivOrModI64)              \
     _(UDivOrModI64)             \
-    _(WasmTruncateToInt64)
+    _(WasmTruncateToInt64)      \
+    _(Int64ToFloatingPointCall)
 
 #endif /* jit_arm_LOpcodes_arm_h */
--- a/js/src/jit/arm/Lowering-arm.cpp
+++ b/js/src/jit/arm/Lowering-arm.cpp
@@ -919,17 +919,21 @@ LIRGeneratorARM::visitWasmTruncateToInt6
     MOZ_ASSERT(opd->type() == MIRType::Double || opd->type() == MIRType::Float32);
 
     defineReturn(new(alloc()) LWasmTruncateToInt64(useRegisterAtStart(opd)), ins);
 }
 
 void
 LIRGeneratorARM::visitInt64ToFloatingPoint(MInt64ToFloatingPoint* ins)
 {
-    MOZ_CRASH("NY");
+    MOZ_ASSERT(ins->type() == MIRType::Double || ins->type() == MIRType::Float32);
+
+    auto lir = new(alloc()) LInt64ToFloatingPointCall();
+    lir->setInt64Operand(0, useInt64RegisterAtStart(ins->input()));
+    defineReturn(lir, ins);
 }
 
 void
 LIRGeneratorARM::visitCopySign(MCopySign* ins)
 {
     MDefinition* lhs = ins->lhs();
     MDefinition* rhs = ins->rhs();
 
--- a/js/src/jit/arm/Simulator-arm.cpp
+++ b/js/src/jit/arm/Simulator-arm.cpp
@@ -2281,16 +2281,17 @@ typedef int64_t (*Prototype_General6)(in
 typedef int64_t (*Prototype_General7)(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3,
                                       int32_t arg4, int32_t arg5, int32_t arg6);
 typedef int64_t (*Prototype_General8)(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3,
                                       int32_t arg4, int32_t arg5, int32_t arg6, int32_t arg7);
 
 typedef double (*Prototype_Double_None)();
 typedef double (*Prototype_Double_Double)(double arg0);
 typedef double (*Prototype_Double_Int)(int32_t arg0);
+typedef double (*Prototype_Double_IntInt)(int32_t arg0, int32_t arg1);
 typedef int32_t (*Prototype_Int_Double)(double arg0);
 typedef int64_t (*Prototype_Int64_Double)(double arg0);
 typedef int32_t (*Prototype_Int_DoubleIntInt)(double arg0, int32_t arg1, int32_t arg2);
 typedef int32_t (*Prototype_Int_IntDoubleIntInt)(int32_t arg0, double arg1, int32_t arg2,
                                                  int32_t arg3);
 typedef float (*Prototype_Float32_Float32)(float arg0);
 
 typedef double (*Prototype_DoubleInt)(double arg0, int32_t arg1);
@@ -2481,16 +2482,23 @@ Simulator::softwareInterrupt(SimInstruct
           }
           case Args_Double_Int: {
             Prototype_Double_Int target = reinterpret_cast<Prototype_Double_Int>(external);
             double dresult = target(arg0);
             scratchVolatileRegisters(/* scratchFloat = true */);
             setCallResultDouble(dresult);
             break;
           }
+          case Args_Double_IntInt: {
+            Prototype_Double_IntInt target = reinterpret_cast<Prototype_Double_IntInt>(external);
+            double dresult = target(arg0, arg1);
+            scratchVolatileRegisters(/* scratchFloat = true */);
+            setCallResultDouble(dresult);
+            break;
+          }
           case Args_Double_DoubleInt: {
             double dval0, dval1;
             int32_t ival;
             getFpArgs(&dval0, &dval1, &ival);
             Prototype_DoubleInt target = reinterpret_cast<Prototype_DoubleInt>(external);
             double dresult = target(dval0, ival);
             scratchVolatileRegisters(/* scratchFloat = true */);
             setCallResultDouble(dresult);