diff options
author | 2016-04-22 12:06:34 -0700 | |
---|---|---|
committer | 2016-04-26 16:51:59 -0700 | |
commit | f09d532a5eeda4b8c629c3d7aa207ac63c4a9070 (patch) | |
tree | 7194c02dfbe75a1336a08b499ab94b0b590ff519 | |
parent | 4e377e58066ccef401276d7d0985521e5e63d1fb (diff) |
MIPS32: java.lang.Math.round(float)
BUG=26327751
Change-Id: I9ec0d600bbbbcf9e1ed07fbfc0ce9187a2ae5727
-rw-r--r-- | compiler/optimizing/intrinsics_mips.cc | 117 | ||||
-rw-r--r-- | compiler/utils/mips/assembler_mips_test.cc | 8 | ||||
-rw-r--r-- | test/082-inline-execute/src/Main.java | 20 |
3 files changed, 144 insertions, 1 deletions
diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc index 19c6a225ac..a30aa7ed19 100644 --- a/compiler/optimizing/intrinsics_mips.cc +++ b/compiler/optimizing/intrinsics_mips.cc @@ -2432,13 +2432,128 @@ void IntrinsicCodeGeneratorMIPS::VisitLongLowestOneBit(HInvoke* invoke) { GenLowestOneBit(invoke->GetLocations(), Primitive::kPrimLong, IsR6(), GetAssembler()); } +// int java.lang.Math.round(float) +void IntrinsicLocationsBuilderMIPS::VisitMathRoundFloat(HInvoke* invoke) { + LocationSummary* locations = new (arena_) LocationSummary(invoke, + LocationSummary::kNoCall, + kIntrinsified); + locations->SetInAt(0, Location::RequiresFpuRegister()); + locations->AddTemp(Location::RequiresFpuRegister()); + locations->SetOut(Location::RequiresRegister()); +} + +void IntrinsicCodeGeneratorMIPS::VisitMathRoundFloat(HInvoke* invoke) { + LocationSummary* locations = invoke->GetLocations(); + MipsAssembler* assembler = GetAssembler(); + FRegister in = locations->InAt(0).AsFpuRegister<FRegister>(); + FRegister half = locations->GetTemp(0).AsFpuRegister<FRegister>(); + Register out = locations->Out().AsRegister<Register>(); + + MipsLabel done; + MipsLabel finite; + MipsLabel add; + + // if (in.isNaN) { + // return 0; + // } + // + // out = floor.w.s(in); + // + // /* + // * This "if" statement is only needed for the pre-R6 version of floor.w.s + // * which outputs Integer.MAX_VALUE for negative numbers with magnitudes + // * too large to fit in a 32-bit integer. + // * + // * Starting with MIPSR6, which always sets FCSR.NAN2008=1, negative + // * numbers which are too large to be represented in a 32-bit signed + // * integer will be processed by floor.w.s to output Integer.MIN_VALUE, + // * and will no longer be processed by this "if" statement. + // */ + // if (out == Integer.MAX_VALUE) { + // TMP = (in < 0.0f) ? 1 : 0; + // /* + // * If TMP is 1, then adding it to out will wrap its value from + // * Integer.MAX_VALUE to Integer.MIN_VALUE. + // */ + // return out += TMP; + // } + // + // /* + // * For negative values not handled by the previous "if" statement the + // * test here will correctly set the value of TMP. + // */ + // TMP = ((in - out) >= 0.5f) ? 1 : 0; + // return out += TMP; + + // Test for NaN. + if (IsR6()) { + __ CmpUnS(FTMP, in, in); + } else { + __ CunS(in, in); + } + + // Return zero for NaN. + __ Move(out, ZERO); + if (IsR6()) { + __ Bc1nez(FTMP, &done); + } else { + __ Bc1t(&done); + } + + // out = floor(in); + __ FloorWS(FTMP, in); + __ Mfc1(out, FTMP); + + __ LoadConst32(TMP, 1); + + // TMP = (out = java.lang.Integer.MAX_VALUE) ? 1 : 0; + __ LoadConst32(AT, std::numeric_limits<int32_t>::max()); + __ Bne(AT, out, &finite); + + __ Mtc1(ZERO, FTMP); + if (IsR6()) { + __ CmpLtS(FTMP, in, FTMP); + __ Mfc1(AT, FTMP); + } else { + __ ColtS(in, FTMP); + } + + __ B(&add); + + __ Bind(&finite); + + // TMP = (0.5f <= (in - out)) ? 1 : 0; + __ Cvtsw(FTMP, FTMP); // Convert output of floor.w.s back to "float". + __ LoadConst32(AT, bit_cast<int32_t, float>(0.5f)); + __ SubS(FTMP, in, FTMP); + __ Mtc1(AT, half); + if (IsR6()) { + __ CmpLeS(FTMP, half, FTMP); + __ Mfc1(AT, FTMP); + } else { + __ ColeS(half, FTMP); + } + + __ Bind(&add); + + if (IsR6()) { + __ Selnez(TMP, TMP, AT); + } else { + __ Movf(TMP, ZERO); + } + + // Return out += TMP. + __ Addu(out, out, TMP); + + __ Bind(&done); +} + // Unimplemented intrinsics. UNIMPLEMENTED_INTRINSIC(MIPS, MathCeil) UNIMPLEMENTED_INTRINSIC(MIPS, MathFloor) UNIMPLEMENTED_INTRINSIC(MIPS, MathRint) UNIMPLEMENTED_INTRINSIC(MIPS, MathRoundDouble) -UNIMPLEMENTED_INTRINSIC(MIPS, MathRoundFloat) UNIMPLEMENTED_INTRINSIC(MIPS, UnsafeCASLong) UNIMPLEMENTED_INTRINSIC(MIPS, ReferenceGetReferent) diff --git a/compiler/utils/mips/assembler_mips_test.cc b/compiler/utils/mips/assembler_mips_test.cc index cec43badf8..56e58849c9 100644 --- a/compiler/utils/mips/assembler_mips_test.cc +++ b/compiler/utils/mips/assembler_mips_test.cc @@ -561,6 +561,14 @@ TEST_F(AssemblerMIPSTest, NegD) { DriverStr(RepeatFF(&mips::MipsAssembler::NegD, "neg.d ${reg1}, ${reg2}"), "NegD"); } +TEST_F(AssemblerMIPSTest, FloorWS) { + DriverStr(RepeatFF(&mips::MipsAssembler::FloorWS, "floor.w.s ${reg1}, ${reg2}"), "floor.w.s"); +} + +TEST_F(AssemblerMIPSTest, FloorWD) { + DriverStr(RepeatFF(&mips::MipsAssembler::FloorWD, "floor.w.d ${reg1}, ${reg2}"), "floor.w.d"); +} + TEST_F(AssemblerMIPSTest, CunS) { DriverStr(RepeatIbFF(&mips::MipsAssembler::CunS, 3, "c.un.s $fcc{imm}, ${reg1}, ${reg2}"), "CunS"); diff --git a/test/082-inline-execute/src/Main.java b/test/082-inline-execute/src/Main.java index 9aaed9d589..bf561e9a8b 100644 --- a/test/082-inline-execute/src/Main.java +++ b/test/082-inline-execute/src/Main.java @@ -809,6 +809,7 @@ public class Main { Assert.assertEquals(Math.round(-3.0d), -3l); Assert.assertEquals(Math.round(0.49999999999999994d), 0l); Assert.assertEquals(Math.round(9007199254740991.0d), 9007199254740991l); // 2^53 - 1 + Assert.assertEquals(Math.round(-9007199254740991.0d), -9007199254740991l); // -(2^53 - 1) Assert.assertEquals(Math.round(Double.NaN), (long)+0.0d); Assert.assertEquals(Math.round(Long.MAX_VALUE + 1.0d), Long.MAX_VALUE); Assert.assertEquals(Math.round(Long.MIN_VALUE - 1.0d), Long.MIN_VALUE); @@ -832,7 +833,16 @@ public class Main { Assert.assertEquals(Math.round(-3.0f), -3); // 0.4999999701976776123046875 Assert.assertEquals(Math.round(Float.intBitsToFloat(0x3EFFFFFF)), (int)+0.0f); + Assert.assertEquals(Math.round(8388607.0f), 8388607); // 2^23 - 1 + Assert.assertEquals(Math.round(8388607.5f), 8388608); // 2^23 - 0.5 + Assert.assertEquals(Math.round(8388608.0f), 8388608); // 2^23 + Assert.assertEquals(Math.round(-8388607.0f), -8388607); // -(2^23 - 1) + Assert.assertEquals(Math.round(-8388607.5f), -8388607); // -(2^23 - 0.5) + Assert.assertEquals(Math.round(-8388608.0f), -8388608); // -2^23 Assert.assertEquals(Math.round(16777215.0f), 16777215); // 2^24 - 1 + Assert.assertEquals(Math.round(16777216.0f), 16777216); // 2^24 + Assert.assertEquals(Math.round(-16777215.0f), -16777215); // -(2^24 - 1) + Assert.assertEquals(Math.round(-16777216.0f), -16777216); // -2^24 Assert.assertEquals(Math.round(Float.NaN), (int)+0.0f); Assert.assertEquals(Math.round(Integer.MAX_VALUE + 1.0f), Integer.MAX_VALUE); Assert.assertEquals(Math.round(Integer.MIN_VALUE - 1.0f), Integer.MIN_VALUE); @@ -1144,6 +1154,7 @@ public class Main { Assert.assertEquals(StrictMath.round(-3.0d), -3l); Assert.assertEquals(StrictMath.round(0.49999999999999994d), 0l); Assert.assertEquals(StrictMath.round(9007199254740991.0d), 9007199254740991l); // 2^53 - 1 + Assert.assertEquals(StrictMath.round(-9007199254740991.0d), -9007199254740991l); // -(2^53 - 1) Assert.assertEquals(StrictMath.round(Double.NaN), (long)+0.0d); Assert.assertEquals(StrictMath.round(Long.MAX_VALUE + 1.0d), Long.MAX_VALUE); Assert.assertEquals(StrictMath.round(Long.MIN_VALUE - 1.0d), Long.MIN_VALUE); @@ -1167,7 +1178,16 @@ public class Main { Assert.assertEquals(StrictMath.round(-3.0f), -3); // 0.4999999701976776123046875 Assert.assertEquals(StrictMath.round(Float.intBitsToFloat(0x3EFFFFFF)), (int)+0.0f); + Assert.assertEquals(StrictMath.round(8388607.0f), 8388607); // 2^23 - 1 + Assert.assertEquals(StrictMath.round(8388607.5f), 8388608); // 2^23 - 0.5 + Assert.assertEquals(StrictMath.round(8388608.0f), 8388608); // 2^23 + Assert.assertEquals(StrictMath.round(-8388607.0f), -8388607); // -(2^23 - 1) + Assert.assertEquals(StrictMath.round(-8388607.5f), -8388607); // -(2^23 - 0.5) + Assert.assertEquals(StrictMath.round(-8388608.0f), -8388608); // -2^23 Assert.assertEquals(StrictMath.round(16777215.0f), 16777215); // 2^24 - 1 + Assert.assertEquals(StrictMath.round(16777216.0f), 16777216); // 2^24 + Assert.assertEquals(StrictMath.round(-16777215.0f), -16777215); // -(2^24 - 1) + Assert.assertEquals(StrictMath.round(-16777216.0f), -16777216); // -2^24 Assert.assertEquals(StrictMath.round(Float.NaN), (int)+0.0f); Assert.assertEquals(StrictMath.round(Integer.MAX_VALUE + 1.0f), Integer.MAX_VALUE); Assert.assertEquals(StrictMath.round(Integer.MIN_VALUE - 1.0f), Integer.MIN_VALUE); |