1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "codegen_arm.h"
18 
19 #include <inttypes.h>
20 
21 #include <string>
22 #include <sstream>
23 
24 #include "backend_arm.h"
25 #include "base/logging.h"
26 #include "dex/mir_graph.h"
27 #include "dex/quick/mir_to_lir-inl.h"
28 
29 namespace art {
30 
31 #ifdef ARM_R4_SUSPEND_FLAG
32 static constexpr RegStorage core_regs_arr[] =
33     {rs_r0, rs_r1, rs_r2, rs_r3, rs_rARM_SUSPEND, rs_r5, rs_r6, rs_r7, rs_r8, rs_rARM_SELF,
34      rs_r10, rs_r11, rs_r12, rs_rARM_SP, rs_rARM_LR, rs_rARM_PC};
35 #else
36 static constexpr RegStorage core_regs_arr[] =
37     {rs_r0, rs_r1, rs_r2, rs_r3, rs_r4, rs_r5, rs_r6, rs_r7, rs_r8, rs_rARM_SELF,
38      rs_r10, rs_r11, rs_r12, rs_rARM_SP, rs_rARM_LR, rs_rARM_PC};
39 #endif
40 static constexpr RegStorage sp_regs_arr[] =
41     {rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, rs_fr8, rs_fr9, rs_fr10,
42      rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15, rs_fr16, rs_fr17, rs_fr18, rs_fr19, rs_fr20,
43      rs_fr21, rs_fr22, rs_fr23, rs_fr24, rs_fr25, rs_fr26, rs_fr27, rs_fr28, rs_fr29, rs_fr30,
44      rs_fr31};
45 static constexpr RegStorage dp_regs_arr[] =
46     {rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, rs_dr8, rs_dr9, rs_dr10,
47      rs_dr11, rs_dr12, rs_dr13, rs_dr14, rs_dr15};
48 #ifdef ARM_R4_SUSPEND_FLAG
49 static constexpr RegStorage reserved_regs_arr[] =
50     {rs_rARM_SUSPEND, rs_rARM_SELF, rs_rARM_SP, rs_rARM_LR, rs_rARM_PC};
51 static constexpr RegStorage core_temps_arr[] = {rs_r0, rs_r1, rs_r2, rs_r3, rs_r12};
52 #else
53 static constexpr RegStorage reserved_regs_arr[] =
54     {rs_rARM_SELF, rs_rARM_SP, rs_rARM_LR, rs_rARM_PC};
55 static constexpr RegStorage core_temps_arr[] = {rs_r0, rs_r1, rs_r2, rs_r3, rs_r4, rs_r12};
56 #endif
57 static constexpr RegStorage sp_temps_arr[] =
58     {rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, rs_fr8, rs_fr9, rs_fr10,
59      rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15};
60 static constexpr RegStorage dp_temps_arr[] =
61     {rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7};
62 
63 static constexpr ArrayRef<const RegStorage> empty_pool;
64 static constexpr ArrayRef<const RegStorage> core_regs(core_regs_arr);
65 static constexpr ArrayRef<const RegStorage> sp_regs(sp_regs_arr);
66 static constexpr ArrayRef<const RegStorage> dp_regs(dp_regs_arr);
67 static constexpr ArrayRef<const RegStorage> reserved_regs(reserved_regs_arr);
68 static constexpr ArrayRef<const RegStorage> core_temps(core_temps_arr);
69 static constexpr ArrayRef<const RegStorage> sp_temps(sp_temps_arr);
70 static constexpr ArrayRef<const RegStorage> dp_temps(dp_temps_arr);
71 
LocCReturn()72 RegLocation ArmMir2Lir::LocCReturn() {
73   return arm_loc_c_return;
74 }
75 
LocCReturnRef()76 RegLocation ArmMir2Lir::LocCReturnRef() {
77   return arm_loc_c_return;
78 }
79 
LocCReturnWide()80 RegLocation ArmMir2Lir::LocCReturnWide() {
81   return arm_loc_c_return_wide;
82 }
83 
LocCReturnFloat()84 RegLocation ArmMir2Lir::LocCReturnFloat() {
85   return arm_loc_c_return_float;
86 }
87 
LocCReturnDouble()88 RegLocation ArmMir2Lir::LocCReturnDouble() {
89   return arm_loc_c_return_double;
90 }
91 
92 // Return a target-dependent special register.
TargetReg(SpecialTargetRegister reg)93 RegStorage ArmMir2Lir::TargetReg(SpecialTargetRegister reg) {
94   RegStorage res_reg;
95   switch (reg) {
96     case kSelf: res_reg = rs_rARM_SELF; break;
97 #ifdef ARM_R4_SUSPEND_FLAG
98     case kSuspend: res_reg =  rs_rARM_SUSPEND; break;
99 #else
100     case kSuspend: res_reg = RegStorage::InvalidReg(); break;
101 #endif
102     case kLr: res_reg =  rs_rARM_LR; break;
103     case kPc: res_reg =  rs_rARM_PC; break;
104     case kSp: res_reg =  rs_rARM_SP; break;
105     case kArg0: res_reg = rs_r0; break;
106     case kArg1: res_reg = rs_r1; break;
107     case kArg2: res_reg = rs_r2; break;
108     case kArg3: res_reg = rs_r3; break;
109     case kFArg0: res_reg = kArm32QuickCodeUseSoftFloat ? rs_r0 : rs_fr0; break;
110     case kFArg1: res_reg = kArm32QuickCodeUseSoftFloat ? rs_r1 : rs_fr1; break;
111     case kFArg2: res_reg = kArm32QuickCodeUseSoftFloat ? rs_r2 : rs_fr2; break;
112     case kFArg3: res_reg = kArm32QuickCodeUseSoftFloat ? rs_r3 : rs_fr3; break;
113     case kFArg4: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr4; break;
114     case kFArg5: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr5; break;
115     case kFArg6: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr6; break;
116     case kFArg7: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr7; break;
117     case kFArg8: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr8; break;
118     case kFArg9: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr9; break;
119     case kFArg10: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr10; break;
120     case kFArg11: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr11; break;
121     case kFArg12: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr12; break;
122     case kFArg13: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr13; break;
123     case kFArg14: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr14; break;
124     case kFArg15: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr15; break;
125     case kRet0: res_reg = rs_r0; break;
126     case kRet1: res_reg = rs_r1; break;
127     case kInvokeTgt: res_reg = rs_rARM_LR; break;
128     case kHiddenArg: res_reg = rs_r12; break;
129     case kHiddenFpArg: res_reg = RegStorage::InvalidReg(); break;
130     case kCount: res_reg = RegStorage::InvalidReg(); break;
131     default: res_reg = RegStorage::InvalidReg();
132   }
133   return res_reg;
134 }
135 
136 /*
137  * Decode the register id.
138  */
GetRegMaskCommon(const RegStorage & reg) const139 ResourceMask ArmMir2Lir::GetRegMaskCommon(const RegStorage& reg) const {
140   return GetRegMaskArm(reg);
141 }
142 
GetRegMaskArm(RegStorage reg)143 constexpr ResourceMask ArmMir2Lir::GetRegMaskArm(RegStorage reg) {
144   return reg.IsDouble()
145       /* Each double register is equal to a pair of single-precision FP registers */
146       ? ResourceMask::TwoBits(reg.GetRegNum() * 2 + kArmFPReg0)
147       : ResourceMask::Bit(reg.IsSingle() ? reg.GetRegNum() + kArmFPReg0 : reg.GetRegNum());
148 }
149 
EncodeArmRegList(int reg_list)150 constexpr ResourceMask ArmMir2Lir::EncodeArmRegList(int reg_list) {
151   return ResourceMask::RawMask(static_cast<uint64_t >(reg_list), 0u);
152 }
153 
EncodeArmRegFpcsList(int reg_list)154 constexpr ResourceMask ArmMir2Lir::EncodeArmRegFpcsList(int reg_list) {
155   return ResourceMask::RawMask(static_cast<uint64_t >(reg_list) << kArmFPReg16, 0u);
156 }
157 
GetPCUseDefEncoding() const158 ResourceMask ArmMir2Lir::GetPCUseDefEncoding() const {
159   return ResourceMask::Bit(kArmRegPC);
160 }
161 
162 // Thumb2 specific setup.  TODO: inline?:
SetupTargetResourceMasks(LIR * lir,uint64_t flags,ResourceMask * use_mask,ResourceMask * def_mask)163 void ArmMir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags,
164                                           ResourceMask* use_mask, ResourceMask* def_mask) {
165   DCHECK_EQ(cu_->instruction_set, kThumb2);
166   DCHECK(!lir->flags.use_def_invalid);
167 
168   int opcode = lir->opcode;
169 
170   // These flags are somewhat uncommon - bypass if we can.
171   if ((flags & (REG_DEF_SP | REG_USE_SP | REG_DEF_LIST0 | REG_DEF_LIST1 |
172                 REG_DEF_FPCS_LIST0 | REG_DEF_FPCS_LIST2 | REG_USE_PC | IS_IT | REG_USE_LIST0 |
173                 REG_USE_LIST1 | REG_USE_FPCS_LIST0 | REG_USE_FPCS_LIST2 | REG_DEF_LR)) != 0) {
174     if (flags & REG_DEF_SP) {
175       def_mask->SetBit(kArmRegSP);
176     }
177 
178     if (flags & REG_USE_SP) {
179       use_mask->SetBit(kArmRegSP);
180     }
181 
182     if (flags & REG_DEF_LIST0) {
183       def_mask->SetBits(EncodeArmRegList(lir->operands[0]));
184     }
185 
186     if (flags & REG_DEF_LIST1) {
187       def_mask->SetBits(EncodeArmRegList(lir->operands[1]));
188     }
189 
190     if (flags & REG_DEF_FPCS_LIST0) {
191       def_mask->SetBits(EncodeArmRegList(lir->operands[0]));
192     }
193 
194     if (flags & REG_DEF_FPCS_LIST2) {
195       for (int i = 0; i < lir->operands[2]; i++) {
196         SetupRegMask(def_mask, lir->operands[1] + i);
197       }
198     }
199 
200     if (flags & REG_USE_PC) {
201       use_mask->SetBit(kArmRegPC);
202     }
203 
204     /* Conservatively treat the IT block */
205     if (flags & IS_IT) {
206       *def_mask = kEncodeAll;
207     }
208 
209     if (flags & REG_USE_LIST0) {
210       use_mask->SetBits(EncodeArmRegList(lir->operands[0]));
211     }
212 
213     if (flags & REG_USE_LIST1) {
214       use_mask->SetBits(EncodeArmRegList(lir->operands[1]));
215     }
216 
217     if (flags & REG_USE_FPCS_LIST0) {
218       use_mask->SetBits(EncodeArmRegList(lir->operands[0]));
219     }
220 
221     if (flags & REG_USE_FPCS_LIST2) {
222       for (int i = 0; i < lir->operands[2]; i++) {
223         SetupRegMask(use_mask, lir->operands[1] + i);
224       }
225     }
226     /* Fixup for kThumbPush/lr and kThumbPop/pc */
227     if (opcode == kThumbPush || opcode == kThumbPop) {
228       constexpr ResourceMask r8Mask = GetRegMaskArm(rs_r8);
229       if ((opcode == kThumbPush) && (use_mask->Intersects(r8Mask))) {
230         use_mask->ClearBits(r8Mask);
231         use_mask->SetBit(kArmRegLR);
232       } else if ((opcode == kThumbPop) && (def_mask->Intersects(r8Mask))) {
233         def_mask->ClearBits(r8Mask);
234         def_mask->SetBit(kArmRegPC);;
235       }
236     }
237     if (flags & REG_DEF_LR) {
238       def_mask->SetBit(kArmRegLR);
239     }
240   }
241 }
242 
ArmConditionEncoding(ConditionCode ccode)243 ArmConditionCode ArmMir2Lir::ArmConditionEncoding(ConditionCode ccode) {
244   ArmConditionCode res;
245   switch (ccode) {
246     case kCondEq: res = kArmCondEq; break;
247     case kCondNe: res = kArmCondNe; break;
248     case kCondCs: res = kArmCondCs; break;
249     case kCondCc: res = kArmCondCc; break;
250     case kCondUlt: res = kArmCondCc; break;
251     case kCondUge: res = kArmCondCs; break;
252     case kCondMi: res = kArmCondMi; break;
253     case kCondPl: res = kArmCondPl; break;
254     case kCondVs: res = kArmCondVs; break;
255     case kCondVc: res = kArmCondVc; break;
256     case kCondHi: res = kArmCondHi; break;
257     case kCondLs: res = kArmCondLs; break;
258     case kCondGe: res = kArmCondGe; break;
259     case kCondLt: res = kArmCondLt; break;
260     case kCondGt: res = kArmCondGt; break;
261     case kCondLe: res = kArmCondLe; break;
262     case kCondAl: res = kArmCondAl; break;
263     case kCondNv: res = kArmCondNv; break;
264     default:
265       LOG(FATAL) << "Bad condition code " << ccode;
266       res = static_cast<ArmConditionCode>(0);  // Quiet gcc
267   }
268   return res;
269 }
270 
271 static const char* core_reg_names[16] = {
272   "r0",
273   "r1",
274   "r2",
275   "r3",
276   "r4",
277   "r5",
278   "r6",
279   "r7",
280   "r8",
281   "rSELF",
282   "r10",
283   "r11",
284   "r12",
285   "sp",
286   "lr",
287   "pc",
288 };
289 
290 
291 static const char* shift_names[4] = {
292   "lsl",
293   "lsr",
294   "asr",
295   "ror"};
296 
297 /* Decode and print a ARM register name */
DecodeRegList(int opcode,int vector,char * buf,size_t buf_size)298 static char* DecodeRegList(int opcode, int vector, char* buf, size_t buf_size) {
299   int i;
300   bool printed = false;
301   buf[0] = 0;
302   for (i = 0; i < 16; i++, vector >>= 1) {
303     if (vector & 0x1) {
304       int reg_id = i;
305       if (opcode == kThumbPush && i == 8) {
306         reg_id = rs_rARM_LR.GetRegNum();
307       } else if (opcode == kThumbPop && i == 8) {
308         reg_id = rs_rARM_PC.GetRegNum();
309       }
310       if (printed) {
311         snprintf(buf + strlen(buf), buf_size - strlen(buf), ", r%d", reg_id);
312       } else {
313         printed = true;
314         snprintf(buf, buf_size, "r%d", reg_id);
315       }
316     }
317   }
318   return buf;
319 }
320 
DecodeFPCSRegList(int count,int base,char * buf,size_t buf_size)321 static char*  DecodeFPCSRegList(int count, int base, char* buf, size_t buf_size) {
322   snprintf(buf, buf_size, "s%d", base);
323   for (int i = 1; i < count; i++) {
324     snprintf(buf + strlen(buf), buf_size - strlen(buf), ", s%d", base + i);
325   }
326   return buf;
327 }
328 
ExpandImmediate(int value)329 static int32_t ExpandImmediate(int value) {
330   int32_t mode = (value & 0xf00) >> 8;
331   uint32_t bits = value & 0xff;
332   switch (mode) {
333     case 0:
334       return bits;
335      case 1:
336       return (bits << 16) | bits;
337      case 2:
338       return (bits << 24) | (bits << 8);
339      case 3:
340       return (bits << 24) | (bits << 16) | (bits << 8) | bits;
341     default:
342       break;
343   }
344   bits = (bits | 0x80) << 24;
345   return bits >> (((value & 0xf80) >> 7) - 8);
346 }
347 
348 const char* cc_names[] = {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
349                          "hi", "ls", "ge", "lt", "gt", "le", "al", "nv"};
350 /*
351  * Interpret a format string and build a string no longer than size
352  * See format key in Assemble.c.
353  */
BuildInsnString(const char * fmt,LIR * lir,unsigned char * base_addr)354 std::string ArmMir2Lir::BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr) {
355   std::string buf;
356   int i;
357   const char* fmt_end = &fmt[strlen(fmt)];
358   char tbuf[256];
359   const char* name;
360   char nc;
361   while (fmt < fmt_end) {
362     int operand;
363     if (*fmt == '!') {
364       fmt++;
365       DCHECK_LT(fmt, fmt_end);
366       nc = *fmt++;
367       if (nc == '!') {
368         strcpy(tbuf, "!");
369       } else {
370          DCHECK_LT(fmt, fmt_end);
371          DCHECK_LT(static_cast<unsigned>(nc-'0'), 4U);
372          operand = lir->operands[nc-'0'];
373          switch (*fmt++) {
374            case 'H':
375              if (operand != 0) {
376                snprintf(tbuf, arraysize(tbuf), ", %s %d", shift_names[operand & 0x3], operand >> 2);
377              } else {
378                strcpy(tbuf, "");
379              }
380              break;
381            case 'B':
382              switch (operand) {
383                case kSY:
384                  name = "sy";
385                  break;
386                case kST:
387                  name = "st";
388                  break;
389                case kISH:
390                  name = "ish";
391                  break;
392                case kISHST:
393                  name = "ishst";
394                  break;
395                case kNSH:
396                  name = "nsh";
397                  break;
398                case kNSHST:
399                  name = "shst";
400                  break;
401                default:
402                  name = "DecodeError2";
403                  break;
404              }
405              strcpy(tbuf, name);
406              break;
407            case 'b':
408              strcpy(tbuf, "0000");
409              for (i = 3; i >= 0; i--) {
410                tbuf[i] += operand & 1;
411                operand >>= 1;
412              }
413              break;
414            case 'n':
415              operand = ~ExpandImmediate(operand);
416              snprintf(tbuf, arraysize(tbuf), "%d [%#x]", operand, operand);
417              break;
418            case 'm':
419              operand = ExpandImmediate(operand);
420              snprintf(tbuf, arraysize(tbuf), "%d [%#x]", operand, operand);
421              break;
422            case 's':
423              snprintf(tbuf, arraysize(tbuf), "s%d", RegStorage::RegNum(operand));
424              break;
425            case 'S':
426              snprintf(tbuf, arraysize(tbuf), "d%d", RegStorage::RegNum(operand));
427              break;
428            case 'h':
429              snprintf(tbuf, arraysize(tbuf), "%04x", operand);
430              break;
431            case 'M':
432            case 'd':
433              snprintf(tbuf, arraysize(tbuf), "%d", operand);
434              break;
435            case 'C':
436              operand = RegStorage::RegNum(operand);
437              DCHECK_LT(operand, static_cast<int>(
438                  sizeof(core_reg_names)/sizeof(core_reg_names[0])));
439              snprintf(tbuf, arraysize(tbuf), "%s", core_reg_names[operand]);
440              break;
441            case 'E':
442              snprintf(tbuf, arraysize(tbuf), "%d", operand*4);
443              break;
444            case 'F':
445              snprintf(tbuf, arraysize(tbuf), "%d", operand*2);
446              break;
447            case 'c':
448              strcpy(tbuf, cc_names[operand]);
449              break;
450            case 't':
451              snprintf(tbuf, arraysize(tbuf), "0x%08" PRIxPTR " (L%p)",
452                  reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 + (operand << 1),
453                  lir->target);
454              break;
455            case 'T':
456              snprintf(tbuf, arraysize(tbuf), "%s", PrettyMethod(
457                  static_cast<uint32_t>(lir->operands[1]),
458                  *UnwrapPointer<DexFile>(lir->operands[2])).c_str());
459              break;
460            case 'u': {
461              int offset_1 = lir->operands[0];
462              int offset_2 = NEXT_LIR(lir)->operands[0];
463              uintptr_t target =
464                  (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) &
465                  ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
466                  0xfffffffc;
467              snprintf(tbuf, arraysize(tbuf), "%p", reinterpret_cast<void *>(target));
468              break;
469           }
470 
471            /* Nothing to print for BLX_2 */
472            case 'v':
473              strcpy(tbuf, "see above");
474              break;
475            case 'R':
476              DecodeRegList(lir->opcode, operand, tbuf, arraysize(tbuf));
477              break;
478            case 'P':
479              DecodeFPCSRegList(operand, 16, tbuf, arraysize(tbuf));
480              break;
481            case 'Q':
482              DecodeFPCSRegList(operand, 0, tbuf, arraysize(tbuf));
483              break;
484            default:
485              strcpy(tbuf, "DecodeError1");
486              break;
487         }
488         buf += tbuf;
489       }
490     } else {
491        buf += *fmt++;
492     }
493   }
494   // Dump thread offset.
495   std::string fmt_str = GetTargetInstFmt(lir->opcode);
496   if (std::string::npos != fmt_str.find(", [!1C, #!2") && rARM_SELF == lir->operands[1] &&
497       std::string::npos != buf.find(", [")) {
498     int offset = lir->operands[2];
499     if (std::string::npos != fmt_str.find("#!2d")) {
500     } else if (std::string::npos != fmt_str.find("#!2E")) {
501       offset *= 4;
502     } else if (std::string::npos != fmt_str.find("#!2F")) {
503       offset *= 2;
504     } else {
505       LOG(FATAL) << "Should not reach here";
506     }
507     std::ostringstream tmp_stream;
508     Thread::DumpThreadOffset<4>(tmp_stream, offset);
509     buf += "  ; ";
510     buf += tmp_stream.str();
511   }
512   return buf;
513 }
514 
DumpResourceMask(LIR * arm_lir,const ResourceMask & mask,const char * prefix)515 void ArmMir2Lir::DumpResourceMask(LIR* arm_lir, const ResourceMask& mask, const char* prefix) {
516   char buf[256];
517   buf[0] = 0;
518 
519   if (mask.Equals(kEncodeAll)) {
520     strcpy(buf, "all");
521   } else {
522     char num[8];
523     int i;
524 
525     for (i = 0; i < kArmRegEnd; i++) {
526       if (mask.HasBit(i)) {
527         snprintf(num, arraysize(num), "%d ", i);
528         strcat(buf, num);
529       }
530     }
531 
532     if (mask.HasBit(ResourceMask::kCCode)) {
533       strcat(buf, "cc ");
534     }
535     if (mask.HasBit(ResourceMask::kFPStatus)) {
536       strcat(buf, "fpcc ");
537     }
538 
539     /* Memory bits */
540     if (arm_lir && (mask.HasBit(ResourceMask::kDalvikReg))) {
541       snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s",
542                DECODE_ALIAS_INFO_REG(arm_lir->flags.alias_info),
543                DECODE_ALIAS_INFO_WIDE(arm_lir->flags.alias_info) ? "(+1)" : "");
544     }
545     if (mask.HasBit(ResourceMask::kLiteral)) {
546       strcat(buf, "lit ");
547     }
548 
549     if (mask.HasBit(ResourceMask::kHeapRef)) {
550       strcat(buf, "heap ");
551     }
552     if (mask.HasBit(ResourceMask::kMustNotAlias)) {
553       strcat(buf, "noalias ");
554     }
555   }
556   if (buf[0]) {
557     LOG(INFO) << prefix << ": " << buf;
558   }
559 }
560 
IsUnconditionalBranch(LIR * lir)561 bool ArmMir2Lir::IsUnconditionalBranch(LIR* lir) {
562   return ((lir->opcode == kThumbBUncond) || (lir->opcode == kThumb2BUncond));
563 }
564 
RegClassForFieldLoadStore(OpSize size,bool is_volatile)565 RegisterClass ArmMir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) {
566   if (UNLIKELY(is_volatile)) {
567     // On arm, atomic 64-bit load/store requires a core register pair.
568     // Smaller aligned load/store is atomic for both core and fp registers.
569     if (size == k64 || size == kDouble) {
570       return kCoreReg;
571     }
572   }
573   return RegClassBySize(size);
574 }
575 
ArmMir2Lir(CompilationUnit * cu,MIRGraph * mir_graph,ArenaAllocator * arena)576 ArmMir2Lir::ArmMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
577     : Mir2Lir(cu, mir_graph, arena),
578       call_method_insns_(arena->Adapter()),
579       dex_cache_access_insns_(arena->Adapter()),
580       dex_cache_arrays_base_reg_(RegStorage::InvalidReg()) {
581   call_method_insns_.reserve(100);
582   // Sanity check - make sure encoding map lines up.
583   for (int i = 0; i < kArmLast; i++) {
584     DCHECK_EQ(ArmMir2Lir::EncodingMap[i].opcode, i)
585         << "Encoding order for " << ArmMir2Lir::EncodingMap[i].name
586         << " is wrong: expecting " << i << ", seeing "
587         << static_cast<int>(ArmMir2Lir::EncodingMap[i].opcode);
588   }
589 }
590 
ArmCodeGenerator(CompilationUnit * const cu,MIRGraph * const mir_graph,ArenaAllocator * const arena)591 Mir2Lir* ArmCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
592                           ArenaAllocator* const arena) {
593   return new ArmMir2Lir(cu, mir_graph, arena);
594 }
595 
CompilerInitializeRegAlloc()596 void ArmMir2Lir::CompilerInitializeRegAlloc() {
597   reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs, empty_pool /* core64 */,
598                                             sp_regs, dp_regs,
599                                             reserved_regs, empty_pool /* reserved64 */,
600                                             core_temps, empty_pool /* core64_temps */,
601                                             sp_temps, dp_temps));
602 
603   // Target-specific adjustments.
604 
605   // Alias single precision floats to appropriate half of overlapping double.
606   for (RegisterInfo* info : reg_pool_->sp_regs_) {
607     int sp_reg_num = info->GetReg().GetRegNum();
608     int dp_reg_num = sp_reg_num >> 1;
609     RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
610     RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
611     // Double precision register's master storage should refer to itself.
612     DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
613     // Redirect single precision's master storage to master.
614     info->SetMaster(dp_reg_info);
615     // Singles should show a single 32-bit mask bit, at first referring to the low half.
616     DCHECK_EQ(info->StorageMask(), RegisterInfo::kLowSingleStorageMask);
617     if (sp_reg_num & 1) {
618       // For odd singles, change to use the high word of the backing double.
619       info->SetStorageMask(RegisterInfo::kHighSingleStorageMask);
620     }
621   }
622 
623 #ifdef ARM_R4_SUSPEND_FLAG
624   // TODO: re-enable this when we can safely save r4 over the suspension code path.
625   bool no_suspend = NO_SUSPEND;  // || !Runtime::Current()->ExplicitSuspendChecks();
626   if (no_suspend) {
627     GetRegInfo(rs_rARM_SUSPEND)->MarkFree();
628   }
629 #endif
630 
631   // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
632   // TODO: adjust when we roll to hard float calling convention.
633   reg_pool_->next_core_reg_ = 2;
634   reg_pool_->next_sp_reg_ = 0;
635   reg_pool_->next_dp_reg_ = 0;
636 }
637 
638 /*
639  * TUNING: is true leaf?  Can't just use METHOD_IS_LEAF to determine as some
640  * instructions might call out to C/assembly helper functions.  Until
641  * machinery is in place, always spill lr.
642  */
643 
AdjustSpillMask()644 void ArmMir2Lir::AdjustSpillMask() {
645   core_spill_mask_ |= (1 << rs_rARM_LR.GetRegNum());
646   num_core_spills_++;
647 }
648 
649 /*
650  * Mark a callee-save fp register as promoted.  Note that
651  * vpush/vpop uses contiguous register lists so we must
652  * include any holes in the mask.  Associate holes with
653  * Dalvik register INVALID_VREG (0xFFFFU).
654  */
MarkPreservedSingle(int v_reg,RegStorage reg)655 void ArmMir2Lir::MarkPreservedSingle(int v_reg, RegStorage reg) {
656   DCHECK_GE(reg.GetRegNum(), ARM_FP_CALLEE_SAVE_BASE);
657   int adjusted_reg_num = reg.GetRegNum() - ARM_FP_CALLEE_SAVE_BASE;
658   // Ensure fp_vmap_table is large enough
659   int table_size = fp_vmap_table_.size();
660   for (int i = table_size; i < (adjusted_reg_num + 1); i++) {
661     fp_vmap_table_.push_back(INVALID_VREG);
662   }
663   // Add the current mapping
664   fp_vmap_table_[adjusted_reg_num] = v_reg;
665   // Size of fp_vmap_table is high-water mark, use to set mask
666   num_fp_spills_ = fp_vmap_table_.size();
667   fp_spill_mask_ = ((1 << num_fp_spills_) - 1) << ARM_FP_CALLEE_SAVE_BASE;
668 }
669 
MarkPreservedDouble(int v_reg,RegStorage reg)670 void ArmMir2Lir::MarkPreservedDouble(int v_reg, RegStorage reg) {
671   // TEMP: perform as 2 singles.
672   int reg_num = reg.GetRegNum() << 1;
673   RegStorage lo = RegStorage::Solo32(RegStorage::kFloatingPoint | reg_num);
674   RegStorage hi = RegStorage::Solo32(RegStorage::kFloatingPoint | reg_num | 1);
675   MarkPreservedSingle(v_reg, lo);
676   MarkPreservedSingle(v_reg + 1, hi);
677 }
678 
679 /* Clobber all regs that might be used by an external C call */
ClobberCallerSave()680 void ArmMir2Lir::ClobberCallerSave() {
681   // TODO: rework this - it's gotten even more ugly.
682   Clobber(rs_r0);
683   Clobber(rs_r1);
684   Clobber(rs_r2);
685   Clobber(rs_r3);
686   Clobber(rs_r12);
687   Clobber(rs_r14lr);
688   Clobber(rs_fr0);
689   Clobber(rs_fr1);
690   Clobber(rs_fr2);
691   Clobber(rs_fr3);
692   Clobber(rs_fr4);
693   Clobber(rs_fr5);
694   Clobber(rs_fr6);
695   Clobber(rs_fr7);
696   Clobber(rs_fr8);
697   Clobber(rs_fr9);
698   Clobber(rs_fr10);
699   Clobber(rs_fr11);
700   Clobber(rs_fr12);
701   Clobber(rs_fr13);
702   Clobber(rs_fr14);
703   Clobber(rs_fr15);
704   Clobber(rs_dr0);
705   Clobber(rs_dr1);
706   Clobber(rs_dr2);
707   Clobber(rs_dr3);
708   Clobber(rs_dr4);
709   Clobber(rs_dr5);
710   Clobber(rs_dr6);
711   Clobber(rs_dr7);
712 }
713 
GetReturnWideAlt()714 RegLocation ArmMir2Lir::GetReturnWideAlt() {
715   RegLocation res = LocCReturnWide();
716   res.reg.SetLowReg(rs_r2.GetReg());
717   res.reg.SetHighReg(rs_r3.GetReg());
718   Clobber(rs_r2);
719   Clobber(rs_r3);
720   MarkInUse(rs_r2);
721   MarkInUse(rs_r3);
722   MarkWide(res.reg);
723   return res;
724 }
725 
GetReturnAlt()726 RegLocation ArmMir2Lir::GetReturnAlt() {
727   RegLocation res = LocCReturn();
728   res.reg.SetReg(rs_r1.GetReg());
729   Clobber(rs_r1);
730   MarkInUse(rs_r1);
731   return res;
732 }
733 
734 /* To be used when explicitly managing register use */
LockCallTemps()735 void ArmMir2Lir::LockCallTemps() {
736   LockTemp(rs_r0);
737   LockTemp(rs_r1);
738   LockTemp(rs_r2);
739   LockTemp(rs_r3);
740   if (!kArm32QuickCodeUseSoftFloat) {
741     LockTemp(rs_fr0);
742     LockTemp(rs_fr1);
743     LockTemp(rs_fr2);
744     LockTemp(rs_fr3);
745     LockTemp(rs_fr4);
746     LockTemp(rs_fr5);
747     LockTemp(rs_fr6);
748     LockTemp(rs_fr7);
749     LockTemp(rs_fr8);
750     LockTemp(rs_fr9);
751     LockTemp(rs_fr10);
752     LockTemp(rs_fr11);
753     LockTemp(rs_fr12);
754     LockTemp(rs_fr13);
755     LockTemp(rs_fr14);
756     LockTemp(rs_fr15);
757     LockTemp(rs_dr0);
758     LockTemp(rs_dr1);
759     LockTemp(rs_dr2);
760     LockTemp(rs_dr3);
761     LockTemp(rs_dr4);
762     LockTemp(rs_dr5);
763     LockTemp(rs_dr6);
764     LockTemp(rs_dr7);
765   }
766 }
767 
768 /* To be used when explicitly managing register use */
FreeCallTemps()769 void ArmMir2Lir::FreeCallTemps() {
770   FreeTemp(rs_r0);
771   FreeTemp(rs_r1);
772   FreeTemp(rs_r2);
773   FreeTemp(rs_r3);
774   FreeTemp(TargetReg(kHiddenArg));
775   if (!kArm32QuickCodeUseSoftFloat) {
776     FreeTemp(rs_fr0);
777     FreeTemp(rs_fr1);
778     FreeTemp(rs_fr2);
779     FreeTemp(rs_fr3);
780     FreeTemp(rs_fr4);
781     FreeTemp(rs_fr5);
782     FreeTemp(rs_fr6);
783     FreeTemp(rs_fr7);
784     FreeTemp(rs_fr8);
785     FreeTemp(rs_fr9);
786     FreeTemp(rs_fr10);
787     FreeTemp(rs_fr11);
788     FreeTemp(rs_fr12);
789     FreeTemp(rs_fr13);
790     FreeTemp(rs_fr14);
791     FreeTemp(rs_fr15);
792     FreeTemp(rs_dr0);
793     FreeTemp(rs_dr1);
794     FreeTemp(rs_dr2);
795     FreeTemp(rs_dr3);
796     FreeTemp(rs_dr4);
797     FreeTemp(rs_dr5);
798     FreeTemp(rs_dr6);
799     FreeTemp(rs_dr7);
800   }
801 }
802 
LoadHelper(QuickEntrypointEnum trampoline)803 RegStorage ArmMir2Lir::LoadHelper(QuickEntrypointEnum trampoline) {
804   LoadWordDisp(rs_rARM_SELF, GetThreadOffset<4>(trampoline).Int32Value(), rs_rARM_LR);
805   return rs_rARM_LR;
806 }
807 
CheckSuspendUsingLoad()808 LIR* ArmMir2Lir::CheckSuspendUsingLoad() {
809   RegStorage tmp = rs_r0;
810   Load32Disp(rs_rARM_SELF, Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
811   LIR* load2 = Load32Disp(tmp, 0, tmp);
812   return load2;
813 }
814 
GetTargetInstFlags(int opcode)815 uint64_t ArmMir2Lir::GetTargetInstFlags(int opcode) {
816   DCHECK(!IsPseudoLirOp(opcode));
817   return ArmMir2Lir::EncodingMap[opcode].flags;
818 }
819 
GetTargetInstName(int opcode)820 const char* ArmMir2Lir::GetTargetInstName(int opcode) {
821   DCHECK(!IsPseudoLirOp(opcode));
822   return ArmMir2Lir::EncodingMap[opcode].name;
823 }
824 
GetTargetInstFmt(int opcode)825 const char* ArmMir2Lir::GetTargetInstFmt(int opcode) {
826   DCHECK(!IsPseudoLirOp(opcode));
827   return ArmMir2Lir::EncodingMap[opcode].fmt;
828 }
829 
830 /*
831  * Somewhat messy code here.  We want to allocate a pair of contiguous
832  * physical single-precision floating point registers starting with
833  * an even numbered reg.  It is possible that the paired s_reg (s_reg+1)
834  * has already been allocated - try to fit if possible.  Fail to
835  * allocate if we can't meet the requirements for the pair of
836  * s_reg<=sX[even] & (s_reg+1)<= sX+1.
837  */
838 // TODO: needs rewrite to support non-backed 64-bit float regs.
AllocPreservedDouble(int s_reg)839 RegStorage ArmMir2Lir::AllocPreservedDouble(int s_reg) {
840   RegStorage res;
841   int v_reg = mir_graph_->SRegToVReg(s_reg);
842   int p_map_idx = SRegToPMap(s_reg);
843   if (promotion_map_[p_map_idx+1].fp_location == kLocPhysReg) {
844     // Upper reg is already allocated.  Can we fit?
845     int high_reg = promotion_map_[p_map_idx+1].fp_reg;
846     if ((high_reg & 1) == 0) {
847       // High reg is even - fail.
848       return res;  // Invalid.
849     }
850     // Is the low reg of the pair free?
851     // FIXME: rework.
852     RegisterInfo* p = GetRegInfo(RegStorage::FloatSolo32(high_reg - 1));
853     if (p->InUse() || p->IsTemp()) {
854       // Already allocated or not preserved - fail.
855       return res;  // Invalid.
856     }
857     // OK - good to go.
858     res = RegStorage::FloatSolo64(p->GetReg().GetRegNum() >> 1);
859     p->MarkInUse();
860     MarkPreservedSingle(v_reg, p->GetReg());
861   } else {
862     /*
863      * TODO: until runtime support is in, make sure we avoid promoting the same vreg to
864      * different underlying physical registers.
865      */
866     for (RegisterInfo* info : reg_pool_->dp_regs_) {
867       if (!info->IsTemp() && !info->InUse()) {
868         res = info->GetReg();
869         info->MarkInUse();
870         MarkPreservedDouble(v_reg, info->GetReg());
871         break;
872       }
873     }
874   }
875   if (res.Valid()) {
876     RegisterInfo* info = GetRegInfo(res);
877     promotion_map_[p_map_idx].fp_location = kLocPhysReg;
878     promotion_map_[p_map_idx].fp_reg =
879         info->FindMatchingView(RegisterInfo::kLowSingleStorageMask)->GetReg().GetReg();
880     promotion_map_[p_map_idx+1].fp_location = kLocPhysReg;
881     promotion_map_[p_map_idx+1].fp_reg =
882         info->FindMatchingView(RegisterInfo::kHighSingleStorageMask)->GetReg().GetReg();
883   }
884   return res;
885 }
886 
887 // Reserve a callee-save sp single register.
AllocPreservedSingle(int s_reg)888 RegStorage ArmMir2Lir::AllocPreservedSingle(int s_reg) {
889   RegStorage res;
890   for (RegisterInfo* info : reg_pool_->sp_regs_) {
891     if (!info->IsTemp() && !info->InUse()) {
892       res = info->GetReg();
893       int p_map_idx = SRegToPMap(s_reg);
894       int v_reg = mir_graph_->SRegToVReg(s_reg);
895       GetRegInfo(res)->MarkInUse();
896       MarkPreservedSingle(v_reg, res);
897       promotion_map_[p_map_idx].fp_location = kLocPhysReg;
898       promotion_map_[p_map_idx].fp_reg = res.GetReg();
899       break;
900     }
901   }
902   return res;
903 }
904 
InstallLiteralPools()905 void ArmMir2Lir::InstallLiteralPools() {
906   patches_.reserve(call_method_insns_.size() + dex_cache_access_insns_.size());
907 
908   // PC-relative calls to methods.
909   for (LIR* p : call_method_insns_) {
910     DCHECK_EQ(p->opcode, kThumb2Bl);
911     uint32_t target_method_idx = p->operands[1];
912     const DexFile* target_dex_file = UnwrapPointer<DexFile>(p->operands[2]);
913     patches_.push_back(LinkerPatch::RelativeCodePatch(p->offset,
914                                                       target_dex_file, target_method_idx));
915   }
916 
917   // PC-relative dex cache array accesses.
918   for (LIR* p : dex_cache_access_insns_) {
919     DCHECK(p->opcode = kThumb2MovImm16 || p->opcode == kThumb2MovImm16H);
920     const LIR* add_pc = UnwrapPointer<LIR>(p->operands[4]);
921     DCHECK(add_pc->opcode == kThumbAddRRLH || add_pc->opcode == kThumbAddRRHH);
922     const DexFile* dex_file = UnwrapPointer<DexFile>(p->operands[2]);
923     uint32_t offset = p->operands[3];
924     DCHECK(!p->flags.is_nop);
925     DCHECK(!add_pc->flags.is_nop);
926     patches_.push_back(LinkerPatch::DexCacheArrayPatch(p->offset,
927                                                        dex_file, add_pc->offset, offset));
928   }
929 
930   // And do the normal processing.
931   Mir2Lir::InstallLiteralPools();
932 }
933 
GetNextReg(ShortyArg arg)934 RegStorage ArmMir2Lir::InToRegStorageArmMapper::GetNextReg(ShortyArg arg) {
935   const RegStorage coreArgMappingToPhysicalReg[] =
936       {rs_r1, rs_r2, rs_r3};
937   const int coreArgMappingToPhysicalRegSize = arraysize(coreArgMappingToPhysicalReg);
938   const RegStorage fpArgMappingToPhysicalReg[] =
939       {rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7,
940        rs_fr8, rs_fr9, rs_fr10, rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15};
941   constexpr uint32_t fpArgMappingToPhysicalRegSize = arraysize(fpArgMappingToPhysicalReg);
942   static_assert(fpArgMappingToPhysicalRegSize % 2 == 0, "Number of FP Arg regs is not even");
943 
944   RegStorage result = RegStorage::InvalidReg();
945   // Regard double as long, float as int for kArm32QuickCodeUseSoftFloat.
946   if (arg.IsFP() && !kArm32QuickCodeUseSoftFloat) {
947     if (arg.IsWide()) {
948       cur_fp_double_reg_ = std::max(cur_fp_double_reg_, RoundUp(cur_fp_reg_, 2));
949       if (cur_fp_double_reg_ < fpArgMappingToPhysicalRegSize) {
950         result = RegStorage::MakeRegPair(fpArgMappingToPhysicalReg[cur_fp_double_reg_],
951                                          fpArgMappingToPhysicalReg[cur_fp_double_reg_ + 1]);
952         result = As64BitFloatReg(result);
953         cur_fp_double_reg_ += 2;
954       }
955     } else {
956       if (cur_fp_reg_ % 2 == 0) {
957         cur_fp_reg_ = std::max(cur_fp_double_reg_, cur_fp_reg_);
958       }
959       if (cur_fp_reg_ < fpArgMappingToPhysicalRegSize) {
960         result = fpArgMappingToPhysicalReg[cur_fp_reg_];
961         cur_fp_reg_++;
962       }
963     }
964   } else {
965     if (cur_core_reg_ < coreArgMappingToPhysicalRegSize) {
966       if (!kArm32QuickCodeUseSoftFloat && arg.IsWide() && cur_core_reg_ == 0) {
967         // Skip r1, and use r2-r3 for the register pair.
968         cur_core_reg_++;
969       }
970       result = coreArgMappingToPhysicalReg[cur_core_reg_++];
971       if (arg.IsWide() && cur_core_reg_ < coreArgMappingToPhysicalRegSize) {
972         result = RegStorage::MakeRegPair(result, coreArgMappingToPhysicalReg[cur_core_reg_++]);
973       }
974     }
975   }
976   return result;
977 }
978 
GenDalvikArgsBulkCopy(CallInfo * info,int first,int count)979 int ArmMir2Lir::GenDalvikArgsBulkCopy(CallInfo* info, int first, int count) {
980   if (kArm32QuickCodeUseSoftFloat) {
981     return Mir2Lir::GenDalvikArgsBulkCopy(info, first, count);
982   }
983   /*
984    * TODO: Improve by adding block copy for large number of arguments.  For now, just
985    * copy a Dalvik vreg at a time.
986    */
987   return count;
988 }
989 
GenMachineSpecificExtendedMethodMIR(BasicBlock * bb,MIR * mir)990 void ArmMir2Lir::GenMachineSpecificExtendedMethodMIR(BasicBlock* bb, MIR* mir) {
991   UNUSED(bb);
992   DCHECK(MIR::DecodedInstruction::IsPseudoMirOp(mir->dalvikInsn.opcode));
993   RegLocation rl_src[3];
994   RegLocation rl_dest = mir_graph_->GetBadLoc();
995   rl_src[0] = rl_src[1] = rl_src[2] = mir_graph_->GetBadLoc();
996   switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) {
997     case kMirOpMaddInt:
998       rl_dest = mir_graph_->GetDest(mir);
999       rl_src[0] = mir_graph_->GetSrc(mir, 0);
1000       rl_src[1] = mir_graph_->GetSrc(mir, 1);
1001       rl_src[2]= mir_graph_->GetSrc(mir, 2);
1002       GenMaddMsubInt(rl_dest, rl_src[0], rl_src[1], rl_src[2], false);
1003       break;
1004     case kMirOpMsubInt:
1005       rl_dest = mir_graph_->GetDest(mir);
1006       rl_src[0] = mir_graph_->GetSrc(mir, 0);
1007       rl_src[1] = mir_graph_->GetSrc(mir, 1);
1008       rl_src[2]= mir_graph_->GetSrc(mir, 2);
1009       GenMaddMsubInt(rl_dest, rl_src[0], rl_src[1], rl_src[2], true);
1010       break;
1011     default:
1012       LOG(FATAL) << "Unexpected opcode: " << mir->dalvikInsn.opcode;
1013   }
1014 }
1015 
1016 }  // namespace art
1017