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

(cherry picked from commit 908c0b28517c2d21f9ddd231e91cdd2c339aeb16)

Change-Id: I1856d914a0cb76c6034d0c0e021525b095e33452
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);
     }
 
     /*