MIPS32: Implement isInfinite intrinsics.

- boolean java.lang.Float.isInfinite(float)
- boolean java.lang.Double.isInfinite(double)

Change-Id: I17dc2380ec864fd7612025ed400e29dd115ccab4
diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc
index 5a35dd5..78b400d 100644
--- a/compiler/optimizing/intrinsics_mips.cc
+++ b/compiler/optimizing/intrinsics_mips.cc
@@ -1502,6 +1502,66 @@
   __ Bind(&end);
 }
 
+static void GenIsInfinite(LocationSummary* locations,
+                          const Primitive::Type type,
+                          const bool isR6,
+                          MipsAssembler* assembler) {
+  FRegister in = locations->InAt(0).AsFpuRegister<FRegister>();
+  Register out = locations->Out().AsRegister<Register>();
+
+  DCHECK(type == Primitive::kPrimFloat || type == Primitive::kPrimDouble);
+
+  if (isR6) {
+    if (type == Primitive::kPrimDouble) {
+        __ ClassD(FTMP, in);
+    } else {
+        __ ClassS(FTMP, in);
+    }
+    __ Mfc1(out, FTMP);
+    __ Andi(out, out, kPositiveInfinity | kNegativeInfinity);
+    __ Sltu(out, ZERO, out);
+  } else {
+    // If one, or more, of the exponent bits is zero, then the number can't be infinite.
+    if (type == Primitive::kPrimDouble) {
+      __ MoveFromFpuHigh(TMP, in);
+      __ LoadConst32(AT, 0x7FF00000);
+    } else {
+      __ Mfc1(TMP, in);
+      __ LoadConst32(AT, 0x7F800000);
+    }
+    __ Xor(TMP, TMP, AT);
+
+    __ Sll(TMP, TMP, 1);
+
+    if (type == Primitive::kPrimDouble) {
+      __ Mfc1(AT, in);
+      __ Or(TMP, TMP, AT);
+    }
+    // If any of the significand bits are one, then the number is not infinite.
+    __ Sltiu(out, TMP, 1);
+  }
+}
+
+// boolean java.lang.Float.isInfinite(float)
+void IntrinsicLocationsBuilderMIPS::VisitFloatIsInfinite(HInvoke* invoke) {
+  CreateFPToIntLocations(arena_, invoke);
+}
+
+void IntrinsicCodeGeneratorMIPS::VisitFloatIsInfinite(HInvoke* invoke) {
+  GenIsInfinite(invoke->GetLocations(), Primitive::kPrimFloat, IsR6(), GetAssembler());
+}
+
+// boolean java.lang.Double.isInfinite(double)
+void IntrinsicLocationsBuilderMIPS::VisitDoubleIsInfinite(HInvoke* invoke) {
+  CreateFPToIntLocations(arena_, invoke);
+}
+
+void IntrinsicCodeGeneratorMIPS::VisitDoubleIsInfinite(HInvoke* invoke) {
+  GenIsInfinite(invoke->GetLocations(), Primitive::kPrimDouble, IsR6(), GetAssembler());
+}
+
+// Unimplemented intrinsics.
+
 UNIMPLEMENTED_INTRINSIC(MIPS, IntegerBitCount)
 UNIMPLEMENTED_INTRINSIC(MIPS, LongBitCount)
 
@@ -1559,9 +1619,6 @@
 UNIMPLEMENTED_INTRINSIC(MIPS, MathTan)
 UNIMPLEMENTED_INTRINSIC(MIPS, MathTanh)
 
-UNIMPLEMENTED_INTRINSIC(MIPS, FloatIsInfinite)
-UNIMPLEMENTED_INTRINSIC(MIPS, DoubleIsInfinite)
-
 UNIMPLEMENTED_INTRINSIC(MIPS, IntegerHighestOneBit)
 UNIMPLEMENTED_INTRINSIC(MIPS, LongHighestOneBit)
 UNIMPLEMENTED_INTRINSIC(MIPS, IntegerLowestOneBit)
@@ -1569,6 +1626,8 @@
 
 UNREACHABLE_INTRINSICS(MIPS)
 
+#undef UNIMPLEMENTED_INTRINSIC
+
 #undef __
 
 }  // namespace mips
diff --git a/test/082-inline-execute/src/Main.java b/test/082-inline-execute/src/Main.java
index 93a9005..9aaed9d 100644
--- a/test/082-inline-execute/src/Main.java
+++ b/test/082-inline-execute/src/Main.java
@@ -40,6 +40,10 @@
     test_Math_rint();
     test_Math_round_D();
     test_Math_round_F();
+    test_Math_isNaN_D();
+    test_Math_isNaN_F();
+    test_Math_isInfinite_D();
+    test_Math_isInfinite_F();
     test_Short_reverseBytes();
     test_Integer_reverseBytes();
     test_Long_reverseBytes();
