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
29namespace art {
30
31#ifdef ARM_R4_SUSPEND_FLAG
32static 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
36static 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
40static 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};
45static 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
49static constexpr RegStorage reserved_regs_arr[] =
50    {rs_rARM_SUSPEND, rs_rARM_SELF, rs_rARM_SP, rs_rARM_LR, rs_rARM_PC};
51static constexpr RegStorage core_temps_arr[] = {rs_r0, rs_r1, rs_r2, rs_r3, rs_r12};
52#else
53static constexpr RegStorage reserved_regs_arr[] =
54    {rs_rARM_SELF, rs_rARM_SP, rs_rARM_LR, rs_rARM_PC};
55static constexpr RegStorage core_temps_arr[] = {rs_r0, rs_r1, rs_r2, rs_r3, rs_r4, rs_r12};
56#endif
57static 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};
60static constexpr RegStorage dp_temps_arr[] =
61    {rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7};
62
63static constexpr ArrayRef<const RegStorage> empty_pool;
64static constexpr ArrayRef<const RegStorage> core_regs(core_regs_arr);
65static constexpr ArrayRef<const RegStorage> sp_regs(sp_regs_arr);
66static constexpr ArrayRef<const RegStorage> dp_regs(dp_regs_arr);
67static constexpr ArrayRef<const RegStorage> reserved_regs(reserved_regs_arr);
68static constexpr ArrayRef<const RegStorage> core_temps(core_temps_arr);
69static constexpr ArrayRef<const RegStorage> sp_temps(sp_temps_arr);
70static constexpr ArrayRef<const RegStorage> dp_temps(dp_temps_arr);
71
72RegLocation ArmMir2Lir::LocCReturn() {
73  return arm_loc_c_return;
74}
75
76RegLocation ArmMir2Lir::LocCReturnRef() {
77  return arm_loc_c_return;
78}
79
80RegLocation ArmMir2Lir::LocCReturnWide() {
81  return arm_loc_c_return_wide;
82}
83
84RegLocation ArmMir2Lir::LocCReturnFloat() {
85  return arm_loc_c_return_float;
86}
87
88RegLocation ArmMir2Lir::LocCReturnDouble() {
89  return arm_loc_c_return_double;
90}
91
92// Return a target-dependent special register.
93RegStorage 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 */
139ResourceMask ArmMir2Lir::GetRegMaskCommon(const RegStorage& reg) const {
140  return GetRegMaskArm(reg);
141}
142
143constexpr 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
150constexpr ResourceMask ArmMir2Lir::EncodeArmRegList(int reg_list) {
151  return ResourceMask::RawMask(static_cast<uint64_t >(reg_list), 0u);
152}
153
154constexpr ResourceMask ArmMir2Lir::EncodeArmRegFpcsList(int reg_list) {
155  return ResourceMask::RawMask(static_cast<uint64_t >(reg_list) << kArmFPReg16, 0u);
156}
157
158ResourceMask ArmMir2Lir::GetPCUseDefEncoding() const {
159  return ResourceMask::Bit(kArmRegPC);
160}
161
162// Thumb2 specific setup.  TODO: inline?:
163void 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
243ArmConditionCode 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
271static 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
291static const char* shift_names[4] = {
292  "lsl",
293  "lsr",
294  "asr",
295  "ror"};
296
297/* Decode and print a ARM register name */
298static 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
321static 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
329static 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
348const 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 */
354std::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
515void 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
561bool ArmMir2Lir::IsUnconditionalBranch(LIR* lir) {
562  return ((lir->opcode == kThumbBUncond) || (lir->opcode == kThumb2BUncond));
563}
564
565RegisterClass 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
576ArmMir2Lir::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
591Mir2Lir* ArmCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
592                          ArenaAllocator* const arena) {
593  return new ArmMir2Lir(cu, mir_graph, arena);
594}
595
596void 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
644void 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 */
655void 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
670void 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 */
680void 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
714RegLocation 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
726RegLocation 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 */
735void 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 */
769void 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
803RegStorage ArmMir2Lir::LoadHelper(QuickEntrypointEnum trampoline) {
804  LoadWordDisp(rs_rARM_SELF, GetThreadOffset<4>(trampoline).Int32Value(), rs_rARM_LR);
805  return rs_rARM_LR;
806}
807
808LIR* 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
815uint64_t ArmMir2Lir::GetTargetInstFlags(int opcode) {
816  DCHECK(!IsPseudoLirOp(opcode));
817  return ArmMir2Lir::EncodingMap[opcode].flags;
818}
819
820const char* ArmMir2Lir::GetTargetInstName(int opcode) {
821  DCHECK(!IsPseudoLirOp(opcode));
822  return ArmMir2Lir::EncodingMap[opcode].name;
823}
824
825const 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.
839RegStorage 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.
888RegStorage 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
905void 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
934RegStorage 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
979int 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
990void 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