blob: 5f27338e6bafca07fd622c19171e69cac394ec4f [file] [log] [blame]
Brian Carlstrom7940e442013-07-12 13:46:57 -07001/*
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
Ian Rogers107c31e2014-01-23 20:55:29 -080017#include "codegen_arm.h"
18
19#include <inttypes.h>
20
Brian Carlstrom7940e442013-07-12 13:46:57 -070021#include <string>
Zheng Xua34e7602015-02-03 12:03:15 +080022#include <sstream>
Brian Carlstrom7940e442013-07-12 13:46:57 -070023
Andreas Gampe53c913b2014-08-12 23:19:23 -070024#include "backend_arm.h"
Andreas Gampe0b9203e2015-01-22 20:39:27 -080025#include "base/logging.h"
26#include "dex/mir_graph.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070027#include "dex/quick/mir_to_lir-inl.h"
28
29namespace art {
30
Wei Jin04f4d8a2014-05-29 18:04:29 -070031#ifdef ARM_R4_SUSPEND_FLAG
Vladimir Marko089142c2014-06-05 10:57:05 +010032static constexpr RegStorage core_regs_arr[] =
buzbee091cc402014-03-31 10:14:40 -070033 {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};
Wei Jin04f4d8a2014-05-29 18:04:29 -070035#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
Vladimir Marko089142c2014-06-05 10:57:05 +010040static constexpr RegStorage sp_regs_arr[] =
buzbee091cc402014-03-31 10:14:40 -070041 {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};
Vladimir Marko089142c2014-06-05 10:57:05 +010045static constexpr RegStorage dp_regs_arr[] =
buzbee091cc402014-03-31 10:14:40 -070046 {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};
Wei Jin04f4d8a2014-05-29 18:04:29 -070048#ifdef ARM_R4_SUSPEND_FLAG
Vladimir Marko089142c2014-06-05 10:57:05 +010049static constexpr RegStorage reserved_regs_arr[] =
buzbee091cc402014-03-31 10:14:40 -070050 {rs_rARM_SUSPEND, rs_rARM_SELF, rs_rARM_SP, rs_rARM_LR, rs_rARM_PC};
Vladimir Marko089142c2014-06-05 10:57:05 +010051static constexpr RegStorage core_temps_arr[] = {rs_r0, rs_r1, rs_r2, rs_r3, rs_r12};
Wei Jin04f4d8a2014-05-29 18:04:29 -070052#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
Vladimir Marko089142c2014-06-05 10:57:05 +010057static constexpr RegStorage sp_temps_arr[] =
buzbee091cc402014-03-31 10:14:40 -070058 {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};
Vladimir Marko089142c2014-06-05 10:57:05 +010060static constexpr RegStorage dp_temps_arr[] =
buzbee091cc402014-03-31 10:14:40 -070061 {rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7};
62
Vladimir Marko089142c2014-06-05 10:57:05 +010063static 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);
Brian Carlstrom7940e442013-07-12 13:46:57 -070071
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070072RegLocation ArmMir2Lir::LocCReturn() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000073 return arm_loc_c_return;
Brian Carlstrom7940e442013-07-12 13:46:57 -070074}
75
buzbeea0cd2d72014-06-01 09:33:49 -070076RegLocation ArmMir2Lir::LocCReturnRef() {
77 return arm_loc_c_return;
78}
79
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070080RegLocation ArmMir2Lir::LocCReturnWide() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000081 return arm_loc_c_return_wide;
Brian Carlstrom7940e442013-07-12 13:46:57 -070082}
83
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070084RegLocation ArmMir2Lir::LocCReturnFloat() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000085 return arm_loc_c_return_float;
Brian Carlstrom7940e442013-07-12 13:46:57 -070086}
87
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070088RegLocation ArmMir2Lir::LocCReturnDouble() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000089 return arm_loc_c_return_double;
Brian Carlstrom7940e442013-07-12 13:46:57 -070090}
91
92// Return a target-dependent special register.
buzbee2700f7e2014-03-07 09:46:20 -080093RegStorage ArmMir2Lir::TargetReg(SpecialTargetRegister reg) {
Zheng Xu5667fdb2014-10-23 18:29:55 +080094 RegStorage res_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -070095 switch (reg) {
buzbee091cc402014-03-31 10:14:40 -070096 case kSelf: res_reg = rs_rARM_SELF; break;
Wei Jin04f4d8a2014-05-29 18:04:29 -070097#ifdef ARM_R4_SUSPEND_FLAG
buzbee091cc402014-03-31 10:14:40 -070098 case kSuspend: res_reg = rs_rARM_SUSPEND; break;
Wei Jin04f4d8a2014-05-29 18:04:29 -070099#else
100 case kSuspend: res_reg = RegStorage::InvalidReg(); break;
101#endif
buzbee091cc402014-03-31 10:14:40 -0700102 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;
Zheng Xu5667fdb2014-10-23 18:29:55 +0800109 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;
buzbee091cc402014-03-31 10:14:40 -0700125 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;
Dmitry Petrochenko58994cd2014-05-17 01:02:18 +0700131 default: res_reg = RegStorage::InvalidReg();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700132 }
buzbee091cc402014-03-31 10:14:40 -0700133 return res_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700134}
135
Brian Carlstrom7940e442013-07-12 13:46:57 -0700136/*
137 * Decode the register id.
138 */
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100139ResourceMask ArmMir2Lir::GetRegMaskCommon(const RegStorage& reg) const {
140 return GetRegMaskArm(reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700141}
142
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100143constexpr 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);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700160}
161
buzbeeb48819d2013-09-14 16:15:25 -0700162// Thumb2 specific setup. TODO: inline?:
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100163void ArmMir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags,
164 ResourceMask* use_mask, ResourceMask* def_mask) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700165 DCHECK_EQ(cu_->instruction_set, kThumb2);
buzbeeb48819d2013-09-14 16:15:25 -0700166 DCHECK(!lir->flags.use_def_invalid);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700167
Brian Carlstrom7940e442013-07-12 13:46:57 -0700168 int opcode = lir->opcode;
169
buzbeeb48819d2013-09-14 16:15:25 -0700170 // 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) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100175 def_mask->SetBit(kArmRegSP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700176 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700177
buzbeeb48819d2013-09-14 16:15:25 -0700178 if (flags & REG_USE_SP) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100179 use_mask->SetBit(kArmRegSP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700180 }
buzbeeb48819d2013-09-14 16:15:25 -0700181
182 if (flags & REG_DEF_LIST0) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100183 def_mask->SetBits(EncodeArmRegList(lir->operands[0]));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700184 }
buzbeeb48819d2013-09-14 16:15:25 -0700185
186 if (flags & REG_DEF_LIST1) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100187 def_mask->SetBits(EncodeArmRegList(lir->operands[1]));
buzbeeb48819d2013-09-14 16:15:25 -0700188 }
189
190 if (flags & REG_DEF_FPCS_LIST0) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100191 def_mask->SetBits(EncodeArmRegList(lir->operands[0]));
buzbeeb48819d2013-09-14 16:15:25 -0700192 }
193
194 if (flags & REG_DEF_FPCS_LIST2) {
195 for (int i = 0; i < lir->operands[2]; i++) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100196 SetupRegMask(def_mask, lir->operands[1] + i);
buzbeeb48819d2013-09-14 16:15:25 -0700197 }
198 }
199
200 if (flags & REG_USE_PC) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100201 use_mask->SetBit(kArmRegPC);
buzbeeb48819d2013-09-14 16:15:25 -0700202 }
203
204 /* Conservatively treat the IT block */
205 if (flags & IS_IT) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100206 *def_mask = kEncodeAll;
buzbeeb48819d2013-09-14 16:15:25 -0700207 }
208
209 if (flags & REG_USE_LIST0) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100210 use_mask->SetBits(EncodeArmRegList(lir->operands[0]));
buzbeeb48819d2013-09-14 16:15:25 -0700211 }
212
213 if (flags & REG_USE_LIST1) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100214 use_mask->SetBits(EncodeArmRegList(lir->operands[1]));
buzbeeb48819d2013-09-14 16:15:25 -0700215 }
216
217 if (flags & REG_USE_FPCS_LIST0) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100218 use_mask->SetBits(EncodeArmRegList(lir->operands[0]));
buzbeeb48819d2013-09-14 16:15:25 -0700219 }
220
221 if (flags & REG_USE_FPCS_LIST2) {
222 for (int i = 0; i < lir->operands[2]; i++) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100223 SetupRegMask(use_mask, lir->operands[1] + i);
buzbeeb48819d2013-09-14 16:15:25 -0700224 }
225 }
226 /* Fixup for kThumbPush/lr and kThumbPop/pc */
227 if (opcode == kThumbPush || opcode == kThumbPop) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100228 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);;
buzbeeb48819d2013-09-14 16:15:25 -0700235 }
236 }
237 if (flags & REG_DEF_LR) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100238 def_mask->SetBit(kArmRegLR);
buzbeeb48819d2013-09-14 16:15:25 -0700239 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700240 }
241}
242
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700243ArmConditionCode ArmMir2Lir::ArmConditionEncoding(ConditionCode ccode) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700244 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;
Vladimir Marko58af1f92013-12-19 13:31:15 +0000250 case kCondUlt: res = kArmCondCc; break;
251 case kCondUge: res = kArmCondCs; break;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700252 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 */
Ian Rogers988e6ea2014-01-08 11:30:50 -0800298static char* DecodeRegList(int opcode, int vector, char* buf, size_t buf_size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700299 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) {
buzbee091cc402014-03-31 10:14:40 -0700306 reg_id = rs_rARM_LR.GetRegNum();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700307 } else if (opcode == kThumbPop && i == 8) {
buzbee091cc402014-03-31 10:14:40 -0700308 reg_id = rs_rARM_PC.GetRegNum();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700309 }
310 if (printed) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800311 snprintf(buf + strlen(buf), buf_size - strlen(buf), ", r%d", reg_id);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700312 } else {
313 printed = true;
Ian Rogers988e6ea2014-01-08 11:30:50 -0800314 snprintf(buf, buf_size, "r%d", reg_id);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700315 }
316 }
317 }
318 return buf;
319}
320
Ian Rogers988e6ea2014-01-08 11:30:50 -0800321static char* DecodeFPCSRegList(int count, int base, char* buf, size_t buf_size) {
322 snprintf(buf, buf_size, "s%d", base);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700323 for (int i = 1; i < count; i++) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800324 snprintf(buf + strlen(buf), buf_size - strlen(buf), ", s%d", base + i);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700325 }
326 return buf;
327}
328
buzbee0d829482013-10-11 15:24:55 -0700329static int32_t ExpandImmediate(int value) {
330 int32_t mode = (value & 0xf00) >> 8;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700331 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
Brian Carlstromb1eba212013-07-17 18:07:19 -0700348const char* cc_names[] = {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
349 "hi", "ls", "ge", "lt", "gt", "le", "al", "nv"};
Brian Carlstrom7940e442013-07-12 13:46:57 -0700350/*
351 * Interpret a format string and build a string no longer than size
352 * See format key in Assemble.c.
353 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700354std::string ArmMir2Lir::BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700355 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++;
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700367 if (nc == '!') {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700368 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) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800376 snprintf(tbuf, arraysize(tbuf), ", %s %d", shift_names[operand & 0x3], operand >> 2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700377 } else {
Brian Carlstromb1eba212013-07-17 18:07:19 -0700378 strcpy(tbuf, "");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700379 }
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':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700408 strcpy(tbuf, "0000");
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700409 for (i = 3; i >= 0; i--) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700410 tbuf[i] += operand & 1;
411 operand >>= 1;
412 }
413 break;
414 case 'n':
415 operand = ~ExpandImmediate(operand);
Ian Rogers988e6ea2014-01-08 11:30:50 -0800416 snprintf(tbuf, arraysize(tbuf), "%d [%#x]", operand, operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700417 break;
418 case 'm':
419 operand = ExpandImmediate(operand);
Ian Rogers988e6ea2014-01-08 11:30:50 -0800420 snprintf(tbuf, arraysize(tbuf), "%d [%#x]", operand, operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700421 break;
422 case 's':
buzbee091cc402014-03-31 10:14:40 -0700423 snprintf(tbuf, arraysize(tbuf), "s%d", RegStorage::RegNum(operand));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700424 break;
425 case 'S':
buzbee091cc402014-03-31 10:14:40 -0700426 snprintf(tbuf, arraysize(tbuf), "d%d", RegStorage::RegNum(operand));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700427 break;
428 case 'h':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800429 snprintf(tbuf, arraysize(tbuf), "%04x", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700430 break;
431 case 'M':
432 case 'd':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800433 snprintf(tbuf, arraysize(tbuf), "%d", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700434 break;
435 case 'C':
buzbee091cc402014-03-31 10:14:40 -0700436 operand = RegStorage::RegNum(operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700437 DCHECK_LT(operand, static_cast<int>(
438 sizeof(core_reg_names)/sizeof(core_reg_names[0])));
Ian Rogers988e6ea2014-01-08 11:30:50 -0800439 snprintf(tbuf, arraysize(tbuf), "%s", core_reg_names[operand]);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700440 break;
441 case 'E':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800442 snprintf(tbuf, arraysize(tbuf), "%d", operand*4);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700443 break;
444 case 'F':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800445 snprintf(tbuf, arraysize(tbuf), "%d", operand*2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700446 break;
447 case 'c':
448 strcpy(tbuf, cc_names[operand]);
449 break;
450 case 't':
Ian Rogers107c31e2014-01-23 20:55:29 -0800451 snprintf(tbuf, arraysize(tbuf), "0x%08" PRIxPTR " (L%p)",
452 reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 + (operand << 1),
Brian Carlstrom7940e442013-07-12 13:46:57 -0700453 lir->target);
454 break;
Vladimir Markof4da6752014-08-01 19:04:18 +0100455 case 'T':
456 snprintf(tbuf, arraysize(tbuf), "%s", PrettyMethod(
457 static_cast<uint32_t>(lir->operands[1]),
Vladimir Markof6737f72015-03-23 17:05:14 +0000458 *UnwrapPointer<DexFile>(lir->operands[2])).c_str());
Vladimir Markof4da6752014-08-01 19:04:18 +0100459 break;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700460 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;
Ian Rogers988e6ea2014-01-08 11:30:50 -0800467 snprintf(tbuf, arraysize(tbuf), "%p", reinterpret_cast<void *>(target));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700468 break;
469 }
470
471 /* Nothing to print for BLX_2 */
472 case 'v':
473 strcpy(tbuf, "see above");
474 break;
475 case 'R':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800476 DecodeRegList(lir->opcode, operand, tbuf, arraysize(tbuf));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700477 break;
478 case 'P':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800479 DecodeFPCSRegList(operand, 16, tbuf, arraysize(tbuf));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700480 break;
481 case 'Q':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800482 DecodeFPCSRegList(operand, 0, tbuf, arraysize(tbuf));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700483 break;
484 default:
Brian Carlstromb1eba212013-07-17 18:07:19 -0700485 strcpy(tbuf, "DecodeError1");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700486 break;
487 }
488 buf += tbuf;
489 }
490 } else {
491 buf += *fmt++;
492 }
493 }
Zheng Xua34e7602015-02-03 12:03:15 +0800494 // 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 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700512 return buf;
513}
514
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100515void ArmMir2Lir::DumpResourceMask(LIR* arm_lir, const ResourceMask& mask, const char* prefix) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700516 char buf[256];
517 buf[0] = 0;
518
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100519 if (mask.Equals(kEncodeAll)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700520 strcpy(buf, "all");
521 } else {
522 char num[8];
523 int i;
524
525 for (i = 0; i < kArmRegEnd; i++) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100526 if (mask.HasBit(i)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800527 snprintf(num, arraysize(num), "%d ", i);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700528 strcat(buf, num);
529 }
530 }
531
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100532 if (mask.HasBit(ResourceMask::kCCode)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700533 strcat(buf, "cc ");
534 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100535 if (mask.HasBit(ResourceMask::kFPStatus)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700536 strcat(buf, "fpcc ");
537 }
538
539 /* Memory bits */
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100540 if (arm_lir && (mask.HasBit(ResourceMask::kDalvikReg))) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800541 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)" : "");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700544 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100545 if (mask.HasBit(ResourceMask::kLiteral)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700546 strcat(buf, "lit ");
547 }
548
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100549 if (mask.HasBit(ResourceMask::kHeapRef)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700550 strcat(buf, "heap ");
551 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100552 if (mask.HasBit(ResourceMask::kMustNotAlias)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700553 strcat(buf, "noalias ");
554 }
555 }
556 if (buf[0]) {
557 LOG(INFO) << prefix << ": " << buf;
558 }
559}
560
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700561bool ArmMir2Lir::IsUnconditionalBranch(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700562 return ((lir->opcode == kThumbBUncond) || (lir->opcode == kThumb2BUncond));
563}
564
Vladimir Marko674744e2014-04-24 15:18:26 +0100565RegisterClass 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
Brian Carlstrom7940e442013-07-12 13:46:57 -0700576ArmMir2Lir::ArmMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
Vladimir Markof4da6752014-08-01 19:04:18 +0100577 : Mir2Lir(cu, mir_graph, arena),
Vladimir Markoe5c76c52015-04-06 12:10:19 +0100578 call_method_insns_(arena->Adapter()),
Vladimir Markocc234812015-04-07 09:36:09 +0100579 dex_cache_access_insns_(arena->Adapter()),
580 dex_cache_arrays_base_reg_(RegStorage::InvalidReg()) {
Vladimir Markof4da6752014-08-01 19:04:18 +0100581 call_method_insns_.reserve(100);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700582 // Sanity check - make sure encoding map lines up.
583 for (int i = 0; i < kArmLast; i++) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700584 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);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700588 }
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
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700596void ArmMir2Lir::CompilerInitializeRegAlloc() {
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100597 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));
Dave Allisonf6b65c12014-04-01 17:45:18 -0700602
buzbee091cc402014-03-31 10:14:40 -0700603 // Target-specific adjustments.
604
605 // Alias single precision floats to appropriate half of overlapping double.
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100606 for (RegisterInfo* info : reg_pool_->sp_regs_) {
buzbee091cc402014-03-31 10:14:40 -0700607 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.
buzbee85089dd2014-05-25 15:10:52 -0700616 DCHECK_EQ(info->StorageMask(), RegisterInfo::kLowSingleStorageMask);
buzbee091cc402014-03-31 10:14:40 -0700617 if (sp_reg_num & 1) {
buzbee85089dd2014-05-25 15:10:52 -0700618 // For odd singles, change to use the high word of the backing double.
619 info->SetStorageMask(RegisterInfo::kHighSingleStorageMask);
buzbee091cc402014-03-31 10:14:40 -0700620 }
621 }
622
Wei Jin04f4d8a2014-05-29 18:04:29 -0700623#ifdef ARM_R4_SUSPEND_FLAG
Dave Allison83252962014-04-03 16:33:48 -0700624 // TODO: re-enable this when we can safely save r4 over the suspension code path.
625 bool no_suspend = NO_SUSPEND; // || !Runtime::Current()->ExplicitSuspendChecks();
buzbee091cc402014-03-31 10:14:40 -0700626 if (no_suspend) {
627 GetRegInfo(rs_rARM_SUSPEND)->MarkFree();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700628 }
Wei Jin04f4d8a2014-05-29 18:04:29 -0700629#endif
Brian Carlstrom7940e442013-07-12 13:46:57 -0700630
buzbee091cc402014-03-31 10:14:40 -0700631 // 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;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700636}
637
Brian Carlstrom7940e442013-07-12 13:46:57 -0700638/*
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
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700644void ArmMir2Lir::AdjustSpillMask() {
buzbee091cc402014-03-31 10:14:40 -0700645 core_spill_mask_ |= (1 << rs_rARM_LR.GetRegNum());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700646 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 */
buzbee091cc402014-03-31 10:14:40 -0700655void 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;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700658 // Ensure fp_vmap_table is large enough
659 int table_size = fp_vmap_table_.size();
buzbee091cc402014-03-31 10:14:40 -0700660 for (int i = table_size; i < (adjusted_reg_num + 1); i++) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700661 fp_vmap_table_.push_back(INVALID_VREG);
662 }
663 // Add the current mapping
buzbee091cc402014-03-31 10:14:40 -0700664 fp_vmap_table_[adjusted_reg_num] = v_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700665 // 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
buzbee091cc402014-03-31 10:14:40 -0700670void 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);
buzbee2700f7e2014-03-07 09:46:20 -0800677}
678
Brian Carlstrom7940e442013-07-12 13:46:57 -0700679/* Clobber all regs that might be used by an external C call */
Vladimir Marko31c2aac2013-12-09 16:31:19 +0000680void ArmMir2Lir::ClobberCallerSave() {
buzbee091cc402014-03-31 10:14:40 -0700681 // 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);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700712}
713
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700714RegLocation ArmMir2Lir::GetReturnWideAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700715 RegLocation res = LocCReturnWide();
buzbee091cc402014-03-31 10:14:40 -0700716 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);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700723 return res;
724}
725
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700726RegLocation ArmMir2Lir::GetReturnAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700727 RegLocation res = LocCReturn();
buzbee091cc402014-03-31 10:14:40 -0700728 res.reg.SetReg(rs_r1.GetReg());
729 Clobber(rs_r1);
730 MarkInUse(rs_r1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700731 return res;
732}
733
Brian Carlstrom7940e442013-07-12 13:46:57 -0700734/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700735void ArmMir2Lir::LockCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700736 LockTemp(rs_r0);
737 LockTemp(rs_r1);
738 LockTemp(rs_r2);
739 LockTemp(rs_r3);
Zheng Xu5667fdb2014-10-23 18:29:55 +0800740 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 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700766}
767
768/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700769void ArmMir2Lir::FreeCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700770 FreeTemp(rs_r0);
771 FreeTemp(rs_r1);
772 FreeTemp(rs_r2);
773 FreeTemp(rs_r3);
Vladimir Markobfe400b2014-12-19 19:27:26 +0000774 FreeTemp(TargetReg(kHiddenArg));
Zheng Xu5667fdb2014-10-23 18:29:55 +0800775 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 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700801}
802
Andreas Gampe98430592014-07-27 19:44:50 -0700803RegStorage ArmMir2Lir::LoadHelper(QuickEntrypointEnum trampoline) {
804 LoadWordDisp(rs_rARM_SELF, GetThreadOffset<4>(trampoline).Int32Value(), rs_rARM_LR);
buzbee2700f7e2014-03-07 09:46:20 -0800805 return rs_rARM_LR;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700806}
807
Dave Allisonb373e092014-02-20 16:06:36 -0800808LIR* ArmMir2Lir::CheckSuspendUsingLoad() {
buzbee2700f7e2014-03-07 09:46:20 -0800809 RegStorage tmp = rs_r0;
buzbee695d13a2014-04-19 13:32:20 -0700810 Load32Disp(rs_rARM_SELF, Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
811 LIR* load2 = Load32Disp(tmp, 0, tmp);
Dave Allisonb373e092014-02-20 16:06:36 -0800812 return load2;
813}
814
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700815uint64_t ArmMir2Lir::GetTargetInstFlags(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700816 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700817 return ArmMir2Lir::EncodingMap[opcode].flags;
818}
819
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700820const char* ArmMir2Lir::GetTargetInstName(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700821 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700822 return ArmMir2Lir::EncodingMap[opcode].name;
823}
824
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700825const char* ArmMir2Lir::GetTargetInstFmt(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700826 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700827 return ArmMir2Lir::EncodingMap[opcode].fmt;
828}
829
buzbee091cc402014-03-31 10:14:40 -0700830/*
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?
buzbeeb5860fb2014-06-21 15:31:01 -0700845 int high_reg = promotion_map_[p_map_idx+1].fp_reg;
buzbee091cc402014-03-31 10:14:40 -0700846 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 */
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100866 for (RegisterInfo* info : reg_pool_->dp_regs_) {
buzbee091cc402014-03-31 10:14:40 -0700867 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()) {
buzbee85089dd2014-05-25 15:10:52 -0700876 RegisterInfo* info = GetRegInfo(res);
buzbee091cc402014-03-31 10:14:40 -0700877 promotion_map_[p_map_idx].fp_location = kLocPhysReg;
buzbeeb5860fb2014-06-21 15:31:01 -0700878 promotion_map_[p_map_idx].fp_reg =
buzbee85089dd2014-05-25 15:10:52 -0700879 info->FindMatchingView(RegisterInfo::kLowSingleStorageMask)->GetReg().GetReg();
buzbee091cc402014-03-31 10:14:40 -0700880 promotion_map_[p_map_idx+1].fp_location = kLocPhysReg;
buzbeeb5860fb2014-06-21 15:31:01 -0700881 promotion_map_[p_map_idx+1].fp_reg =
buzbee85089dd2014-05-25 15:10:52 -0700882 info->FindMatchingView(RegisterInfo::kHighSingleStorageMask)->GetReg().GetReg();
buzbee091cc402014-03-31 10:14:40 -0700883 }
884 return res;
885}
886
buzbeeb5860fb2014-06-21 15:31:01 -0700887// Reserve a callee-save sp single register.
888RegStorage ArmMir2Lir::AllocPreservedSingle(int s_reg) {
889 RegStorage res;
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100890 for (RegisterInfo* info : reg_pool_->sp_regs_) {
buzbeeb5860fb2014-06-21 15:31:01 -0700891 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
Vladimir Markof4da6752014-08-01 19:04:18 +0100905void ArmMir2Lir::InstallLiteralPools() {
Vladimir Markoe5c76c52015-04-06 12:10:19 +0100906 patches_.reserve(call_method_insns_.size() + dex_cache_access_insns_.size());
907
Vladimir Markof4da6752014-08-01 19:04:18 +0100908 // PC-relative calls to methods.
Vladimir Markof4da6752014-08-01 19:04:18 +0100909 for (LIR* p : call_method_insns_) {
Vladimir Markoe5c76c52015-04-06 12:10:19 +0100910 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));
Vladimir Markof4da6752014-08-01 19:04:18 +0100928 }
929
930 // And do the normal processing.
931 Mir2Lir::InstallLiteralPools();
932}
933
Serguei Katkov717a3e42014-11-13 17:19:42 +0600934RegStorage ArmMir2Lir::InToRegStorageArmMapper::GetNextReg(ShortyArg arg) {
Zheng Xu5667fdb2014-10-23 18:29:55 +0800935 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};
Andreas Gampe785d2f22014-11-03 22:57:30 -0800941 constexpr uint32_t fpArgMappingToPhysicalRegSize = arraysize(fpArgMappingToPhysicalReg);
942 static_assert(fpArgMappingToPhysicalRegSize % 2 == 0, "Number of FP Arg regs is not even");
Zheng Xu5667fdb2014-10-23 18:29:55 +0800943
Zheng Xu5667fdb2014-10-23 18:29:55 +0800944 RegStorage result = RegStorage::InvalidReg();
Serguei Katkov717a3e42014-11-13 17:19:42 +0600945 // Regard double as long, float as int for kArm32QuickCodeUseSoftFloat.
946 if (arg.IsFP() && !kArm32QuickCodeUseSoftFloat) {
947 if (arg.IsWide()) {
Zheng Xu5667fdb2014-10-23 18:29:55 +0800948 cur_fp_double_reg_ = std::max(cur_fp_double_reg_, RoundUp(cur_fp_reg_, 2));
949 if (cur_fp_double_reg_ < fpArgMappingToPhysicalRegSize) {
Serguei Katkov717a3e42014-11-13 17:19:42 +0600950 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;
Zheng Xu5667fdb2014-10-23 18:29:55 +0800954 }
955 } else {
Zheng Xu5667fdb2014-10-23 18:29:55 +0800956 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) {
Nicolas Geoffray69c15d32015-01-13 11:42:13 +0000966 if (!kArm32QuickCodeUseSoftFloat && arg.IsWide() && cur_core_reg_ == 0) {
967 // Skip r1, and use r2-r3 for the register pair.
968 cur_core_reg_++;
969 }
Zheng Xu5667fdb2014-10-23 18:29:55 +0800970 result = coreArgMappingToPhysicalReg[cur_core_reg_++];
Serguei Katkov717a3e42014-11-13 17:19:42 +0600971 if (arg.IsWide() && cur_core_reg_ < coreArgMappingToPhysicalRegSize) {
972 result = RegStorage::MakeRegPair(result, coreArgMappingToPhysicalReg[cur_core_reg_++]);
973 }
Zheng Xu5667fdb2014-10-23 18:29:55 +0800974 }
975 }
976 return result;
977}
978
Serguei Katkov717a3e42014-11-13 17:19:42 +0600979int ArmMir2Lir::GenDalvikArgsBulkCopy(CallInfo* info, int first, int count) {
Zheng Xu5667fdb2014-10-23 18:29:55 +0800980 if (kArm32QuickCodeUseSoftFloat) {
Serguei Katkov717a3e42014-11-13 17:19:42 +0600981 return Mir2Lir::GenDalvikArgsBulkCopy(info, first, count);
Zheng Xu5667fdb2014-10-23 18:29:55 +0800982 }
Serguei Katkov717a3e42014-11-13 17:19:42 +0600983 /*
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;
Zheng Xu5667fdb2014-10-23 18:29:55 +0800988}
989
Ningsheng Jiana262f772014-11-25 16:48:07 +0800990void 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
Brian Carlstrom7940e442013-07-12 13:46:57 -07001016} // namespace art