blob: 5538d798b2fd7b037c76399abcee989b2ce1edcc [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>
22
Andreas Gampe53c913b2014-08-12 23:19:23 -070023#include "backend_arm.h"
Andreas Gampe0b9203e2015-01-22 20:39:27 -080024#include "base/logging.h"
25#include "dex/mir_graph.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070026#include "dex/quick/mir_to_lir-inl.h"
27
28namespace art {
29
Wei Jin04f4d8a2014-05-29 18:04:29 -070030#ifdef ARM_R4_SUSPEND_FLAG
Vladimir Marko089142c2014-06-05 10:57:05 +010031static constexpr RegStorage core_regs_arr[] =
buzbee091cc402014-03-31 10:14:40 -070032 {rs_r0, rs_r1, rs_r2, rs_r3, rs_rARM_SUSPEND, rs_r5, rs_r6, rs_r7, rs_r8, rs_rARM_SELF,
33 rs_r10, rs_r11, rs_r12, rs_rARM_SP, rs_rARM_LR, rs_rARM_PC};
Wei Jin04f4d8a2014-05-29 18:04:29 -070034#else
35static constexpr RegStorage core_regs_arr[] =
36 {rs_r0, rs_r1, rs_r2, rs_r3, rs_r4, rs_r5, rs_r6, rs_r7, rs_r8, rs_rARM_SELF,
37 rs_r10, rs_r11, rs_r12, rs_rARM_SP, rs_rARM_LR, rs_rARM_PC};
38#endif
Vladimir Marko089142c2014-06-05 10:57:05 +010039static constexpr RegStorage sp_regs_arr[] =
buzbee091cc402014-03-31 10:14:40 -070040 {rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, rs_fr8, rs_fr9, rs_fr10,
41 rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15, rs_fr16, rs_fr17, rs_fr18, rs_fr19, rs_fr20,
42 rs_fr21, rs_fr22, rs_fr23, rs_fr24, rs_fr25, rs_fr26, rs_fr27, rs_fr28, rs_fr29, rs_fr30,
43 rs_fr31};
Vladimir Marko089142c2014-06-05 10:57:05 +010044static constexpr RegStorage dp_regs_arr[] =
buzbee091cc402014-03-31 10:14:40 -070045 {rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, rs_dr8, rs_dr9, rs_dr10,
46 rs_dr11, rs_dr12, rs_dr13, rs_dr14, rs_dr15};
Wei Jin04f4d8a2014-05-29 18:04:29 -070047#ifdef ARM_R4_SUSPEND_FLAG
Vladimir Marko089142c2014-06-05 10:57:05 +010048static constexpr RegStorage reserved_regs_arr[] =
buzbee091cc402014-03-31 10:14:40 -070049 {rs_rARM_SUSPEND, rs_rARM_SELF, rs_rARM_SP, rs_rARM_LR, rs_rARM_PC};
Vladimir Marko089142c2014-06-05 10:57:05 +010050static constexpr RegStorage core_temps_arr[] = {rs_r0, rs_r1, rs_r2, rs_r3, rs_r12};
Wei Jin04f4d8a2014-05-29 18:04:29 -070051#else
52static constexpr RegStorage reserved_regs_arr[] =
53 {rs_rARM_SELF, rs_rARM_SP, rs_rARM_LR, rs_rARM_PC};
54static constexpr RegStorage core_temps_arr[] = {rs_r0, rs_r1, rs_r2, rs_r3, rs_r4, rs_r12};
55#endif
Vladimir Marko089142c2014-06-05 10:57:05 +010056static constexpr RegStorage sp_temps_arr[] =
buzbee091cc402014-03-31 10:14:40 -070057 {rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, rs_fr8, rs_fr9, rs_fr10,
58 rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15};
Vladimir Marko089142c2014-06-05 10:57:05 +010059static constexpr RegStorage dp_temps_arr[] =
buzbee091cc402014-03-31 10:14:40 -070060 {rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7};
61
Vladimir Marko089142c2014-06-05 10:57:05 +010062static constexpr ArrayRef<const RegStorage> empty_pool;
63static constexpr ArrayRef<const RegStorage> core_regs(core_regs_arr);
64static constexpr ArrayRef<const RegStorage> sp_regs(sp_regs_arr);
65static constexpr ArrayRef<const RegStorage> dp_regs(dp_regs_arr);
66static constexpr ArrayRef<const RegStorage> reserved_regs(reserved_regs_arr);
67static constexpr ArrayRef<const RegStorage> core_temps(core_temps_arr);
68static constexpr ArrayRef<const RegStorage> sp_temps(sp_temps_arr);
69static constexpr ArrayRef<const RegStorage> dp_temps(dp_temps_arr);
Brian Carlstrom7940e442013-07-12 13:46:57 -070070
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070071RegLocation ArmMir2Lir::LocCReturn() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000072 return arm_loc_c_return;
Brian Carlstrom7940e442013-07-12 13:46:57 -070073}
74
buzbeea0cd2d72014-06-01 09:33:49 -070075RegLocation ArmMir2Lir::LocCReturnRef() {
76 return arm_loc_c_return;
77}
78
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070079RegLocation ArmMir2Lir::LocCReturnWide() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000080 return arm_loc_c_return_wide;
Brian Carlstrom7940e442013-07-12 13:46:57 -070081}
82
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070083RegLocation ArmMir2Lir::LocCReturnFloat() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000084 return arm_loc_c_return_float;
Brian Carlstrom7940e442013-07-12 13:46:57 -070085}
86
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070087RegLocation ArmMir2Lir::LocCReturnDouble() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000088 return arm_loc_c_return_double;
Brian Carlstrom7940e442013-07-12 13:46:57 -070089}
90
91// Return a target-dependent special register.
buzbee2700f7e2014-03-07 09:46:20 -080092RegStorage ArmMir2Lir::TargetReg(SpecialTargetRegister reg) {
Zheng Xu5667fdb2014-10-23 18:29:55 +080093 RegStorage res_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -070094 switch (reg) {
buzbee091cc402014-03-31 10:14:40 -070095 case kSelf: res_reg = rs_rARM_SELF; break;
Wei Jin04f4d8a2014-05-29 18:04:29 -070096#ifdef ARM_R4_SUSPEND_FLAG
buzbee091cc402014-03-31 10:14:40 -070097 case kSuspend: res_reg = rs_rARM_SUSPEND; break;
Wei Jin04f4d8a2014-05-29 18:04:29 -070098#else
99 case kSuspend: res_reg = RegStorage::InvalidReg(); break;
100#endif
buzbee091cc402014-03-31 10:14:40 -0700101 case kLr: res_reg = rs_rARM_LR; break;
102 case kPc: res_reg = rs_rARM_PC; break;
103 case kSp: res_reg = rs_rARM_SP; break;
104 case kArg0: res_reg = rs_r0; break;
105 case kArg1: res_reg = rs_r1; break;
106 case kArg2: res_reg = rs_r2; break;
107 case kArg3: res_reg = rs_r3; break;
Zheng Xu5667fdb2014-10-23 18:29:55 +0800108 case kFArg0: res_reg = kArm32QuickCodeUseSoftFloat ? rs_r0 : rs_fr0; break;
109 case kFArg1: res_reg = kArm32QuickCodeUseSoftFloat ? rs_r1 : rs_fr1; break;
110 case kFArg2: res_reg = kArm32QuickCodeUseSoftFloat ? rs_r2 : rs_fr2; break;
111 case kFArg3: res_reg = kArm32QuickCodeUseSoftFloat ? rs_r3 : rs_fr3; break;
112 case kFArg4: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr4; break;
113 case kFArg5: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr5; break;
114 case kFArg6: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr6; break;
115 case kFArg7: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr7; break;
116 case kFArg8: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr8; break;
117 case kFArg9: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr9; break;
118 case kFArg10: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr10; break;
119 case kFArg11: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr11; break;
120 case kFArg12: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr12; break;
121 case kFArg13: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr13; break;
122 case kFArg14: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr14; break;
123 case kFArg15: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr15; break;
buzbee091cc402014-03-31 10:14:40 -0700124 case kRet0: res_reg = rs_r0; break;
125 case kRet1: res_reg = rs_r1; break;
126 case kInvokeTgt: res_reg = rs_rARM_LR; break;
127 case kHiddenArg: res_reg = rs_r12; break;
128 case kHiddenFpArg: res_reg = RegStorage::InvalidReg(); break;
129 case kCount: res_reg = RegStorage::InvalidReg(); break;
Dmitry Petrochenko58994cd2014-05-17 01:02:18 +0700130 default: res_reg = RegStorage::InvalidReg();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700131 }
buzbee091cc402014-03-31 10:14:40 -0700132 return res_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700133}
134
Brian Carlstrom7940e442013-07-12 13:46:57 -0700135/*
136 * Decode the register id.
137 */
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100138ResourceMask ArmMir2Lir::GetRegMaskCommon(const RegStorage& reg) const {
139 return GetRegMaskArm(reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700140}
141
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100142constexpr ResourceMask ArmMir2Lir::GetRegMaskArm(RegStorage reg) {
143 return reg.IsDouble()
144 /* Each double register is equal to a pair of single-precision FP registers */
145 ? ResourceMask::TwoBits(reg.GetRegNum() * 2 + kArmFPReg0)
146 : ResourceMask::Bit(reg.IsSingle() ? reg.GetRegNum() + kArmFPReg0 : reg.GetRegNum());
147}
148
149constexpr ResourceMask ArmMir2Lir::EncodeArmRegList(int reg_list) {
150 return ResourceMask::RawMask(static_cast<uint64_t >(reg_list), 0u);
151}
152
153constexpr ResourceMask ArmMir2Lir::EncodeArmRegFpcsList(int reg_list) {
154 return ResourceMask::RawMask(static_cast<uint64_t >(reg_list) << kArmFPReg16, 0u);
155}
156
157ResourceMask ArmMir2Lir::GetPCUseDefEncoding() const {
158 return ResourceMask::Bit(kArmRegPC);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700159}
160
buzbeeb48819d2013-09-14 16:15:25 -0700161// Thumb2 specific setup. TODO: inline?:
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100162void ArmMir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags,
163 ResourceMask* use_mask, ResourceMask* def_mask) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700164 DCHECK_EQ(cu_->instruction_set, kThumb2);
buzbeeb48819d2013-09-14 16:15:25 -0700165 DCHECK(!lir->flags.use_def_invalid);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700166
Brian Carlstrom7940e442013-07-12 13:46:57 -0700167 int opcode = lir->opcode;
168
buzbeeb48819d2013-09-14 16:15:25 -0700169 // These flags are somewhat uncommon - bypass if we can.
170 if ((flags & (REG_DEF_SP | REG_USE_SP | REG_DEF_LIST0 | REG_DEF_LIST1 |
171 REG_DEF_FPCS_LIST0 | REG_DEF_FPCS_LIST2 | REG_USE_PC | IS_IT | REG_USE_LIST0 |
172 REG_USE_LIST1 | REG_USE_FPCS_LIST0 | REG_USE_FPCS_LIST2 | REG_DEF_LR)) != 0) {
173 if (flags & REG_DEF_SP) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100174 def_mask->SetBit(kArmRegSP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700175 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700176
buzbeeb48819d2013-09-14 16:15:25 -0700177 if (flags & REG_USE_SP) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100178 use_mask->SetBit(kArmRegSP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700179 }
buzbeeb48819d2013-09-14 16:15:25 -0700180
181 if (flags & REG_DEF_LIST0) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100182 def_mask->SetBits(EncodeArmRegList(lir->operands[0]));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700183 }
buzbeeb48819d2013-09-14 16:15:25 -0700184
185 if (flags & REG_DEF_LIST1) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100186 def_mask->SetBits(EncodeArmRegList(lir->operands[1]));
buzbeeb48819d2013-09-14 16:15:25 -0700187 }
188
189 if (flags & REG_DEF_FPCS_LIST0) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100190 def_mask->SetBits(EncodeArmRegList(lir->operands[0]));
buzbeeb48819d2013-09-14 16:15:25 -0700191 }
192
193 if (flags & REG_DEF_FPCS_LIST2) {
194 for (int i = 0; i < lir->operands[2]; i++) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100195 SetupRegMask(def_mask, lir->operands[1] + i);
buzbeeb48819d2013-09-14 16:15:25 -0700196 }
197 }
198
199 if (flags & REG_USE_PC) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100200 use_mask->SetBit(kArmRegPC);
buzbeeb48819d2013-09-14 16:15:25 -0700201 }
202
203 /* Conservatively treat the IT block */
204 if (flags & IS_IT) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100205 *def_mask = kEncodeAll;
buzbeeb48819d2013-09-14 16:15:25 -0700206 }
207
208 if (flags & REG_USE_LIST0) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100209 use_mask->SetBits(EncodeArmRegList(lir->operands[0]));
buzbeeb48819d2013-09-14 16:15:25 -0700210 }
211
212 if (flags & REG_USE_LIST1) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100213 use_mask->SetBits(EncodeArmRegList(lir->operands[1]));
buzbeeb48819d2013-09-14 16:15:25 -0700214 }
215
216 if (flags & REG_USE_FPCS_LIST0) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100217 use_mask->SetBits(EncodeArmRegList(lir->operands[0]));
buzbeeb48819d2013-09-14 16:15:25 -0700218 }
219
220 if (flags & REG_USE_FPCS_LIST2) {
221 for (int i = 0; i < lir->operands[2]; i++) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100222 SetupRegMask(use_mask, lir->operands[1] + i);
buzbeeb48819d2013-09-14 16:15:25 -0700223 }
224 }
225 /* Fixup for kThumbPush/lr and kThumbPop/pc */
226 if (opcode == kThumbPush || opcode == kThumbPop) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100227 constexpr ResourceMask r8Mask = GetRegMaskArm(rs_r8);
228 if ((opcode == kThumbPush) && (use_mask->Intersects(r8Mask))) {
229 use_mask->ClearBits(r8Mask);
230 use_mask->SetBit(kArmRegLR);
231 } else if ((opcode == kThumbPop) && (def_mask->Intersects(r8Mask))) {
232 def_mask->ClearBits(r8Mask);
233 def_mask->SetBit(kArmRegPC);;
buzbeeb48819d2013-09-14 16:15:25 -0700234 }
235 }
236 if (flags & REG_DEF_LR) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100237 def_mask->SetBit(kArmRegLR);
buzbeeb48819d2013-09-14 16:15:25 -0700238 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700239 }
240}
241
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700242ArmConditionCode ArmMir2Lir::ArmConditionEncoding(ConditionCode ccode) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700243 ArmConditionCode res;
244 switch (ccode) {
245 case kCondEq: res = kArmCondEq; break;
246 case kCondNe: res = kArmCondNe; break;
247 case kCondCs: res = kArmCondCs; break;
248 case kCondCc: res = kArmCondCc; break;
Vladimir Marko58af1f92013-12-19 13:31:15 +0000249 case kCondUlt: res = kArmCondCc; break;
250 case kCondUge: res = kArmCondCs; break;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700251 case kCondMi: res = kArmCondMi; break;
252 case kCondPl: res = kArmCondPl; break;
253 case kCondVs: res = kArmCondVs; break;
254 case kCondVc: res = kArmCondVc; break;
255 case kCondHi: res = kArmCondHi; break;
256 case kCondLs: res = kArmCondLs; break;
257 case kCondGe: res = kArmCondGe; break;
258 case kCondLt: res = kArmCondLt; break;
259 case kCondGt: res = kArmCondGt; break;
260 case kCondLe: res = kArmCondLe; break;
261 case kCondAl: res = kArmCondAl; break;
262 case kCondNv: res = kArmCondNv; break;
263 default:
264 LOG(FATAL) << "Bad condition code " << ccode;
265 res = static_cast<ArmConditionCode>(0); // Quiet gcc
266 }
267 return res;
268}
269
270static const char* core_reg_names[16] = {
271 "r0",
272 "r1",
273 "r2",
274 "r3",
275 "r4",
276 "r5",
277 "r6",
278 "r7",
279 "r8",
280 "rSELF",
281 "r10",
282 "r11",
283 "r12",
284 "sp",
285 "lr",
286 "pc",
287};
288
289
290static const char* shift_names[4] = {
291 "lsl",
292 "lsr",
293 "asr",
294 "ror"};
295
296/* Decode and print a ARM register name */
Ian Rogers988e6ea2014-01-08 11:30:50 -0800297static char* DecodeRegList(int opcode, int vector, char* buf, size_t buf_size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700298 int i;
299 bool printed = false;
300 buf[0] = 0;
301 for (i = 0; i < 16; i++, vector >>= 1) {
302 if (vector & 0x1) {
303 int reg_id = i;
304 if (opcode == kThumbPush && i == 8) {
buzbee091cc402014-03-31 10:14:40 -0700305 reg_id = rs_rARM_LR.GetRegNum();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700306 } else if (opcode == kThumbPop && i == 8) {
buzbee091cc402014-03-31 10:14:40 -0700307 reg_id = rs_rARM_PC.GetRegNum();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700308 }
309 if (printed) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800310 snprintf(buf + strlen(buf), buf_size - strlen(buf), ", r%d", reg_id);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700311 } else {
312 printed = true;
Ian Rogers988e6ea2014-01-08 11:30:50 -0800313 snprintf(buf, buf_size, "r%d", reg_id);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700314 }
315 }
316 }
317 return buf;
318}
319
Ian Rogers988e6ea2014-01-08 11:30:50 -0800320static char* DecodeFPCSRegList(int count, int base, char* buf, size_t buf_size) {
321 snprintf(buf, buf_size, "s%d", base);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700322 for (int i = 1; i < count; i++) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800323 snprintf(buf + strlen(buf), buf_size - strlen(buf), ", s%d", base + i);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700324 }
325 return buf;
326}
327
buzbee0d829482013-10-11 15:24:55 -0700328static int32_t ExpandImmediate(int value) {
329 int32_t mode = (value & 0xf00) >> 8;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700330 uint32_t bits = value & 0xff;
331 switch (mode) {
332 case 0:
333 return bits;
334 case 1:
335 return (bits << 16) | bits;
336 case 2:
337 return (bits << 24) | (bits << 8);
338 case 3:
339 return (bits << 24) | (bits << 16) | (bits << 8) | bits;
340 default:
341 break;
342 }
343 bits = (bits | 0x80) << 24;
344 return bits >> (((value & 0xf80) >> 7) - 8);
345}
346
Brian Carlstromb1eba212013-07-17 18:07:19 -0700347const char* cc_names[] = {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
348 "hi", "ls", "ge", "lt", "gt", "le", "al", "nv"};
Brian Carlstrom7940e442013-07-12 13:46:57 -0700349/*
350 * Interpret a format string and build a string no longer than size
351 * See format key in Assemble.c.
352 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700353std::string ArmMir2Lir::BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700354 std::string buf;
355 int i;
356 const char* fmt_end = &fmt[strlen(fmt)];
357 char tbuf[256];
358 const char* name;
359 char nc;
360 while (fmt < fmt_end) {
361 int operand;
362 if (*fmt == '!') {
363 fmt++;
364 DCHECK_LT(fmt, fmt_end);
365 nc = *fmt++;
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700366 if (nc == '!') {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700367 strcpy(tbuf, "!");
368 } else {
369 DCHECK_LT(fmt, fmt_end);
370 DCHECK_LT(static_cast<unsigned>(nc-'0'), 4U);
371 operand = lir->operands[nc-'0'];
372 switch (*fmt++) {
373 case 'H':
374 if (operand != 0) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800375 snprintf(tbuf, arraysize(tbuf), ", %s %d", shift_names[operand & 0x3], operand >> 2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700376 } else {
Brian Carlstromb1eba212013-07-17 18:07:19 -0700377 strcpy(tbuf, "");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700378 }
379 break;
380 case 'B':
381 switch (operand) {
382 case kSY:
383 name = "sy";
384 break;
385 case kST:
386 name = "st";
387 break;
388 case kISH:
389 name = "ish";
390 break;
391 case kISHST:
392 name = "ishst";
393 break;
394 case kNSH:
395 name = "nsh";
396 break;
397 case kNSHST:
398 name = "shst";
399 break;
400 default:
401 name = "DecodeError2";
402 break;
403 }
404 strcpy(tbuf, name);
405 break;
406 case 'b':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700407 strcpy(tbuf, "0000");
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700408 for (i = 3; i >= 0; i--) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700409 tbuf[i] += operand & 1;
410 operand >>= 1;
411 }
412 break;
413 case 'n':
414 operand = ~ExpandImmediate(operand);
Ian Rogers988e6ea2014-01-08 11:30:50 -0800415 snprintf(tbuf, arraysize(tbuf), "%d [%#x]", operand, operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700416 break;
417 case 'm':
418 operand = ExpandImmediate(operand);
Ian Rogers988e6ea2014-01-08 11:30:50 -0800419 snprintf(tbuf, arraysize(tbuf), "%d [%#x]", operand, operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700420 break;
421 case 's':
buzbee091cc402014-03-31 10:14:40 -0700422 snprintf(tbuf, arraysize(tbuf), "s%d", RegStorage::RegNum(operand));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700423 break;
424 case 'S':
buzbee091cc402014-03-31 10:14:40 -0700425 snprintf(tbuf, arraysize(tbuf), "d%d", RegStorage::RegNum(operand));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700426 break;
427 case 'h':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800428 snprintf(tbuf, arraysize(tbuf), "%04x", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700429 break;
430 case 'M':
431 case 'd':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800432 snprintf(tbuf, arraysize(tbuf), "%d", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700433 break;
434 case 'C':
buzbee091cc402014-03-31 10:14:40 -0700435 operand = RegStorage::RegNum(operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700436 DCHECK_LT(operand, static_cast<int>(
437 sizeof(core_reg_names)/sizeof(core_reg_names[0])));
Ian Rogers988e6ea2014-01-08 11:30:50 -0800438 snprintf(tbuf, arraysize(tbuf), "%s", core_reg_names[operand]);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700439 break;
440 case 'E':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800441 snprintf(tbuf, arraysize(tbuf), "%d", operand*4);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700442 break;
443 case 'F':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800444 snprintf(tbuf, arraysize(tbuf), "%d", operand*2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700445 break;
446 case 'c':
447 strcpy(tbuf, cc_names[operand]);
448 break;
449 case 't':
Ian Rogers107c31e2014-01-23 20:55:29 -0800450 snprintf(tbuf, arraysize(tbuf), "0x%08" PRIxPTR " (L%p)",
451 reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 + (operand << 1),
Brian Carlstrom7940e442013-07-12 13:46:57 -0700452 lir->target);
453 break;
Vladimir Markof4da6752014-08-01 19:04:18 +0100454 case 'T':
455 snprintf(tbuf, arraysize(tbuf), "%s", PrettyMethod(
456 static_cast<uint32_t>(lir->operands[1]),
457 *reinterpret_cast<const DexFile*>(UnwrapPointer(lir->operands[2]))).c_str());
458 break;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700459 case 'u': {
460 int offset_1 = lir->operands[0];
461 int offset_2 = NEXT_LIR(lir)->operands[0];
462 uintptr_t target =
463 (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) &
464 ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
465 0xfffffffc;
Ian Rogers988e6ea2014-01-08 11:30:50 -0800466 snprintf(tbuf, arraysize(tbuf), "%p", reinterpret_cast<void *>(target));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700467 break;
468 }
469
470 /* Nothing to print for BLX_2 */
471 case 'v':
472 strcpy(tbuf, "see above");
473 break;
474 case 'R':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800475 DecodeRegList(lir->opcode, operand, tbuf, arraysize(tbuf));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700476 break;
477 case 'P':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800478 DecodeFPCSRegList(operand, 16, tbuf, arraysize(tbuf));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700479 break;
480 case 'Q':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800481 DecodeFPCSRegList(operand, 0, tbuf, arraysize(tbuf));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700482 break;
483 default:
Brian Carlstromb1eba212013-07-17 18:07:19 -0700484 strcpy(tbuf, "DecodeError1");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700485 break;
486 }
487 buf += tbuf;
488 }
489 } else {
490 buf += *fmt++;
491 }
492 }
493 return buf;
494}
495
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100496void ArmMir2Lir::DumpResourceMask(LIR* arm_lir, const ResourceMask& mask, const char* prefix) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700497 char buf[256];
498 buf[0] = 0;
499
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100500 if (mask.Equals(kEncodeAll)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700501 strcpy(buf, "all");
502 } else {
503 char num[8];
504 int i;
505
506 for (i = 0; i < kArmRegEnd; i++) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100507 if (mask.HasBit(i)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800508 snprintf(num, arraysize(num), "%d ", i);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700509 strcat(buf, num);
510 }
511 }
512
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100513 if (mask.HasBit(ResourceMask::kCCode)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700514 strcat(buf, "cc ");
515 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100516 if (mask.HasBit(ResourceMask::kFPStatus)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700517 strcat(buf, "fpcc ");
518 }
519
520 /* Memory bits */
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100521 if (arm_lir && (mask.HasBit(ResourceMask::kDalvikReg))) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800522 snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s",
523 DECODE_ALIAS_INFO_REG(arm_lir->flags.alias_info),
524 DECODE_ALIAS_INFO_WIDE(arm_lir->flags.alias_info) ? "(+1)" : "");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700525 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100526 if (mask.HasBit(ResourceMask::kLiteral)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700527 strcat(buf, "lit ");
528 }
529
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100530 if (mask.HasBit(ResourceMask::kHeapRef)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700531 strcat(buf, "heap ");
532 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100533 if (mask.HasBit(ResourceMask::kMustNotAlias)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700534 strcat(buf, "noalias ");
535 }
536 }
537 if (buf[0]) {
538 LOG(INFO) << prefix << ": " << buf;
539 }
540}
541
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700542bool ArmMir2Lir::IsUnconditionalBranch(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700543 return ((lir->opcode == kThumbBUncond) || (lir->opcode == kThumb2BUncond));
544}
545
Vladimir Marko674744e2014-04-24 15:18:26 +0100546RegisterClass ArmMir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) {
547 if (UNLIKELY(is_volatile)) {
548 // On arm, atomic 64-bit load/store requires a core register pair.
549 // Smaller aligned load/store is atomic for both core and fp registers.
550 if (size == k64 || size == kDouble) {
551 return kCoreReg;
552 }
553 }
554 return RegClassBySize(size);
555}
556
Brian Carlstrom7940e442013-07-12 13:46:57 -0700557ArmMir2Lir::ArmMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
Vladimir Markof4da6752014-08-01 19:04:18 +0100558 : Mir2Lir(cu, mir_graph, arena),
559 call_method_insns_(arena->Adapter()) {
560 call_method_insns_.reserve(100);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700561 // Sanity check - make sure encoding map lines up.
562 for (int i = 0; i < kArmLast; i++) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700563 DCHECK_EQ(ArmMir2Lir::EncodingMap[i].opcode, i)
564 << "Encoding order for " << ArmMir2Lir::EncodingMap[i].name
565 << " is wrong: expecting " << i << ", seeing "
566 << static_cast<int>(ArmMir2Lir::EncodingMap[i].opcode);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700567 }
568}
569
570Mir2Lir* ArmCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
571 ArenaAllocator* const arena) {
572 return new ArmMir2Lir(cu, mir_graph, arena);
573}
574
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700575void ArmMir2Lir::CompilerInitializeRegAlloc() {
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100576 reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs, empty_pool /* core64 */,
577 sp_regs, dp_regs,
578 reserved_regs, empty_pool /* reserved64 */,
579 core_temps, empty_pool /* core64_temps */,
580 sp_temps, dp_temps));
Dave Allisonf6b65c12014-04-01 17:45:18 -0700581
buzbee091cc402014-03-31 10:14:40 -0700582 // Target-specific adjustments.
583
584 // Alias single precision floats to appropriate half of overlapping double.
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100585 for (RegisterInfo* info : reg_pool_->sp_regs_) {
buzbee091cc402014-03-31 10:14:40 -0700586 int sp_reg_num = info->GetReg().GetRegNum();
587 int dp_reg_num = sp_reg_num >> 1;
588 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
589 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
590 // Double precision register's master storage should refer to itself.
591 DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
592 // Redirect single precision's master storage to master.
593 info->SetMaster(dp_reg_info);
594 // Singles should show a single 32-bit mask bit, at first referring to the low half.
buzbee85089dd2014-05-25 15:10:52 -0700595 DCHECK_EQ(info->StorageMask(), RegisterInfo::kLowSingleStorageMask);
buzbee091cc402014-03-31 10:14:40 -0700596 if (sp_reg_num & 1) {
buzbee85089dd2014-05-25 15:10:52 -0700597 // For odd singles, change to use the high word of the backing double.
598 info->SetStorageMask(RegisterInfo::kHighSingleStorageMask);
buzbee091cc402014-03-31 10:14:40 -0700599 }
600 }
601
Wei Jin04f4d8a2014-05-29 18:04:29 -0700602#ifdef ARM_R4_SUSPEND_FLAG
Dave Allison83252962014-04-03 16:33:48 -0700603 // TODO: re-enable this when we can safely save r4 over the suspension code path.
604 bool no_suspend = NO_SUSPEND; // || !Runtime::Current()->ExplicitSuspendChecks();
buzbee091cc402014-03-31 10:14:40 -0700605 if (no_suspend) {
606 GetRegInfo(rs_rARM_SUSPEND)->MarkFree();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700607 }
Wei Jin04f4d8a2014-05-29 18:04:29 -0700608#endif
Brian Carlstrom7940e442013-07-12 13:46:57 -0700609
buzbee091cc402014-03-31 10:14:40 -0700610 // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
611 // TODO: adjust when we roll to hard float calling convention.
612 reg_pool_->next_core_reg_ = 2;
613 reg_pool_->next_sp_reg_ = 0;
614 reg_pool_->next_dp_reg_ = 0;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700615}
616
Brian Carlstrom7940e442013-07-12 13:46:57 -0700617/*
618 * TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some
619 * instructions might call out to C/assembly helper functions. Until
620 * machinery is in place, always spill lr.
621 */
622
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700623void ArmMir2Lir::AdjustSpillMask() {
buzbee091cc402014-03-31 10:14:40 -0700624 core_spill_mask_ |= (1 << rs_rARM_LR.GetRegNum());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700625 num_core_spills_++;
626}
627
628/*
629 * Mark a callee-save fp register as promoted. Note that
630 * vpush/vpop uses contiguous register lists so we must
631 * include any holes in the mask. Associate holes with
632 * Dalvik register INVALID_VREG (0xFFFFU).
633 */
buzbee091cc402014-03-31 10:14:40 -0700634void ArmMir2Lir::MarkPreservedSingle(int v_reg, RegStorage reg) {
635 DCHECK_GE(reg.GetRegNum(), ARM_FP_CALLEE_SAVE_BASE);
636 int adjusted_reg_num = reg.GetRegNum() - ARM_FP_CALLEE_SAVE_BASE;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700637 // Ensure fp_vmap_table is large enough
638 int table_size = fp_vmap_table_.size();
buzbee091cc402014-03-31 10:14:40 -0700639 for (int i = table_size; i < (adjusted_reg_num + 1); i++) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700640 fp_vmap_table_.push_back(INVALID_VREG);
641 }
642 // Add the current mapping
buzbee091cc402014-03-31 10:14:40 -0700643 fp_vmap_table_[adjusted_reg_num] = v_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700644 // Size of fp_vmap_table is high-water mark, use to set mask
645 num_fp_spills_ = fp_vmap_table_.size();
646 fp_spill_mask_ = ((1 << num_fp_spills_) - 1) << ARM_FP_CALLEE_SAVE_BASE;
647}
648
buzbee091cc402014-03-31 10:14:40 -0700649void ArmMir2Lir::MarkPreservedDouble(int v_reg, RegStorage reg) {
650 // TEMP: perform as 2 singles.
651 int reg_num = reg.GetRegNum() << 1;
652 RegStorage lo = RegStorage::Solo32(RegStorage::kFloatingPoint | reg_num);
653 RegStorage hi = RegStorage::Solo32(RegStorage::kFloatingPoint | reg_num | 1);
654 MarkPreservedSingle(v_reg, lo);
655 MarkPreservedSingle(v_reg + 1, hi);
buzbee2700f7e2014-03-07 09:46:20 -0800656}
657
Brian Carlstrom7940e442013-07-12 13:46:57 -0700658/* Clobber all regs that might be used by an external C call */
Vladimir Marko31c2aac2013-12-09 16:31:19 +0000659void ArmMir2Lir::ClobberCallerSave() {
buzbee091cc402014-03-31 10:14:40 -0700660 // TODO: rework this - it's gotten even more ugly.
661 Clobber(rs_r0);
662 Clobber(rs_r1);
663 Clobber(rs_r2);
664 Clobber(rs_r3);
665 Clobber(rs_r12);
666 Clobber(rs_r14lr);
667 Clobber(rs_fr0);
668 Clobber(rs_fr1);
669 Clobber(rs_fr2);
670 Clobber(rs_fr3);
671 Clobber(rs_fr4);
672 Clobber(rs_fr5);
673 Clobber(rs_fr6);
674 Clobber(rs_fr7);
675 Clobber(rs_fr8);
676 Clobber(rs_fr9);
677 Clobber(rs_fr10);
678 Clobber(rs_fr11);
679 Clobber(rs_fr12);
680 Clobber(rs_fr13);
681 Clobber(rs_fr14);
682 Clobber(rs_fr15);
683 Clobber(rs_dr0);
684 Clobber(rs_dr1);
685 Clobber(rs_dr2);
686 Clobber(rs_dr3);
687 Clobber(rs_dr4);
688 Clobber(rs_dr5);
689 Clobber(rs_dr6);
690 Clobber(rs_dr7);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700691}
692
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700693RegLocation ArmMir2Lir::GetReturnWideAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700694 RegLocation res = LocCReturnWide();
buzbee091cc402014-03-31 10:14:40 -0700695 res.reg.SetLowReg(rs_r2.GetReg());
696 res.reg.SetHighReg(rs_r3.GetReg());
697 Clobber(rs_r2);
698 Clobber(rs_r3);
699 MarkInUse(rs_r2);
700 MarkInUse(rs_r3);
701 MarkWide(res.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700702 return res;
703}
704
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700705RegLocation ArmMir2Lir::GetReturnAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700706 RegLocation res = LocCReturn();
buzbee091cc402014-03-31 10:14:40 -0700707 res.reg.SetReg(rs_r1.GetReg());
708 Clobber(rs_r1);
709 MarkInUse(rs_r1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700710 return res;
711}
712
Brian Carlstrom7940e442013-07-12 13:46:57 -0700713/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700714void ArmMir2Lir::LockCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700715 LockTemp(rs_r0);
716 LockTemp(rs_r1);
717 LockTemp(rs_r2);
718 LockTemp(rs_r3);
Zheng Xu5667fdb2014-10-23 18:29:55 +0800719 if (!kArm32QuickCodeUseSoftFloat) {
720 LockTemp(rs_fr0);
721 LockTemp(rs_fr1);
722 LockTemp(rs_fr2);
723 LockTemp(rs_fr3);
724 LockTemp(rs_fr4);
725 LockTemp(rs_fr5);
726 LockTemp(rs_fr6);
727 LockTemp(rs_fr7);
728 LockTemp(rs_fr8);
729 LockTemp(rs_fr9);
730 LockTemp(rs_fr10);
731 LockTemp(rs_fr11);
732 LockTemp(rs_fr12);
733 LockTemp(rs_fr13);
734 LockTemp(rs_fr14);
735 LockTemp(rs_fr15);
736 LockTemp(rs_dr0);
737 LockTemp(rs_dr1);
738 LockTemp(rs_dr2);
739 LockTemp(rs_dr3);
740 LockTemp(rs_dr4);
741 LockTemp(rs_dr5);
742 LockTemp(rs_dr6);
743 LockTemp(rs_dr7);
744 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700745}
746
747/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700748void ArmMir2Lir::FreeCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700749 FreeTemp(rs_r0);
750 FreeTemp(rs_r1);
751 FreeTemp(rs_r2);
752 FreeTemp(rs_r3);
Vladimir Markobfe400b2014-12-19 19:27:26 +0000753 FreeTemp(TargetReg(kHiddenArg));
Zheng Xu5667fdb2014-10-23 18:29:55 +0800754 if (!kArm32QuickCodeUseSoftFloat) {
755 FreeTemp(rs_fr0);
756 FreeTemp(rs_fr1);
757 FreeTemp(rs_fr2);
758 FreeTemp(rs_fr3);
759 FreeTemp(rs_fr4);
760 FreeTemp(rs_fr5);
761 FreeTemp(rs_fr6);
762 FreeTemp(rs_fr7);
763 FreeTemp(rs_fr8);
764 FreeTemp(rs_fr9);
765 FreeTemp(rs_fr10);
766 FreeTemp(rs_fr11);
767 FreeTemp(rs_fr12);
768 FreeTemp(rs_fr13);
769 FreeTemp(rs_fr14);
770 FreeTemp(rs_fr15);
771 FreeTemp(rs_dr0);
772 FreeTemp(rs_dr1);
773 FreeTemp(rs_dr2);
774 FreeTemp(rs_dr3);
775 FreeTemp(rs_dr4);
776 FreeTemp(rs_dr5);
777 FreeTemp(rs_dr6);
778 FreeTemp(rs_dr7);
779 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700780}
781
Andreas Gampe98430592014-07-27 19:44:50 -0700782RegStorage ArmMir2Lir::LoadHelper(QuickEntrypointEnum trampoline) {
783 LoadWordDisp(rs_rARM_SELF, GetThreadOffset<4>(trampoline).Int32Value(), rs_rARM_LR);
buzbee2700f7e2014-03-07 09:46:20 -0800784 return rs_rARM_LR;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700785}
786
Dave Allisonb373e092014-02-20 16:06:36 -0800787LIR* ArmMir2Lir::CheckSuspendUsingLoad() {
buzbee2700f7e2014-03-07 09:46:20 -0800788 RegStorage tmp = rs_r0;
buzbee695d13a2014-04-19 13:32:20 -0700789 Load32Disp(rs_rARM_SELF, Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
790 LIR* load2 = Load32Disp(tmp, 0, tmp);
Dave Allisonb373e092014-02-20 16:06:36 -0800791 return load2;
792}
793
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700794uint64_t ArmMir2Lir::GetTargetInstFlags(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700795 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700796 return ArmMir2Lir::EncodingMap[opcode].flags;
797}
798
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700799const char* ArmMir2Lir::GetTargetInstName(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700800 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700801 return ArmMir2Lir::EncodingMap[opcode].name;
802}
803
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700804const char* ArmMir2Lir::GetTargetInstFmt(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700805 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700806 return ArmMir2Lir::EncodingMap[opcode].fmt;
807}
808
buzbee091cc402014-03-31 10:14:40 -0700809/*
810 * Somewhat messy code here. We want to allocate a pair of contiguous
811 * physical single-precision floating point registers starting with
812 * an even numbered reg. It is possible that the paired s_reg (s_reg+1)
813 * has already been allocated - try to fit if possible. Fail to
814 * allocate if we can't meet the requirements for the pair of
815 * s_reg<=sX[even] & (s_reg+1)<= sX+1.
816 */
817// TODO: needs rewrite to support non-backed 64-bit float regs.
818RegStorage ArmMir2Lir::AllocPreservedDouble(int s_reg) {
819 RegStorage res;
820 int v_reg = mir_graph_->SRegToVReg(s_reg);
821 int p_map_idx = SRegToPMap(s_reg);
822 if (promotion_map_[p_map_idx+1].fp_location == kLocPhysReg) {
823 // Upper reg is already allocated. Can we fit?
buzbeeb5860fb2014-06-21 15:31:01 -0700824 int high_reg = promotion_map_[p_map_idx+1].fp_reg;
buzbee091cc402014-03-31 10:14:40 -0700825 if ((high_reg & 1) == 0) {
826 // High reg is even - fail.
827 return res; // Invalid.
828 }
829 // Is the low reg of the pair free?
830 // FIXME: rework.
831 RegisterInfo* p = GetRegInfo(RegStorage::FloatSolo32(high_reg - 1));
832 if (p->InUse() || p->IsTemp()) {
833 // Already allocated or not preserved - fail.
834 return res; // Invalid.
835 }
836 // OK - good to go.
837 res = RegStorage::FloatSolo64(p->GetReg().GetRegNum() >> 1);
838 p->MarkInUse();
839 MarkPreservedSingle(v_reg, p->GetReg());
840 } else {
841 /*
842 * TODO: until runtime support is in, make sure we avoid promoting the same vreg to
843 * different underlying physical registers.
844 */
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100845 for (RegisterInfo* info : reg_pool_->dp_regs_) {
buzbee091cc402014-03-31 10:14:40 -0700846 if (!info->IsTemp() && !info->InUse()) {
847 res = info->GetReg();
848 info->MarkInUse();
849 MarkPreservedDouble(v_reg, info->GetReg());
850 break;
851 }
852 }
853 }
854 if (res.Valid()) {
buzbee85089dd2014-05-25 15:10:52 -0700855 RegisterInfo* info = GetRegInfo(res);
buzbee091cc402014-03-31 10:14:40 -0700856 promotion_map_[p_map_idx].fp_location = kLocPhysReg;
buzbeeb5860fb2014-06-21 15:31:01 -0700857 promotion_map_[p_map_idx].fp_reg =
buzbee85089dd2014-05-25 15:10:52 -0700858 info->FindMatchingView(RegisterInfo::kLowSingleStorageMask)->GetReg().GetReg();
buzbee091cc402014-03-31 10:14:40 -0700859 promotion_map_[p_map_idx+1].fp_location = kLocPhysReg;
buzbeeb5860fb2014-06-21 15:31:01 -0700860 promotion_map_[p_map_idx+1].fp_reg =
buzbee85089dd2014-05-25 15:10:52 -0700861 info->FindMatchingView(RegisterInfo::kHighSingleStorageMask)->GetReg().GetReg();
buzbee091cc402014-03-31 10:14:40 -0700862 }
863 return res;
864}
865
buzbeeb5860fb2014-06-21 15:31:01 -0700866// Reserve a callee-save sp single register.
867RegStorage ArmMir2Lir::AllocPreservedSingle(int s_reg) {
868 RegStorage res;
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100869 for (RegisterInfo* info : reg_pool_->sp_regs_) {
buzbeeb5860fb2014-06-21 15:31:01 -0700870 if (!info->IsTemp() && !info->InUse()) {
871 res = info->GetReg();
872 int p_map_idx = SRegToPMap(s_reg);
873 int v_reg = mir_graph_->SRegToVReg(s_reg);
874 GetRegInfo(res)->MarkInUse();
875 MarkPreservedSingle(v_reg, res);
876 promotion_map_[p_map_idx].fp_location = kLocPhysReg;
877 promotion_map_[p_map_idx].fp_reg = res.GetReg();
878 break;
879 }
880 }
881 return res;
882}
883
Vladimir Markof4da6752014-08-01 19:04:18 +0100884void ArmMir2Lir::InstallLiteralPools() {
885 // PC-relative calls to methods.
886 patches_.reserve(call_method_insns_.size());
887 for (LIR* p : call_method_insns_) {
888 DCHECK_EQ(p->opcode, kThumb2Bl);
889 uint32_t target_method_idx = p->operands[1];
890 const DexFile* target_dex_file =
891 reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[2]));
892
893 patches_.push_back(LinkerPatch::RelativeCodePatch(p->offset,
894 target_dex_file, target_method_idx));
895 }
896
897 // And do the normal processing.
898 Mir2Lir::InstallLiteralPools();
899}
900
Serguei Katkov717a3e42014-11-13 17:19:42 +0600901RegStorage ArmMir2Lir::InToRegStorageArmMapper::GetNextReg(ShortyArg arg) {
Zheng Xu5667fdb2014-10-23 18:29:55 +0800902 const RegStorage coreArgMappingToPhysicalReg[] =
903 {rs_r1, rs_r2, rs_r3};
904 const int coreArgMappingToPhysicalRegSize = arraysize(coreArgMappingToPhysicalReg);
905 const RegStorage fpArgMappingToPhysicalReg[] =
906 {rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7,
907 rs_fr8, rs_fr9, rs_fr10, rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15};
Andreas Gampe785d2f22014-11-03 22:57:30 -0800908 constexpr uint32_t fpArgMappingToPhysicalRegSize = arraysize(fpArgMappingToPhysicalReg);
909 static_assert(fpArgMappingToPhysicalRegSize % 2 == 0, "Number of FP Arg regs is not even");
Zheng Xu5667fdb2014-10-23 18:29:55 +0800910
Zheng Xu5667fdb2014-10-23 18:29:55 +0800911 RegStorage result = RegStorage::InvalidReg();
Serguei Katkov717a3e42014-11-13 17:19:42 +0600912 // Regard double as long, float as int for kArm32QuickCodeUseSoftFloat.
913 if (arg.IsFP() && !kArm32QuickCodeUseSoftFloat) {
914 if (arg.IsWide()) {
Zheng Xu5667fdb2014-10-23 18:29:55 +0800915 cur_fp_double_reg_ = std::max(cur_fp_double_reg_, RoundUp(cur_fp_reg_, 2));
916 if (cur_fp_double_reg_ < fpArgMappingToPhysicalRegSize) {
Serguei Katkov717a3e42014-11-13 17:19:42 +0600917 result = RegStorage::MakeRegPair(fpArgMappingToPhysicalReg[cur_fp_double_reg_],
918 fpArgMappingToPhysicalReg[cur_fp_double_reg_ + 1]);
919 result = As64BitFloatReg(result);
920 cur_fp_double_reg_ += 2;
Zheng Xu5667fdb2014-10-23 18:29:55 +0800921 }
922 } else {
Zheng Xu5667fdb2014-10-23 18:29:55 +0800923 if (cur_fp_reg_ % 2 == 0) {
924 cur_fp_reg_ = std::max(cur_fp_double_reg_, cur_fp_reg_);
925 }
926 if (cur_fp_reg_ < fpArgMappingToPhysicalRegSize) {
927 result = fpArgMappingToPhysicalReg[cur_fp_reg_];
928 cur_fp_reg_++;
929 }
930 }
931 } else {
932 if (cur_core_reg_ < coreArgMappingToPhysicalRegSize) {
Nicolas Geoffray69c15d32015-01-13 11:42:13 +0000933 if (!kArm32QuickCodeUseSoftFloat && arg.IsWide() && cur_core_reg_ == 0) {
934 // Skip r1, and use r2-r3 for the register pair.
935 cur_core_reg_++;
936 }
Zheng Xu5667fdb2014-10-23 18:29:55 +0800937 result = coreArgMappingToPhysicalReg[cur_core_reg_++];
Serguei Katkov717a3e42014-11-13 17:19:42 +0600938 if (arg.IsWide() && cur_core_reg_ < coreArgMappingToPhysicalRegSize) {
939 result = RegStorage::MakeRegPair(result, coreArgMappingToPhysicalReg[cur_core_reg_++]);
940 }
Zheng Xu5667fdb2014-10-23 18:29:55 +0800941 }
942 }
943 return result;
944}
945
Serguei Katkov717a3e42014-11-13 17:19:42 +0600946int ArmMir2Lir::GenDalvikArgsBulkCopy(CallInfo* info, int first, int count) {
Zheng Xu5667fdb2014-10-23 18:29:55 +0800947 if (kArm32QuickCodeUseSoftFloat) {
Serguei Katkov717a3e42014-11-13 17:19:42 +0600948 return Mir2Lir::GenDalvikArgsBulkCopy(info, first, count);
Zheng Xu5667fdb2014-10-23 18:29:55 +0800949 }
Serguei Katkov717a3e42014-11-13 17:19:42 +0600950 /*
951 * TODO: Improve by adding block copy for large number of arguments. For now, just
952 * copy a Dalvik vreg at a time.
953 */
954 return count;
Zheng Xu5667fdb2014-10-23 18:29:55 +0800955}
956
Ningsheng Jiana262f772014-11-25 16:48:07 +0800957void ArmMir2Lir::GenMachineSpecificExtendedMethodMIR(BasicBlock* bb, MIR* mir) {
958 UNUSED(bb);
959 DCHECK(MIR::DecodedInstruction::IsPseudoMirOp(mir->dalvikInsn.opcode));
960 RegLocation rl_src[3];
961 RegLocation rl_dest = mir_graph_->GetBadLoc();
962 rl_src[0] = rl_src[1] = rl_src[2] = mir_graph_->GetBadLoc();
963 switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) {
964 case kMirOpMaddInt:
965 rl_dest = mir_graph_->GetDest(mir);
966 rl_src[0] = mir_graph_->GetSrc(mir, 0);
967 rl_src[1] = mir_graph_->GetSrc(mir, 1);
968 rl_src[2]= mir_graph_->GetSrc(mir, 2);
969 GenMaddMsubInt(rl_dest, rl_src[0], rl_src[1], rl_src[2], false);
970 break;
971 case kMirOpMsubInt:
972 rl_dest = mir_graph_->GetDest(mir);
973 rl_src[0] = mir_graph_->GetSrc(mir, 0);
974 rl_src[1] = mir_graph_->GetSrc(mir, 1);
975 rl_src[2]= mir_graph_->GetSrc(mir, 2);
976 GenMaddMsubInt(rl_dest, rl_src[0], rl_src[1], rl_src[2], true);
977 break;
978 default:
979 LOG(FATAL) << "Unexpected opcode: " << mir->dalvikInsn.opcode;
980 }
981}
982
Brian Carlstrom7940e442013-07-12 13:46:57 -0700983} // namespace art