blob: 1fe2beadc45dc518f30cea76f6b25c0c939dd9ca [file] [log] [blame]
Brian Carlstrom7940e442013-07-12 13:46:57 -07001/*
2 * Copyright (C) 2012 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
17#include "codegen_mips.h"
Ian Rogers107c31e2014-01-23 20:55:29 -080018
19#include <inttypes.h>
20
21#include <string>
22
Brian Carlstrom7940e442013-07-12 13:46:57 -070023#include "dex/compiler_internals.h"
24#include "dex/quick/mir_to_lir-inl.h"
25#include "mips_lir.h"
26
Brian Carlstrom7940e442013-07-12 13:46:57 -070027namespace art {
28
buzbee2700f7e2014-03-07 09:46:20 -080029static int core_regs[] = {rZERO, rAT, rV0, rV1, rA0, rA1, rA2, rA3,
30 rT0, rT1, rT2, rT3, rT4, rT5, rT6, rT7,
31 rS0, rS1, rS2, rS3, rS4, rS5, rS6, rS7, rT8,
32 rT9, rK0, rK1, rGP, rSP, rFP, rRA};
33static int ReservedRegs[] = {rZERO, rAT, rS0, rS1, rK0, rK1, rGP, rSP,
34 rRA};
35static int core_temps[] = {rV0, rV1, rA0, rA1, rA2, rA3, rT0, rT1, rT2,
36 rT3, rT4, rT5, rT6, rT7, rT8};
37static int FpRegs[] = {rF0, rF1, rF2, rF3, rF4, rF5, rF6, rF7,
38 rF8, rF9, rF10, rF11, rF12, rF13, rF14, rF15};
39static int fp_temps[] = {rF0, rF1, rF2, rF3, rF4, rF5, rF6, rF7,
40 rF8, rF9, rF10, rF11, rF12, rF13, rF14, rF15};
Brian Carlstrom7940e442013-07-12 13:46:57 -070041
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070042RegLocation MipsMir2Lir::LocCReturn() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000043 return mips_loc_c_return;
Brian Carlstrom7940e442013-07-12 13:46:57 -070044}
45
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070046RegLocation MipsMir2Lir::LocCReturnWide() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000047 return mips_loc_c_return_wide;
Brian Carlstrom7940e442013-07-12 13:46:57 -070048}
49
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070050RegLocation MipsMir2Lir::LocCReturnFloat() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000051 return mips_loc_c_return_float;
Brian Carlstrom7940e442013-07-12 13:46:57 -070052}
53
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070054RegLocation MipsMir2Lir::LocCReturnDouble() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000055 return mips_loc_c_return_double;
Brian Carlstrom7940e442013-07-12 13:46:57 -070056}
57
58// Return a target-dependent special register.
buzbee2700f7e2014-03-07 09:46:20 -080059RegStorage MipsMir2Lir::TargetReg(SpecialTargetRegister reg) {
60 int res_reg = RegStorage::kInvalidRegVal;
Brian Carlstrom7940e442013-07-12 13:46:57 -070061 switch (reg) {
buzbee2700f7e2014-03-07 09:46:20 -080062 case kSelf: res_reg = rMIPS_SELF; break;
63 case kSuspend: res_reg = rMIPS_SUSPEND; break;
64 case kLr: res_reg = rMIPS_LR; break;
65 case kPc: res_reg = rMIPS_PC; break;
66 case kSp: res_reg = rMIPS_SP; break;
67 case kArg0: res_reg = rMIPS_ARG0; break;
68 case kArg1: res_reg = rMIPS_ARG1; break;
69 case kArg2: res_reg = rMIPS_ARG2; break;
70 case kArg3: res_reg = rMIPS_ARG3; break;
71 case kFArg0: res_reg = rMIPS_FARG0; break;
72 case kFArg1: res_reg = rMIPS_FARG1; break;
73 case kFArg2: res_reg = rMIPS_FARG2; break;
74 case kFArg3: res_reg = rMIPS_FARG3; break;
75 case kRet0: res_reg = rMIPS_RET0; break;
76 case kRet1: res_reg = rMIPS_RET1; break;
77 case kInvokeTgt: res_reg = rMIPS_INVOKE_TGT; break;
78 case kHiddenArg: res_reg = rT0; break;
79 case kHiddenFpArg: res_reg = RegStorage::kInvalidRegVal; break;
80 case kCount: res_reg = rMIPS_COUNT; break;
Brian Carlstrom7940e442013-07-12 13:46:57 -070081 }
buzbee2700f7e2014-03-07 09:46:20 -080082 return RegStorage::Solo32(res_reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -070083}
84
buzbee2700f7e2014-03-07 09:46:20 -080085RegStorage MipsMir2Lir::GetArgMappingToPhysicalReg(int arg_num) {
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -080086 // For the 32-bit internal ABI, the first 3 arguments are passed in registers.
87 switch (arg_num) {
88 case 0:
buzbee2700f7e2014-03-07 09:46:20 -080089 return rs_rMIPS_ARG1;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -080090 case 1:
buzbee2700f7e2014-03-07 09:46:20 -080091 return rs_rMIPS_ARG2;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -080092 case 2:
buzbee2700f7e2014-03-07 09:46:20 -080093 return rs_rMIPS_ARG3;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -080094 default:
buzbee2700f7e2014-03-07 09:46:20 -080095 return RegStorage::InvalidReg();
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -080096 }
97}
98
Brian Carlstrom7940e442013-07-12 13:46:57 -070099// Create a double from a pair of singles.
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700100int MipsMir2Lir::S2d(int low_reg, int high_reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700101 return MIPS_S2D(low_reg, high_reg);
102}
103
104// Return mask to strip off fp reg flags and bias.
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700105uint32_t MipsMir2Lir::FpRegMask() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700106 return MIPS_FP_REG_MASK;
107}
108
109// True if both regs single, both core or both double.
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700110bool MipsMir2Lir::SameRegType(int reg1, int reg2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700111 return (MIPS_REGTYPE(reg1) == MIPS_REGTYPE(reg2));
112}
113
114/*
115 * Decode the register id.
116 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700117uint64_t MipsMir2Lir::GetRegMaskCommon(int reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700118 uint64_t seed;
119 int shift;
120 int reg_id;
121
122
123 reg_id = reg & 0x1f;
124 /* Each double register is equal to a pair of single-precision FP registers */
125 seed = MIPS_DOUBLEREG(reg) ? 3 : 1;
126 /* FP register starts at bit position 16 */
127 shift = MIPS_FPREG(reg) ? kMipsFPReg0 : 0;
128 /* Expand the double register id into single offset */
129 shift += reg_id;
130 return (seed << shift);
131}
132
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700133uint64_t MipsMir2Lir::GetPCUseDefEncoding() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700134 return ENCODE_MIPS_REG_PC;
135}
136
137
buzbeeb48819d2013-09-14 16:15:25 -0700138void MipsMir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700139 DCHECK_EQ(cu_->instruction_set, kMips);
buzbeeb48819d2013-09-14 16:15:25 -0700140 DCHECK(!lir->flags.use_def_invalid);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700141
142 // Mips-specific resource map setup here.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700143 if (flags & REG_DEF_SP) {
buzbeeb48819d2013-09-14 16:15:25 -0700144 lir->u.m.def_mask |= ENCODE_MIPS_REG_SP;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700145 }
146
147 if (flags & REG_USE_SP) {
buzbeeb48819d2013-09-14 16:15:25 -0700148 lir->u.m.use_mask |= ENCODE_MIPS_REG_SP;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700149 }
150
151 if (flags & REG_DEF_LR) {
buzbeeb48819d2013-09-14 16:15:25 -0700152 lir->u.m.def_mask |= ENCODE_MIPS_REG_LR;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700153 }
154}
155
156/* For dumping instructions */
157#define MIPS_REG_COUNT 32
158static const char *mips_reg_name[MIPS_REG_COUNT] = {
159 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
160 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
161 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
162 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
163};
164
165/*
166 * Interpret a format string and build a string no longer than size
167 * See format key in Assemble.c.
168 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700169std::string MipsMir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700170 std::string buf;
171 int i;
172 const char *fmt_end = &fmt[strlen(fmt)];
173 char tbuf[256];
174 char nc;
175 while (fmt < fmt_end) {
176 int operand;
177 if (*fmt == '!') {
178 fmt++;
179 DCHECK_LT(fmt, fmt_end);
180 nc = *fmt++;
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700181 if (nc == '!') {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700182 strcpy(tbuf, "!");
183 } else {
184 DCHECK_LT(fmt, fmt_end);
185 DCHECK_LT(static_cast<unsigned>(nc-'0'), 4u);
186 operand = lir->operands[nc-'0'];
187 switch (*fmt++) {
188 case 'b':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700189 strcpy(tbuf, "0000");
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700190 for (i = 3; i >= 0; i--) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700191 tbuf[i] += operand & 1;
192 operand >>= 1;
193 }
194 break;
195 case 's':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800196 snprintf(tbuf, arraysize(tbuf), "$f%d", operand & MIPS_FP_REG_MASK);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700197 break;
198 case 'S':
199 DCHECK_EQ(((operand & MIPS_FP_REG_MASK) & 1), 0);
Ian Rogers988e6ea2014-01-08 11:30:50 -0800200 snprintf(tbuf, arraysize(tbuf), "$f%d", operand & MIPS_FP_REG_MASK);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700201 break;
202 case 'h':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800203 snprintf(tbuf, arraysize(tbuf), "%04x", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700204 break;
205 case 'M':
206 case 'd':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800207 snprintf(tbuf, arraysize(tbuf), "%d", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700208 break;
209 case 'D':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800210 snprintf(tbuf, arraysize(tbuf), "%d", operand+1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700211 break;
212 case 'E':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800213 snprintf(tbuf, arraysize(tbuf), "%d", operand*4);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700214 break;
215 case 'F':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800216 snprintf(tbuf, arraysize(tbuf), "%d", operand*2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700217 break;
218 case 't':
Ian Rogers107c31e2014-01-23 20:55:29 -0800219 snprintf(tbuf, arraysize(tbuf), "0x%08" PRIxPTR " (L%p)",
220 reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 + (operand << 1),
221 lir->target);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700222 break;
223 case 'T':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800224 snprintf(tbuf, arraysize(tbuf), "0x%08x", operand << 2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700225 break;
226 case 'u': {
227 int offset_1 = lir->operands[0];
228 int offset_2 = NEXT_LIR(lir)->operands[0];
229 uintptr_t target =
230 (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) & ~3) +
231 (offset_1 << 21 >> 9) + (offset_2 << 1)) & 0xfffffffc;
Ian Rogers988e6ea2014-01-08 11:30:50 -0800232 snprintf(tbuf, arraysize(tbuf), "%p", reinterpret_cast<void*>(target));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700233 break;
234 }
235
236 /* Nothing to print for BLX_2 */
237 case 'v':
238 strcpy(tbuf, "see above");
239 break;
240 case 'r':
241 DCHECK(operand >= 0 && operand < MIPS_REG_COUNT);
242 strcpy(tbuf, mips_reg_name[operand]);
243 break;
244 case 'N':
245 // Placeholder for delay slot handling
246 strcpy(tbuf, "; nop");
247 break;
248 default:
Brian Carlstromb1eba212013-07-17 18:07:19 -0700249 strcpy(tbuf, "DecodeError");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700250 break;
251 }
252 buf += tbuf;
253 }
254 } else {
255 buf += *fmt++;
256 }
257 }
258 return buf;
259}
260
261// FIXME: need to redo resource maps for MIPS - fix this at that time
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700262void MipsMir2Lir::DumpResourceMask(LIR *mips_lir, uint64_t mask, const char *prefix) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700263 char buf[256];
264 buf[0] = 0;
265
266 if (mask == ENCODE_ALL) {
267 strcpy(buf, "all");
268 } else {
269 char num[8];
270 int i;
271
272 for (i = 0; i < kMipsRegEnd; i++) {
273 if (mask & (1ULL << i)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800274 snprintf(num, arraysize(num), "%d ", i);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700275 strcat(buf, num);
276 }
277 }
278
279 if (mask & ENCODE_CCODE) {
280 strcat(buf, "cc ");
281 }
282 if (mask & ENCODE_FP_STATUS) {
283 strcat(buf, "fpcc ");
284 }
285 /* Memory bits */
286 if (mips_lir && (mask & ENCODE_DALVIK_REG)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800287 snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s",
288 DECODE_ALIAS_INFO_REG(mips_lir->flags.alias_info),
289 DECODE_ALIAS_INFO_WIDE(mips_lir->flags.alias_info) ? "(+1)" : "");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700290 }
291 if (mask & ENCODE_LITERAL) {
292 strcat(buf, "lit ");
293 }
294
295 if (mask & ENCODE_HEAP_REF) {
296 strcat(buf, "heap ");
297 }
298 if (mask & ENCODE_MUST_NOT_ALIAS) {
299 strcat(buf, "noalias ");
300 }
301 }
302 if (buf[0]) {
303 LOG(INFO) << prefix << ": " << buf;
304 }
305}
306
307/*
308 * TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some
309 * instructions might call out to C/assembly helper functions. Until
310 * machinery is in place, always spill lr.
311 */
312
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700313void MipsMir2Lir::AdjustSpillMask() {
buzbee2700f7e2014-03-07 09:46:20 -0800314 core_spill_mask_ |= (1 << rRA);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700315 num_core_spills_++;
316}
317
318/*
319 * Mark a callee-save fp register as promoted. Note that
320 * vpush/vpop uses contiguous register lists so we must
321 * include any holes in the mask. Associate holes with
322 * Dalvik register INVALID_VREG (0xFFFFU).
323 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700324void MipsMir2Lir::MarkPreservedSingle(int s_reg, int reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700325 LOG(FATAL) << "No support yet for promoted FP regs";
326}
327
buzbee2700f7e2014-03-07 09:46:20 -0800328void MipsMir2Lir::FlushRegWide(RegStorage reg) {
329 RegisterInfo* info1 = GetRegInfo(reg.GetLowReg());
330 RegisterInfo* info2 = GetRegInfo(reg.GetHighReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700331 DCHECK(info1 && info2 && info1->pair && info2->pair &&
332 (info1->partner == info2->reg) &&
333 (info2->partner == info1->reg));
334 if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) {
335 if (!(info1->is_temp && info2->is_temp)) {
336 /* Should not happen. If it does, there's a problem in eval_loc */
337 LOG(FATAL) << "Long half-temp, half-promoted";
338 }
339
340 info1->dirty = false;
341 info2->dirty = false;
342 if (mir_graph_->SRegToVReg(info2->s_reg) < mir_graph_->SRegToVReg(info1->s_reg))
343 info1 = info2;
344 int v_reg = mir_graph_->SRegToVReg(info1->s_reg);
buzbee2700f7e2014-03-07 09:46:20 -0800345 StoreBaseDispWide(rs_rMIPS_SP, VRegOffset(v_reg),
346 RegStorage(RegStorage::k64BitPair, info1->reg, info1->partner));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700347 }
348}
349
buzbee2700f7e2014-03-07 09:46:20 -0800350void MipsMir2Lir::FlushReg(RegStorage reg) {
351 DCHECK(!reg.IsPair());
352 RegisterInfo* info = GetRegInfo(reg.GetReg());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700353 if (info->live && info->dirty) {
354 info->dirty = false;
355 int v_reg = mir_graph_->SRegToVReg(info->s_reg);
buzbee2700f7e2014-03-07 09:46:20 -0800356 StoreBaseDisp(rs_rMIPS_SP, VRegOffset(v_reg), reg, kWord);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700357 }
358}
359
360/* Give access to the target-dependent FP register encoding to common code */
361bool MipsMir2Lir::IsFpReg(int reg) {
362 return MIPS_FPREG(reg);
363}
364
buzbee2700f7e2014-03-07 09:46:20 -0800365bool MipsMir2Lir::IsFpReg(RegStorage reg) {
366 return IsFpReg(reg.IsPair() ? reg.GetLowReg() : reg.GetReg());
367}
368
Brian Carlstrom7940e442013-07-12 13:46:57 -0700369/* Clobber all regs that might be used by an external C call */
Vladimir Marko31c2aac2013-12-09 16:31:19 +0000370void MipsMir2Lir::ClobberCallerSave() {
buzbee2700f7e2014-03-07 09:46:20 -0800371 Clobber(rZERO);
372 Clobber(rAT);
373 Clobber(rV0);
374 Clobber(rV1);
375 Clobber(rA0);
376 Clobber(rA1);
377 Clobber(rA2);
378 Clobber(rA3);
379 Clobber(rT0);
380 Clobber(rT1);
381 Clobber(rT2);
382 Clobber(rT3);
383 Clobber(rT4);
384 Clobber(rT5);
385 Clobber(rT6);
386 Clobber(rT7);
387 Clobber(rT8);
388 Clobber(rT9);
389 Clobber(rK0);
390 Clobber(rK1);
391 Clobber(rGP);
392 Clobber(rFP);
393 Clobber(rRA);
394 Clobber(rF0);
395 Clobber(rF1);
396 Clobber(rF2);
397 Clobber(rF3);
398 Clobber(rF4);
399 Clobber(rF5);
400 Clobber(rF6);
401 Clobber(rF7);
402 Clobber(rF8);
403 Clobber(rF9);
404 Clobber(rF10);
405 Clobber(rF11);
406 Clobber(rF12);
407 Clobber(rF13);
408 Clobber(rF14);
409 Clobber(rF15);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700410}
411
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700412RegLocation MipsMir2Lir::GetReturnWideAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700413 UNIMPLEMENTED(FATAL) << "No GetReturnWideAlt for MIPS";
414 RegLocation res = LocCReturnWide();
415 return res;
416}
417
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700418RegLocation MipsMir2Lir::GetReturnAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700419 UNIMPLEMENTED(FATAL) << "No GetReturnAlt for MIPS";
420 RegLocation res = LocCReturn();
421 return res;
422}
423
Brian Carlstrom7940e442013-07-12 13:46:57 -0700424/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700425void MipsMir2Lir::LockCallTemps() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700426 LockTemp(rMIPS_ARG0);
427 LockTemp(rMIPS_ARG1);
428 LockTemp(rMIPS_ARG2);
429 LockTemp(rMIPS_ARG3);
430}
431
432/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700433void MipsMir2Lir::FreeCallTemps() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700434 FreeTemp(rMIPS_ARG0);
435 FreeTemp(rMIPS_ARG1);
436 FreeTemp(rMIPS_ARG2);
437 FreeTemp(rMIPS_ARG3);
438}
439
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700440void MipsMir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700441#if ANDROID_SMP != 0
442 NewLIR1(kMipsSync, 0 /* Only stype currently supported */);
443#endif
444}
445
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000446// Alloc a pair of core registers, or a double.
447RegStorage MipsMir2Lir::AllocTypedTempWide(bool fp_hint, int reg_class) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700448 int high_reg;
449 int low_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700450
451 if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
buzbee2700f7e2014-03-07 09:46:20 -0800452 return AllocTempDouble();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700453 }
454
buzbee2700f7e2014-03-07 09:46:20 -0800455 low_reg = AllocTemp().GetReg();
456 high_reg = AllocTemp().GetReg();
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000457 return RegStorage(RegStorage::k64BitPair, low_reg, high_reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700458}
459
buzbee2700f7e2014-03-07 09:46:20 -0800460RegStorage MipsMir2Lir::AllocTypedTemp(bool fp_hint, int reg_class) {
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700461 if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700462 return AllocTempFloat();
463}
464 return AllocTemp();
465}
466
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700467void MipsMir2Lir::CompilerInitializeRegAlloc() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700468 int num_regs = sizeof(core_regs)/sizeof(*core_regs);
469 int num_reserved = sizeof(ReservedRegs)/sizeof(*ReservedRegs);
470 int num_temps = sizeof(core_temps)/sizeof(*core_temps);
471 int num_fp_regs = sizeof(FpRegs)/sizeof(*FpRegs);
472 int num_fp_temps = sizeof(fp_temps)/sizeof(*fp_temps);
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700473 reg_pool_ = static_cast<RegisterPool*>(arena_->Alloc(sizeof(*reg_pool_),
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000474 kArenaAllocRegAlloc));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700475 reg_pool_->num_core_regs = num_regs;
476 reg_pool_->core_regs = static_cast<RegisterInfo*>
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000477 (arena_->Alloc(num_regs * sizeof(*reg_pool_->core_regs), kArenaAllocRegAlloc));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700478 reg_pool_->num_fp_regs = num_fp_regs;
479 reg_pool_->FPRegs = static_cast<RegisterInfo*>
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000480 (arena_->Alloc(num_fp_regs * sizeof(*reg_pool_->FPRegs), kArenaAllocRegAlloc));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700481 CompilerInitPool(reg_pool_->core_regs, core_regs, reg_pool_->num_core_regs);
482 CompilerInitPool(reg_pool_->FPRegs, FpRegs, reg_pool_->num_fp_regs);
483 // Keep special registers from being allocated
484 for (int i = 0; i < num_reserved; i++) {
485 if (NO_SUSPEND && (ReservedRegs[i] == rMIPS_SUSPEND)) {
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700486 // To measure cost of suspend check
Brian Carlstrom7940e442013-07-12 13:46:57 -0700487 continue;
488 }
489 MarkInUse(ReservedRegs[i]);
490 }
491 // Mark temp regs - all others not in use can be used for promotion
492 for (int i = 0; i < num_temps; i++) {
493 MarkTemp(core_temps[i]);
494 }
495 for (int i = 0; i < num_fp_temps; i++) {
496 MarkTemp(fp_temps[i]);
497 }
498}
499
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700500void MipsMir2Lir::FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) {
buzbee2700f7e2014-03-07 09:46:20 -0800501 DCHECK(rl_keep.wide);
502 DCHECK(rl_free.wide);
503 if ((rl_free.reg.GetLowReg() != rl_keep.reg.GetLowReg()) &&
504 (rl_free.reg.GetLowReg() != rl_keep.reg.GetHighReg()) &&
505 (rl_free.reg.GetHighReg() != rl_keep.reg.GetLowReg()) &&
506 (rl_free.reg.GetHighReg() != rl_keep.reg.GetHighReg())) {
507 // No overlap, free.
508 FreeTemp(rl_free.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700509 }
510}
511/*
512 * In the Arm code a it is typical to use the link register
513 * to hold the target address. However, for Mips we must
514 * ensure that all branch instructions can be restarted if
515 * there is a trap in the shadow. Allocate a temp register.
516 */
Ian Rogersdd7624d2014-03-14 17:43:00 -0700517RegStorage MipsMir2Lir::LoadHelper(ThreadOffset<4> offset) {
buzbee2700f7e2014-03-07 09:46:20 -0800518 LoadWordDisp(rs_rMIPS_SELF, offset.Int32Value(), rs_rT9);
519 return rs_rT9;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700520}
521
Dave Allisonb373e092014-02-20 16:06:36 -0800522LIR* MipsMir2Lir::CheckSuspendUsingLoad() {
buzbee2700f7e2014-03-07 09:46:20 -0800523 RegStorage tmp = AllocTemp();
Ian Rogersdd7624d2014-03-14 17:43:00 -0700524 LoadWordDisp(rs_rMIPS_SELF, Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
Dave Allisonb373e092014-02-20 16:06:36 -0800525 LIR *inst = LoadWordDisp(tmp, 0, tmp);
526 FreeTemp(tmp);
527 return inst;
528}
529
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700530void MipsMir2Lir::SpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700531 if (num_core_spills_ == 0) {
532 return;
533 }
534 uint32_t mask = core_spill_mask_;
535 int offset = num_core_spills_ * 4;
buzbee2700f7e2014-03-07 09:46:20 -0800536 OpRegImm(kOpSub, rs_rSP, offset);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700537 for (int reg = 0; mask; mask >>= 1, reg++) {
538 if (mask & 0x1) {
539 offset -= 4;
buzbee2700f7e2014-03-07 09:46:20 -0800540 StoreWordDisp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700541 }
542 }
543}
544
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700545void MipsMir2Lir::UnSpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700546 if (num_core_spills_ == 0) {
547 return;
548 }
549 uint32_t mask = core_spill_mask_;
550 int offset = frame_size_;
551 for (int reg = 0; mask; mask >>= 1, reg++) {
552 if (mask & 0x1) {
553 offset -= 4;
buzbee2700f7e2014-03-07 09:46:20 -0800554 LoadWordDisp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700555 }
556 }
buzbee2700f7e2014-03-07 09:46:20 -0800557 OpRegImm(kOpAdd, rs_rSP, frame_size_);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700558}
559
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700560bool MipsMir2Lir::IsUnconditionalBranch(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700561 return (lir->opcode == kMipsB);
562}
563
564MipsMir2Lir::MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
565 : Mir2Lir(cu, mir_graph, arena) {
566 for (int i = 0; i < kMipsLast; i++) {
567 if (MipsMir2Lir::EncodingMap[i].opcode != i) {
568 LOG(FATAL) << "Encoding order for " << MipsMir2Lir::EncodingMap[i].name
569 << " is wrong: expecting " << i << ", seeing "
570 << static_cast<int>(MipsMir2Lir::EncodingMap[i].opcode);
571 }
572 }
573}
574
575Mir2Lir* MipsCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
576 ArenaAllocator* const arena) {
577 return new MipsMir2Lir(cu, mir_graph, arena);
578}
579
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700580uint64_t MipsMir2Lir::GetTargetInstFlags(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700581 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700582 return MipsMir2Lir::EncodingMap[opcode].flags;
583}
584
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700585const char* MipsMir2Lir::GetTargetInstName(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700586 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700587 return MipsMir2Lir::EncodingMap[opcode].name;
588}
589
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700590const char* MipsMir2Lir::GetTargetInstFmt(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700591 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700592 return MipsMir2Lir::EncodingMap[opcode].fmt;
593}
594
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700595} // namespace art