diff options
| author | 2017-04-07 11:18:59 +0200 | |
|---|---|---|
| committer | 2017-04-07 11:18:59 +0200 | |
| commit | 716d0738c0ed8f924a44e5c645fa89c1a6079c95 (patch) | |
| tree | eb16f7564328d18cf51b415d771a45e58616a8f2 | |
| parent | f040074c2b9ca348196c176e11491f603a151006 (diff) | |
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
| -rw-r--r-- | compiler/optimizing/intrinsics_mips64.cc | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/compiler/optimizing/intrinsics_mips64.cc b/compiler/optimizing/intrinsics_mips64.cc index 6098767aae..c2518a7861 100644 --- a/compiler/optimizing/intrinsics_mips64.cc +++ b/compiler/optimizing/intrinsics_mips64.cc @@ -834,15 +834,15 @@ static void GenRoundingMode(LocationSummary* locations, __ 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 @@ static void GenRoundingMode(LocationSummary* locations, } __ 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; |