@@ -836,6 +840,106 @@
     Assert.assertEquals(Math.round(Float.NEGATIVE_INFINITY), Integer.MIN_VALUE);
   }
 
+  public static void test_Math_isNaN_D() {
+    // Quiet NaN.
+    Assert.assertTrue(Double.isNaN(Double.longBitsToDouble(0x7FF4000000000000l)));
+    Assert.assertTrue(Double.isNaN(Double.longBitsToDouble(0xFFF4000000000000l)));
+    // Signaling NaN.
+    Assert.assertTrue(Double.isNaN(Double.longBitsToDouble(0x7FF8000000000000l)));
+    Assert.assertTrue(Double.isNaN(Double.longBitsToDouble(0xFFF8000000000000l)));
+    // Distinct from +/- infinity.
+    Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0x7FF0000000000000l)));
+    Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0xFFF0000000000000l)));
+    // Distinct from normal numbers.
+    Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0x7FE0000000000000l)));
+    Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0xFFE0000000000000l)));
+    Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0x0010000000000000l)));
+    Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0x8010000000000000l)));
+    // Distinct from +/- zero.
+    Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0x0000000000000000l)));
+    Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0x8000000000000000l)));
+    // Distinct from subnormal numbers.
+    Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0x0008000000000000l)));
+    Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0x8008000000000000l)));
+    Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0x0000000000000001l)));
+    Assert.assertFalse(Double.isNaN(Double.longBitsToDouble(0x8000000000000001l)));
+  }
+
+  public static void test_Math_isNaN_F() {
+    // Quiet NaN.
+    Assert.assertTrue(Float.isNaN(Float.intBitsToFloat(0x7FA00000)));
+    Assert.assertTrue(Float.isNaN(Float.intBitsToFloat(0xFFA00000)));
+    // Signaling NaN.
+    Assert.assertTrue(Float.isNaN(Float.intBitsToFloat(0x7FC00000)));
+    Assert.assertTrue(Float.isNaN(Float.intBitsToFloat(0xFFC00000)));
+    // Distinct from +/- infinity.
+    Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0x7F800000)));
+    Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0xFF800000)));
+    // Distinct from normal numbers.
+    Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0x7F000000)));
+    Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0xFF000000)));
+    Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0x00800000)));
+    Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0x80800000)));
+    // Distinct from +/- zero.
+    Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0x00000000)));
+    Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0x80000000)));
+    // Distinct from subnormal numbers.
+    Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0x00400000)));
+    Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0x80400000)));
+    Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0x00000001)));
+    Assert.assertFalse(Float.isNaN(Float.intBitsToFloat(0x80000001)));
+  }
+
+  public static void test_Math_isInfinite_D() {
+    // Distinct from Quiet NaN.
+    Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0x7FF4000000000000l)));
+    Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0xFFF4000000000000l)));
+    // Distinct from Signaling NaN.
+    Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0x7FF8000000000000l)));
+    Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0xFFF8000000000000l)));
+    // +/- infinity.
+    Assert.assertTrue(Double.isInfinite(Double.longBitsToDouble(0x7FF0000000000000l)));
+    Assert.assertTrue(Double.isInfinite(Double.longBitsToDouble(0xFFF0000000000000l)));
+    // Distinct from normal numbers.
+    Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0x7FE0000000000000l)));
+    Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0xFFE0000000000000l)));
+    Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0x0010000000000000l)));
+    Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0x8010000000000000l)));
+    // Distinct from +/- zero.
+    Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0x0000000000000000l)));
+    Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0x8000000000000000l)));
+    // Distinct from subnormal numbers.
+    Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0x0008000000000000l)));
+    Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0x8008000000000000l)));
+    Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0x0000000000000001l)));
+    Assert.assertFalse(Double.isInfinite(Double.longBitsToDouble(0x8000000000000001l)));
+  }
+
+  public static void test_Math_isInfinite_F() {
+    // Distinct from Quiet NaN.
+    Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x7FA00000)));
+    Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0xFFA00000)));
+    // Distinct from Signaling NaN.
+    Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x7FC00000)));
+    Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0xFFC00000)));
+    // +/- infinity.
+    Assert.assertTrue(Float.isInfinite(Float.intBitsToFloat(0x7F800000)));
+    Assert.assertTrue(Float.isInfinite(Float.intBitsToFloat(0xFF800000)));
+    // Distinct from normal numbers.
+    Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x7F000000)));
+    Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0xFF000000)));
+    Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x00800000)));
+    Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x80800000)));
+    // Distinct from +/- zero.
+    Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x00000000)));
+    Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x80000000)));
+    // Distinct from subnormal numbers.
+    Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x00400000)));
+    Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x80400000)));
+    Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x00000001)));
+    Assert.assertFalse(Float.isInfinite(Float.intBitsToFloat(0x80000001)));
+  }
+
   public static void test_StrictMath_abs_I() {
     StrictMath.abs(-1);
     Assert.assertEquals(StrictMath.abs(0), 0);