blob: 580dcb789fa2d49145de23ce18ee130c6101d4b1 [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()),
579 dex_cache_access_insns_(arena->Adapter()) {
Vladimir Markof4da6752014-08-01 19:04:18 +0100580 call_method_insns_.reserve(100);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700581 // Sanity check - make sure encoding map lines up.
582 for (int i = 0; i < kArmLast; i++) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700583 DCHECK_EQ(ArmMir2Lir::EncodingMap[i].opcode, i)
584 << "Encoding order for " << ArmMir2Lir::EncodingMap[i].name
585 << " is wrong: expecting " << i << ", seeing "
586 << static_cast<int>(ArmMir2Lir::EncodingMap[i].opcode);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700587 }
588}
589
590Mir2Lir* ArmCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
591 ArenaAllocator* const arena) {
592 return new ArmMir2Lir(cu, mir_graph, arena);
593}
594
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700595void ArmMir2Lir::CompilerInitializeRegAlloc() {
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100596 reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs, empty_pool /* core64 */,
597 sp_regs, dp_regs,
598 reserved_regs, empty_pool /* reserved64 */,
599 core_temps, empty_pool /* core64_temps */,
600 sp_temps, dp_temps));
Dave Allisonf6b65c12014-04-01 17:45:18 -0700601
buzbee091cc402014-03-31 10:14:40 -0700602 // Target-specific adjustments.
603
604 // Alias single precision floats to appropriate half of overlapping double.
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100605 for (RegisterInfo* info : reg_pool_->sp_regs_) {
buzbee091cc402014-03-31 10:14:40 -0700606 int sp_reg_num = info->GetReg().GetRegNum();
607 int dp_reg_num = sp_reg_num >> 1;
608 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
609 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
610 // Double precision register's master storage should refer to itself.
611 DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
612 // Redirect single precision's master storage to master.
613 info->SetMaster(dp_reg_info);
614 // Singles should show a single 32-bit mask bit, at first referring to the low half.
buzbee85089dd2014-05-25 15:10:52 -0700615 DCHECK_EQ(info->StorageMask(), RegisterInfo::kLowSingleStorageMask);
buzbee091cc402014-03-31 10:14:40 -0700616 if (sp_reg_num & 1) {
buzbee85089dd2014-05-25 15:10:52 -0700617 // For odd singles, change to use the high word of the backing double.
618 info->SetStorageMask(RegisterInfo::kHighSingleStorageMask);
buzbee091cc402014-03-31 10:14:40 -0700619 }
620 }
621
Wei Jin04f4d8a2014-05-29 18:04:29 -0700622#ifdef ARM_R4_SUSPEND_FLAG
Dave Allison83252962014-04-03 16:33:48 -0700623 // TODO: re-enable this when we can safely save r4 over the suspension code path.
624 bool no_suspend = NO_SUSPEND; // || !Runtime::Current()->ExplicitSuspendChecks();
buzbee091cc402014-03-31 10:14:40 -0700625 if (no_suspend) {
626 GetRegInfo(rs_rARM_SUSPEND)->MarkFree();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700627 }
Wei Jin04f4d8a2014-05-29 18:04:29 -0700628#endif
Brian Carlstrom7940e442013-07-12 13:46:57 -0700629
buzbee091cc402014-03-31 10:14:40 -0700630 // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
631 // TODO: adjust when we roll to hard float calling convention.
632 reg_pool_->next_core_reg_ = 2;
633 reg_pool_->next_sp_reg_ = 0;
634 reg_pool_->next_dp_reg_ = 0;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700635}
636
Brian Carlstrom7940e442013-07-12 13:46:57 -0700637/*
638 * TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some
639 * instructions might call out to C/assembly helper functions. Until
640 * machinery is in place, always spill lr.
641 */
642
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700643void ArmMir2Lir::AdjustSpillMask() {
buzbee091cc402014-03-31 10:14:40 -0700644 core_spill_mask_ |= (1 << rs_rARM_LR.GetRegNum());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700645 num_core_spills_++;
646}
647
648/*
649 * Mark a callee-save fp register as promoted. Note that
650 * vpush/vpop uses contiguous register lists so we must
651 * include any holes in the mask. Associate holes with
652 * Dalvik register INVALID_VREG (0xFFFFU).
653 */
buzbee091cc402014-03-31 10:14:40 -0700654void ArmMir2Lir::MarkPreservedSingle(int v_reg, RegStorage reg) {
655 DCHECK_GE(reg.GetRegNum(), ARM_FP_CALLEE_SAVE_BASE);
656 int adjusted_reg_num = reg.GetRegNum() - ARM_FP_CALLEE_SAVE_BASE;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700657 // Ensure fp_vmap_table is large enough
658 int table_size = fp_vmap_table_.size();
buzbee091cc402014-03-31 10:14:40 -0700659 for (int i = table_size; i < (adjusted_reg_num + 1); i++) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700660 fp_vmap_table_.push_back(INVALID_VREG);
661 }
662 // Add the current mapping
buzbee091cc402014-03-31 10:14:40 -0700663 fp_vmap_table_[adjusted_reg_num] = v_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700664 // Size of fp_vmap_table is high-water mark, use to set mask
665 num_fp_spills_ = fp_vmap_table_.size();
666 fp_spill_mask_ = ((1 << num_fp_spills_) - 1) << ARM_FP_CALLEE_SAVE_BASE;
667}
668
buzbee091cc402014-03-31 10:14:40 -0700669void ArmMir2Lir::MarkPreservedDouble(int v_reg, RegStorage reg) {
670 // TEMP: perform as 2 singles.
671 int reg_num = reg.GetRegNum() << 1;
672 RegStorage lo = RegStorage::Solo32(RegStorage::kFloatingPoint | reg_num);
673 RegStorage hi = RegStorage::Solo32(RegStorage::kFloatingPoint | reg_num | 1);
674 MarkPreservedSingle(v_reg, lo);
675 MarkPreservedSingle(v_reg + 1, hi);
buzbee2700f7e2014-03-07 09:46:20 -0800676}
677
Brian Carlstrom7940e442013-07-12 13:46:57 -0700678/* Clobber all regs that might be used by an external C call */
Vladimir Marko31c2aac2013-12-09 16:31:19 +0000679void ArmMir2Lir::ClobberCallerSave() {
buzbee091cc402014-03-31 10:14:40 -0700680 // TODO: rework this - it's gotten even more ugly.
681 Clobber(rs_r0);
682 Clobber(rs_r1);
683 Clobber(rs_r2);
684 Clobber(rs_r3);
685 Clobber(rs_r12);
686 Clobber(rs_r14lr);
687 Clobber(rs_fr0);
688 Clobber(rs_fr1);
689 Clobber(rs_fr2);
690 Clobber(rs_fr3);
691 Clobber(rs_fr4);
692 Clobber(rs_fr5);
693 Clobber(rs_fr6);
694 Clobber(rs_fr7);
695 Clobber(rs_fr8);
696 Clobber(rs_fr9);
697 Clobber(rs_fr10);
698 Clobber(rs_fr11);
699 Clobber(rs_fr12);
700 Clobber(rs_fr13);
701 Clobber(rs_fr14);
702 Clobber(rs_fr15);
703 Clobber(rs_dr0);
704 Clobber(rs_dr1);
705 Clobber(rs_dr2);
706 Clobber(rs_dr3);
707 Clobber(rs_dr4);
708 Clobber(rs_dr5);
709 Clobber(rs_dr6);
710 Clobber(rs_dr7);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700711}
712
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700713RegLocation ArmMir2Lir::GetReturnWideAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700714 RegLocation res = LocCReturnWide();
buzbee091cc402014-03-31 10:14:40 -0700715 res.reg.SetLowReg(rs_r2.GetReg());
716 res.reg.SetHighReg(rs_r3.GetReg());
717 Clobber(rs_r2);
718 Clobber(rs_r3);
719 MarkInUse(rs_r2);
720 MarkInUse(rs_r3);
721 MarkWide(res.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700722 return res;
723}
724
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700725RegLocation ArmMir2Lir::GetReturnAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700726 RegLocation res = LocCReturn();
buzbee091cc402014-03-31 10:14:40 -0700727 res.reg.SetReg(rs_r1.GetReg());
728 Clobber(rs_r1);
729 MarkInUse(rs_r1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700730 return res;
731}
732
Brian Carlstrom7940e442013-07-12 13:46:57 -0700733/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700734void ArmMir2Lir::LockCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700735 LockTemp(rs_r0);
736 LockTemp(rs_r1);
737 LockTemp(rs_r2);
738 LockTemp(rs_r3);
Zheng Xu5667fdb2014-10-23 18:29:55 +0800739 if (!kArm32QuickCodeUseSoftFloat) {
740 LockTemp(rs_fr0);
741 LockTemp(rs_fr1);
742 LockTemp(rs_fr2);
743 LockTemp(rs_fr3);
744 LockTemp(rs_fr4);
745 LockTemp(rs_fr5);
746 LockTemp(rs_fr6);
747 LockTemp(rs_fr7);
748 LockTemp(rs_fr8);
749 LockTemp(rs_fr9);
750 LockTemp(rs_fr10);
751 LockTemp(rs_fr11);
752 LockTemp(rs_fr12);
753 LockTemp(rs_fr13);
754 LockTemp(rs_fr14);
755 LockTemp(rs_fr15);
756 LockTemp(rs_dr0);
757 LockTemp(rs_dr1);
758 LockTemp(rs_dr2);
759 LockTemp(rs_dr3);
760 LockTemp(rs_dr4);
761 LockTemp(rs_dr5);
762 LockTemp(rs_dr6);
763 LockTemp(rs_dr7);
764 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700765}
766
767/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700768void ArmMir2Lir::FreeCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700769 FreeTemp(rs_r0);
770 FreeTemp(rs_r1);
771 FreeTemp(rs_r2);
772 FreeTemp(rs_r3);
Vladimir Markobfe400b2014-12-19 19:27:26 +0000773 FreeTemp(TargetReg(kHiddenArg));
Zheng Xu5667fdb2014-10-23 18:29:55 +0800774 if (!kArm32QuickCodeUseSoftFloat) {
775 FreeTemp(rs_fr0);
776 FreeTemp(rs_fr1);
777 FreeTemp(rs_fr2);
778 FreeTemp(rs_fr3);
779 FreeTemp(rs_fr4);
780 FreeTemp(rs_fr5);
781 FreeTemp(rs_fr6);
782 FreeTemp(rs_fr7);
783 FreeTemp(rs_fr8);
784 FreeTemp(rs_fr9);
785 FreeTemp(rs_fr10);
786 FreeTemp(rs_fr11);
787 FreeTemp(rs_fr12);
788 FreeTemp(rs_fr13);
789 FreeTemp(rs_fr14);
790 FreeTemp(rs_fr15);
791 FreeTemp(rs_dr0);
792 FreeTemp(rs_dr1);
793 FreeTemp(rs_dr2);
794 FreeTemp(rs_dr3);
795 FreeTemp(rs_dr4);
796 FreeTemp(rs_dr5);
797 FreeTemp(rs_dr6);
798 FreeTemp(rs_dr7);
799 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700800}
801
Andreas Gampe98430592014-07-27 19:44:50 -0700802RegStorage ArmMir2Lir::LoadHelper(QuickEntrypointEnum trampoline) {
803 LoadWordDisp(rs_rARM_SELF, GetThreadOffset<4>(trampoline).Int32Value(), rs_rARM_LR);
buzbee2700f7e2014-03-07 09:46:20 -0800804 return rs_rARM_LR;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700805}
806
Dave Allisonb373e092014-02-20 16:06:36 -0800807LIR* ArmMir2Lir::CheckSuspendUsingLoad() {
buzbee2700f7e2014-03-07 09:46:20 -0800808 RegStorage tmp = rs_r0;
buzbee695d13a2014-04-19 13:32:20 -0700809 Load32Disp(rs_rARM_SELF, Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
810 LIR* load2 = Load32Disp(tmp, 0, tmp);
Dave Allisonb373e092014-02-20 16:06:36 -0800811 return load2;
812}
813
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700814uint64_t ArmMir2Lir::GetTargetInstFlags(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700815 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700816 return ArmMir2Lir::EncodingMap[opcode].flags;
817}
818
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700819const char* ArmMir2Lir::GetTargetInstName(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700820 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700821 return ArmMir2Lir::EncodingMap[opcode].name;
822}
823
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700824const char* ArmMir2Lir::GetTargetInstFmt(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700825 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700826 return ArmMir2Lir::EncodingMap[opcode].fmt;
827}
828
buzbee091cc402014-03-31 10:14:40 -0700829/*
830 * Somewhat messy code here. We want to allocate a pair of contiguous
831 * physical single-precision floating point registers starting with
832 * an even numbered reg. It is possible that the paired s_reg (s_reg+1)
833 * has already been allocated - try to fit if possible. Fail to
834 * allocate if we can't meet the requirements for the pair of
835 * s_reg<=sX[even] & (s_reg+1)<= sX+1.
836 */
837// TODO: needs rewrite to support non-backed 64-bit float regs.
838RegStorage ArmMir2Lir::AllocPreservedDouble(int s_reg) {
839 RegStorage res;
840 int v_reg = mir_graph_->SRegToVReg(s_reg);
841 int p_map_idx = SRegToPMap(s_reg);
842 if (promotion_map_[p_map_idx+1].fp_location == kLocPhysReg) {
843 // Upper reg is already allocated. Can we fit?
buzbeeb5860fb2014-06-21 15:31:01 -0700844 int high_reg = promotion_map_[p_map_idx+1].fp_reg;
buzbee091cc402014-03-31 10:14:40 -0700845 if ((high_reg & 1) == 0) {
846 // High reg is even - fail.
847 return res; // Invalid.
848 }
849 // Is the low reg of the pair free?
850 // FIXME: rework.
851 RegisterInfo* p = GetRegInfo(RegStorage::FloatSolo32(high_reg - 1));
852 if (p->InUse() || p->IsTemp()) {
853 // Already allocated or not preserved - fail.
854 return res; // Invalid.
855 }
856 // OK - good to go.
857 res = RegStorage::FloatSolo64(p->GetReg().GetRegNum() >> 1);
858 p->MarkInUse();
859 MarkPreservedSingle(v_reg, p->GetReg());
860 } else {
861 /*
862 * TODO: until runtime support is in, make sure we avoid promoting the same vreg to
863 * different underlying physical registers.
864 */
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100865 for (RegisterInfo* info : reg_pool_->dp_regs_) {
buzbee091cc402014-03-31 10:14:40 -0700866 if (!info->IsTemp() && !info->InUse()) {
867 res = info->GetReg();
868 info->MarkInUse();
869 MarkPreservedDouble(v_reg, info->GetReg());
870 break;
871 }
872 }
873 }
874 if (res.Valid()) {
buzbee85089dd2014-05-25 15:10:52 -0700875 RegisterInfo* info = GetRegInfo(res);
buzbee091cc402014-03-31 10:14:40 -0700876 promotion_map_[p_map_idx].fp_location = kLocPhysReg;
buzbeeb5860fb2014-06-21 15:31:01 -0700877 promotion_map_[p_map_idx].fp_reg =
buzbee85089dd2014-05-25 15:10:52 -0700878 info->FindMatchingView(RegisterInfo::kLowSingleStorageMask)->GetReg().GetReg();
buzbee091cc402014-03-31 10:14:40 -0700879 promotion_map_[p_map_idx+1].fp_location = kLocPhysReg;
buzbeeb5860fb2014-06-21 15:31:01 -0700880 promotion_map_[p_map_idx+1].fp_reg =
buzbee85089dd2014-05-25 15:10:52 -0700881 info->FindMatchingView(RegisterInfo::kHighSingleStorageMask)->GetReg().GetReg();
buzbee091cc402014-03-31 10:14:40 -0700882 }
883 return res;
884}
885
buzbeeb5860fb2014-06-21 15:31:01 -0700886// Reserve a callee-save sp single register.
887RegStorage ArmMir2Lir::AllocPreservedSingle(int s_reg) {
888 RegStorage res;
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100889 for (RegisterInfo* info : reg_pool_->sp_regs_) {
buzbeeb5860fb2014-06-21 15:31:01 -0700890 if (!info->IsTemp() && !info->InUse()) {
891 res = info->GetReg();
892 int p_map_idx = SRegToPMap(s_reg);
893 int v_reg = mir_graph_->SRegToVReg(s_reg);
894 GetRegInfo(res)->MarkInUse();
895 MarkPreservedSingle(v_reg, res);
896 promotion_map_[p_map_idx].fp_location = kLocPhysReg;
897 promotion_map_[p_map_idx].fp_reg = res.GetReg();
898 break;
899 }
900 }
901 return res;
902}
903
Vladimir Markof4da6752014-08-01 19:04:18 +0100904void ArmMir2Lir::InstallLiteralPools() {
Vladimir Markoe5c76c52015-04-06 12:10:19 +0100905 patches_.reserve(call_method_insns_.size() + dex_cache_access_insns_.size());
906
Vladimir Markof4da6752014-08-01 19:04:18 +0100907 // PC-relative calls to methods.
Vladimir Markof4da6752014-08-01 19:04:18 +0100908 for (LIR* p : call_method_insns_) {
Vladimir Markoe5c76c52015-04-06 12:10:19 +0100909 DCHECK_EQ(p->opcode, kThumb2Bl);
910 uint32_t target_method_idx = p->operands[1];
911 const DexFile* target_dex_file = UnwrapPointer<DexFile>(p->operands[2]);
912 patches_.push_back(LinkerPatch::RelativeCodePatch(p->offset,
913 target_dex_file, target_method_idx));
914 }
915
916 // PC-relative dex cache array accesses.
917 for (LIR* p : dex_cache_access_insns_) {
918 DCHECK(p->opcode = kThumb2MovImm16 || p->opcode == kThumb2MovImm16H);
919 const LIR* add_pc = UnwrapPointer<LIR>(p->operands[4]);
920 DCHECK(add_pc->opcode == kThumbAddRRLH || add_pc->opcode == kThumbAddRRHH);
921 const DexFile* dex_file = UnwrapPointer<DexFile>(p->operands[2]);
922 uint32_t offset = p->operands[3];
923 DCHECK(!p->flags.is_nop);
924 DCHECK(!add_pc->flags.is_nop);
925 patches_.push_back(LinkerPatch::DexCacheArrayPatch(p->offset,
926 dex_file, add_pc->offset, offset));
Vladimir Markof4da6752014-08-01 19:04:18 +0100927 }
928
929 // And do the normal processing.
930 Mir2Lir::InstallLiteralPools();
931}
932
Serguei Katkov717a3e42014-11-13 17:19:42 +0600933RegStorage ArmMir2Lir::InToRegStorageArmMapper::GetNextReg(ShortyArg arg) {
Zheng Xu5667fdb2014-10-23 18:29:55 +0800934 const RegStorage coreArgMappingToPhysicalReg[] =
935 {rs_r1, rs_r2, rs_r3};
936 const int coreArgMappingToPhysicalRegSize = arraysize(coreArgMappingToPhysicalReg);
937 const RegStorage fpArgMappingToPhysicalReg[] =
938 {rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7,
939 rs_fr8, rs_fr9, rs_fr10, rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15};
Andreas Gampe785d2f22014-11-03 22:57:30 -0800940 constexpr uint32_t fpArgMappingToPhysicalRegSize = arraysize(fpArgMappingToPhysicalReg);
941 static_assert(fpArgMappingToPhysicalRegSize % 2 == 0, "Number of FP Arg regs is not even");
Zheng Xu5667fdb2014-10-23 18:29:55 +0800942
Zheng Xu5667fdb2014-10-23 18:29:55 +0800943 RegStorage result = RegStorage::InvalidReg();
Serguei Katkov717a3e42014-11-13 17:19:42 +0600944 // Regard double as long, float as int for kArm32QuickCodeUseSoftFloat.
945 if (arg.IsFP() && !kArm32QuickCodeUseSoftFloat) {
946 if (arg.IsWide()) {
Zheng Xu5667fdb2014-10-23 18:29:55 +0800947 cur_fp_double_reg_ = std::max(cur_fp_double_reg_, RoundUp(cur_fp_reg_, 2));
948 if (cur_fp_double_reg_ < fpArgMappingToPhysicalRegSize) {
Serguei Katkov717a3e42014-11-13 17:19:42 +0600949 result = RegStorage::MakeRegPair(fpArgMappingToPhysicalReg[cur_fp_double_reg_],
950 fpArgMappingToPhysicalReg[cur_fp_double_reg_ + 1]);
951 result = As64BitFloatReg(result);
952 cur_fp_double_reg_ += 2;
Zheng Xu5667fdb2014-10-23 18:29:55 +0800953 }
954 } else {
Zheng Xu5667fdb2014-10-23 18:29:55 +0800955 if (cur_fp_reg_ % 2 == 0) {
956 cur_fp_reg_ = std::max(cur_fp_double_reg_, cur_fp_reg_);
957 }
958 if (cur_fp_reg_ < fpArgMappingToPhysicalRegSize) {
959 result = fpArgMappingToPhysicalReg[cur_fp_reg_];
960 cur_fp_reg_++;
961 }
962 }
963 } else {
964 if (cur_core_reg_ < coreArgMappingToPhysicalRegSize) {
Nicolas Geoffray69c15d32015-01-13 11:42:13 +0000965 if (!kArm32QuickCodeUseSoftFloat && arg.IsWide() && cur_core_reg_ == 0) {
966 // Skip r1, and use r2-r3 for the register pair.
967 cur_core_reg_++;
968 }
Zheng Xu5667fdb2014-10-23 18:29:55 +0800969 result = coreArgMappingToPhysicalReg[cur_core_reg_++];
Serguei Katkov717a3e42014-11-13 17:19:42 +0600970 if (arg.IsWide() && cur_core_reg_ < coreArgMappingToPhysicalRegSize) {
971 result = RegStorage::MakeRegPair(result, coreArgMappingToPhysicalReg[cur_core_reg_++]);
972 }
Zheng Xu5667fdb2014-10-23 18:29:55 +0800973 }
974 }
975 return result;
976}
977
Serguei Katkov717a3e42014-11-13 17:19:42 +0600978int ArmMir2Lir::GenDalvikArgsBulkCopy(CallInfo* info, int first, int count) {
Zheng Xu5667fdb2014-10-23 18:29:55 +0800979 if (kArm32QuickCodeUseSoftFloat) {
Serguei Katkov717a3e42014-11-13 17:19:42 +0600980 return Mir2Lir::GenDalvikArgsBulkCopy(info, first, count);
Zheng Xu5667fdb2014-10-23 18:29:55 +0800981 }
Serguei Katkov717a3e42014-11-13 17:19:42 +0600982 /*
983 * TODO: Improve by adding block copy for large number of arguments. For now, just
984 * copy a Dalvik vreg at a time.
985 */
986 return count;
Zheng Xu5667fdb2014-10-23 18:29:55 +0800987}
988
Ningsheng Jiana262f772014-11-25 16:48:07 +0800989void ArmMir2Lir::GenMachineSpecificExtendedMethodMIR(BasicBlock* bb, MIR* mir) {
990 UNUSED(bb);
991 DCHECK(MIR::DecodedInstruction::IsPseudoMirOp(mir->dalvikInsn.opcode));
992 RegLocation rl_src[3];
993 RegLocation rl_dest = mir_graph_->GetBadLoc();
994 rl_src[0] = rl_src[1] = rl_src[2] = mir_graph_->GetBadLoc();
995 switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) {
996 case kMirOpMaddInt:
997 rl_dest = mir_graph_->GetDest(mir);
998 rl_src[0] = mir_graph_->GetSrc(mir, 0);
999 rl_src[1] = mir_graph_->GetSrc(mir, 1);
1000 rl_src[2]= mir_graph_->GetSrc(mir, 2);
1001 GenMaddMsubInt(rl_dest, rl_src[0], rl_src[1], rl_src[2], false);
1002 break;
1003 case kMirOpMsubInt:
1004 rl_dest = mir_graph_->GetDest(mir);
1005 rl_src[0] = mir_graph_->GetSrc(mir, 0);
1006 rl_src[1] = mir_graph_->GetSrc(mir, 1);
1007 rl_src[2]= mir_graph_->GetSrc(mir, 2);
1008 GenMaddMsubInt(rl_dest, rl_src[0], rl_src[1], rl_src[2], true);
1009 break;
1010 default:
1011 LOG(FATAL) << "Unexpected opcode: " << mir->dalvikInsn.opcode;
1012 }
1013}
1014
Brian Carlstrom7940e442013-07-12 13:46:57 -07001015} // namespace art