From: David Srbecky <dsrbecky@google.com>
Date: Thu, 4 Apr 2019 16:16:17 +0100
Subject: [PATCH] Fix mterp assembly to use uxtw instead of lsl where needed.

Bug: https://bugs.llvm.org/show_bug.cgi?id=41504
Origin: https://android-review.googlesource.com/c/platform/art/+/940018

The old instructions are invalid according to the ARM spec.

Event though UXTW and LSL are aliases this is binary change:
"add x0, x1, w2, lsl #1" was invalid and would be treated as
"add x0, x1, x2, uxtx #1" which would keep the high bits.

With uxtw, we ignore the high bits, as expected in code.

Test: test.py -r --target --interpreter
Change-Id: I66f67ccc5a401d0cf6ac5b42d41d8df26a190046
---
 runtime/interpreter/mterp/arm64/array.S |  6 +++---
 runtime/interpreter/mterp/arm64/main.S  | 18 +++++++++---------
 runtime/interpreter/mterp/arm64/other.S |  2 +-
 3 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/runtime/interpreter/mterp/arm64/array.S b/runtime/interpreter/mterp/arm64/array.S
index a023d22..628f832 100644
--- a/runtime/interpreter/mterp/arm64/array.S
+++ b/runtime/interpreter/mterp/arm64/array.S
@@ -75,7 +75,7 @@
     GET_VREG w1, w3                     // w1<- vCC (requested index)
     cbz     w0, common_errNullObject        // yes, bail
     ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]    // w3<- arrayObj->length
-    add     x0, x0, w1, lsl #3          // w0<- arrayObj + index*width
+    add     x0, x0, w1, uxtw #3         // w0<- arrayObj + index*width
     cmp     w1, w3                      // compare unsigned index, length
     bcs     common_errArrayIndex        // index >= length, bail
     FETCH_ADVANCE_INST 2                // advance rPC, load wINST
@@ -104,7 +104,7 @@
     GET_VREG w1, w3                     // w1<- vCC (requested index)
     cbz     w0, common_errNullObject    // bail if null
     ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]     // w3<- arrayObj->length
-    add     x0, x0, w1, lsl #$shift     // w0<- arrayObj + index*width
+    add     x0, x0, w1, uxtw #$shift    // w0<- arrayObj + index*width
     cmp     w1, w3                      // compare unsigned index, length
     bcs     common_errArrayIndex        // index >= length, bail
     FETCH_ADVANCE_INST 2                // advance rPC, load rINST
@@ -154,7 +154,7 @@
     GET_VREG w1, w3                     // w1<- vCC (requested index)
     cbz     w0, common_errNullObject    // bail if null
     ldr     w3, [x0, #MIRROR_ARRAY_LENGTH_OFFSET]    // w3<- arrayObj->length
-    add     x0, x0, w1, lsl #3          // w0<- arrayObj + index*width
+    add     x0, x0, w1, uxtw #3         // w0<- arrayObj + index*width
     cmp     w1, w3                      // compare unsigned index, length
     bcs     common_errArrayIndex        // index >= length, bail
     GET_VREG_WIDE x1, w4
diff --git a/runtime/interpreter/mterp/arm64/main.S b/runtime/interpreter/mterp/arm64/main.S
index aefec61..fd745f1 100644
--- a/runtime/interpreter/mterp/arm64/main.S
+++ b/runtime/interpreter/mterp/arm64/main.S
@@ -268,23 +268,23 @@ codes.
  * Get/set the 64-bit value from a Dalvik register.
  */
 .macro GET_VREG_WIDE reg, vreg
-    add     ip2, xFP, \vreg, lsl #2
+    add     ip2, xFP, \vreg, uxtw #2
     ldr     \reg, [ip2]
 .endm
 .macro SET_VREG_WIDE reg, vreg
-    add     ip2, xFP, \vreg, lsl #2
+    add     ip2, xFP, \vreg, uxtw #2
     str     \reg, [ip2]
-    add     ip2, xREFS, \vreg, lsl #2
+    add     ip2, xREFS, \vreg, uxtw #2
     str     xzr, [ip2]
 .endm
 .macro GET_VREG_DOUBLE reg, vreg
-    add     ip2, xFP, \vreg, lsl #2
+    add     ip2, xFP, \vreg, uxtw #2
     ldr     \reg, [ip2]
 .endm
 .macro SET_VREG_DOUBLE reg, vreg
-    add     ip2, xFP, \vreg, lsl #2
+    add     ip2, xFP, \vreg, uxtw #2
     str     \reg, [ip2]
-    add     ip2, xREFS, \vreg, lsl #2
+    add     ip2, xREFS, \vreg, uxtw #2
     str     xzr, [ip2]
 .endm
 
@@ -300,7 +300,7 @@ codes.
  * Convert a virtual register index into an address.
  */
 .macro VREG_INDEX_TO_ADDR reg, vreg
-    add     \reg, xFP, \vreg, lsl #2   /* WARNING: handle shadow frame vreg zero if store */
+    add     \reg, xFP, \vreg, uxtw #2   /* WARNING: handle shadow frame vreg zero if store */
 .endm
 
 /*
@@ -418,9 +418,9 @@ ENTRY ExecuteMterpImpl
     mov     xSELF, x0
     ldr     w0, [x2, #SHADOWFRAME_NUMBER_OF_VREGS_OFFSET]
     add     xFP, x2, #SHADOWFRAME_VREGS_OFFSET     // point to vregs.
-    add     xREFS, xFP, w0, lsl #2                 // point to reference array in shadow frame
+    add     xREFS, xFP, w0, uxtw #2                // point to reference array in shadow frame
     ldr     w0, [x2, #SHADOWFRAME_DEX_PC_OFFSET]   // Get starting dex_pc.
-    add     xPC, x1, w0, lsl #1                    // Create direct pointer to 1st dex opcode
+    add     xPC, x1, w0, uxtw #1                   // Create direct pointer to 1st dex opcode
     CFI_DEFINE_DEX_PC_WITH_OFFSET(CFI_TMP, CFI_DEX, 0)
     EXPORT_PC
 
diff --git a/runtime/interpreter/mterp/arm64/other.S b/runtime/interpreter/mterp/arm64/other.S
index f1d0ef3..eccd521 100644
--- a/runtime/interpreter/mterp/arm64/other.S
+++ b/runtime/interpreter/mterp/arm64/other.S
@@ -263,7 +263,7 @@
     ldr     x0, [xFP, #OFF_FP_RESULT_REGISTER]  // get pointer to result JType.
     ldr     x0, [x0]                    // r0 <- result.i.
     GET_INST_OPCODE ip                  // extract opcode from wINST
-    SET_VREG_WIDE x0, x2                // fp[AA]<- r0
+    SET_VREG_WIDE x0, w2                // fp[AA]<- r0
     GOTO_OPCODE ip                      // jump to next instruction
 
 %def op_move_wide():
