Fix mterp assembly to use uxtw instead of lsl where needed.
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
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 @@
* 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 @@
* 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 @@
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():