Implemented the RoundUint64ToFloat32 TurboFan operator for x64, arm64,
and ppc64. R=titzer@chromium.org Review URL: https://codereview.chromium.org/1438013003 Cr-Commit-Position: refs/heads/master@{#32031}
This commit is contained in:
parent
7c449a62ed
commit
2f7d6b46d0
@ -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;
|
||||
|
@ -112,6 +112,7 @@ namespace compiler {
|
||||
V(Arm64Int64ToFloat32) \
|
||||
V(Arm64Int64ToFloat64) \
|
||||
V(Arm64Uint32ToFloat64) \
|
||||
V(Arm64Uint64ToFloat32) \
|
||||
V(Arm64Uint64ToFloat64) \
|
||||
V(Arm64Float64ExtractLowWord32) \
|
||||
V(Arm64Float64ExtractHighWord32) \
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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) \
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -76,6 +76,7 @@ namespace compiler {
|
||||
V(Mips64TruncUwD) \
|
||||
V(Mips64CvtDW) \
|
||||
V(Mips64CvtSL) \
|
||||
V(Mips64CvtSUl) \
|
||||
V(Mips64CvtDL) \
|
||||
V(Mips64CvtDUw) \
|
||||
V(Mips64CvtDUl) \
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -275,6 +275,7 @@
|
||||
V(TruncateInt64ToInt32) \
|
||||
V(RoundInt64ToFloat32) \
|
||||
V(RoundInt64ToFloat64) \
|
||||
V(RoundUint64ToFloat32) \
|
||||
V(RoundUint64ToFloat64) \
|
||||
V(BitcastFloat32ToInt32) \
|
||||
V(BitcastFloat64ToInt64) \
|
||||
|
@ -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());
|
||||
|
@ -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) \
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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));
|
||||
|
@ -81,6 +81,7 @@ namespace compiler {
|
||||
V(SSEInt32ToFloat64) \
|
||||
V(SSEInt64ToFloat32) \
|
||||
V(SSEInt64ToFloat64) \
|
||||
V(SSEUint64ToFloat32) \
|
||||
V(SSEUint64ToFloat64) \
|
||||
V(SSEUint32ToFloat64) \
|
||||
V(SSEFloat64ExtractLowWord32) \
|
||||
|
@ -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()};
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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<float>(frb_val);
|
||||
set_d_register_from_double(frt, frt_val);
|
||||
return;
|
||||
}
|
||||
}
|
||||
UNIMPLEMENTED(); // Not used by V8.
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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<float> m(kMachUint64);
|
||||
m.Return(m.RoundUint64ToFloat32(m.Parameter(0)));
|
||||
|
||||
for (int i = 0; i < arraysize(values); i++) {
|
||||
CHECK_EQ(bit_cast<float>(values[i].expected), m.Call(values[i].input));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user