blob: aaf4449c1a9befa1f156454ca03969fd0a3709d0 [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;
455 case 'u': {
456 int offset_1 = lir->operands[0];
457 int offset_2 = NEXT_LIR(lir)->operands[0];
458 uintptr_t target =
459 (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) &
460 ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
461 0xfffffffc;
Ian Rogers988e6ea2014-01-08 11:30:50 -0800462 snprintf(tbuf, arraysize(tbuf), "%p", reinterpret_cast<void *>(target));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700463 break;
464 }
465
466 /* Nothing to print for BLX_2 */
467 case 'v':
468 strcpy(tbuf, "see above");
469 break;
470 case 'R':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800471 DecodeRegList(lir->opcode, operand, tbuf, arraysize(tbuf));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700472 break;
473 case 'P':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800474 DecodeFPCSRegList(operand, 16, tbuf, arraysize(tbuf));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700475 break;
476 case 'Q':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800477 DecodeFPCSRegList(operand, 0, tbuf, arraysize(tbuf));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700478 break;
479 default:
Brian Carlstromb1eba212013-07-17 18:07:19 -0700480 strcpy(tbuf, "DecodeError1");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700481 break;
482 }
483 buf += tbuf;
484 }
485 } else {
486 buf += *fmt++;
487 }
488 }
489 return buf;
490}
491
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100492void ArmMir2Lir::DumpResourceMask(LIR* arm_lir, const ResourceMask& mask, const char* prefix) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700493 char buf[256];
494 buf[0] = 0;
495
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100496 if (mask.Equals(kEncodeAll)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700497 strcpy(buf, "all");
498 } else {
499 char num[8];
500 int i;
501
502 for (i = 0; i < kArmRegEnd; i++) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100503 if (mask.HasBit(i)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800504 snprintf(num, arraysize(num), "%d ", i);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700505 strcat(buf, num);
506 }
507 }
508
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100509 if (mask.HasBit(ResourceMask::kCCode)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700510 strcat(buf, "cc ");
511 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100512 if (mask.HasBit(ResourceMask::kFPStatus)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700513 strcat(buf, "fpcc ");
514 }
515
516 /* Memory bits */
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100517 if (arm_lir && (mask.HasBit(ResourceMask::kDalvikReg))) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800518 snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s",
519 DECODE_ALIAS_INFO_REG(arm_lir->flags.alias_info),
520 DECODE_ALIAS_INFO_WIDE(arm_lir->flags.alias_info) ? "(+1)" : "");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700521 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100522 if (mask.HasBit(ResourceMask::kLiteral)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700523 strcat(buf, "lit ");
524 }
525
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100526 if (mask.HasBit(ResourceMask::kHeapRef)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700527 strcat(buf, "heap ");
528 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100529 if (mask.HasBit(ResourceMask::kMustNotAlias)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700530 strcat(buf, "noalias ");
531 }
532 }
533 if (buf[0]) {
534 LOG(INFO) << prefix << ": " << buf;
535 }
536}
537
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700538bool ArmMir2Lir::IsUnconditionalBranch(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700539 return ((lir->opcode == kThumbBUncond) || (lir->opcode == kThumb2BUncond));
540}
541
Vladimir Marko674744e2014-04-24 15:18:26 +0100542RegisterClass ArmMir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) {
543 if (UNLIKELY(is_volatile)) {
544 // On arm, atomic 64-bit load/store requires a core register pair.
545 // Smaller aligned load/store is atomic for both core and fp registers.
546 if (size == k64 || size == kDouble) {
547 return kCoreReg;
548 }
549 }
550 return RegClassBySize(size);
551}
552
Brian Carlstrom7940e442013-07-12 13:46:57 -0700553ArmMir2Lir::ArmMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
554 : Mir2Lir(cu, mir_graph, arena) {
555 // Sanity check - make sure encoding map lines up.
556 for (int i = 0; i < kArmLast; i++) {
557 if (ArmMir2Lir::EncodingMap[i].opcode != i) {
558 LOG(FATAL) << "Encoding order for " << ArmMir2Lir::EncodingMap[i].name
559 << " is wrong: expecting " << i << ", seeing "
560 << static_cast<int>(ArmMir2Lir::EncodingMap[i].opcode);
561 }
562 }
563}
564
565Mir2Lir* ArmCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
566 ArenaAllocator* const arena) {
567 return new ArmMir2Lir(cu, mir_graph, arena);
568}
569
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700570void ArmMir2Lir::CompilerInitializeRegAlloc() {
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100571 reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs, empty_pool /* core64 */,
572 sp_regs, dp_regs,
573 reserved_regs, empty_pool /* reserved64 */,
574 core_temps, empty_pool /* core64_temps */,
575 sp_temps, dp_temps));
Dave Allisonf6b65c12014-04-01 17:45:18 -0700576
buzbee091cc402014-03-31 10:14:40 -0700577 // Target-specific adjustments.
578
579 // Alias single precision floats to appropriate half of overlapping double.
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100580 for (RegisterInfo* info : reg_pool_->sp_regs_) {
buzbee091cc402014-03-31 10:14:40 -0700581 int sp_reg_num = info->GetReg().GetRegNum();
582 int dp_reg_num = sp_reg_num >> 1;
583 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
584 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
585 // Double precision register's master storage should refer to itself.
586 DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
587 // Redirect single precision's master storage to master.
588 info->SetMaster(dp_reg_info);
589 // Singles should show a single 32-bit mask bit, at first referring to the low half.
buzbee85089dd2014-05-25 15:10:52 -0700590 DCHECK_EQ(info->StorageMask(), RegisterInfo::kLowSingleStorageMask);
buzbee091cc402014-03-31 10:14:40 -0700591 if (sp_reg_num & 1) {
buzbee85089dd2014-05-25 15:10:52 -0700592 // For odd singles, change to use the high word of the backing double.
593 info->SetStorageMask(RegisterInfo::kHighSingleStorageMask);
buzbee091cc402014-03-31 10:14:40 -0700594 }
595 }
596
Wei Jin04f4d8a2014-05-29 18:04:29 -0700597#ifdef ARM_R4_SUSPEND_FLAG
Dave Allison83252962014-04-03 16:33:48 -0700598 // TODO: re-enable this when we can safely save r4 over the suspension code path.
599 bool no_suspend = NO_SUSPEND; // || !Runtime::Current()->ExplicitSuspendChecks();
buzbee091cc402014-03-31 10:14:40 -0700600 if (no_suspend) {
601 GetRegInfo(rs_rARM_SUSPEND)->MarkFree();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700602 }
Wei Jin04f4d8a2014-05-29 18:04:29 -0700603#endif
Brian Carlstrom7940e442013-07-12 13:46:57 -0700604
buzbee091cc402014-03-31 10:14:40 -0700605 // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
606 // TODO: adjust when we roll to hard float calling convention.
607 reg_pool_->next_core_reg_ = 2;
608 reg_pool_->next_sp_reg_ = 0;
609 reg_pool_->next_dp_reg_ = 0;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700610}
611
Brian Carlstrom7940e442013-07-12 13:46:57 -0700612/*
613 * TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some
614 * instructions might call out to C/assembly helper functions. Until
615 * machinery is in place, always spill lr.
616 */
617
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700618void ArmMir2Lir::AdjustSpillMask() {
buzbee091cc402014-03-31 10:14:40 -0700619 core_spill_mask_ |= (1 << rs_rARM_LR.GetRegNum());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700620 num_core_spills_++;
621}
622
623/*
624 * Mark a callee-save fp register as promoted. Note that
625 * vpush/vpop uses contiguous register lists so we must
626 * include any holes in the mask. Associate holes with
627 * Dalvik register INVALID_VREG (0xFFFFU).
628 */
buzbee091cc402014-03-31 10:14:40 -0700629void ArmMir2Lir::MarkPreservedSingle(int v_reg, RegStorage reg) {
630 DCHECK_GE(reg.GetRegNum(), ARM_FP_CALLEE_SAVE_BASE);
631 int adjusted_reg_num = reg.GetRegNum() - ARM_FP_CALLEE_SAVE_BASE;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700632 // Ensure fp_vmap_table is large enough
633 int table_size = fp_vmap_table_.size();
buzbee091cc402014-03-31 10:14:40 -0700634 for (int i = table_size; i < (adjusted_reg_num + 1); i++) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700635 fp_vmap_table_.push_back(INVALID_VREG);
636 }
637 // Add the current mapping
buzbee091cc402014-03-31 10:14:40 -0700638 fp_vmap_table_[adjusted_reg_num] = v_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700639 // Size of fp_vmap_table is high-water mark, use to set mask
640 num_fp_spills_ = fp_vmap_table_.size();
641 fp_spill_mask_ = ((1 << num_fp_spills_) - 1) << ARM_FP_CALLEE_SAVE_BASE;
642}
643
buzbee091cc402014-03-31 10:14:40 -0700644void ArmMir2Lir::MarkPreservedDouble(int v_reg, RegStorage reg) {
645 // TEMP: perform as 2 singles.
646 int reg_num = reg.GetRegNum() << 1;
647 RegStorage lo = RegStorage::Solo32(RegStorage::kFloatingPoint | reg_num);
648 RegStorage hi = RegStorage::Solo32(RegStorage::kFloatingPoint | reg_num | 1);
649 MarkPreservedSingle(v_reg, lo);
650 MarkPreservedSingle(v_reg + 1, hi);
buzbee2700f7e2014-03-07 09:46:20 -0800651}
652
Brian Carlstrom7940e442013-07-12 13:46:57 -0700653/* Clobber all regs that might be used by an external C call */
Vladimir Marko31c2aac2013-12-09 16:31:19 +0000654void ArmMir2Lir::ClobberCallerSave() {
buzbee091cc402014-03-31 10:14:40 -0700655 // TODO: rework this - it's gotten even more ugly.
656 Clobber(rs_r0);
657 Clobber(rs_r1);
658 Clobber(rs_r2);
659 Clobber(rs_r3);
660 Clobber(rs_r12);
661 Clobber(rs_r14lr);
662 Clobber(rs_fr0);
663 Clobber(rs_fr1);
664 Clobber(rs_fr2);
665 Clobber(rs_fr3);
666 Clobber(rs_fr4);
667 Clobber(rs_fr5);
668 Clobber(rs_fr6);
669 Clobber(rs_fr7);
670 Clobber(rs_fr8);
671 Clobber(rs_fr9);
672 Clobber(rs_fr10);
673 Clobber(rs_fr11);
674 Clobber(rs_fr12);
675 Clobber(rs_fr13);
676 Clobber(rs_fr14);
677 Clobber(rs_fr15);
678 Clobber(rs_dr0);
679 Clobber(rs_dr1);
680 Clobber(rs_dr2);
681 Clobber(rs_dr3);
682 Clobber(rs_dr4);
683 Clobber(rs_dr5);
684 Clobber(rs_dr6);
685 Clobber(rs_dr7);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700686}
687
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700688RegLocation ArmMir2Lir::GetReturnWideAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700689 RegLocation res = LocCReturnWide();
buzbee091cc402014-03-31 10:14:40 -0700690 res.reg.SetLowReg(rs_r2.GetReg());
691 res.reg.SetHighReg(rs_r3.GetReg());
692 Clobber(rs_r2);
693 Clobber(rs_r3);
694 MarkInUse(rs_r2);
695 MarkInUse(rs_r3);
696 MarkWide(res.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700697 return res;
698}
699
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700700RegLocation ArmMir2Lir::GetReturnAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700701 RegLocation res = LocCReturn();
buzbee091cc402014-03-31 10:14:40 -0700702 res.reg.SetReg(rs_r1.GetReg());
703 Clobber(rs_r1);
704 MarkInUse(rs_r1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700705 return res;
706}
707
Brian Carlstrom7940e442013-07-12 13:46:57 -0700708/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700709void ArmMir2Lir::LockCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700710 LockTemp(rs_r0);
711 LockTemp(rs_r1);
712 LockTemp(rs_r2);
713 LockTemp(rs_r3);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700714}
715
716/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700717void ArmMir2Lir::FreeCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700718 FreeTemp(rs_r0);
719 FreeTemp(rs_r1);
720 FreeTemp(rs_r2);
721 FreeTemp(rs_r3);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700722}
723
Andreas Gampe98430592014-07-27 19:44:50 -0700724RegStorage ArmMir2Lir::LoadHelper(QuickEntrypointEnum trampoline) {
725 LoadWordDisp(rs_rARM_SELF, GetThreadOffset<4>(trampoline).Int32Value(), rs_rARM_LR);
buzbee2700f7e2014-03-07 09:46:20 -0800726 return rs_rARM_LR;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700727}
728
Dave Allisonb373e092014-02-20 16:06:36 -0800729LIR* ArmMir2Lir::CheckSuspendUsingLoad() {
buzbee2700f7e2014-03-07 09:46:20 -0800730 RegStorage tmp = rs_r0;
buzbee695d13a2014-04-19 13:32:20 -0700731 Load32Disp(rs_rARM_SELF, Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
732 LIR* load2 = Load32Disp(tmp, 0, tmp);
Dave Allisonb373e092014-02-20 16:06:36 -0800733 return load2;
734}
735
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700736uint64_t ArmMir2Lir::GetTargetInstFlags(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700737 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700738 return ArmMir2Lir::EncodingMap[opcode].flags;
739}
740
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700741const char* ArmMir2Lir::GetTargetInstName(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700742 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700743 return ArmMir2Lir::EncodingMap[opcode].name;
744}
745
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700746const char* ArmMir2Lir::GetTargetInstFmt(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700747 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700748 return ArmMir2Lir::EncodingMap[opcode].fmt;
749}
750
buzbee091cc402014-03-31 10:14:40 -0700751/*
752 * Somewhat messy code here. We want to allocate a pair of contiguous
753 * physical single-precision floating point registers starting with
754 * an even numbered reg. It is possible that the paired s_reg (s_reg+1)
755 * has already been allocated - try to fit if possible. Fail to
756 * allocate if we can't meet the requirements for the pair of
757 * s_reg<=sX[even] & (s_reg+1)<= sX+1.
758 */
759// TODO: needs rewrite to support non-backed 64-bit float regs.
760RegStorage ArmMir2Lir::AllocPreservedDouble(int s_reg) {
761 RegStorage res;
762 int v_reg = mir_graph_->SRegToVReg(s_reg);
763 int p_map_idx = SRegToPMap(s_reg);
764 if (promotion_map_[p_map_idx+1].fp_location == kLocPhysReg) {
765 // Upper reg is already allocated. Can we fit?
buzbeeb5860fb2014-06-21 15:31:01 -0700766 int high_reg = promotion_map_[p_map_idx+1].fp_reg;
buzbee091cc402014-03-31 10:14:40 -0700767 if ((high_reg & 1) == 0) {
768 // High reg is even - fail.
769 return res; // Invalid.
770 }
771 // Is the low reg of the pair free?
772 // FIXME: rework.
773 RegisterInfo* p = GetRegInfo(RegStorage::FloatSolo32(high_reg - 1));
774 if (p->InUse() || p->IsTemp()) {
775 // Already allocated or not preserved - fail.
776 return res; // Invalid.
777 }
778 // OK - good to go.
779 res = RegStorage::FloatSolo64(p->GetReg().GetRegNum() >> 1);
780 p->MarkInUse();
781 MarkPreservedSingle(v_reg, p->GetReg());
782 } else {
783 /*
784 * TODO: until runtime support is in, make sure we avoid promoting the same vreg to
785 * different underlying physical registers.
786 */
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100787 for (RegisterInfo* info : reg_pool_->dp_regs_) {
buzbee091cc402014-03-31 10:14:40 -0700788 if (!info->IsTemp() && !info->InUse()) {
789 res = info->GetReg();
790 info->MarkInUse();
791 MarkPreservedDouble(v_reg, info->GetReg());
792 break;
793 }
794 }
795 }
796 if (res.Valid()) {
buzbee85089dd2014-05-25 15:10:52 -0700797 RegisterInfo* info = GetRegInfo(res);
buzbee091cc402014-03-31 10:14:40 -0700798 promotion_map_[p_map_idx].fp_location = kLocPhysReg;
buzbeeb5860fb2014-06-21 15:31:01 -0700799 promotion_map_[p_map_idx].fp_reg =
buzbee85089dd2014-05-25 15:10:52 -0700800 info->FindMatchingView(RegisterInfo::kLowSingleStorageMask)->GetReg().GetReg();
buzbee091cc402014-03-31 10:14:40 -0700801 promotion_map_[p_map_idx+1].fp_location = kLocPhysReg;
buzbeeb5860fb2014-06-21 15:31:01 -0700802 promotion_map_[p_map_idx+1].fp_reg =
buzbee85089dd2014-05-25 15:10:52 -0700803 info->FindMatchingView(RegisterInfo::kHighSingleStorageMask)->GetReg().GetReg();
buzbee091cc402014-03-31 10:14:40 -0700804 }
805 return res;
806}
807
buzbeeb5860fb2014-06-21 15:31:01 -0700808// Reserve a callee-save sp single register.
809RegStorage ArmMir2Lir::AllocPreservedSingle(int s_reg) {
810 RegStorage res;
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100811 for (RegisterInfo* info : reg_pool_->sp_regs_) {
buzbeeb5860fb2014-06-21 15:31:01 -0700812 if (!info->IsTemp() && !info->InUse()) {
813 res = info->GetReg();
814 int p_map_idx = SRegToPMap(s_reg);
815 int v_reg = mir_graph_->SRegToVReg(s_reg);
816 GetRegInfo(res)->MarkInUse();
817 MarkPreservedSingle(v_reg, res);
818 promotion_map_[p_map_idx].fp_location = kLocPhysReg;
819 promotion_map_[p_map_idx].fp_reg = res.GetReg();
820 break;
821 }
822 }
823 return res;
824}
825
Brian Carlstrom7940e442013-07-12 13:46:57 -0700826} // namespace art