diff --git a/src/compiler/arm64/code-generator-arm64.cc b/src/compiler/arm64/code-generator-arm64.cc index fa73763383..748d94c159 100644 --- a/src/compiler/arm64/code-generator-arm64.cc +++ b/src/compiler/arm64/code-generator-arm64.cc @@ -992,6 +992,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { case kArm64Uint32ToFloat64: __ Ucvtf(i.OutputDoubleRegister(), i.InputRegister32(0)); break; + case kArm64Uint64ToFloat32: + __ Ucvtf(i.OutputDoubleRegister().S(), i.InputRegister64(0)); + break; case kArm64Uint64ToFloat64: __ Ucvtf(i.OutputDoubleRegister(), i.InputRegister64(0)); break; diff --git a/src/compiler/arm64/instruction-codes-arm64.h b/src/compiler/arm64/instruction-codes-arm64.h index 5b44410a37..e593f37a44 100644 --- a/src/compiler/arm64/instruction-codes-arm64.h +++ b/src/compiler/arm64/instruction-codes-arm64.h @@ -112,6 +112,7 @@ namespace compiler { V(Arm64Int64ToFloat32) \ V(Arm64Int64ToFloat64) \ V(Arm64Uint32ToFloat64) \ + V(Arm64Uint64ToFloat32) \ V(Arm64Uint64ToFloat64) \ V(Arm64Float64ExtractLowWord32) \ V(Arm64Float64ExtractHighWord32) \ diff --git a/src/compiler/arm64/instruction-selector-arm64.cc b/src/compiler/arm64/instruction-selector-arm64.cc index 4061c5883e..fe0f442185 100644 --- a/src/compiler/arm64/instruction-selector-arm64.cc +++ b/src/compiler/arm64/instruction-selector-arm64.cc @@ -1326,6 +1326,11 @@ void InstructionSelector::VisitRoundInt64ToFloat64(Node* node) { } +void InstructionSelector::VisitRoundUint64ToFloat32(Node* node) { + VisitRR(this, kArm64Uint64ToFloat32, node); +} + + void InstructionSelector::VisitRoundUint64ToFloat64(Node* node) { VisitRR(this, kArm64Uint64ToFloat64, node); } diff --git a/src/compiler/instruction-selector.cc b/src/compiler/instruction-selector.cc index c16cd31c69..db953c2e42 100644 --- a/src/compiler/instruction-selector.cc +++ b/src/compiler/instruction-selector.cc @@ -830,6 +830,8 @@ void InstructionSelector::VisitNode(Node* node) { return MarkAsFloat64(node), VisitRoundInt64ToFloat64(node); case IrOpcode::kBitcastFloat32ToInt32: return MarkAsWord32(node), VisitBitcastFloat32ToInt32(node); + case IrOpcode::kRoundUint64ToFloat32: + return MarkAsFloat64(node), VisitRoundUint64ToFloat32(node); case IrOpcode::kRoundUint64ToFloat64: return MarkAsFloat64(node), VisitRoundUint64ToFloat64(node); case IrOpcode::kBitcastFloat64ToInt64: @@ -1067,6 +1069,11 @@ void InstructionSelector::VisitRoundInt64ToFloat64(Node* node) { } +void InstructionSelector::VisitRoundUint64ToFloat32(Node* node) { + UNIMPLEMENTED(); +} + + void InstructionSelector::VisitRoundUint64ToFloat64(Node* node) { UNIMPLEMENTED(); } diff --git a/src/compiler/machine-operator.cc b/src/compiler/machine-operator.cc index 4a20465da0..910a924b3b 100644 --- a/src/compiler/machine-operator.cc +++ b/src/compiler/machine-operator.cc @@ -138,6 +138,7 @@ CheckedStoreRepresentation CheckedStoreRepresentationOf(Operator const* op) { V(ChangeInt32ToFloat64, Operator::kNoProperties, 1, 0, 1) \ V(RoundInt64ToFloat32, Operator::kNoProperties, 1, 0, 1) \ V(RoundInt64ToFloat64, Operator::kNoProperties, 1, 0, 1) \ + V(RoundUint64ToFloat32, Operator::kNoProperties, 1, 0, 1) \ V(RoundUint64ToFloat64, Operator::kNoProperties, 1, 0, 1) \ V(ChangeInt32ToInt64, Operator::kNoProperties, 1, 0, 1) \ V(ChangeUint32ToFloat64, Operator::kNoProperties, 1, 0, 1) \ diff --git a/src/compiler/machine-operator.h b/src/compiler/machine-operator.h index 9da11b39f8..b687cad47a 100644 --- a/src/compiler/machine-operator.h +++ b/src/compiler/machine-operator.h @@ -214,6 +214,7 @@ class MachineOperatorBuilder final : public ZoneObject { const Operator* TruncateInt64ToInt32(); const Operator* RoundInt64ToFloat32(); const Operator* RoundInt64ToFloat64(); + const Operator* RoundUint64ToFloat32(); const Operator* RoundUint64ToFloat64(); // These operators reinterpret the bits of a floating point number as an diff --git a/src/compiler/mips64/code-generator-mips64.cc b/src/compiler/mips64/code-generator-mips64.cc index beea307995..6eae2d710c 100644 --- a/src/compiler/mips64/code-generator-mips64.cc +++ b/src/compiler/mips64/code-generator-mips64.cc @@ -960,6 +960,10 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { __ Cvt_d_ul(i.OutputDoubleRegister(), i.InputRegister(0)); break; } + case kMips64CvtSUl: { + __ Cvt_s_ul(i.OutputDoubleRegister(), i.InputRegister(0)); + break; + } case kMips64TruncWD: { FPURegister scratch = kScratchDoubleReg; // Other arches use round to zero here, so we follow. diff --git a/src/compiler/mips64/instruction-codes-mips64.h b/src/compiler/mips64/instruction-codes-mips64.h index c4582150a8..8a3d384d85 100644 --- a/src/compiler/mips64/instruction-codes-mips64.h +++ b/src/compiler/mips64/instruction-codes-mips64.h @@ -76,6 +76,7 @@ namespace compiler { V(Mips64TruncUwD) \ V(Mips64CvtDW) \ V(Mips64CvtSL) \ + V(Mips64CvtSUl) \ V(Mips64CvtDL) \ V(Mips64CvtDUw) \ V(Mips64CvtDUl) \ diff --git a/src/compiler/mips64/instruction-selector-mips64.cc b/src/compiler/mips64/instruction-selector-mips64.cc index 4f5eebf1a7..e7b6585ee6 100644 --- a/src/compiler/mips64/instruction-selector-mips64.cc +++ b/src/compiler/mips64/instruction-selector-mips64.cc @@ -627,6 +627,11 @@ void InstructionSelector::VisitRoundInt64ToFloat64(Node* node) { } +void InstructionSelector::VisitRoundUint64ToFloat32(Node* node) { + VisitRR(this, kMips64CvtSUl, node); +} + + void InstructionSelector::VisitRoundUint64ToFloat64(Node* node) { VisitRR(this, kMips64CvtDUl, node); } diff --git a/src/compiler/opcodes.h b/src/compiler/opcodes.h index 3d74175065..e0f8d09967 100644 --- a/src/compiler/opcodes.h +++ b/src/compiler/opcodes.h @@ -275,6 +275,7 @@ V(TruncateInt64ToInt32) \ V(RoundInt64ToFloat32) \ V(RoundInt64ToFloat64) \ + V(RoundUint64ToFloat32) \ V(RoundUint64ToFloat64) \ V(BitcastFloat32ToInt32) \ V(BitcastFloat64ToInt64) \ diff --git a/src/compiler/ppc/code-generator-ppc.cc b/src/compiler/ppc/code-generator-ppc.cc index 06aff27e0a..bdc8f5c379 100644 --- a/src/compiler/ppc/code-generator-ppc.cc +++ b/src/compiler/ppc/code-generator-ppc.cc @@ -1107,6 +1107,11 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { __ ConvertInt64ToDouble(i.InputRegister(0), i.OutputDoubleRegister()); DCHECK_EQ(LeaveRC, i.OutputRCBit()); break; + case kPPC_Uint64ToFloat32: + __ ConvertUnsignedInt64ToFloat(i.InputRegister(0), + i.OutputDoubleRegister()); + DCHECK_EQ(LeaveRC, i.OutputRCBit()); + break; case kPPC_Uint64ToDouble: __ ConvertUnsignedInt64ToDouble(i.InputRegister(0), i.OutputDoubleRegister()); diff --git a/src/compiler/ppc/instruction-codes-ppc.h b/src/compiler/ppc/instruction-codes-ppc.h index 85508b32bb..c76ad1d571 100644 --- a/src/compiler/ppc/instruction-codes-ppc.h +++ b/src/compiler/ppc/instruction-codes-ppc.h @@ -80,6 +80,7 @@ namespace compiler { V(PPC_Int64ToInt32) \ V(PPC_Int64ToFloat32) \ V(PPC_Int64ToDouble) \ + V(PPC_Uint64ToFloat32) \ V(PPC_Uint64ToDouble) \ V(PPC_Int32ToDouble) \ V(PPC_Uint32ToDouble) \ diff --git a/src/compiler/ppc/instruction-selector-ppc.cc b/src/compiler/ppc/instruction-selector-ppc.cc index 46f9823186..47014253f3 100644 --- a/src/compiler/ppc/instruction-selector-ppc.cc +++ b/src/compiler/ppc/instruction-selector-ppc.cc @@ -973,6 +973,11 @@ void InstructionSelector::VisitRoundInt64ToFloat64(Node* node) { } +void InstructionSelector::VisitRoundUint64ToFloat32(Node* node) { + VisitRR(this, kPPC_Uint64ToFloat32, node); +} + + void InstructionSelector::VisitRoundUint64ToFloat64(Node* node) { VisitRR(this, kPPC_Uint64ToDouble, node); } diff --git a/src/compiler/raw-machine-assembler.h b/src/compiler/raw-machine-assembler.h index da458bab98..451dbf4f37 100644 --- a/src/compiler/raw-machine-assembler.h +++ b/src/compiler/raw-machine-assembler.h @@ -464,6 +464,9 @@ class RawMachineAssembler { Node* RoundInt64ToFloat64(Node* a) { return AddNode(machine()->RoundInt64ToFloat64(), a); } + Node* RoundUint64ToFloat32(Node* a) { + return AddNode(machine()->RoundUint64ToFloat32(), a); + } Node* RoundUint64ToFloat64(Node* a) { return AddNode(machine()->RoundUint64ToFloat64(), a); } diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc index f62fad6ed6..06c44bb48d 100644 --- a/src/compiler/typer.cc +++ b/src/compiler/typer.cc @@ -2120,6 +2120,11 @@ Type* Typer::Visitor::TypeRoundInt64ToFloat64(Node* node) { } +Type* Typer::Visitor::TypeRoundUint64ToFloat32(Node* node) { + return Type::Intersect(Type::PlainNumber(), Type::UntaggedFloat32(), zone()); +} + + Type* Typer::Visitor::TypeRoundUint64ToFloat64(Node* node) { return Type::Intersect(Type::PlainNumber(), Type::UntaggedFloat64(), zone()); } diff --git a/src/compiler/verifier.cc b/src/compiler/verifier.cc index 5e1eae6856..c438945f3b 100644 --- a/src/compiler/verifier.cc +++ b/src/compiler/verifier.cc @@ -890,6 +890,7 @@ void Verifier::Visitor::Check(Node* node) { case IrOpcode::kRoundInt64ToFloat32: case IrOpcode::kRoundInt64ToFloat64: case IrOpcode::kRoundUint64ToFloat64: + case IrOpcode::kRoundUint64ToFloat32: case IrOpcode::kTruncateFloat64ToFloat32: case IrOpcode::kTruncateFloat64ToInt32: case IrOpcode::kBitcastFloat32ToInt32: diff --git a/src/compiler/x64/code-generator-x64.cc b/src/compiler/x64/code-generator-x64.cc index 6276726307..c4be56d585 100644 --- a/src/compiler/x64/code-generator-x64.cc +++ b/src/compiler/x64/code-generator-x64.cc @@ -1041,6 +1041,15 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { __ Cvtqsi2sd(i.OutputDoubleRegister(), i.InputOperand(0)); } break; + case kSSEUint64ToFloat32: + if (instr->InputAt(0)->IsRegister()) { + __ movq(kScratchRegister, i.InputRegister(0)); + } else { + __ movq(kScratchRegister, i.InputOperand(0)); + } + __ Cvtqui2ss(i.OutputDoubleRegister(), kScratchRegister, + i.TempRegister(0)); + break; case kSSEUint64ToFloat64: if (instr->InputAt(0)->IsRegister()) { __ movq(kScratchRegister, i.InputRegister(0)); diff --git a/src/compiler/x64/instruction-codes-x64.h b/src/compiler/x64/instruction-codes-x64.h index a76b7c38f8..e2ea0cd4b8 100644 --- a/src/compiler/x64/instruction-codes-x64.h +++ b/src/compiler/x64/instruction-codes-x64.h @@ -81,6 +81,7 @@ namespace compiler { V(SSEInt32ToFloat64) \ V(SSEInt64ToFloat32) \ V(SSEInt64ToFloat64) \ + V(SSEUint64ToFloat32) \ V(SSEUint64ToFloat64) \ V(SSEUint32ToFloat64) \ V(SSEFloat64ExtractLowWord32) \ diff --git a/src/compiler/x64/instruction-selector-x64.cc b/src/compiler/x64/instruction-selector-x64.cc index 426b5c65cc..f52639d873 100644 --- a/src/compiler/x64/instruction-selector-x64.cc +++ b/src/compiler/x64/instruction-selector-x64.cc @@ -971,6 +971,14 @@ void InstructionSelector::VisitRoundInt64ToFloat64(Node* node) { } +void InstructionSelector::VisitRoundUint64ToFloat32(Node* node) { + X64OperandGenerator g(this); + InstructionOperand temps[] = {g.TempRegister()}; + Emit(kSSEUint64ToFloat32, g.DefineAsRegister(node), g.Use(node->InputAt(0)), + arraysize(temps), temps); +} + + void InstructionSelector::VisitRoundUint64ToFloat64(Node* node) { X64OperandGenerator g(this); InstructionOperand temps[] = {g.TempRegister()}; diff --git a/src/mips64/macro-assembler-mips64.cc b/src/mips64/macro-assembler-mips64.cc index f59b28a51b..52b8579656 100644 --- a/src/mips64/macro-assembler-mips64.cc +++ b/src/mips64/macro-assembler-mips64.cc @@ -1548,6 +1548,41 @@ void MacroAssembler::Cvt_d_ul(FPURegister fd, Register rs) { } +void MacroAssembler::Cvt_s_ul(FPURegister fd, FPURegister fs) { + // Move the data from fs to t8. + dmfc1(t8, fs); + Cvt_s_ul(fd, t8); +} + + +void MacroAssembler::Cvt_s_ul(FPURegister fd, Register rs) { + // Convert rs to a FP value in fd. + + DCHECK(!rs.is(t9)); + DCHECK(!rs.is(at)); + + Label positive, conversion_done; + + Branch(&positive, ge, rs, Operand(zero_reg)); + + // Rs >= 2^31. + andi(t9, rs, 1); + dsrl(rs, rs, 1); + or_(t9, t9, rs); + dmtc1(t9, fd); + cvt_s_l(fd, fd); + Branch(USE_DELAY_SLOT, &conversion_done); + add_s(fd, fd, fd); // In delay slot. + + bind(&positive); + // Rs < 2^31, we can do simple conversion. + dmtc1(rs, fd); + cvt_s_l(fd, fd); + + bind(&conversion_done); +} + + void MacroAssembler::Round_l_d(FPURegister fd, FPURegister fs) { round_l_d(fd, fs); } diff --git a/src/mips64/macro-assembler-mips64.h b/src/mips64/macro-assembler-mips64.h index 5128a86958..0e88ca4d6d 100644 --- a/src/mips64/macro-assembler-mips64.h +++ b/src/mips64/macro-assembler-mips64.h @@ -825,6 +825,10 @@ class MacroAssembler: public Assembler { void Cvt_d_ul(FPURegister fd, FPURegister fs); void Cvt_d_ul(FPURegister fd, Register rs); + // Convert unsigned long to float. + void Cvt_s_ul(FPURegister fd, FPURegister fs); + void Cvt_s_ul(FPURegister fd, Register rs); + // Convert double to unsigned long. void Trunc_l_ud(FPURegister fd, FPURegister fs, FPURegister scratch); diff --git a/src/ppc/assembler-ppc.cc b/src/ppc/assembler-ppc.cc index c471d24479..92010b6cee 100644 --- a/src/ppc/assembler-ppc.cc +++ b/src/ppc/assembler-ppc.cc @@ -2169,6 +2169,12 @@ void Assembler::fcfidu(const DoubleRegister frt, const DoubleRegister frb, } +void Assembler::fcfidus(const DoubleRegister frt, const DoubleRegister frb, + RCBit rc) { + emit(EXT3 | FCFIDU | frt.code() * B21 | frb.code() * B11 | rc); +} + + void Assembler::fcfids(const DoubleRegister frt, const DoubleRegister frb, RCBit rc) { emit(EXT3 | FCFID | frt.code() * B21 | frb.code() * B11 | rc); diff --git a/src/ppc/assembler-ppc.h b/src/ppc/assembler-ppc.h index 1a1d85c1e8..46659287e1 100644 --- a/src/ppc/assembler-ppc.h +++ b/src/ppc/assembler-ppc.h @@ -1052,6 +1052,8 @@ class Assembler : public AssemblerBase { RCBit rc = LeaveRC); void fcfidu(const DoubleRegister frt, const DoubleRegister frb, RCBit rc = LeaveRC); + void fcfidus(const DoubleRegister frt, const DoubleRegister frb, + RCBit rc = LeaveRC); void fcfids(const DoubleRegister frt, const DoubleRegister frb, RCBit rc = LeaveRC); void fctid(const DoubleRegister frt, const DoubleRegister frb, diff --git a/src/ppc/disasm-ppc.cc b/src/ppc/disasm-ppc.cc index b5c87ca005..918dd0a31f 100644 --- a/src/ppc/disasm-ppc.cc +++ b/src/ppc/disasm-ppc.cc @@ -889,6 +889,10 @@ void Decoder::DecodeExt3(Instruction* instr) { Format(instr, "fcfids'. 'Dt, 'Db"); break; } + case FCFIDU: { + Format(instr, "fcfidus'.'Dt, 'Db"); + break; + } default: { Unknown(instr); // not used by V8 } diff --git a/src/ppc/macro-assembler-ppc.cc b/src/ppc/macro-assembler-ppc.cc index 711422af92..406b7707c7 100644 --- a/src/ppc/macro-assembler-ppc.cc +++ b/src/ppc/macro-assembler-ppc.cc @@ -671,6 +671,13 @@ void MacroAssembler::ConvertInt64ToDouble(Register src, } +void MacroAssembler::ConvertUnsignedInt64ToFloat(Register src, + DoubleRegister double_dst) { + MovInt64ToDouble(double_dst, src); + fcfidus(double_dst, double_dst); +} + + void MacroAssembler::ConvertUnsignedInt64ToDouble(Register src, DoubleRegister double_dst) { MovInt64ToDouble(double_dst, src); diff --git a/src/ppc/macro-assembler-ppc.h b/src/ppc/macro-assembler-ppc.h index 1ec51bfa59..8a8bca9751 100644 --- a/src/ppc/macro-assembler-ppc.h +++ b/src/ppc/macro-assembler-ppc.h @@ -387,9 +387,10 @@ class MacroAssembler : public Assembler { const Register int_scratch); #if V8_TARGET_ARCH_PPC64 - void ConvertInt64ToDouble(Register src, DoubleRegister double_dst); - void ConvertUnsignedInt64ToDouble(Register src, DoubleRegister double_dst); void ConvertInt64ToFloat(Register src, DoubleRegister double_dst); + void ConvertInt64ToDouble(Register src, DoubleRegister double_dst); + void ConvertUnsignedInt64ToFloat(Register src, DoubleRegister double_dst); + void ConvertUnsignedInt64ToDouble(Register src, DoubleRegister double_dst); #endif // Converts the double_input to an integer. Note that, upon return, diff --git a/src/ppc/simulator-ppc.cc b/src/ppc/simulator-ppc.cc index 2707343ed5..2062bd26af 100644 --- a/src/ppc/simulator-ppc.cc +++ b/src/ppc/simulator-ppc.cc @@ -2707,6 +2707,15 @@ void Simulator::ExecuteExt3(Instruction* instr) { set_d_register_from_double(frt, frt_val); return; } + case FCFIDU: { + // fcfidus + int frt = instr->RTValue(); + int frb = instr->RBValue(); + uint64_t frb_val = get_d_register(frb); + double frt_val = static_cast(frb_val); + set_d_register_from_double(frt, frt_val); + return; + } } UNIMPLEMENTED(); // Not used by V8. } diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc index 1a936afc98..8223aa9635 100644 --- a/src/x64/macro-assembler-x64.cc +++ b/src/x64/macro-assembler-x64.cc @@ -899,6 +899,25 @@ void MacroAssembler::Cvtqsi2sd(XMMRegister dst, const Operand& src) { } +void MacroAssembler::Cvtqui2ss(XMMRegister dst, Register src, Register tmp) { + Label msb_set_src; + Label jmp_return; + testq(src, src); + j(sign, &msb_set_src, Label::kNear); + Cvtqsi2ss(dst, src); + jmp(&jmp_return, Label::kNear); + bind(&msb_set_src); + movq(tmp, src); + shrq(src, Immediate(1)); + // Recover the least significant bit to avoid rounding errors. + andq(tmp, Immediate(1)); + orq(src, tmp); + Cvtqsi2ss(dst, src); + addss(dst, dst); + bind(&jmp_return); +} + + void MacroAssembler::Cvtqui2sd(XMMRegister dst, Register src, Register tmp) { Label msb_set_src; Label jmp_return; @@ -909,7 +928,6 @@ void MacroAssembler::Cvtqui2sd(XMMRegister dst, Register src, Register tmp) { bind(&msb_set_src); movq(tmp, src); shrq(src, Immediate(1)); - // Recover the least significant bit to avoid rounding errors. andq(tmp, Immediate(1)); orq(src, tmp); Cvtqsi2sd(dst, src); diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h index f236b9d2f9..5d66c6ec1e 100644 --- a/src/x64/macro-assembler-x64.h +++ b/src/x64/macro-assembler-x64.h @@ -823,6 +823,8 @@ class MacroAssembler: public Assembler { void Cvtqsi2sd(XMMRegister dst, Register src); void Cvtqsi2sd(XMMRegister dst, const Operand& src); + + void Cvtqui2ss(XMMRegister dst, Register src, Register tmp); void Cvtqui2sd(XMMRegister dst, Register src, Register tmp); void Cvtsd2si(Register dst, XMMRegister src); diff --git a/test/cctest/compiler/test-run-machops.cc b/test/cctest/compiler/test-run-machops.cc index 4ba78e1c65..0dadfb6577 100644 --- a/test/cctest/compiler/test-run-machops.cc +++ b/test/cctest/compiler/test-run-machops.cc @@ -5535,6 +5535,96 @@ TEST(RunRoundUint64ToFloat64) { } +TEST(RunRoundUint64ToFloat32) { + struct { + uint64_t input; + uint32_t expected; + } values[] = {{0x0, 0x0}, + {0x1, 0x3f800000}, + {0xffffffff, 0x4f800000}, + {0x1b09788b, 0x4dd84bc4}, + {0x4c5fce8, 0x4c98bf9d}, + {0xcc0de5bf, 0x4f4c0de6}, + {0x2, 0x40000000}, + {0x3, 0x40400000}, + {0x4, 0x40800000}, + {0x5, 0x40a00000}, + {0x8, 0x41000000}, + {0x9, 0x41100000}, + {0xffffffffffffffff, 0x5f800000}, + {0xfffffffffffffffe, 0x5f800000}, + {0xfffffffffffffffd, 0x5f800000}, + {0x0, 0x0}, + {0x100000000, 0x4f800000}, + {0xffffffff00000000, 0x5f800000}, + {0x1b09788b00000000, 0x5dd84bc4}, + {0x4c5fce800000000, 0x5c98bf9d}, + {0xcc0de5bf00000000, 0x5f4c0de6}, + {0x200000000, 0x50000000}, + {0x300000000, 0x50400000}, + {0x400000000, 0x50800000}, + {0x500000000, 0x50a00000}, + {0x800000000, 0x51000000}, + {0x900000000, 0x51100000}, + {0x273a798e187937a3, 0x5e1ce9e6}, + {0xece3af835495a16b, 0x5f6ce3b0}, + {0xb668ecc11223344, 0x5d3668ed}, + {0x9e, 0x431e0000}, + {0x43, 0x42860000}, + {0xaf73, 0x472f7300}, + {0x116b, 0x458b5800}, + {0x658ecc, 0x4acb1d98}, + {0x2b3b4c, 0x4a2ced30}, + {0x88776655, 0x4f087766}, + {0x70000000, 0x4ee00000}, + {0x7200000, 0x4ce40000}, + {0x7fffffff, 0x4f000000}, + {0x56123761, 0x4eac246f}, + {0x7fffff00, 0x4efffffe}, + {0x761c4761eeeeeeee, 0x5eec388f}, + {0x80000000eeeeeeee, 0x5f000000}, + {0x88888888dddddddd, 0x5f088889}, + {0xa0000000dddddddd, 0x5f200000}, + {0xddddddddaaaaaaaa, 0x5f5dddde}, + {0xe0000000aaaaaaaa, 0x5f600000}, + {0xeeeeeeeeeeeeeeee, 0x5f6eeeef}, + {0xfffffffdeeeeeeee, 0x5f800000}, + {0xf0000000dddddddd, 0x5f700000}, + {0x7fffffdddddddd, 0x5b000000}, + {0x3fffffaaaaaaaa, 0x5a7fffff}, + {0x1fffffaaaaaaaa, 0x59fffffd}, + {0xfffff, 0x497ffff0}, + {0x7ffff, 0x48ffffe0}, + {0x3ffff, 0x487fffc0}, + {0x1ffff, 0x47ffff80}, + {0xffff, 0x477fff00}, + {0x7fff, 0x46fffe00}, + {0x3fff, 0x467ffc00}, + {0x1fff, 0x45fff800}, + {0xfff, 0x457ff000}, + {0x7ff, 0x44ffe000}, + {0x3ff, 0x447fc000}, + {0x1ff, 0x43ff8000}, + {0x3fffffffffff, 0x56800000}, + {0x1fffffffffff, 0x56000000}, + {0xfffffffffff, 0x55800000}, + {0x7ffffffffff, 0x55000000}, + {0x3ffffffffff, 0x54800000}, + {0x1ffffffffff, 0x54000000}, + {0x8000008000000000, 0x5f000000}, + {0x8000008000000001, 0x5f000001}, + {0x8000000000000400, 0x5f000000}, + {0x8000000000000401, 0x5f000000}}; + + BufferedRawMachineAssemblerTester m(kMachUint64); + m.Return(m.RoundUint64ToFloat32(m.Parameter(0))); + + for (int i = 0; i < arraysize(values); i++) { + CHECK_EQ(bit_cast(values[i].expected), m.Call(values[i].input)); + } +} + + #endif