ART: Mterp arm64 2-operand double rem fix
An instruction ordering bug caused 2-operand double-precision
rem operations to be performed incorrectly on the arm64 fast
interpreter. Also, fixes the existing omnibus-opcodes smoke test
to better catch 2-operand float and double operation problems
(the problem was masked in the existing test).
Bug: 27604215
Change-Id: I9fac1e61d9defe7d623c611406c35921abb65b04
diff --git a/runtime/interpreter/mterp/arm64/op_rem_double_2addr.S b/runtime/interpreter/mterp/arm64/op_rem_double_2addr.S
index db18aa7..9868f41 100644
--- a/runtime/interpreter/mterp/arm64/op_rem_double_2addr.S
+++ b/runtime/interpreter/mterp/arm64/op_rem_double_2addr.S
@@ -3,9 +3,9 @@
ubfx w2, wINST, #8, #4 // w2<- A
GET_VREG_WIDE d1, w1 // d1<- vB
GET_VREG_WIDE d0, w2 // d0<- vA
- FETCH_ADVANCE_INST 1 // advance rPC, load rINST
bl fmod
ubfx w2, wINST, #8, #4 // w2<- A (need to reload - killed across call)
+ FETCH_ADVANCE_INST 1 // advance rPC, load rINST
GET_INST_OPCODE ip // extract opcode from rINST
SET_VREG_WIDE d0, w2 // vAA<- result
GOTO_OPCODE ip // jump to next instruction
diff --git a/runtime/interpreter/mterp/out/mterp_arm64.S b/runtime/interpreter/mterp/out/mterp_arm64.S
index cdb27e8..6ae59d8 100644
--- a/runtime/interpreter/mterp/out/mterp_arm64.S
+++ b/runtime/interpreter/mterp/out/mterp_arm64.S
@@ -5984,9 +5984,9 @@
ubfx w2, wINST, #8, #4 // w2<- A
GET_VREG_WIDE d1, w1 // d1<- vB
GET_VREG_WIDE d0, w2 // d0<- vA
- FETCH_ADVANCE_INST 1 // advance rPC, load rINST
bl fmod
ubfx w2, wINST, #8, #4 // w2<- A (need to reload - killed across call)
+ FETCH_ADVANCE_INST 1 // advance rPC, load rINST
GET_INST_OPCODE ip // extract opcode from rINST
SET_VREG_WIDE d0, w2 // vAA<- result
GOTO_OPCODE ip // jump to next instruction
diff --git a/test/003-omnibus-opcodes/src/FloatMath.java b/test/003-omnibus-opcodes/src/FloatMath.java
index 96befe9..fcdb4fe 100644
--- a/test/003-omnibus-opcodes/src/FloatMath.java
+++ b/test/003-omnibus-opcodes/src/FloatMath.java
@@ -135,7 +135,8 @@
static float[] floatOperTest(float x, float y) {
System.out.println("FloatMath.floatOperTest");
- float[] results = new float[9];
+ float[] results = new float[10];
+ float tmp;
/* this seems to generate "op-float" instructions */
results[0] = x + y;
@@ -145,7 +146,21 @@
results[4] = x % -y;
/* this seems to generate "op-float/2addr" instructions */
- results[8] = x + (((((x + y) - y) * y) / y) % y);
+ tmp = x;
+ tmp += y;
+ results[5] = tmp;
+ tmp = x;
+ tmp -= y;
+ results[6] = tmp;
+ tmp = x;
+ tmp *= y;
+ results[7] = tmp;
+ tmp = x;
+ tmp /= y;
+ results[8] = tmp;
+ tmp = x;
+ tmp %= -y;
+ results[9] = tmp;
return results;
}
@@ -155,7 +170,11 @@
Main.assertTrue(results[2] > -210000.01f && results[2] < -209999.99f);
Main.assertTrue(results[3] > -23333.34f && results[3] < -23333.32f);
Main.assertTrue(results[4] > 0.999f && results[4] < 1.001f);
- Main.assertTrue(results[8] > 70000.99f && results[8] < 70001.01f);
+ Main.assertTrue(results[5] > 69996.99f && results[5] < 69997.01f);
+ Main.assertTrue(results[6] > 70002.99f && results[6] < 70003.01f);
+ Main.assertTrue(results[7] > -210000.01f && results[7] < -209999.99f);
+ Main.assertTrue(results[8] > -23333.34f && results[8] < -23333.32f);
+ Main.assertTrue(results[9] > 0.999f && results[9] < 1.001f);
}
/*
@@ -165,7 +184,8 @@
static double[] doubleOperTest(double x, double y) {
System.out.println("FloatMath.doubleOperTest");
- double[] results = new double[9];
+ double[] results = new double[10];
+ double tmp;
/* this seems to generate "op-double" instructions */
results[0] = x + y;
@@ -175,7 +195,21 @@
results[4] = x % -y;
/* this seems to generate "op-double/2addr" instructions */
- results[8] = x + (((((x + y) - y) * y) / y) % y);
+ tmp = x;
+ tmp += y;
+ results[5] = tmp;
+ tmp = x;
+ tmp -= y;
+ results[6] = tmp;
+ tmp = x;
+ tmp *= y;
+ results[7] = tmp;
+ tmp = x;
+ tmp /= y;
+ results[8] = tmp;
+ tmp = x;
+ tmp %= -y;
+ results[9] = tmp;
return results;
}
@@ -185,7 +219,11 @@
Main.assertTrue(results[2] > -210000.01 && results[2] < -209999.99);
Main.assertTrue(results[3] > -23333.34 && results[3] < -23333.32);
Main.assertTrue(results[4] > 0.999 && results[4] < 1.001);
- Main.assertTrue(results[8] > 70000.99 && results[8] < 70001.01);
+ Main.assertTrue(results[5] > 69996.99 && results[5] < 69997.01);
+ Main.assertTrue(results[6] > 70002.99 && results[6] < 70003.01);
+ Main.assertTrue(results[7] > -210000.01 && results[7] < -209999.99);
+ Main.assertTrue(results[8] > -23333.34 && results[8] < -23333.32);
+ Main.assertTrue(results[9] > 0.999 && results[9] < 1.001);
}
/*