diff --git a/js/src/assembler/assembler/ARMAssembler.h b/js/src/assembler/assembler/ARMAssembler.h index 5f2d148ff5b..2c000f32d73 100644 --- a/js/src/assembler/assembler/ARMAssembler.h +++ b/js/src/assembler/assembler/ARMAssembler.h @@ -205,6 +205,7 @@ namespace JSC { FMRS = 0x0e100a10, FSITOD = 0x0eb80bc0, FTOSID = 0x0ebd0b40, + FTOSIZD = 0x0ebd0bc0, FMSTAT = 0x0ef1fa10 #if WTF_ARM_ARCH_VERSION >= 5 ,CLZ = 0x016f0f10, @@ -426,6 +427,12 @@ namespace JSC { emitInst(static_cast(cc) | CMP | SET_CC, 0, rn, op2); } + void cmn_r(int rn, ARMWord op2, Condition cc = AL) + { + spewInsWithOp2("cmn", cc, rn, op2); + emitInst(static_cast(cc) | CMN | SET_CC, 0, rn, op2); + } + void orr_r(int rd, int rn, ARMWord op2, Condition cc = AL) { spewInsWithOp2("orr", cc, rd, rn, op2); @@ -673,16 +680,18 @@ namespace JSC { void fdtr_u(bool isLoad, int dd, int rn, ARMWord offset, Condition cc = AL) { + char const * ins = isLoad ? "vldr.f64" : "vstr.f64"; js::JaegerSpew(js::JSpew_Insns, - IPFX "%-15s %s, [%s, #+%u]\n", MAYBE_PAD, "vldr.f64", nameFpRegD(dd), nameGpReg(rn), offset); + IPFX "%-15s %s, [%s, #+%u]\n", MAYBE_PAD, ins, nameFpRegD(dd), nameGpReg(rn), offset); ASSERT(offset <= 0xff); emitInst(static_cast(cc) | FDTR | DT_UP | (isLoad ? DT_LOAD : 0), dd, rn, offset); } void fdtr_d(bool isLoad, int dd, int rn, ARMWord offset, Condition cc = AL) { + char const * ins = isLoad ? "vldr.f64" : "vstr.f64"; js::JaegerSpew(js::JSpew_Insns, - IPFX "%-15s %s, [%s, #-%u]\n", MAYBE_PAD, "vldr.f64", nameFpRegD(dd), nameGpReg(rn), offset); + IPFX "%-15s %s, [%s, #-%u]\n", MAYBE_PAD, ins, nameFpRegD(dd), nameGpReg(rn), offset); ASSERT(offset <= 0xff); emitInst(static_cast(cc) | FDTR | (isLoad ? DT_LOAD : 0), dd, rn, offset); } @@ -741,6 +750,13 @@ namespace JSC { emitInst(static_cast(cc) | FTOSID, fd, 0, dm); } + void ftosizd_r(int fd, int dm, Condition cc = AL) + { + // TODO: emitInst doesn't work for VFP instructions, though it + // seems to work for current usage. + emitInst(static_cast(cc) | FTOSIZD, fd, 0, dm); + } + void fmstat(Condition cc = AL) { // TODO: emitInst doesn't work for VFP instructions, though it diff --git a/js/src/assembler/assembler/MacroAssemblerARM.h b/js/src/assembler/assembler/MacroAssemblerARM.h index 339d36806a5..b7ab2e47b54 100644 --- a/js/src/assembler/assembler/MacroAssemblerARM.h +++ b/js/src/assembler/assembler/MacroAssemblerARM.h @@ -853,7 +853,7 @@ public: bool supportsFloatingPointTruncate() const { - return false; + return true; } bool supportsFloatingPointSqrt() const @@ -972,13 +972,17 @@ public: // Truncates 'src' to an integer, and places the resulting 'dest'. // If the result is not representable as a 32 bit value, branch. // May also branch for some values that are representable in 32 bits - // (specifically, in this case, INT_MIN). + // (specifically, in this case, INT_MIN and INT_MAX). Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest) { - (void)(src); - (void)(dest); - ASSERT_NOT_REACHED(); - return jump(); + m_assembler.ftosizd_r(ARMRegisters::SD0, src); + // If FTOSIZD (VCVT.S32.F64) can't fit the result into a 32-bit + // integer, it saturates at INT_MAX or INT_MIN. Testing this is + // probably quicker than testing FPSCR for exception. + m_assembler.fmrs_r(dest, ARMRegisters::SD0); + m_assembler.cmn_r(dest, ARMAssembler::getOp2(1)); + m_assembler.cmp_r(dest, ARMAssembler::getOp2(0x80000000), ARMCondition(NonZero)); + return Jump(m_assembler.jmp(ARMCondition(Zero))); } // Convert 'src' to an integer, and places the resulting 'dest'.