blob: dd8f7fe3d882fa5b8bee46a8acded42c712a9038 [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"
Brian Carlstrom7940e442013-07-12 13:46:57 -070024#include "dex/compiler_internals.h"
25#include "dex/quick/mir_to_lir-inl.h"
26
27namespace art {
28
Wei Jin04f4d8a2014-05-29 18:04:29 -070029#ifdef ARM_R4_SUSPEND_FLAG
Vladimir Marko089142c2014-06-05 10:57:05 +010030static constexpr RegStorage core_regs_arr[] =
buzbee091cc402014-03-31 10:14:40 -070031 {rs_r0, rs_r1, rs_r2, rs_r3, rs_rARM_SUSPEND, rs_r5, rs_r6, rs_r7, rs_r8, rs_rARM_SELF,
32 rs_r10, rs_r11, rs_r12, rs_rARM_SP, rs_rARM_LR, rs_rARM_PC};
Wei Jin04f4d8a2014-05-29 18:04:29 -070033#else
34static constexpr RegStorage core_regs_arr[] =
35 {rs_r0, rs_r1, rs_r2, rs_r3, rs_r4, rs_r5, rs_r6, rs_r7, rs_r8, rs_rARM_SELF,
36 rs_r10, rs_r11, rs_r12, rs_rARM_SP, rs_rARM_LR, rs_rARM_PC};
37#endif
Vladimir Marko089142c2014-06-05 10:57:05 +010038static constexpr RegStorage sp_regs_arr[] =
buzbee091cc402014-03-31 10:14:40 -070039 {rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, rs_fr8, rs_fr9, rs_fr10,
40 rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15, rs_fr16, rs_fr17, rs_fr18, rs_fr19, rs_fr20,
41 rs_fr21, rs_fr22, rs_fr23, rs_fr24, rs_fr25, rs_fr26, rs_fr27, rs_fr28, rs_fr29, rs_fr30,
42 rs_fr31};
Vladimir Marko089142c2014-06-05 10:57:05 +010043static constexpr RegStorage dp_regs_arr[] =
buzbee091cc402014-03-31 10:14:40 -070044 {rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, rs_dr8, rs_dr9, rs_dr10,
45 rs_dr11, rs_dr12, rs_dr13, rs_dr14, rs_dr15};
Wei Jin04f4d8a2014-05-29 18:04:29 -070046#ifdef ARM_R4_SUSPEND_FLAG
Vladimir Marko089142c2014-06-05 10:57:05 +010047static constexpr RegStorage reserved_regs_arr[] =
buzbee091cc402014-03-31 10:14:40 -070048 {rs_rARM_SUSPEND, rs_rARM_SELF, rs_rARM_SP, rs_rARM_LR, rs_rARM_PC};
Vladimir Marko089142c2014-06-05 10:57:05 +010049static constexpr RegStorage core_temps_arr[] = {rs_r0, rs_r1, rs_r2, rs_r3, rs_r12};
Wei Jin04f4d8a2014-05-29 18:04:29 -070050#else
51static constexpr RegStorage reserved_regs_arr[] =
52 {rs_rARM_SELF, rs_rARM_SP, rs_rARM_LR, rs_rARM_PC};
53static constexpr RegStorage core_temps_arr[] = {rs_r0, rs_r1, rs_r2, rs_r3, rs_r4, rs_r12};
54#endif
Vladimir Marko089142c2014-06-05 10:57:05 +010055static constexpr RegStorage sp_temps_arr[] =
buzbee091cc402014-03-31 10:14:40 -070056 {rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, rs_fr8, rs_fr9, rs_fr10,
57 rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15};
Vladimir Marko089142c2014-06-05 10:57:05 +010058static constexpr RegStorage dp_temps_arr[] =
buzbee091cc402014-03-31 10:14:40 -070059 {rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7};
60
Vladimir Marko089142c2014-06-05 10:57:05 +010061static constexpr ArrayRef<const RegStorage> empty_pool;
62static constexpr ArrayRef<const RegStorage> core_regs(core_regs_arr);
63static constexpr ArrayRef<const RegStorage> sp_regs(sp_regs_arr);
64static constexpr ArrayRef<const RegStorage> dp_regs(dp_regs_arr);
65static constexpr ArrayRef<const RegStorage> reserved_regs(reserved_regs_arr);
66static constexpr ArrayRef<const RegStorage> core_temps(core_temps_arr);
67static constexpr ArrayRef<const RegStorage> sp_temps(sp_temps_arr);
68static constexpr ArrayRef<const RegStorage> dp_temps(dp_temps_arr);
Brian Carlstrom7940e442013-07-12 13:46:57 -070069
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070070RegLocation ArmMir2Lir::LocCReturn() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000071 return arm_loc_c_return;
Brian Carlstrom7940e442013-07-12 13:46:57 -070072}
73
buzbeea0cd2d72014-06-01 09:33:49 -070074RegLocation ArmMir2Lir::LocCReturnRef() {
75 return arm_loc_c_return;
76}
77
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070078RegLocation ArmMir2Lir::LocCReturnWide() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000079 return arm_loc_c_return_wide;
Brian Carlstrom7940e442013-07-12 13:46:57 -070080}
81
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070082RegLocation ArmMir2Lir::LocCReturnFloat() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000083 return arm_loc_c_return_float;
Brian Carlstrom7940e442013-07-12 13:46:57 -070084}
85
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070086RegLocation ArmMir2Lir::LocCReturnDouble() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000087 return arm_loc_c_return_double;
Brian Carlstrom7940e442013-07-12 13:46:57 -070088}
89
90// Return a target-dependent special register.
buzbee2700f7e2014-03-07 09:46:20 -080091RegStorage ArmMir2Lir::TargetReg(SpecialTargetRegister reg) {
buzbee091cc402014-03-31 10:14:40 -070092 RegStorage res_reg = RegStorage::InvalidReg();
Brian Carlstrom7940e442013-07-12 13:46:57 -070093 switch (reg) {
buzbee091cc402014-03-31 10:14:40 -070094 case kSelf: res_reg = rs_rARM_SELF; break;
Wei Jin04f4d8a2014-05-29 18:04:29 -070095#ifdef ARM_R4_SUSPEND_FLAG
buzbee091cc402014-03-31 10:14:40 -070096 case kSuspend: res_reg = rs_rARM_SUSPEND; break;
Wei Jin04f4d8a2014-05-29 18:04:29 -070097#else
98 case kSuspend: res_reg = RegStorage::InvalidReg(); break;
99#endif
buzbee091cc402014-03-31 10:14:40 -0700100 case kLr: res_reg = rs_rARM_LR; break;
101 case kPc: res_reg = rs_rARM_PC; break;
102 case kSp: res_reg = rs_rARM_SP; break;
103 case kArg0: res_reg = rs_r0; break;
104 case kArg1: res_reg = rs_r1; break;
105 case kArg2: res_reg = rs_r2; break;
106 case kArg3: res_reg = rs_r3; break;
107 case kFArg0: res_reg = rs_r0; break;
108 case kFArg1: res_reg = rs_r1; break;
109 case kFArg2: res_reg = rs_r2; break;
110 case kFArg3: res_reg = rs_r3; break;
111 case kRet0: res_reg = rs_r0; break;
112 case kRet1: res_reg = rs_r1; break;
113 case kInvokeTgt: res_reg = rs_rARM_LR; break;
114 case kHiddenArg: res_reg = rs_r12; break;
115 case kHiddenFpArg: res_reg = RegStorage::InvalidReg(); break;
116 case kCount: res_reg = RegStorage::InvalidReg(); break;
Dmitry Petrochenko58994cd2014-05-17 01:02:18 +0700117 default: res_reg = RegStorage::InvalidReg();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700118 }
buzbee091cc402014-03-31 10:14:40 -0700119 return res_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700120}
121
buzbee2700f7e2014-03-07 09:46:20 -0800122RegStorage ArmMir2Lir::GetArgMappingToPhysicalReg(int arg_num) {
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800123 // For the 32-bit internal ABI, the first 3 arguments are passed in registers.
124 switch (arg_num) {
125 case 0:
buzbee091cc402014-03-31 10:14:40 -0700126 return rs_r1;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800127 case 1:
buzbee091cc402014-03-31 10:14:40 -0700128 return rs_r2;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800129 case 2:
buzbee091cc402014-03-31 10:14:40 -0700130 return rs_r3;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800131 default:
buzbee2700f7e2014-03-07 09:46:20 -0800132 return RegStorage::InvalidReg();
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800133 }
134}
Brian Carlstrom7940e442013-07-12 13:46:57 -0700135
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 }
494 return buf;
495}
496
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100497void ArmMir2Lir::DumpResourceMask(LIR* arm_lir, const ResourceMask& mask, const char* prefix) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700498 char buf[256];
499 buf[0] = 0;
500
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100501 if (mask.Equals(kEncodeAll)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700502 strcpy(buf, "all");
503 } else {
504 char num[8];
505 int i;
506
507 for (i = 0; i < kArmRegEnd; i++) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100508 if (mask.HasBit(i)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800509 snprintf(num, arraysize(num), "%d ", i);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700510 strcat(buf, num);
511 }
512 }
513
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100514 if (mask.HasBit(ResourceMask::kCCode)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700515 strcat(buf, "cc ");
516 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100517 if (mask.HasBit(ResourceMask::kFPStatus)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700518 strcat(buf, "fpcc ");
519 }
520
521 /* Memory bits */
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100522 if (arm_lir && (mask.HasBit(ResourceMask::kDalvikReg))) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800523 snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s",
524 DECODE_ALIAS_INFO_REG(arm_lir->flags.alias_info),
525 DECODE_ALIAS_INFO_WIDE(arm_lir->flags.alias_info) ? "(+1)" : "");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700526 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100527 if (mask.HasBit(ResourceMask::kLiteral)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700528 strcat(buf, "lit ");
529 }
530
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100531 if (mask.HasBit(ResourceMask::kHeapRef)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700532 strcat(buf, "heap ");
533 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100534 if (mask.HasBit(ResourceMask::kMustNotAlias)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700535 strcat(buf, "noalias ");
536 }
537 }
538 if (buf[0]) {
539 LOG(INFO) << prefix << ": " << buf;
540 }
541}
542
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700543bool ArmMir2Lir::IsUnconditionalBranch(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700544 return ((lir->opcode == kThumbBUncond) || (lir->opcode == kThumb2BUncond));
545}
546
Vladimir Marko674744e2014-04-24 15:18:26 +0100547RegisterClass ArmMir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) {
548 if (UNLIKELY(is_volatile)) {
549 // On arm, atomic 64-bit load/store requires a core register pair.
550 // Smaller aligned load/store is atomic for both core and fp registers.
551 if (size == k64 || size == kDouble) {
552 return kCoreReg;
553 }
554 }
555 return RegClassBySize(size);
556}
557
Brian Carlstrom7940e442013-07-12 13:46:57 -0700558ArmMir2Lir::ArmMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
Vladimir Markof4da6752014-08-01 19:04:18 +0100559 : Mir2Lir(cu, mir_graph, arena),
560 call_method_insns_(arena->Adapter()) {
561 call_method_insns_.reserve(100);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700562 // Sanity check - make sure encoding map lines up.
563 for (int i = 0; i < kArmLast; i++) {
564 if (ArmMir2Lir::EncodingMap[i].opcode != i) {
565 LOG(FATAL) << "Encoding order for " << ArmMir2Lir::EncodingMap[i].name
566 << " is wrong: expecting " << i << ", seeing "
567 << static_cast<int>(ArmMir2Lir::EncodingMap[i].opcode);
568 }
569 }
570}
571
572Mir2Lir* ArmCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
573 ArenaAllocator* const arena) {
574 return new ArmMir2Lir(cu, mir_graph, arena);
575}
576
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700577void ArmMir2Lir::CompilerInitializeRegAlloc() {
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100578 reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs, empty_pool /* core64 */,
579 sp_regs, dp_regs,
580 reserved_regs, empty_pool /* reserved64 */,
581 core_temps, empty_pool /* core64_temps */,
582 sp_temps, dp_temps));
Dave Allisonf6b65c12014-04-01 17:45:18 -0700583
buzbee091cc402014-03-31 10:14:40 -0700584 // Target-specific adjustments.
585
586 // Alias single precision floats to appropriate half of overlapping double.
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100587 for (RegisterInfo* info : reg_pool_->sp_regs_) {
buzbee091cc402014-03-31 10:14:40 -0700588 int sp_reg_num = info->GetReg().GetRegNum();
589 int dp_reg_num = sp_reg_num >> 1;
590 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
591 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
592 // Double precision register's master storage should refer to itself.
593 DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
594 // Redirect single precision's master storage to master.
595 info->SetMaster(dp_reg_info);
596 // Singles should show a single 32-bit mask bit, at first referring to the low half.
buzbee85089dd2014-05-25 15:10:52 -0700597 DCHECK_EQ(info->StorageMask(), RegisterInfo::kLowSingleStorageMask);
buzbee091cc402014-03-31 10:14:40 -0700598 if (sp_reg_num & 1) {
buzbee85089dd2014-05-25 15:10:52 -0700599 // For odd singles, change to use the high word of the backing double.
600 info->SetStorageMask(RegisterInfo::kHighSingleStorageMask);
buzbee091cc402014-03-31 10:14:40 -0700601 }
602 }
603
Wei Jin04f4d8a2014-05-29 18:04:29 -0700604#ifdef ARM_R4_SUSPEND_FLAG
Dave Allison83252962014-04-03 16:33:48 -0700605 // TODO: re-enable this when we can safely save r4 over the suspension code path.
606 bool no_suspend = NO_SUSPEND; // || !Runtime::Current()->ExplicitSuspendChecks();
buzbee091cc402014-03-31 10:14:40 -0700607 if (no_suspend) {
608 GetRegInfo(rs_rARM_SUSPEND)->MarkFree();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700609 }
Wei Jin04f4d8a2014-05-29 18:04:29 -0700610#endif
Brian Carlstrom7940e442013-07-12 13:46:57 -0700611
buzbee091cc402014-03-31 10:14:40 -0700612 // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
613 // TODO: adjust when we roll to hard float calling convention.
614 reg_pool_->next_core_reg_ = 2;
615 reg_pool_->next_sp_reg_ = 0;
616 reg_pool_->next_dp_reg_ = 0;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700617}
618
Brian Carlstrom7940e442013-07-12 13:46:57 -0700619/*
620 * TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some
621 * instructions might call out to C/assembly helper functions. Until
622 * machinery is in place, always spill lr.
623 */
624
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700625void ArmMir2Lir::AdjustSpillMask() {
buzbee091cc402014-03-31 10:14:40 -0700626 core_spill_mask_ |= (1 << rs_rARM_LR.GetRegNum());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700627 num_core_spills_++;
628}
629
630/*
631 * Mark a callee-save fp register as promoted. Note that
632 * vpush/vpop uses contiguous register lists so we must
633 * include any holes in the mask. Associate holes with
634 * Dalvik register INVALID_VREG (0xFFFFU).
635 */
buzbee091cc402014-03-31 10:14:40 -0700636void ArmMir2Lir::MarkPreservedSingle(int v_reg, RegStorage reg) {
637 DCHECK_GE(reg.GetRegNum(), ARM_FP_CALLEE_SAVE_BASE);
638 int adjusted_reg_num = reg.GetRegNum() - ARM_FP_CALLEE_SAVE_BASE;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700639 // Ensure fp_vmap_table is large enough
640 int table_size = fp_vmap_table_.size();
buzbee091cc402014-03-31 10:14:40 -0700641 for (int i = table_size; i < (adjusted_reg_num + 1); i++) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700642 fp_vmap_table_.push_back(INVALID_VREG);
643 }
644 // Add the current mapping
buzbee091cc402014-03-31 10:14:40 -0700645 fp_vmap_table_[adjusted_reg_num] = v_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700646 // Size of fp_vmap_table is high-water mark, use to set mask
647 num_fp_spills_ = fp_vmap_table_.size();
648 fp_spill_mask_ = ((1 << num_fp_spills_) - 1) << ARM_FP_CALLEE_SAVE_BASE;
649}
650
buzbee091cc402014-03-31 10:14:40 -0700651void ArmMir2Lir::MarkPreservedDouble(int v_reg, RegStorage reg) {
652 // TEMP: perform as 2 singles.
653 int reg_num = reg.GetRegNum() << 1;
654 RegStorage lo = RegStorage::Solo32(RegStorage::kFloatingPoint | reg_num);
655 RegStorage hi = RegStorage::Solo32(RegStorage::kFloatingPoint | reg_num | 1);
656 MarkPreservedSingle(v_reg, lo);
657 MarkPreservedSingle(v_reg + 1, hi);
buzbee2700f7e2014-03-07 09:46:20 -0800658}
659
Brian Carlstrom7940e442013-07-12 13:46:57 -0700660/* Clobber all regs that might be used by an external C call */
Vladimir Marko31c2aac2013-12-09 16:31:19 +0000661void ArmMir2Lir::ClobberCallerSave() {
buzbee091cc402014-03-31 10:14:40 -0700662 // TODO: rework this - it's gotten even more ugly.
663 Clobber(rs_r0);
664 Clobber(rs_r1);
665 Clobber(rs_r2);
666 Clobber(rs_r3);
667 Clobber(rs_r12);
668 Clobber(rs_r14lr);
669 Clobber(rs_fr0);
670 Clobber(rs_fr1);
671 Clobber(rs_fr2);
672 Clobber(rs_fr3);
673 Clobber(rs_fr4);
674 Clobber(rs_fr5);
675 Clobber(rs_fr6);
676 Clobber(rs_fr7);
677 Clobber(rs_fr8);
678 Clobber(rs_fr9);
679 Clobber(rs_fr10);
680 Clobber(rs_fr11);
681 Clobber(rs_fr12);
682 Clobber(rs_fr13);
683 Clobber(rs_fr14);
684 Clobber(rs_fr15);
685 Clobber(rs_dr0);
686 Clobber(rs_dr1);
687 Clobber(rs_dr2);
688 Clobber(rs_dr3);
689 Clobber(rs_dr4);
690 Clobber(rs_dr5);
691 Clobber(rs_dr6);
692 Clobber(rs_dr7);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700693}
694
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700695RegLocation ArmMir2Lir::GetReturnWideAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700696 RegLocation res = LocCReturnWide();
buzbee091cc402014-03-31 10:14:40 -0700697 res.reg.SetLowReg(rs_r2.GetReg());
698 res.reg.SetHighReg(rs_r3.GetReg());
699 Clobber(rs_r2);
700 Clobber(rs_r3);
701 MarkInUse(rs_r2);
702 MarkInUse(rs_r3);
703 MarkWide(res.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700704 return res;
705}
706
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700707RegLocation ArmMir2Lir::GetReturnAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700708 RegLocation res = LocCReturn();
buzbee091cc402014-03-31 10:14:40 -0700709 res.reg.SetReg(rs_r1.GetReg());
710 Clobber(rs_r1);
711 MarkInUse(rs_r1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700712 return res;
713}
714
Brian Carlstrom7940e442013-07-12 13:46:57 -0700715/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700716void ArmMir2Lir::LockCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700717 LockTemp(rs_r0);
718 LockTemp(rs_r1);
719 LockTemp(rs_r2);
720 LockTemp(rs_r3);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700721}
722
723/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700724void ArmMir2Lir::FreeCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700725 FreeTemp(rs_r0);
726 FreeTemp(rs_r1);
727 FreeTemp(rs_r2);
728 FreeTemp(rs_r3);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700729}
730
Andreas Gampe98430592014-07-27 19:44:50 -0700731RegStorage ArmMir2Lir::LoadHelper(QuickEntrypointEnum trampoline) {
732 LoadWordDisp(rs_rARM_SELF, GetThreadOffset<4>(trampoline).Int32Value(), rs_rARM_LR);
buzbee2700f7e2014-03-07 09:46:20 -0800733 return rs_rARM_LR;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700734}
735
Dave Allisonb373e092014-02-20 16:06:36 -0800736LIR* ArmMir2Lir::CheckSuspendUsingLoad() {
buzbee2700f7e2014-03-07 09:46:20 -0800737 RegStorage tmp = rs_r0;
buzbee695d13a2014-04-19 13:32:20 -0700738 Load32Disp(rs_rARM_SELF, Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
739 LIR* load2 = Load32Disp(tmp, 0, tmp);
Dave Allisonb373e092014-02-20 16:06:36 -0800740 return load2;
741}
742
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700743uint64_t ArmMir2Lir::GetTargetInstFlags(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700744 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700745 return ArmMir2Lir::EncodingMap[opcode].flags;
746}
747
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700748const char* ArmMir2Lir::GetTargetInstName(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700749 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700750 return ArmMir2Lir::EncodingMap[opcode].name;
751}
752
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700753const char* ArmMir2Lir::GetTargetInstFmt(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700754 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700755 return ArmMir2Lir::EncodingMap[opcode].fmt;
756}
757
buzbee091cc402014-03-31 10:14:40 -0700758/*
759 * Somewhat messy code here. We want to allocate a pair of contiguous
760 * physical single-precision floating point registers starting with
761 * an even numbered reg. It is possible that the paired s_reg (s_reg+1)
762 * has already been allocated - try to fit if possible. Fail to
763 * allocate if we can't meet the requirements for the pair of
764 * s_reg<=sX[even] & (s_reg+1)<= sX+1.
765 */
766// TODO: needs rewrite to support non-backed 64-bit float regs.
767RegStorage ArmMir2Lir::AllocPreservedDouble(int s_reg) {
768 RegStorage res;
769 int v_reg = mir_graph_->SRegToVReg(s_reg);
770 int p_map_idx = SRegToPMap(s_reg);
771 if (promotion_map_[p_map_idx+1].fp_location == kLocPhysReg) {
772 // Upper reg is already allocated. Can we fit?
buzbeeb5860fb2014-06-21 15:31:01 -0700773 int high_reg = promotion_map_[p_map_idx+1].fp_reg;
buzbee091cc402014-03-31 10:14:40 -0700774 if ((high_reg & 1) == 0) {
775 // High reg is even - fail.
776 return res; // Invalid.
777 }
778 // Is the low reg of the pair free?
779 // FIXME: rework.
780 RegisterInfo* p = GetRegInfo(RegStorage::FloatSolo32(high_reg - 1));
781 if (p->InUse() || p->IsTemp()) {
782 // Already allocated or not preserved - fail.
783 return res; // Invalid.
784 }
785 // OK - good to go.
786 res = RegStorage::FloatSolo64(p->GetReg().GetRegNum() >> 1);
787 p->MarkInUse();
788 MarkPreservedSingle(v_reg, p->GetReg());
789 } else {
790 /*
791 * TODO: until runtime support is in, make sure we avoid promoting the same vreg to
792 * different underlying physical registers.
793 */
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100794 for (RegisterInfo* info : reg_pool_->dp_regs_) {
buzbee091cc402014-03-31 10:14:40 -0700795 if (!info->IsTemp() && !info->InUse()) {
796 res = info->GetReg();
797 info->MarkInUse();
798 MarkPreservedDouble(v_reg, info->GetReg());
799 break;
800 }
801 }
802 }
803 if (res.Valid()) {
buzbee85089dd2014-05-25 15:10:52 -0700804 RegisterInfo* info = GetRegInfo(res);
buzbee091cc402014-03-31 10:14:40 -0700805 promotion_map_[p_map_idx].fp_location = kLocPhysReg;
buzbeeb5860fb2014-06-21 15:31:01 -0700806 promotion_map_[p_map_idx].fp_reg =
buzbee85089dd2014-05-25 15:10:52 -0700807 info->FindMatchingView(RegisterInfo::kLowSingleStorageMask)->GetReg().GetReg();
buzbee091cc402014-03-31 10:14:40 -0700808 promotion_map_[p_map_idx+1].fp_location = kLocPhysReg;
buzbeeb5860fb2014-06-21 15:31:01 -0700809 promotion_map_[p_map_idx+1].fp_reg =
buzbee85089dd2014-05-25 15:10:52 -0700810 info->FindMatchingView(RegisterInfo::kHighSingleStorageMask)->GetReg().GetReg();
buzbee091cc402014-03-31 10:14:40 -0700811 }
812 return res;
813}
814
buzbeeb5860fb2014-06-21 15:31:01 -0700815// Reserve a callee-save sp single register.
816RegStorage ArmMir2Lir::AllocPreservedSingle(int s_reg) {
817 RegStorage res;
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100818 for (RegisterInfo* info : reg_pool_->sp_regs_) {
buzbeeb5860fb2014-06-21 15:31:01 -0700819 if (!info->IsTemp() && !info->InUse()) {
820 res = info->GetReg();
821 int p_map_idx = SRegToPMap(s_reg);
822 int v_reg = mir_graph_->SRegToVReg(s_reg);
823 GetRegInfo(res)->MarkInUse();
824 MarkPreservedSingle(v_reg, res);
825 promotion_map_[p_map_idx].fp_location = kLocPhysReg;
826 promotion_map_[p_map_idx].fp_reg = res.GetReg();
827 break;
828 }
829 }
830 return res;
831}
832
Vladimir Markof4da6752014-08-01 19:04:18 +0100833void ArmMir2Lir::InstallLiteralPools() {
834 // PC-relative calls to methods.
835 patches_.reserve(call_method_insns_.size());
836 for (LIR* p : call_method_insns_) {
837 DCHECK_EQ(p->opcode, kThumb2Bl);
838 uint32_t target_method_idx = p->operands[1];
839 const DexFile* target_dex_file =
840 reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[2]));
841
842 patches_.push_back(LinkerPatch::RelativeCodePatch(p->offset,
843 target_dex_file, target_method_idx));
844 }
845
846 // And do the normal processing.
847 Mir2Lir::InstallLiteralPools();
848}
849
Brian Carlstrom7940e442013-07-12 13:46:57 -0700850} // namespace art