blob: 13f9072bbe5d0b1ccdd6f9ce682910c494875204 [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]),
458 *reinterpret_cast<const DexFile*>(UnwrapPointer(lir->operands[2]))).c_str());
459 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),
578 call_method_insns_(arena->Adapter()) {
579 call_method_insns_.reserve(100);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700580 // Sanity check - make sure encoding map lines up.
581 for (int i = 0; i < kArmLast; i++) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700582 DCHECK_EQ(ArmMir2Lir::EncodingMap[i].opcode, i)
583 << "Encoding order for " << ArmMir2Lir::EncodingMap[i].name
584 << " is wrong: expecting " << i << ", seeing "
585 << static_cast<int>(ArmMir2Lir::EncodingMap[i].opcode);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700586 }
587}
588
589Mir2Lir* ArmCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
590 ArenaAllocator* const arena) {
591 return new ArmMir2Lir(cu, mir_graph, arena);
592}
593
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700594void ArmMir2Lir::CompilerInitializeRegAlloc() {
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100595 reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs, empty_pool /* core64 */,
596 sp_regs, dp_regs,
597 reserved_regs, empty_pool /* reserved64 */,
598 core_temps, empty_pool /* core64_temps */,
599 sp_temps, dp_temps));
Dave Allisonf6b65c12014-04-01 17:45:18 -0700600
buzbee091cc402014-03-31 10:14:40 -0700601 // Target-specific adjustments.
602
603 // Alias single precision floats to appropriate half of overlapping double.
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100604 for (RegisterInfo* info : reg_pool_->sp_regs_) {
buzbee091cc402014-03-31 10:14:40 -0700605 int sp_reg_num = info->GetReg().GetRegNum();
606 int dp_reg_num = sp_reg_num >> 1;
607 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
608 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
609 // Double precision register's master storage should refer to itself.
610 DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
611 // Redirect single precision's master storage to master.
612 info->SetMaster(dp_reg_info);
613 // Singles should show a single 32-bit mask bit, at first referring to the low half.
buzbee85089dd2014-05-25 15:10:52 -0700614 DCHECK_EQ(info->StorageMask(), RegisterInfo::kLowSingleStorageMask);
buzbee091cc402014-03-31 10:14:40 -0700615 if (sp_reg_num & 1) {
buzbee85089dd2014-05-25 15:10:52 -0700616 // For odd singles, change to use the high word of the backing double.
617 info->SetStorageMask(RegisterInfo::kHighSingleStorageMask);
buzbee091cc402014-03-31 10:14:40 -0700618 }
619 }
620
Wei Jin04f4d8a2014-05-29 18:04:29 -0700621#ifdef ARM_R4_SUSPEND_FLAG
Dave Allison83252962014-04-03 16:33:48 -0700622 // TODO: re-enable this when we can safely save r4 over the suspension code path.
623 bool no_suspend = NO_SUSPEND; // || !Runtime::Current()->ExplicitSuspendChecks();
buzbee091cc402014-03-31 10:14:40 -0700624 if (no_suspend) {
625 GetRegInfo(rs_rARM_SUSPEND)->MarkFree();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700626 }
Wei Jin04f4d8a2014-05-29 18:04:29 -0700627#endif
Brian Carlstrom7940e442013-07-12 13:46:57 -0700628
buzbee091cc402014-03-31 10:14:40 -0700629 // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
630 // TODO: adjust when we roll to hard float calling convention.
631 reg_pool_->next_core_reg_ = 2;
632 reg_pool_->next_sp_reg_ = 0;
633 reg_pool_->next_dp_reg_ = 0;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700634}
635
Brian Carlstrom7940e442013-07-12 13:46:57 -0700636/*
637 * TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some
638 * instructions might call out to C/assembly helper functions. Until
639 * machinery is in place, always spill lr.
640 */
641
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700642void ArmMir2Lir::AdjustSpillMask() {
buzbee091cc402014-03-31 10:14:40 -0700643 core_spill_mask_ |= (1 << rs_rARM_LR.GetRegNum());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700644 num_core_spills_++;
645}
646
647/*
648 * Mark a callee-save fp register as promoted. Note that
649 * vpush/vpop uses contiguous register lists so we must
650 * include any holes in the mask. Associate holes with
651 * Dalvik register INVALID_VREG (0xFFFFU).
652 */
buzbee091cc402014-03-31 10:14:40 -0700653void ArmMir2Lir::MarkPreservedSingle(int v_reg, RegStorage reg) {
654 DCHECK_GE(reg.GetRegNum(), ARM_FP_CALLEE_SAVE_BASE);
655 int adjusted_reg_num = reg.GetRegNum() - ARM_FP_CALLEE_SAVE_BASE;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700656 // Ensure fp_vmap_table is large enough
657 int table_size = fp_vmap_table_.size();
buzbee091cc402014-03-31 10:14:40 -0700658 for (int i = table_size; i < (adjusted_reg_num + 1); i++) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700659 fp_vmap_table_.push_back(INVALID_VREG);
660 }
661 // Add the current mapping
buzbee091cc402014-03-31 10:14:40 -0700662 fp_vmap_table_[adjusted_reg_num] = v_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700663 // Size of fp_vmap_table is high-water mark, use to set mask
664 num_fp_spills_ = fp_vmap_table_.size();
665 fp_spill_mask_ = ((1 << num_fp_spills_) - 1) << ARM_FP_CALLEE_SAVE_BASE;
666}
667
buzbee091cc402014-03-31 10:14:40 -0700668void ArmMir2Lir::MarkPreservedDouble(int v_reg, RegStorage reg) {
669 // TEMP: perform as 2 singles.
670 int reg_num = reg.GetRegNum() << 1;
671 RegStorage lo = RegStorage::Solo32(RegStorage::kFloatingPoint | reg_num);
672 RegStorage hi = RegStorage::Solo32(RegStorage::kFloatingPoint | reg_num | 1);
673 MarkPreservedSingle(v_reg, lo);
674 MarkPreservedSingle(v_reg + 1, hi);
buzbee2700f7e2014-03-07 09:46:20 -0800675}
676
Brian Carlstrom7940e442013-07-12 13:46:57 -0700677/* Clobber all regs that might be used by an external C call */
Vladimir Marko31c2aac2013-12-09 16:31:19 +0000678void ArmMir2Lir::ClobberCallerSave() {
buzbee091cc402014-03-31 10:14:40 -0700679 // TODO: rework this - it's gotten even more ugly.
680 Clobber(rs_r0);
681 Clobber(rs_r1);
682 Clobber(rs_r2);
683 Clobber(rs_r3);
684 Clobber(rs_r12);
685 Clobber(rs_r14lr);
686 Clobber(rs_fr0);
687 Clobber(rs_fr1);
688 Clobber(rs_fr2);
689 Clobber(rs_fr3);
690 Clobber(rs_fr4);
691 Clobber(rs_fr5);
692 Clobber(rs_fr6);
693 Clobber(rs_fr7);
694 Clobber(rs_fr8);
695 Clobber(rs_fr9);
696 Clobber(rs_fr10);
697 Clobber(rs_fr11);
698 Clobber(rs_fr12);
699 Clobber(rs_fr13);
700 Clobber(rs_fr14);
701 Clobber(rs_fr15);
702 Clobber(rs_dr0);
703 Clobber(rs_dr1);
704 Clobber(rs_dr2);
705 Clobber(rs_dr3);
706 Clobber(rs_dr4);
707 Clobber(rs_dr5);
708 Clobber(rs_dr6);
709 Clobber(rs_dr7);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700710}
711
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700712RegLocation ArmMir2Lir::GetReturnWideAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700713 RegLocation res = LocCReturnWide();
buzbee091cc402014-03-31 10:14:40 -0700714 res.reg.SetLowReg(rs_r2.GetReg());
715 res.reg.SetHighReg(rs_r3.GetReg());
716 Clobber(rs_r2);
717 Clobber(rs_r3);
718 MarkInUse(rs_r2);
719 MarkInUse(rs_r3);
720 MarkWide(res.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700721 return res;
722}
723
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700724RegLocation ArmMir2Lir::GetReturnAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700725 RegLocation res = LocCReturn();
buzbee091cc402014-03-31 10:14:40 -0700726 res.reg.SetReg(rs_r1.GetReg());
727 Clobber(rs_r1);
728 MarkInUse(rs_r1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700729 return res;
730}
731
Brian Carlstrom7940e442013-07-12 13:46:57 -0700732/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700733void ArmMir2Lir::LockCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700734 LockTemp(rs_r0);
735 LockTemp(rs_r1);
736 LockTemp(rs_r2);
737 LockTemp(rs_r3);
Zheng Xu5667fdb2014-10-23 18:29:55 +0800738 if (!kArm32QuickCodeUseSoftFloat) {
739 LockTemp(rs_fr0);
740 LockTemp(rs_fr1);
741 LockTemp(rs_fr2);
742 LockTemp(rs_fr3);
743 LockTemp(rs_fr4);
744 LockTemp(rs_fr5);
745 LockTemp(rs_fr6);
746 LockTemp(rs_fr7);
747 LockTemp(rs_fr8);
748 LockTemp(rs_fr9);
749 LockTemp(rs_fr10);
750 LockTemp(rs_fr11);
751 LockTemp(rs_fr12);
752 LockTemp(rs_fr13);
753 LockTemp(rs_fr14);
754 LockTemp(rs_fr15);
755 LockTemp(rs_dr0);
756 LockTemp(rs_dr1);
757 LockTemp(rs_dr2);
758 LockTemp(rs_dr3);
759 LockTemp(rs_dr4);
760 LockTemp(rs_dr5);
761 LockTemp(rs_dr6);
762 LockTemp(rs_dr7);
763 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700764}
765
766/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700767void ArmMir2Lir::FreeCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700768 FreeTemp(rs_r0);
769 FreeTemp(rs_r1);
770 FreeTemp(rs_r2);
771 FreeTemp(rs_r3);
Vladimir Markobfe400b2014-12-19 19:27:26 +0000772 FreeTemp(TargetReg(kHiddenArg));
Zheng Xu5667fdb2014-10-23 18:29:55 +0800773 if (!kArm32QuickCodeUseSoftFloat) {
774 FreeTemp(rs_fr0);
775 FreeTemp(rs_fr1);
776 FreeTemp(rs_fr2);
777 FreeTemp(rs_fr3);
778 FreeTemp(rs_fr4);
779 FreeTemp(rs_fr5);
780 FreeTemp(rs_fr6);
781 FreeTemp(rs_fr7);
782 FreeTemp(rs_fr8);
783 FreeTemp(rs_fr9);
784 FreeTemp(rs_fr10);
785 FreeTemp(rs_fr11);
786 FreeTemp(rs_fr12);
787 FreeTemp(rs_fr13);
788 FreeTemp(rs_fr14);
789 FreeTemp(rs_fr15);
790 FreeTemp(rs_dr0);
791 FreeTemp(rs_dr1);
792 FreeTemp(rs_dr2);
793 FreeTemp(rs_dr3);
794 FreeTemp(rs_dr4);
795 FreeTemp(rs_dr5);
796 FreeTemp(rs_dr6);
797 FreeTemp(rs_dr7);
798 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700799}
800
Andreas Gampe98430592014-07-27 19:44:50 -0700801RegStorage ArmMir2Lir::LoadHelper(QuickEntrypointEnum trampoline) {
802 LoadWordDisp(rs_rARM_SELF, GetThreadOffset<4>(trampoline).Int32Value(), rs_rARM_LR);
buzbee2700f7e2014-03-07 09:46:20 -0800803 return rs_rARM_LR;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700804}
805
Dave Allisonb373e092014-02-20 16:06:36 -0800806LIR* ArmMir2Lir::CheckSuspendUsingLoad() {
buzbee2700f7e2014-03-07 09:46:20 -0800807 RegStorage tmp = rs_r0;
buzbee695d13a2014-04-19 13:32:20 -0700808 Load32Disp(rs_rARM_SELF, Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
809 LIR* load2 = Load32Disp(tmp, 0, tmp);
Dave Allisonb373e092014-02-20 16:06:36 -0800810 return load2;
811}
812
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700813uint64_t ArmMir2Lir::GetTargetInstFlags(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700814 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700815 return ArmMir2Lir::EncodingMap[opcode].flags;
816}
817
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700818const char* ArmMir2Lir::GetTargetInstName(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700819 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700820 return ArmMir2Lir::EncodingMap[opcode].name;
821}
822
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700823const char* ArmMir2Lir::GetTargetInstFmt(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700824 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700825 return ArmMir2Lir::EncodingMap[opcode].fmt;
826}
827
buzbee091cc402014-03-31 10:14:40 -0700828/*
829 * Somewhat messy code here. We want to allocate a pair of contiguous
830 * physical single-precision floating point registers starting with
831 * an even numbered reg. It is possible that the paired s_reg (s_reg+1)
832 * has already been allocated - try to fit if possible. Fail to
833 * allocate if we can't meet the requirements for the pair of
834 * s_reg<=sX[even] & (s_reg+1)<= sX+1.
835 */
836// TODO: needs rewrite to support non-backed 64-bit float regs.
837RegStorage ArmMir2Lir::AllocPreservedDouble(int s_reg) {
838 RegStorage res;
839 int v_reg = mir_graph_->SRegToVReg(s_reg);
840 int p_map_idx = SRegToPMap(s_reg);
841 if (promotion_map_[p_map_idx+1].fp_location == kLocPhysReg) {
842 // Upper reg is already allocated. Can we fit?
buzbeeb5860fb2014-06-21 15:31:01 -0700843 int high_reg = promotion_map_[p_map_idx+1].fp_reg;
buzbee091cc402014-03-31 10:14:40 -0700844 if ((high_reg & 1) == 0) {
845 // High reg is even - fail.
846 return res; // Invalid.
847 }
848 // Is the low reg of the pair free?
849 // FIXME: rework.
850 RegisterInfo* p = GetRegInfo(RegStorage::FloatSolo32(high_reg - 1));
851 if (p->InUse() || p->IsTemp()) {
852 // Already allocated or not preserved - fail.
853 return res; // Invalid.
854 }
855 // OK - good to go.
856 res = RegStorage::FloatSolo64(p->GetReg().GetRegNum() >> 1);
857 p->MarkInUse();
858 MarkPreservedSingle(v_reg, p->GetReg());
859 } else {
860 /*
861 * TODO: until runtime support is in, make sure we avoid promoting the same vreg to
862 * different underlying physical registers.
863 */
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100864 for (RegisterInfo* info : reg_pool_->dp_regs_) {
buzbee091cc402014-03-31 10:14:40 -0700865 if (!info->IsTemp() && !info->InUse()) {
866 res = info->GetReg();
867 info->MarkInUse();
868 MarkPreservedDouble(v_reg, info->GetReg());
869 break;
870 }
871 }
872 }
873 if (res.Valid()) {
buzbee85089dd2014-05-25 15:10:52 -0700874 RegisterInfo* info = GetRegInfo(res);
buzbee091cc402014-03-31 10:14:40 -0700875 promotion_map_[p_map_idx].fp_location = kLocPhysReg;
buzbeeb5860fb2014-06-21 15:31:01 -0700876 promotion_map_[p_map_idx].fp_reg =
buzbee85089dd2014-05-25 15:10:52 -0700877 info->FindMatchingView(RegisterInfo::kLowSingleStorageMask)->GetReg().GetReg();
buzbee091cc402014-03-31 10:14:40 -0700878 promotion_map_[p_map_idx+1].fp_location = kLocPhysReg;
buzbeeb5860fb2014-06-21 15:31:01 -0700879 promotion_map_[p_map_idx+1].fp_reg =
buzbee85089dd2014-05-25 15:10:52 -0700880 info->FindMatchingView(RegisterInfo::kHighSingleStorageMask)->GetReg().GetReg();
buzbee091cc402014-03-31 10:14:40 -0700881 }
882 return res;
883}
884
buzbeeb5860fb2014-06-21 15:31:01 -0700885// Reserve a callee-save sp single register.
886RegStorage ArmMir2Lir::AllocPreservedSingle(int s_reg) {
887 RegStorage res;
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100888 for (RegisterInfo* info : reg_pool_->sp_regs_) {
buzbeeb5860fb2014-06-21 15:31:01 -0700889 if (!info->IsTemp() && !info->InUse()) {
890 res = info->GetReg();
891 int p_map_idx = SRegToPMap(s_reg);
892 int v_reg = mir_graph_->SRegToVReg(s_reg);
893 GetRegInfo(res)->MarkInUse();
894 MarkPreservedSingle(v_reg, res);
895 promotion_map_[p_map_idx].fp_location = kLocPhysReg;
896 promotion_map_[p_map_idx].fp_reg = res.GetReg();
897 break;
898 }
899 }
900 return res;
901}
902
Vladimir Markof4da6752014-08-01 19:04:18 +0100903void ArmMir2Lir::InstallLiteralPools() {
904 // PC-relative calls to methods.
905 patches_.reserve(call_method_insns_.size());
906 for (LIR* p : call_method_insns_) {
907 DCHECK_EQ(p->opcode, kThumb2Bl);
908 uint32_t target_method_idx = p->operands[1];
909 const DexFile* target_dex_file =
910 reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[2]));
911
912 patches_.push_back(LinkerPatch::RelativeCodePatch(p->offset,
913 target_dex_file, target_method_idx));
914 }
915
916 // And do the normal processing.
917 Mir2Lir::InstallLiteralPools();
918}
919
Serguei Katkov717a3e42014-11-13 17:19:42 +0600920RegStorage ArmMir2Lir::InToRegStorageArmMapper::GetNextReg(ShortyArg arg) {
Zheng Xu5667fdb2014-10-23 18:29:55 +0800921 const RegStorage coreArgMappingToPhysicalReg[] =
922 {rs_r1, rs_r2, rs_r3};
923 const int coreArgMappingToPhysicalRegSize = arraysize(coreArgMappingToPhysicalReg);
924 const RegStorage fpArgMappingToPhysicalReg[] =
925 {rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7,
926 rs_fr8, rs_fr9, rs_fr10, rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15};
Andreas Gampe785d2f22014-11-03 22:57:30 -0800927 constexpr uint32_t fpArgMappingToPhysicalRegSize = arraysize(fpArgMappingToPhysicalReg);
928 static_assert(fpArgMappingToPhysicalRegSize % 2 == 0, "Number of FP Arg regs is not even");
Zheng Xu5667fdb2014-10-23 18:29:55 +0800929
Zheng Xu5667fdb2014-10-23 18:29:55 +0800930 RegStorage result = RegStorage::InvalidReg();
Serguei Katkov717a3e42014-11-13 17:19:42 +0600931 // Regard double as long, float as int for kArm32QuickCodeUseSoftFloat.
932 if (arg.IsFP() && !kArm32QuickCodeUseSoftFloat) {
933 if (arg.IsWide()) {
Zheng Xu5667fdb2014-10-23 18:29:55 +0800934 cur_fp_double_reg_ = std::max(cur_fp_double_reg_, RoundUp(cur_fp_reg_, 2));
935 if (cur_fp_double_reg_ < fpArgMappingToPhysicalRegSize) {
Serguei Katkov717a3e42014-11-13 17:19:42 +0600936 result = RegStorage::MakeRegPair(fpArgMappingToPhysicalReg[cur_fp_double_reg_],
937 fpArgMappingToPhysicalReg[cur_fp_double_reg_ + 1]);
938 result = As64BitFloatReg(result);
939 cur_fp_double_reg_ += 2;
Zheng Xu5667fdb2014-10-23 18:29:55 +0800940 }
941 } else {
Zheng Xu5667fdb2014-10-23 18:29:55 +0800942 if (cur_fp_reg_ % 2 == 0) {
943 cur_fp_reg_ = std::max(cur_fp_double_reg_, cur_fp_reg_);
944 }
945 if (cur_fp_reg_ < fpArgMappingToPhysicalRegSize) {
946 result = fpArgMappingToPhysicalReg[cur_fp_reg_];
947 cur_fp_reg_++;
948 }
949 }
950 } else {
951 if (cur_core_reg_ < coreArgMappingToPhysicalRegSize) {
Nicolas Geoffray69c15d32015-01-13 11:42:13 +0000952 if (!kArm32QuickCodeUseSoftFloat && arg.IsWide() && cur_core_reg_ == 0) {
953 // Skip r1, and use r2-r3 for the register pair.
954 cur_core_reg_++;
955 }
Zheng Xu5667fdb2014-10-23 18:29:55 +0800956 result = coreArgMappingToPhysicalReg[cur_core_reg_++];
Serguei Katkov717a3e42014-11-13 17:19:42 +0600957 if (arg.IsWide() && cur_core_reg_ < coreArgMappingToPhysicalRegSize) {
958 result = RegStorage::MakeRegPair(result, coreArgMappingToPhysicalReg[cur_core_reg_++]);
959 }
Zheng Xu5667fdb2014-10-23 18:29:55 +0800960 }
961 }
962 return result;
963}
964
Serguei Katkov717a3e42014-11-13 17:19:42 +0600965int ArmMir2Lir::GenDalvikArgsBulkCopy(CallInfo* info, int first, int count) {
Zheng Xu5667fdb2014-10-23 18:29:55 +0800966 if (kArm32QuickCodeUseSoftFloat) {
Serguei Katkov717a3e42014-11-13 17:19:42 +0600967 return Mir2Lir::GenDalvikArgsBulkCopy(info, first, count);
Zheng Xu5667fdb2014-10-23 18:29:55 +0800968 }
Serguei Katkov717a3e42014-11-13 17:19:42 +0600969 /*
970 * TODO: Improve by adding block copy for large number of arguments. For now, just
971 * copy a Dalvik vreg at a time.
972 */
973 return count;
Zheng Xu5667fdb2014-10-23 18:29:55 +0800974}
975
Ningsheng Jiana262f772014-11-25 16:48:07 +0800976void ArmMir2Lir::GenMachineSpecificExtendedMethodMIR(BasicBlock* bb, MIR* mir) {
977 UNUSED(bb);
978 DCHECK(MIR::DecodedInstruction::IsPseudoMirOp(mir->dalvikInsn.opcode));
979 RegLocation rl_src[3];
980 RegLocation rl_dest = mir_graph_->GetBadLoc();
981 rl_src[0] = rl_src[1] = rl_src[2] = mir_graph_->GetBadLoc();
982 switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) {
983 case kMirOpMaddInt:
984 rl_dest = mir_graph_->GetDest(mir);
985 rl_src[0] = mir_graph_->GetSrc(mir, 0);
986 rl_src[1] = mir_graph_->GetSrc(mir, 1);
987 rl_src[2]= mir_graph_->GetSrc(mir, 2);
988 GenMaddMsubInt(rl_dest, rl_src[0], rl_src[1], rl_src[2], false);
989 break;
990 case kMirOpMsubInt:
991 rl_dest = mir_graph_->GetDest(mir);
992 rl_src[0] = mir_graph_->GetSrc(mir, 0);
993 rl_src[1] = mir_graph_->GetSrc(mir, 1);
994 rl_src[2]= mir_graph_->GetSrc(mir, 2);
995 GenMaddMsubInt(rl_dest, rl_src[0], rl_src[1], rl_src[2], true);
996 break;
997 default:
998 LOG(FATAL) << "Unexpected opcode: " << mir->dalvikInsn.opcode;
999 }
1000}
1001
Brian Carlstrom7940e442013-07-12 13:46:57 -07001002} // namespace art