MIPS64: Fix Math.ceil/floor intrinsics

The latest MIPS64R6 emulator supports NAN2008 standard. When
FCSR.NAN2008=1 (required from R6) ceil.l.d and floor.l.d instructions
will return -2^63 when the input value is smaller than -2^63. This
wasn't the case when FCSR.NAN2008=0. In that case, result from the
instructions was 2^63-1 when the input value was smaller than -2^63.

This fixes test 082-inline-execute.

Test: ./testrunner.py --target --optimizing --64 -j1 (in QEMU)

Change-Id: I3d2cdd1d55b3694549f88f4f5b903a0c4f1c0d09
diff --git a/compiler/optimizing/intrinsics_mips64.cc b/compiler/optimizing/intrinsics_mips64.cc
index 6098767..c2518a7 100644
--- a/compiler/optimizing/intrinsics_mips64.cc
+++ b/compiler/optimizing/intrinsics_mips64.cc
@@ -834,15 +834,15 @@
   __ Bnezc(AT, &done);
 
   //     Long outLong = floor/ceil(in);
-  //     if outLong == Long.MAX_VALUE {
+  //     if (outLong == Long.MAX_VALUE) || (outLong == Long.MIN_VALUE) {
   //         // floor()/ceil() has almost certainly returned a value
   //         // which can't be successfully represented as a signed
   //         // 64-bit number.  Java expects that the input value will
   //         // be returned in these cases.
   //         // There is also a small probability that floor(in)/ceil(in)
   //         // correctly truncates/rounds up the input value to
-  //         // Long.MAX_VALUE.  In that case, this exception handling
-  //         // code still does the correct thing.
+  //         // Long.MAX_VALUE or Long.MIN_VALUE. In these cases, this
+  //         // exception handling code still does the correct thing.
   //         return in;
   //     }
   if (mode == kFloor) {
@@ -852,8 +852,14 @@
   }
   __ Dmfc1(AT, out);
   __ MovD(out, in);
-  __ LoadConst64(TMP, kPrimLongMax);
-  __ Beqc(AT, TMP, &done);
+  __ Daddiu(TMP, AT, 1);
+  __ Dati(TMP, 0x8000);  // TMP = AT + 0x8000 0000 0000 0001
+                         // or    AT - 0x7FFF FFFF FFFF FFFF.
+                         // IOW, TMP = 1 if AT = Long.MIN_VALUE
+                         // or   TMP = 0 if AT = Long.MAX_VALUE.
+  __ Dsrl(TMP, TMP, 1);  // TMP = 0 if AT = Long.MIN_VALUE
+                         //         or AT = Long.MAX_VALUE.
+  __ Beqzc(TMP, &done);
 
   //     double out = outLong;
   //     return out;