ART: Change rrr add and sub for ARM64

OpRegRegImm will fall back to loading a constant into a register
and then doing the operation with three registers. That is, for
example, the case when we allocate large stack frames. However,
the currently chosen operations are add/sub shifted, which does
*not* allow to specify SP (x31 will be interpreted as xzr). Switch
to add/sub extended. There won't be a practical difference, as we
do not call with anything other than 0 shift.

Change-Id: I2b78df9f044d2963e3e890777c855b339952f9f4
diff --git a/compiler/dex/quick/arm64/utility_arm64.cc b/compiler/dex/quick/arm64/utility_arm64.cc
index 2254b8b..9b32a46 100644
--- a/compiler/dex/quick/arm64/utility_arm64.cc
+++ b/compiler/dex/quick/arm64/utility_arm64.cc
@@ -660,6 +660,7 @@
   int32_t log_imm = -1;
   bool is_wide = r_dest.Is64Bit();
   ArmOpcode wide = (is_wide) ? WIDE(0) : UNWIDE(0);
+  int info = 0;
 
   switch (op) {
     case kOpLsl: {
@@ -692,7 +693,14 @@
         return NewLIR4(opcode | wide, r_dest.GetReg(), r_src1.GetReg(), abs_value >> 12, 1);
       } else {
         log_imm = -1;
-        alt_opcode = (neg) ? kA64Add4rrro : kA64Sub4rrro;
+        alt_opcode = (neg) ? kA64Add4rrre : kA64Sub4rrre;
+        // To make it correct, we need:
+        // 23..21 = 001  = extend
+        // 15..13 = 01x  = LSL/UXTW/X  /  x defines wide or not
+        // 12..10 = 000  = no shift (in case of SP)
+        // => info =   00101x000
+        // =>      =0x 0 5  (0/8)
+        info = (is_wide ? 8 : 0) | 0x50;
       }
       break;
     // case kOpRsub:
@@ -734,7 +742,7 @@
   if (log_imm >= 0) {
     return NewLIR3(opcode | wide, r_dest.GetReg(), r_src1.GetReg(), log_imm);
   } else {
-    RegStorage r_scratch = AllocTemp();
+    RegStorage r_scratch;
     if (IS_WIDE(wide)) {
       r_scratch = AllocTempWide();
       LoadConstantWide(r_scratch, value);
@@ -743,7 +751,7 @@
       LoadConstant(r_scratch, value);
     }
     if (EncodingMap[alt_opcode].flags & IS_QUAD_OP)
-      res = NewLIR4(alt_opcode | wide, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg(), 0);
+      res = NewLIR4(alt_opcode | wide, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg(), info);
     else
       res = NewLIR3(alt_opcode | wide, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg());
     FreeTemp(r_scratch);