blob: d3743531fb13b0dc9cfb0195cd592ed8391e0a06 [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) {
Zheng Xu5667fdb2014-10-23 18:29:55 +080092 RegStorage res_reg;
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;
Zheng Xu5667fdb2014-10-23 18:29:55 +0800107 case kFArg0: res_reg = kArm32QuickCodeUseSoftFloat ? rs_r0 : rs_fr0; break;
108 case kFArg1: res_reg = kArm32QuickCodeUseSoftFloat ? rs_r1 : rs_fr1; break;
109 case kFArg2: res_reg = kArm32QuickCodeUseSoftFloat ? rs_r2 : rs_fr2; break;
110 case kFArg3: res_reg = kArm32QuickCodeUseSoftFloat ? rs_r3 : rs_fr3; break;
111 case kFArg4: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr4; break;
112 case kFArg5: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr5; break;
113 case kFArg6: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr6; break;
114 case kFArg7: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr7; break;
115 case kFArg8: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr8; break;
116 case kFArg9: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr9; break;
117 case kFArg10: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr10; break;
118 case kFArg11: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr11; break;
119 case kFArg12: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr12; break;
120 case kFArg13: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr13; break;
121 case kFArg14: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr14; break;
122 case kFArg15: res_reg = kArm32QuickCodeUseSoftFloat ? RegStorage::InvalidReg() : rs_fr15; break;
buzbee091cc402014-03-31 10:14:40 -0700123 case kRet0: res_reg = rs_r0; break;
124 case kRet1: res_reg = rs_r1; break;
125 case kInvokeTgt: res_reg = rs_rARM_LR; break;
126 case kHiddenArg: res_reg = rs_r12; break;
127 case kHiddenFpArg: res_reg = RegStorage::InvalidReg(); break;
128 case kCount: res_reg = RegStorage::InvalidReg(); break;
Dmitry Petrochenko58994cd2014-05-17 01:02:18 +0700129 default: res_reg = RegStorage::InvalidReg();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700130 }
buzbee091cc402014-03-31 10:14:40 -0700131 return res_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700132}
133
Brian Carlstrom7940e442013-07-12 13:46:57 -0700134/*
135 * Decode the register id.
136 */
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100137ResourceMask ArmMir2Lir::GetRegMaskCommon(const RegStorage& reg) const {
138 return GetRegMaskArm(reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700139}
140
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100141constexpr ResourceMask ArmMir2Lir::GetRegMaskArm(RegStorage reg) {
142 return reg.IsDouble()
143 /* Each double register is equal to a pair of single-precision FP registers */
144 ? ResourceMask::TwoBits(reg.GetRegNum() * 2 + kArmFPReg0)
145 : ResourceMask::Bit(reg.IsSingle() ? reg.GetRegNum() + kArmFPReg0 : reg.GetRegNum());
146}
147
148constexpr ResourceMask ArmMir2Lir::EncodeArmRegList(int reg_list) {
149 return ResourceMask::RawMask(static_cast<uint64_t >(reg_list), 0u);
150}
151
152constexpr ResourceMask ArmMir2Lir::EncodeArmRegFpcsList(int reg_list) {
153 return ResourceMask::RawMask(static_cast<uint64_t >(reg_list) << kArmFPReg16, 0u);
154}
155
156ResourceMask ArmMir2Lir::GetPCUseDefEncoding() const {
157 return ResourceMask::Bit(kArmRegPC);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700158}
159
buzbeeb48819d2013-09-14 16:15:25 -0700160// Thumb2 specific setup. TODO: inline?:
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100161void ArmMir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags,
162 ResourceMask* use_mask, ResourceMask* def_mask) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700163 DCHECK_EQ(cu_->instruction_set, kThumb2);
buzbeeb48819d2013-09-14 16:15:25 -0700164 DCHECK(!lir->flags.use_def_invalid);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700165
Brian Carlstrom7940e442013-07-12 13:46:57 -0700166 int opcode = lir->opcode;
167
buzbeeb48819d2013-09-14 16:15:25 -0700168 // These flags are somewhat uncommon - bypass if we can.
169 if ((flags & (REG_DEF_SP | REG_USE_SP | REG_DEF_LIST0 | REG_DEF_LIST1 |
170 REG_DEF_FPCS_LIST0 | REG_DEF_FPCS_LIST2 | REG_USE_PC | IS_IT | REG_USE_LIST0 |
171 REG_USE_LIST1 | REG_USE_FPCS_LIST0 | REG_USE_FPCS_LIST2 | REG_DEF_LR)) != 0) {
172 if (flags & REG_DEF_SP) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100173 def_mask->SetBit(kArmRegSP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700174 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700175
buzbeeb48819d2013-09-14 16:15:25 -0700176 if (flags & REG_USE_SP) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100177 use_mask->SetBit(kArmRegSP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700178 }
buzbeeb48819d2013-09-14 16:15:25 -0700179
180 if (flags & REG_DEF_LIST0) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100181 def_mask->SetBits(EncodeArmRegList(lir->operands[0]));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700182 }
buzbeeb48819d2013-09-14 16:15:25 -0700183
184 if (flags & REG_DEF_LIST1) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100185 def_mask->SetBits(EncodeArmRegList(lir->operands[1]));
buzbeeb48819d2013-09-14 16:15:25 -0700186 }
187
188 if (flags & REG_DEF_FPCS_LIST0) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100189 def_mask->SetBits(EncodeArmRegList(lir->operands[0]));
buzbeeb48819d2013-09-14 16:15:25 -0700190 }
191
192 if (flags & REG_DEF_FPCS_LIST2) {
193 for (int i = 0; i < lir->operands[2]; i++) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100194 SetupRegMask(def_mask, lir->operands[1] + i);
buzbeeb48819d2013-09-14 16:15:25 -0700195 }
196 }
197
198 if (flags & REG_USE_PC) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100199 use_mask->SetBit(kArmRegPC);
buzbeeb48819d2013-09-14 16:15:25 -0700200 }
201
202 /* Conservatively treat the IT block */
203 if (flags & IS_IT) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100204 *def_mask = kEncodeAll;
buzbeeb48819d2013-09-14 16:15:25 -0700205 }
206
207 if (flags & REG_USE_LIST0) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100208 use_mask->SetBits(EncodeArmRegList(lir->operands[0]));
buzbeeb48819d2013-09-14 16:15:25 -0700209 }
210
211 if (flags & REG_USE_LIST1) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100212 use_mask->SetBits(EncodeArmRegList(lir->operands[1]));
buzbeeb48819d2013-09-14 16:15:25 -0700213 }
214
215 if (flags & REG_USE_FPCS_LIST0) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100216 use_mask->SetBits(EncodeArmRegList(lir->operands[0]));
buzbeeb48819d2013-09-14 16:15:25 -0700217 }
218
219 if (flags & REG_USE_FPCS_LIST2) {
220 for (int i = 0; i < lir->operands[2]; i++) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100221 SetupRegMask(use_mask, lir->operands[1] + i);
buzbeeb48819d2013-09-14 16:15:25 -0700222 }
223 }
224 /* Fixup for kThumbPush/lr and kThumbPop/pc */
225 if (opcode == kThumbPush || opcode == kThumbPop) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100226 constexpr ResourceMask r8Mask = GetRegMaskArm(rs_r8);
227 if ((opcode == kThumbPush) && (use_mask->Intersects(r8Mask))) {
228 use_mask->ClearBits(r8Mask);
229 use_mask->SetBit(kArmRegLR);
230 } else if ((opcode == kThumbPop) && (def_mask->Intersects(r8Mask))) {
231 def_mask->ClearBits(r8Mask);
232 def_mask->SetBit(kArmRegPC);;
buzbeeb48819d2013-09-14 16:15:25 -0700233 }
234 }
235 if (flags & REG_DEF_LR) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100236 def_mask->SetBit(kArmRegLR);
buzbeeb48819d2013-09-14 16:15:25 -0700237 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700238 }
239}
240
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700241ArmConditionCode ArmMir2Lir::ArmConditionEncoding(ConditionCode ccode) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700242 ArmConditionCode res;
243 switch (ccode) {
244 case kCondEq: res = kArmCondEq; break;
245 case kCondNe: res = kArmCondNe; break;
246 case kCondCs: res = kArmCondCs; break;
247 case kCondCc: res = kArmCondCc; break;
Vladimir Marko58af1f92013-12-19 13:31:15 +0000248 case kCondUlt: res = kArmCondCc; break;
249 case kCondUge: res = kArmCondCs; break;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700250 case kCondMi: res = kArmCondMi; break;
251 case kCondPl: res = kArmCondPl; break;
252 case kCondVs: res = kArmCondVs; break;
253 case kCondVc: res = kArmCondVc; break;
254 case kCondHi: res = kArmCondHi; break;
255 case kCondLs: res = kArmCondLs; break;
256 case kCondGe: res = kArmCondGe; break;
257 case kCondLt: res = kArmCondLt; break;
258 case kCondGt: res = kArmCondGt; break;
259 case kCondLe: res = kArmCondLe; break;
260 case kCondAl: res = kArmCondAl; break;
261 case kCondNv: res = kArmCondNv; break;
262 default:
263 LOG(FATAL) << "Bad condition code " << ccode;
264 res = static_cast<ArmConditionCode>(0); // Quiet gcc
265 }
266 return res;
267}
268
269static const char* core_reg_names[16] = {
270 "r0",
271 "r1",
272 "r2",
273 "r3",
274 "r4",
275 "r5",
276 "r6",
277 "r7",
278 "r8",
279 "rSELF",
280 "r10",
281 "r11",
282 "r12",
283 "sp",
284 "lr",
285 "pc",
286};
287
288
289static const char* shift_names[4] = {
290 "lsl",
291 "lsr",
292 "asr",
293 "ror"};
294
295/* Decode and print a ARM register name */
Ian Rogers988e6ea2014-01-08 11:30:50 -0800296static char* DecodeRegList(int opcode, int vector, char* buf, size_t buf_size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700297 int i;
298 bool printed = false;
299 buf[0] = 0;
300 for (i = 0; i < 16; i++, vector >>= 1) {
301 if (vector & 0x1) {
302 int reg_id = i;
303 if (opcode == kThumbPush && i == 8) {
buzbee091cc402014-03-31 10:14:40 -0700304 reg_id = rs_rARM_LR.GetRegNum();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700305 } else if (opcode == kThumbPop && i == 8) {
buzbee091cc402014-03-31 10:14:40 -0700306 reg_id = rs_rARM_PC.GetRegNum();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700307 }
308 if (printed) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800309 snprintf(buf + strlen(buf), buf_size - strlen(buf), ", r%d", reg_id);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700310 } else {
311 printed = true;
Ian Rogers988e6ea2014-01-08 11:30:50 -0800312 snprintf(buf, buf_size, "r%d", reg_id);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700313 }
314 }
315 }
316 return buf;
317}
318
Ian Rogers988e6ea2014-01-08 11:30:50 -0800319static char* DecodeFPCSRegList(int count, int base, char* buf, size_t buf_size) {
320 snprintf(buf, buf_size, "s%d", base);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700321 for (int i = 1; i < count; i++) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800322 snprintf(buf + strlen(buf), buf_size - strlen(buf), ", s%d", base + i);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700323 }
324 return buf;
325}
326
buzbee0d829482013-10-11 15:24:55 -0700327static int32_t ExpandImmediate(int value) {
328 int32_t mode = (value & 0xf00) >> 8;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700329 uint32_t bits = value & 0xff;
330 switch (mode) {
331 case 0:
332 return bits;
333 case 1:
334 return (bits << 16) | bits;
335 case 2:
336 return (bits << 24) | (bits << 8);
337 case 3:
338 return (bits << 24) | (bits << 16) | (bits << 8) | bits;
339 default:
340 break;
341 }
342 bits = (bits | 0x80) << 24;
343 return bits >> (((value & 0xf80) >> 7) - 8);
344}
345
Brian Carlstromb1eba212013-07-17 18:07:19 -0700346const char* cc_names[] = {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
347 "hi", "ls", "ge", "lt", "gt", "le", "al", "nv"};
Brian Carlstrom7940e442013-07-12 13:46:57 -0700348/*
349 * Interpret a format string and build a string no longer than size
350 * See format key in Assemble.c.
351 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700352std::string ArmMir2Lir::BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700353 std::string buf;
354 int i;
355 const char* fmt_end = &fmt[strlen(fmt)];
356 char tbuf[256];
357 const char* name;
358 char nc;
359 while (fmt < fmt_end) {
360 int operand;
361 if (*fmt == '!') {
362 fmt++;
363 DCHECK_LT(fmt, fmt_end);
364 nc = *fmt++;
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700365 if (nc == '!') {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700366 strcpy(tbuf, "!");
367 } else {
368 DCHECK_LT(fmt, fmt_end);
369 DCHECK_LT(static_cast<unsigned>(nc-'0'), 4U);
370 operand = lir->operands[nc-'0'];
371 switch (*fmt++) {
372 case 'H':
373 if (operand != 0) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800374 snprintf(tbuf, arraysize(tbuf), ", %s %d", shift_names[operand & 0x3], operand >> 2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700375 } else {
Brian Carlstromb1eba212013-07-17 18:07:19 -0700376 strcpy(tbuf, "");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700377 }
378 break;
379 case 'B':
380 switch (operand) {
381 case kSY:
382 name = "sy";
383 break;
384 case kST:
385 name = "st";
386 break;
387 case kISH:
388 name = "ish";
389 break;
390 case kISHST:
391 name = "ishst";
392 break;
393 case kNSH:
394 name = "nsh";
395 break;
396 case kNSHST:
397 name = "shst";
398 break;
399 default:
400 name = "DecodeError2";
401 break;
402 }
403 strcpy(tbuf, name);
404 break;
405 case 'b':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700406 strcpy(tbuf, "0000");
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700407 for (i = 3; i >= 0; i--) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700408 tbuf[i] += operand & 1;
409 operand >>= 1;
410 }
411 break;
412 case 'n':
413 operand = ~ExpandImmediate(operand);
Ian Rogers988e6ea2014-01-08 11:30:50 -0800414 snprintf(tbuf, arraysize(tbuf), "%d [%#x]", operand, operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700415 break;
416 case 'm':
417 operand = ExpandImmediate(operand);
Ian Rogers988e6ea2014-01-08 11:30:50 -0800418 snprintf(tbuf, arraysize(tbuf), "%d [%#x]", operand, operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700419 break;
420 case 's':
buzbee091cc402014-03-31 10:14:40 -0700421 snprintf(tbuf, arraysize(tbuf), "s%d", RegStorage::RegNum(operand));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700422 break;
423 case 'S':
buzbee091cc402014-03-31 10:14:40 -0700424 snprintf(tbuf, arraysize(tbuf), "d%d", RegStorage::RegNum(operand));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700425 break;
426 case 'h':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800427 snprintf(tbuf, arraysize(tbuf), "%04x", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700428 break;
429 case 'M':
430 case 'd':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800431 snprintf(tbuf, arraysize(tbuf), "%d", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700432 break;
433 case 'C':
buzbee091cc402014-03-31 10:14:40 -0700434 operand = RegStorage::RegNum(operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700435 DCHECK_LT(operand, static_cast<int>(
436 sizeof(core_reg_names)/sizeof(core_reg_names[0])));
Ian Rogers988e6ea2014-01-08 11:30:50 -0800437 snprintf(tbuf, arraysize(tbuf), "%s", core_reg_names[operand]);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700438 break;
439 case 'E':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800440 snprintf(tbuf, arraysize(tbuf), "%d", operand*4);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700441 break;
442 case 'F':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800443 snprintf(tbuf, arraysize(tbuf), "%d", operand*2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700444 break;
445 case 'c':
446 strcpy(tbuf, cc_names[operand]);
447 break;
448 case 't':
Ian Rogers107c31e2014-01-23 20:55:29 -0800449 snprintf(tbuf, arraysize(tbuf), "0x%08" PRIxPTR " (L%p)",
450 reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 + (operand << 1),
Brian Carlstrom7940e442013-07-12 13:46:57 -0700451 lir->target);
452 break;
Vladimir Markof4da6752014-08-01 19:04:18 +0100453 case 'T':
454 snprintf(tbuf, arraysize(tbuf), "%s", PrettyMethod(
455 static_cast<uint32_t>(lir->operands[1]),
456 *reinterpret_cast<const DexFile*>(UnwrapPointer(lir->operands[2]))).c_str());
457 break;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700458 case 'u': {
459 int offset_1 = lir->operands[0];
460 int offset_2 = NEXT_LIR(lir)->operands[0];
461 uintptr_t target =
462 (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) &
463 ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
464 0xfffffffc;
Ian Rogers988e6ea2014-01-08 11:30:50 -0800465 snprintf(tbuf, arraysize(tbuf), "%p", reinterpret_cast<void *>(target));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700466 break;
467 }
468
469 /* Nothing to print for BLX_2 */
470 case 'v':
471 strcpy(tbuf, "see above");
472 break;
473 case 'R':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800474 DecodeRegList(lir->opcode, operand, tbuf, arraysize(tbuf));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700475 break;
476 case 'P':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800477 DecodeFPCSRegList(operand, 16, tbuf, arraysize(tbuf));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700478 break;
479 case 'Q':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800480 DecodeFPCSRegList(operand, 0, tbuf, arraysize(tbuf));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700481 break;
482 default:
Brian Carlstromb1eba212013-07-17 18:07:19 -0700483 strcpy(tbuf, "DecodeError1");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700484 break;
485 }
486 buf += tbuf;
487 }
488 } else {
489 buf += *fmt++;
490 }
491 }
492 return buf;
493}
494
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100495void ArmMir2Lir::DumpResourceMask(LIR* arm_lir, const ResourceMask& mask, const char* prefix) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700496 char buf[256];
497 buf[0] = 0;
498
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100499 if (mask.Equals(kEncodeAll)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700500 strcpy(buf, "all");
501 } else {
502 char num[8];
503 int i;
504
505 for (i = 0; i < kArmRegEnd; i++) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100506 if (mask.HasBit(i)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800507 snprintf(num, arraysize(num), "%d ", i);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700508 strcat(buf, num);
509 }
510 }
511
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100512 if (mask.HasBit(ResourceMask::kCCode)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700513 strcat(buf, "cc ");
514 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100515 if (mask.HasBit(ResourceMask::kFPStatus)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700516 strcat(buf, "fpcc ");
517 }
518
519 /* Memory bits */
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100520 if (arm_lir && (mask.HasBit(ResourceMask::kDalvikReg))) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800521 snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s",
522 DECODE_ALIAS_INFO_REG(arm_lir->flags.alias_info),
523 DECODE_ALIAS_INFO_WIDE(arm_lir->flags.alias_info) ? "(+1)" : "");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700524 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100525 if (mask.HasBit(ResourceMask::kLiteral)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700526 strcat(buf, "lit ");
527 }
528
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100529 if (mask.HasBit(ResourceMask::kHeapRef)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700530 strcat(buf, "heap ");
531 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100532 if (mask.HasBit(ResourceMask::kMustNotAlias)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700533 strcat(buf, "noalias ");
534 }
535 }
536 if (buf[0]) {
537 LOG(INFO) << prefix << ": " << buf;
538 }
539}
540
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700541bool ArmMir2Lir::IsUnconditionalBranch(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700542 return ((lir->opcode == kThumbBUncond) || (lir->opcode == kThumb2BUncond));
543}
544
Vladimir Marko674744e2014-04-24 15:18:26 +0100545RegisterClass ArmMir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) {
546 if (UNLIKELY(is_volatile)) {
547 // On arm, atomic 64-bit load/store requires a core register pair.
548 // Smaller aligned load/store is atomic for both core and fp registers.
549 if (size == k64 || size == kDouble) {
550 return kCoreReg;
551 }
552 }
553 return RegClassBySize(size);
554}
555
Brian Carlstrom7940e442013-07-12 13:46:57 -0700556ArmMir2Lir::ArmMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
Vladimir Markof4da6752014-08-01 19:04:18 +0100557 : Mir2Lir(cu, mir_graph, arena),
558 call_method_insns_(arena->Adapter()) {
559 call_method_insns_.reserve(100);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700560 // Sanity check - make sure encoding map lines up.
561 for (int i = 0; i < kArmLast; i++) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700562 DCHECK_EQ(ArmMir2Lir::EncodingMap[i].opcode, i)
563 << "Encoding order for " << ArmMir2Lir::EncodingMap[i].name
564 << " is wrong: expecting " << i << ", seeing "
565 << static_cast<int>(ArmMir2Lir::EncodingMap[i].opcode);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700566 }
567}
568
569Mir2Lir* ArmCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
570 ArenaAllocator* const arena) {
571 return new ArmMir2Lir(cu, mir_graph, arena);
572}
573
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700574void ArmMir2Lir::CompilerInitializeRegAlloc() {
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100575 reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs, empty_pool /* core64 */,
576 sp_regs, dp_regs,
577 reserved_regs, empty_pool /* reserved64 */,
578 core_temps, empty_pool /* core64_temps */,
579 sp_temps, dp_temps));
Dave Allisonf6b65c12014-04-01 17:45:18 -0700580
buzbee091cc402014-03-31 10:14:40 -0700581 // Target-specific adjustments.
582
583 // Alias single precision floats to appropriate half of overlapping double.
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100584 for (RegisterInfo* info : reg_pool_->sp_regs_) {
buzbee091cc402014-03-31 10:14:40 -0700585 int sp_reg_num = info->GetReg().GetRegNum();
586 int dp_reg_num = sp_reg_num >> 1;
587 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
588 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
589 // Double precision register's master storage should refer to itself.
590 DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
591 // Redirect single precision's master storage to master.
592 info->SetMaster(dp_reg_info);
593 // Singles should show a single 32-bit mask bit, at first referring to the low half.
buzbee85089dd2014-05-25 15:10:52 -0700594 DCHECK_EQ(info->StorageMask(), RegisterInfo::kLowSingleStorageMask);
buzbee091cc402014-03-31 10:14:40 -0700595 if (sp_reg_num & 1) {
buzbee85089dd2014-05-25 15:10:52 -0700596 // For odd singles, change to use the high word of the backing double.
597 info->SetStorageMask(RegisterInfo::kHighSingleStorageMask);
buzbee091cc402014-03-31 10:14:40 -0700598 }
599 }
600
Wei Jin04f4d8a2014-05-29 18:04:29 -0700601#ifdef ARM_R4_SUSPEND_FLAG
Dave Allison83252962014-04-03 16:33:48 -0700602 // TODO: re-enable this when we can safely save r4 over the suspension code path.
603 bool no_suspend = NO_SUSPEND; // || !Runtime::Current()->ExplicitSuspendChecks();
buzbee091cc402014-03-31 10:14:40 -0700604 if (no_suspend) {
605 GetRegInfo(rs_rARM_SUSPEND)->MarkFree();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700606 }
Wei Jin04f4d8a2014-05-29 18:04:29 -0700607#endif
Brian Carlstrom7940e442013-07-12 13:46:57 -0700608
buzbee091cc402014-03-31 10:14:40 -0700609 // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
610 // TODO: adjust when we roll to hard float calling convention.
611 reg_pool_->next_core_reg_ = 2;
612 reg_pool_->next_sp_reg_ = 0;
613 reg_pool_->next_dp_reg_ = 0;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700614}
615
Brian Carlstrom7940e442013-07-12 13:46:57 -0700616/*
617 * TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some
618 * instructions might call out to C/assembly helper functions. Until
619 * machinery is in place, always spill lr.
620 */
621
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700622void ArmMir2Lir::AdjustSpillMask() {
buzbee091cc402014-03-31 10:14:40 -0700623 core_spill_mask_ |= (1 << rs_rARM_LR.GetRegNum());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700624 num_core_spills_++;
625}
626
627/*
628 * Mark a callee-save fp register as promoted. Note that
629 * vpush/vpop uses contiguous register lists so we must
630 * include any holes in the mask. Associate holes with
631 * Dalvik register INVALID_VREG (0xFFFFU).
632 */
buzbee091cc402014-03-31 10:14:40 -0700633void ArmMir2Lir::MarkPreservedSingle(int v_reg, RegStorage reg) {
634 DCHECK_GE(reg.GetRegNum(), ARM_FP_CALLEE_SAVE_BASE);
635 int adjusted_reg_num = reg.GetRegNum() - ARM_FP_CALLEE_SAVE_BASE;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700636 // Ensure fp_vmap_table is large enough
637 int table_size = fp_vmap_table_.size();
buzbee091cc402014-03-31 10:14:40 -0700638 for (int i = table_size; i < (adjusted_reg_num + 1); i++) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700639 fp_vmap_table_.push_back(INVALID_VREG);
640 }
641 // Add the current mapping
buzbee091cc402014-03-31 10:14:40 -0700642 fp_vmap_table_[adjusted_reg_num] = v_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700643 // Size of fp_vmap_table is high-water mark, use to set mask
644 num_fp_spills_ = fp_vmap_table_.size();
645 fp_spill_mask_ = ((1 << num_fp_spills_) - 1) << ARM_FP_CALLEE_SAVE_BASE;
646}
647
buzbee091cc402014-03-31 10:14:40 -0700648void ArmMir2Lir::MarkPreservedDouble(int v_reg, RegStorage reg) {
649 // TEMP: perform as 2 singles.
650 int reg_num = reg.GetRegNum() << 1;
651 RegStorage lo = RegStorage::Solo32(RegStorage::kFloatingPoint | reg_num);
652 RegStorage hi = RegStorage::Solo32(RegStorage::kFloatingPoint | reg_num | 1);
653 MarkPreservedSingle(v_reg, lo);
654 MarkPreservedSingle(v_reg + 1, hi);
buzbee2700f7e2014-03-07 09:46:20 -0800655}
656
Brian Carlstrom7940e442013-07-12 13:46:57 -0700657/* Clobber all regs that might be used by an external C call */
Vladimir Marko31c2aac2013-12-09 16:31:19 +0000658void ArmMir2Lir::ClobberCallerSave() {
buzbee091cc402014-03-31 10:14:40 -0700659 // TODO: rework this - it's gotten even more ugly.
660 Clobber(rs_r0);
661 Clobber(rs_r1);
662 Clobber(rs_r2);
663 Clobber(rs_r3);
664 Clobber(rs_r12);
665 Clobber(rs_r14lr);
666 Clobber(rs_fr0);
667 Clobber(rs_fr1);
668 Clobber(rs_fr2);
669 Clobber(rs_fr3);
670 Clobber(rs_fr4);
671 Clobber(rs_fr5);
672 Clobber(rs_fr6);
673 Clobber(rs_fr7);
674 Clobber(rs_fr8);
675 Clobber(rs_fr9);
676 Clobber(rs_fr10);
677 Clobber(rs_fr11);
678 Clobber(rs_fr12);
679 Clobber(rs_fr13);
680 Clobber(rs_fr14);
681 Clobber(rs_fr15);
682 Clobber(rs_dr0);
683 Clobber(rs_dr1);
684 Clobber(rs_dr2);
685 Clobber(rs_dr3);
686 Clobber(rs_dr4);
687 Clobber(rs_dr5);
688 Clobber(rs_dr6);
689 Clobber(rs_dr7);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700690}
691
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700692RegLocation ArmMir2Lir::GetReturnWideAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700693 RegLocation res = LocCReturnWide();
buzbee091cc402014-03-31 10:14:40 -0700694 res.reg.SetLowReg(rs_r2.GetReg());
695 res.reg.SetHighReg(rs_r3.GetReg());
696 Clobber(rs_r2);
697 Clobber(rs_r3);
698 MarkInUse(rs_r2);
699 MarkInUse(rs_r3);
700 MarkWide(res.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700701 return res;
702}
703
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700704RegLocation ArmMir2Lir::GetReturnAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700705 RegLocation res = LocCReturn();
buzbee091cc402014-03-31 10:14:40 -0700706 res.reg.SetReg(rs_r1.GetReg());
707 Clobber(rs_r1);
708 MarkInUse(rs_r1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700709 return res;
710}
711
Brian Carlstrom7940e442013-07-12 13:46:57 -0700712/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700713void ArmMir2Lir::LockCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700714 LockTemp(rs_r0);
715 LockTemp(rs_r1);
716 LockTemp(rs_r2);
717 LockTemp(rs_r3);
Zheng Xu5667fdb2014-10-23 18:29:55 +0800718 if (!kArm32QuickCodeUseSoftFloat) {
719 LockTemp(rs_fr0);
720 LockTemp(rs_fr1);
721 LockTemp(rs_fr2);
722 LockTemp(rs_fr3);
723 LockTemp(rs_fr4);
724 LockTemp(rs_fr5);
725 LockTemp(rs_fr6);
726 LockTemp(rs_fr7);
727 LockTemp(rs_fr8);
728 LockTemp(rs_fr9);
729 LockTemp(rs_fr10);
730 LockTemp(rs_fr11);
731 LockTemp(rs_fr12);
732 LockTemp(rs_fr13);
733 LockTemp(rs_fr14);
734 LockTemp(rs_fr15);
735 LockTemp(rs_dr0);
736 LockTemp(rs_dr1);
737 LockTemp(rs_dr2);
738 LockTemp(rs_dr3);
739 LockTemp(rs_dr4);
740 LockTemp(rs_dr5);
741 LockTemp(rs_dr6);
742 LockTemp(rs_dr7);
743 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700744}
745
746/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700747void ArmMir2Lir::FreeCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700748 FreeTemp(rs_r0);
749 FreeTemp(rs_r1);
750 FreeTemp(rs_r2);
751 FreeTemp(rs_r3);
Zheng Xu5667fdb2014-10-23 18:29:55 +0800752 if (!kArm32QuickCodeUseSoftFloat) {
753 FreeTemp(rs_fr0);
754 FreeTemp(rs_fr1);
755 FreeTemp(rs_fr2);
756 FreeTemp(rs_fr3);
757 FreeTemp(rs_fr4);
758 FreeTemp(rs_fr5);
759 FreeTemp(rs_fr6);
760 FreeTemp(rs_fr7);
761 FreeTemp(rs_fr8);
762 FreeTemp(rs_fr9);
763 FreeTemp(rs_fr10);
764 FreeTemp(rs_fr11);
765 FreeTemp(rs_fr12);
766 FreeTemp(rs_fr13);
767 FreeTemp(rs_fr14);
768 FreeTemp(rs_fr15);
769 FreeTemp(rs_dr0);
770 FreeTemp(rs_dr1);
771 FreeTemp(rs_dr2);
772 FreeTemp(rs_dr3);
773 FreeTemp(rs_dr4);
774 FreeTemp(rs_dr5);
775 FreeTemp(rs_dr6);
776 FreeTemp(rs_dr7);
777 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700778}
779
Andreas Gampe98430592014-07-27 19:44:50 -0700780RegStorage ArmMir2Lir::LoadHelper(QuickEntrypointEnum trampoline) {
781 LoadWordDisp(rs_rARM_SELF, GetThreadOffset<4>(trampoline).Int32Value(), rs_rARM_LR);
buzbee2700f7e2014-03-07 09:46:20 -0800782 return rs_rARM_LR;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700783}
784
Dave Allisonb373e092014-02-20 16:06:36 -0800785LIR* ArmMir2Lir::CheckSuspendUsingLoad() {
buzbee2700f7e2014-03-07 09:46:20 -0800786 RegStorage tmp = rs_r0;
buzbee695d13a2014-04-19 13:32:20 -0700787 Load32Disp(rs_rARM_SELF, Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
788 LIR* load2 = Load32Disp(tmp, 0, tmp);
Dave Allisonb373e092014-02-20 16:06:36 -0800789 return load2;
790}
791
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700792uint64_t ArmMir2Lir::GetTargetInstFlags(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700793 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700794 return ArmMir2Lir::EncodingMap[opcode].flags;
795}
796
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700797const char* ArmMir2Lir::GetTargetInstName(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700798 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700799 return ArmMir2Lir::EncodingMap[opcode].name;
800}
801
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700802const char* ArmMir2Lir::GetTargetInstFmt(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700803 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700804 return ArmMir2Lir::EncodingMap[opcode].fmt;
805}
806
buzbee091cc402014-03-31 10:14:40 -0700807/*
808 * Somewhat messy code here. We want to allocate a pair of contiguous
809 * physical single-precision floating point registers starting with
810 * an even numbered reg. It is possible that the paired s_reg (s_reg+1)
811 * has already been allocated - try to fit if possible. Fail to
812 * allocate if we can't meet the requirements for the pair of
813 * s_reg<=sX[even] & (s_reg+1)<= sX+1.
814 */
815// TODO: needs rewrite to support non-backed 64-bit float regs.
816RegStorage ArmMir2Lir::AllocPreservedDouble(int s_reg) {
817 RegStorage res;
818 int v_reg = mir_graph_->SRegToVReg(s_reg);
819 int p_map_idx = SRegToPMap(s_reg);
820 if (promotion_map_[p_map_idx+1].fp_location == kLocPhysReg) {
821 // Upper reg is already allocated. Can we fit?
buzbeeb5860fb2014-06-21 15:31:01 -0700822 int high_reg = promotion_map_[p_map_idx+1].fp_reg;
buzbee091cc402014-03-31 10:14:40 -0700823 if ((high_reg & 1) == 0) {
824 // High reg is even - fail.
825 return res; // Invalid.
826 }
827 // Is the low reg of the pair free?
828 // FIXME: rework.
829 RegisterInfo* p = GetRegInfo(RegStorage::FloatSolo32(high_reg - 1));
830 if (p->InUse() || p->IsTemp()) {
831 // Already allocated or not preserved - fail.
832 return res; // Invalid.
833 }
834 // OK - good to go.
835 res = RegStorage::FloatSolo64(p->GetReg().GetRegNum() >> 1);
836 p->MarkInUse();
837 MarkPreservedSingle(v_reg, p->GetReg());
838 } else {
839 /*
840 * TODO: until runtime support is in, make sure we avoid promoting the same vreg to
841 * different underlying physical registers.
842 */
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100843 for (RegisterInfo* info : reg_pool_->dp_regs_) {
buzbee091cc402014-03-31 10:14:40 -0700844 if (!info->IsTemp() && !info->InUse()) {
845 res = info->GetReg();
846 info->MarkInUse();
847 MarkPreservedDouble(v_reg, info->GetReg());
848 break;
849 }
850 }
851 }
852 if (res.Valid()) {
buzbee85089dd2014-05-25 15:10:52 -0700853 RegisterInfo* info = GetRegInfo(res);
buzbee091cc402014-03-31 10:14:40 -0700854 promotion_map_[p_map_idx].fp_location = kLocPhysReg;
buzbeeb5860fb2014-06-21 15:31:01 -0700855 promotion_map_[p_map_idx].fp_reg =
buzbee85089dd2014-05-25 15:10:52 -0700856 info->FindMatchingView(RegisterInfo::kLowSingleStorageMask)->GetReg().GetReg();
buzbee091cc402014-03-31 10:14:40 -0700857 promotion_map_[p_map_idx+1].fp_location = kLocPhysReg;
buzbeeb5860fb2014-06-21 15:31:01 -0700858 promotion_map_[p_map_idx+1].fp_reg =
buzbee85089dd2014-05-25 15:10:52 -0700859 info->FindMatchingView(RegisterInfo::kHighSingleStorageMask)->GetReg().GetReg();
buzbee091cc402014-03-31 10:14:40 -0700860 }
861 return res;
862}
863
buzbeeb5860fb2014-06-21 15:31:01 -0700864// Reserve a callee-save sp single register.
865RegStorage ArmMir2Lir::AllocPreservedSingle(int s_reg) {
866 RegStorage res;
Vladimir Markoe39c54e2014-09-22 14:50:02 +0100867 for (RegisterInfo* info : reg_pool_->sp_regs_) {
buzbeeb5860fb2014-06-21 15:31:01 -0700868 if (!info->IsTemp() && !info->InUse()) {
869 res = info->GetReg();
870 int p_map_idx = SRegToPMap(s_reg);
871 int v_reg = mir_graph_->SRegToVReg(s_reg);
872 GetRegInfo(res)->MarkInUse();
873 MarkPreservedSingle(v_reg, res);
874 promotion_map_[p_map_idx].fp_location = kLocPhysReg;
875 promotion_map_[p_map_idx].fp_reg = res.GetReg();
876 break;
877 }
878 }
879 return res;
880}
881
Vladimir Markof4da6752014-08-01 19:04:18 +0100882void ArmMir2Lir::InstallLiteralPools() {
883 // PC-relative calls to methods.
884 patches_.reserve(call_method_insns_.size());
885 for (LIR* p : call_method_insns_) {
886 DCHECK_EQ(p->opcode, kThumb2Bl);
887 uint32_t target_method_idx = p->operands[1];
888 const DexFile* target_dex_file =
889 reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[2]));
890
891 patches_.push_back(LinkerPatch::RelativeCodePatch(p->offset,
892 target_dex_file, target_method_idx));
893 }
894
895 // And do the normal processing.
896 Mir2Lir::InstallLiteralPools();
897}
898
Serguei Katkov717a3e42014-11-13 17:19:42 +0600899RegStorage ArmMir2Lir::InToRegStorageArmMapper::GetNextReg(ShortyArg arg) {
Zheng Xu5667fdb2014-10-23 18:29:55 +0800900 const RegStorage coreArgMappingToPhysicalReg[] =
901 {rs_r1, rs_r2, rs_r3};
902 const int coreArgMappingToPhysicalRegSize = arraysize(coreArgMappingToPhysicalReg);
903 const RegStorage fpArgMappingToPhysicalReg[] =
904 {rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7,
905 rs_fr8, rs_fr9, rs_fr10, rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15};
Andreas Gampe785d2f22014-11-03 22:57:30 -0800906 constexpr uint32_t fpArgMappingToPhysicalRegSize = arraysize(fpArgMappingToPhysicalReg);
907 static_assert(fpArgMappingToPhysicalRegSize % 2 == 0, "Number of FP Arg regs is not even");
Zheng Xu5667fdb2014-10-23 18:29:55 +0800908
Zheng Xu5667fdb2014-10-23 18:29:55 +0800909 RegStorage result = RegStorage::InvalidReg();
Serguei Katkov717a3e42014-11-13 17:19:42 +0600910 // Regard double as long, float as int for kArm32QuickCodeUseSoftFloat.
911 if (arg.IsFP() && !kArm32QuickCodeUseSoftFloat) {
912 if (arg.IsWide()) {
Zheng Xu5667fdb2014-10-23 18:29:55 +0800913 cur_fp_double_reg_ = std::max(cur_fp_double_reg_, RoundUp(cur_fp_reg_, 2));
914 if (cur_fp_double_reg_ < fpArgMappingToPhysicalRegSize) {
Serguei Katkov717a3e42014-11-13 17:19:42 +0600915 result = RegStorage::MakeRegPair(fpArgMappingToPhysicalReg[cur_fp_double_reg_],
916 fpArgMappingToPhysicalReg[cur_fp_double_reg_ + 1]);
917 result = As64BitFloatReg(result);
918 cur_fp_double_reg_ += 2;
Zheng Xu5667fdb2014-10-23 18:29:55 +0800919 }
920 } else {
Zheng Xu5667fdb2014-10-23 18:29:55 +0800921 if (cur_fp_reg_ % 2 == 0) {
922 cur_fp_reg_ = std::max(cur_fp_double_reg_, cur_fp_reg_);
923 }
924 if (cur_fp_reg_ < fpArgMappingToPhysicalRegSize) {
925 result = fpArgMappingToPhysicalReg[cur_fp_reg_];
926 cur_fp_reg_++;
927 }
928 }
929 } else {
930 if (cur_core_reg_ < coreArgMappingToPhysicalRegSize) {
931 result = coreArgMappingToPhysicalReg[cur_core_reg_++];
Serguei Katkov717a3e42014-11-13 17:19:42 +0600932 if (arg.IsWide() && cur_core_reg_ < coreArgMappingToPhysicalRegSize) {
933 result = RegStorage::MakeRegPair(result, coreArgMappingToPhysicalReg[cur_core_reg_++]);
934 }
Zheng Xu5667fdb2014-10-23 18:29:55 +0800935 }
936 }
937 return result;
938}
939
Serguei Katkov717a3e42014-11-13 17:19:42 +0600940int ArmMir2Lir::GenDalvikArgsBulkCopy(CallInfo* info, int first, int count) {
Zheng Xu5667fdb2014-10-23 18:29:55 +0800941 if (kArm32QuickCodeUseSoftFloat) {
Serguei Katkov717a3e42014-11-13 17:19:42 +0600942 return Mir2Lir::GenDalvikArgsBulkCopy(info, first, count);
Zheng Xu5667fdb2014-10-23 18:29:55 +0800943 }
Serguei Katkov717a3e42014-11-13 17:19:42 +0600944 /*
945 * TODO: Improve by adding block copy for large number of arguments. For now, just
946 * copy a Dalvik vreg at a time.
947 */
948 return count;
Zheng Xu5667fdb2014-10-23 18:29:55 +0800949}
950
Ningsheng Jiana262f772014-11-25 16:48:07 +0800951void ArmMir2Lir::GenMachineSpecificExtendedMethodMIR(BasicBlock* bb, MIR* mir) {
952 UNUSED(bb);
953 DCHECK(MIR::DecodedInstruction::IsPseudoMirOp(mir->dalvikInsn.opcode));
954 RegLocation rl_src[3];
955 RegLocation rl_dest = mir_graph_->GetBadLoc();
956 rl_src[0] = rl_src[1] = rl_src[2] = mir_graph_->GetBadLoc();
957 switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) {
958 case kMirOpMaddInt:
959 rl_dest = mir_graph_->GetDest(mir);
960 rl_src[0] = mir_graph_->GetSrc(mir, 0);
961 rl_src[1] = mir_graph_->GetSrc(mir, 1);
962 rl_src[2]= mir_graph_->GetSrc(mir, 2);
963 GenMaddMsubInt(rl_dest, rl_src[0], rl_src[1], rl_src[2], false);
964 break;
965 case kMirOpMsubInt:
966 rl_dest = mir_graph_->GetDest(mir);
967 rl_src[0] = mir_graph_->GetSrc(mir, 0);
968 rl_src[1] = mir_graph_->GetSrc(mir, 1);
969 rl_src[2]= mir_graph_->GetSrc(mir, 2);
970 GenMaddMsubInt(rl_dest, rl_src[0], rl_src[1], rl_src[2], true);
971 break;
972 default:
973 LOG(FATAL) << "Unexpected opcode: " << mir->dalvikInsn.opcode;
974 }
975}
976
Brian Carlstrom7940e442013-07-12 13:46:57 -0700977} // namespace art