blob: b744adcd97e59f47149b1d08012251ffda8544e4 [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
29static int core_regs[] = {r_ZERO, r_AT, r_V0, r_V1, r_A0, r_A1, r_A2, r_A3,
30 r_T0, r_T1, r_T2, r_T3, r_T4, r_T5, r_T6, r_T7,
31 r_S0, r_S1, r_S2, r_S3, r_S4, r_S5, r_S6, r_S7, r_T8,
32 r_T9, r_K0, r_K1, r_GP, r_SP, r_FP, r_RA};
33static int ReservedRegs[] = {r_ZERO, r_AT, r_S0, r_S1, r_K0, r_K1, r_GP, r_SP,
34 r_RA};
35static int core_temps[] = {r_V0, r_V1, r_A0, r_A1, r_A2, r_A3, r_T0, r_T1, r_T2,
36 r_T3, r_T4, r_T5, r_T6, r_T7, r_T8};
37static int FpRegs[] = {r_F0, r_F1, r_F2, r_F3, r_F4, r_F5, r_F6, r_F7,
38 r_F8, r_F9, r_F10, r_F11, r_F12, r_F13, r_F14, r_F15};
39static int fp_temps[] = {r_F0, r_F1, r_F2, r_F3, r_F4, r_F5, r_F6, r_F7,
40 r_F8, r_F9, r_F10, r_F11, r_F12, r_F13, r_F14, r_F15};
41
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070042RegLocation MipsMir2Lir::LocCReturn() {
Brian Carlstrom7940e442013-07-12 13:46:57 -070043 RegLocation res = MIPS_LOC_C_RETURN;
44 return res;
45}
46
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070047RegLocation MipsMir2Lir::LocCReturnWide() {
Brian Carlstrom7940e442013-07-12 13:46:57 -070048 RegLocation res = MIPS_LOC_C_RETURN_WIDE;
49 return res;
50}
51
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070052RegLocation MipsMir2Lir::LocCReturnFloat() {
Brian Carlstrom7940e442013-07-12 13:46:57 -070053 RegLocation res = MIPS_LOC_C_RETURN_FLOAT;
54 return res;
55}
56
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070057RegLocation MipsMir2Lir::LocCReturnDouble() {
Brian Carlstrom7940e442013-07-12 13:46:57 -070058 RegLocation res = MIPS_LOC_C_RETURN_DOUBLE;
59 return res;
60}
61
62// Return a target-dependent special register.
63int MipsMir2Lir::TargetReg(SpecialTargetRegister reg) {
64 int res = INVALID_REG;
65 switch (reg) {
66 case kSelf: res = rMIPS_SELF; break;
67 case kSuspend: res = rMIPS_SUSPEND; break;
68 case kLr: res = rMIPS_LR; break;
69 case kPc: res = rMIPS_PC; break;
70 case kSp: res = rMIPS_SP; break;
71 case kArg0: res = rMIPS_ARG0; break;
72 case kArg1: res = rMIPS_ARG1; break;
73 case kArg2: res = rMIPS_ARG2; break;
74 case kArg3: res = rMIPS_ARG3; break;
75 case kFArg0: res = rMIPS_FARG0; break;
76 case kFArg1: res = rMIPS_FARG1; break;
77 case kFArg2: res = rMIPS_FARG2; break;
78 case kFArg3: res = rMIPS_FARG3; break;
79 case kRet0: res = rMIPS_RET0; break;
80 case kRet1: res = rMIPS_RET1; break;
81 case kInvokeTgt: res = rMIPS_INVOKE_TGT; break;
Jeff Hao88474b42013-10-23 16:24:40 -070082 case kHiddenArg: res = r_T0; break;
83 case kHiddenFpArg: res = INVALID_REG; break;
Brian Carlstrom7940e442013-07-12 13:46:57 -070084 case kCount: res = rMIPS_COUNT; break;
85 }
86 return res;
87}
88
89// Create a double from a pair of singles.
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070090int MipsMir2Lir::S2d(int low_reg, int high_reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070091 return MIPS_S2D(low_reg, high_reg);
92}
93
94// Return mask to strip off fp reg flags and bias.
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070095uint32_t MipsMir2Lir::FpRegMask() {
Brian Carlstrom7940e442013-07-12 13:46:57 -070096 return MIPS_FP_REG_MASK;
97}
98
99// True if both regs single, both core or both double.
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700100bool MipsMir2Lir::SameRegType(int reg1, int reg2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700101 return (MIPS_REGTYPE(reg1) == MIPS_REGTYPE(reg2));
102}
103
104/*
105 * Decode the register id.
106 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700107uint64_t MipsMir2Lir::GetRegMaskCommon(int reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700108 uint64_t seed;
109 int shift;
110 int reg_id;
111
112
113 reg_id = reg & 0x1f;
114 /* Each double register is equal to a pair of single-precision FP registers */
115 seed = MIPS_DOUBLEREG(reg) ? 3 : 1;
116 /* FP register starts at bit position 16 */
117 shift = MIPS_FPREG(reg) ? kMipsFPReg0 : 0;
118 /* Expand the double register id into single offset */
119 shift += reg_id;
120 return (seed << shift);
121}
122
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700123uint64_t MipsMir2Lir::GetPCUseDefEncoding() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700124 return ENCODE_MIPS_REG_PC;
125}
126
127
buzbeeb48819d2013-09-14 16:15:25 -0700128void MipsMir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700129 DCHECK_EQ(cu_->instruction_set, kMips);
buzbeeb48819d2013-09-14 16:15:25 -0700130 DCHECK(!lir->flags.use_def_invalid);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700131
132 // Mips-specific resource map setup here.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700133 if (flags & REG_DEF_SP) {
buzbeeb48819d2013-09-14 16:15:25 -0700134 lir->u.m.def_mask |= ENCODE_MIPS_REG_SP;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700135 }
136
137 if (flags & REG_USE_SP) {
buzbeeb48819d2013-09-14 16:15:25 -0700138 lir->u.m.use_mask |= ENCODE_MIPS_REG_SP;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700139 }
140
141 if (flags & REG_DEF_LR) {
buzbeeb48819d2013-09-14 16:15:25 -0700142 lir->u.m.def_mask |= ENCODE_MIPS_REG_LR;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700143 }
144}
145
146/* For dumping instructions */
147#define MIPS_REG_COUNT 32
148static const char *mips_reg_name[MIPS_REG_COUNT] = {
149 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
150 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
151 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
152 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
153};
154
155/*
156 * Interpret a format string and build a string no longer than size
157 * See format key in Assemble.c.
158 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700159std::string MipsMir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700160 std::string buf;
161 int i;
162 const char *fmt_end = &fmt[strlen(fmt)];
163 char tbuf[256];
164 char nc;
165 while (fmt < fmt_end) {
166 int operand;
167 if (*fmt == '!') {
168 fmt++;
169 DCHECK_LT(fmt, fmt_end);
170 nc = *fmt++;
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700171 if (nc == '!') {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700172 strcpy(tbuf, "!");
173 } else {
174 DCHECK_LT(fmt, fmt_end);
175 DCHECK_LT(static_cast<unsigned>(nc-'0'), 4u);
176 operand = lir->operands[nc-'0'];
177 switch (*fmt++) {
178 case 'b':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700179 strcpy(tbuf, "0000");
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700180 for (i = 3; i >= 0; i--) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700181 tbuf[i] += operand & 1;
182 operand >>= 1;
183 }
184 break;
185 case 's':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800186 snprintf(tbuf, arraysize(tbuf), "$f%d", operand & MIPS_FP_REG_MASK);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700187 break;
188 case 'S':
189 DCHECK_EQ(((operand & MIPS_FP_REG_MASK) & 1), 0);
Ian Rogers988e6ea2014-01-08 11:30:50 -0800190 snprintf(tbuf, arraysize(tbuf), "$f%d", operand & MIPS_FP_REG_MASK);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700191 break;
192 case 'h':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800193 snprintf(tbuf, arraysize(tbuf), "%04x", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700194 break;
195 case 'M':
196 case 'd':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800197 snprintf(tbuf, arraysize(tbuf), "%d", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700198 break;
199 case 'D':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800200 snprintf(tbuf, arraysize(tbuf), "%d", operand+1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700201 break;
202 case 'E':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800203 snprintf(tbuf, arraysize(tbuf), "%d", operand*4);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700204 break;
205 case 'F':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800206 snprintf(tbuf, arraysize(tbuf), "%d", operand*2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700207 break;
208 case 't':
Ian Rogers107c31e2014-01-23 20:55:29 -0800209 snprintf(tbuf, arraysize(tbuf), "0x%08" PRIxPTR " (L%p)",
210 reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 + (operand << 1),
211 lir->target);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700212 break;
213 case 'T':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800214 snprintf(tbuf, arraysize(tbuf), "0x%08x", operand << 2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700215 break;
216 case 'u': {
217 int offset_1 = lir->operands[0];
218 int offset_2 = NEXT_LIR(lir)->operands[0];
219 uintptr_t target =
220 (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) & ~3) +
221 (offset_1 << 21 >> 9) + (offset_2 << 1)) & 0xfffffffc;
Ian Rogers988e6ea2014-01-08 11:30:50 -0800222 snprintf(tbuf, arraysize(tbuf), "%p", reinterpret_cast<void*>(target));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700223 break;
224 }
225
226 /* Nothing to print for BLX_2 */
227 case 'v':
228 strcpy(tbuf, "see above");
229 break;
230 case 'r':
231 DCHECK(operand >= 0 && operand < MIPS_REG_COUNT);
232 strcpy(tbuf, mips_reg_name[operand]);
233 break;
234 case 'N':
235 // Placeholder for delay slot handling
236 strcpy(tbuf, "; nop");
237 break;
238 default:
Brian Carlstromb1eba212013-07-17 18:07:19 -0700239 strcpy(tbuf, "DecodeError");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700240 break;
241 }
242 buf += tbuf;
243 }
244 } else {
245 buf += *fmt++;
246 }
247 }
248 return buf;
249}
250
251// FIXME: need to redo resource maps for MIPS - fix this at that time
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700252void MipsMir2Lir::DumpResourceMask(LIR *mips_lir, uint64_t mask, const char *prefix) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700253 char buf[256];
254 buf[0] = 0;
255
256 if (mask == ENCODE_ALL) {
257 strcpy(buf, "all");
258 } else {
259 char num[8];
260 int i;
261
262 for (i = 0; i < kMipsRegEnd; i++) {
263 if (mask & (1ULL << i)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800264 snprintf(num, arraysize(num), "%d ", i);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700265 strcat(buf, num);
266 }
267 }
268
269 if (mask & ENCODE_CCODE) {
270 strcat(buf, "cc ");
271 }
272 if (mask & ENCODE_FP_STATUS) {
273 strcat(buf, "fpcc ");
274 }
275 /* Memory bits */
276 if (mips_lir && (mask & ENCODE_DALVIK_REG)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800277 snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s",
278 DECODE_ALIAS_INFO_REG(mips_lir->flags.alias_info),
279 DECODE_ALIAS_INFO_WIDE(mips_lir->flags.alias_info) ? "(+1)" : "");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700280 }
281 if (mask & ENCODE_LITERAL) {
282 strcat(buf, "lit ");
283 }
284
285 if (mask & ENCODE_HEAP_REF) {
286 strcat(buf, "heap ");
287 }
288 if (mask & ENCODE_MUST_NOT_ALIAS) {
289 strcat(buf, "noalias ");
290 }
291 }
292 if (buf[0]) {
293 LOG(INFO) << prefix << ": " << buf;
294 }
295}
296
297/*
298 * TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some
299 * instructions might call out to C/assembly helper functions. Until
300 * machinery is in place, always spill lr.
301 */
302
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700303void MipsMir2Lir::AdjustSpillMask() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700304 core_spill_mask_ |= (1 << r_RA);
305 num_core_spills_++;
306}
307
308/*
309 * Mark a callee-save fp register as promoted. Note that
310 * vpush/vpop uses contiguous register lists so we must
311 * include any holes in the mask. Associate holes with
312 * Dalvik register INVALID_VREG (0xFFFFU).
313 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700314void MipsMir2Lir::MarkPreservedSingle(int s_reg, int reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700315 LOG(FATAL) << "No support yet for promoted FP regs";
316}
317
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700318void MipsMir2Lir::FlushRegWide(int reg1, int reg2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700319 RegisterInfo* info1 = GetRegInfo(reg1);
320 RegisterInfo* info2 = GetRegInfo(reg2);
321 DCHECK(info1 && info2 && info1->pair && info2->pair &&
322 (info1->partner == info2->reg) &&
323 (info2->partner == info1->reg));
324 if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) {
325 if (!(info1->is_temp && info2->is_temp)) {
326 /* Should not happen. If it does, there's a problem in eval_loc */
327 LOG(FATAL) << "Long half-temp, half-promoted";
328 }
329
330 info1->dirty = false;
331 info2->dirty = false;
332 if (mir_graph_->SRegToVReg(info2->s_reg) < mir_graph_->SRegToVReg(info1->s_reg))
333 info1 = info2;
334 int v_reg = mir_graph_->SRegToVReg(info1->s_reg);
335 StoreBaseDispWide(rMIPS_SP, VRegOffset(v_reg), info1->reg, info1->partner);
336 }
337}
338
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700339void MipsMir2Lir::FlushReg(int reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700340 RegisterInfo* info = GetRegInfo(reg);
341 if (info->live && info->dirty) {
342 info->dirty = false;
343 int v_reg = mir_graph_->SRegToVReg(info->s_reg);
344 StoreBaseDisp(rMIPS_SP, VRegOffset(v_reg), reg, kWord);
345 }
346}
347
348/* Give access to the target-dependent FP register encoding to common code */
349bool MipsMir2Lir::IsFpReg(int reg) {
350 return MIPS_FPREG(reg);
351}
352
353/* Clobber all regs that might be used by an external C call */
Vladimir Marko31c2aac2013-12-09 16:31:19 +0000354void MipsMir2Lir::ClobberCallerSave() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700355 Clobber(r_ZERO);
356 Clobber(r_AT);
357 Clobber(r_V0);
358 Clobber(r_V1);
359 Clobber(r_A0);
360 Clobber(r_A1);
361 Clobber(r_A2);
362 Clobber(r_A3);
363 Clobber(r_T0);
364 Clobber(r_T1);
365 Clobber(r_T2);
366 Clobber(r_T3);
367 Clobber(r_T4);
368 Clobber(r_T5);
369 Clobber(r_T6);
370 Clobber(r_T7);
371 Clobber(r_T8);
372 Clobber(r_T9);
373 Clobber(r_K0);
374 Clobber(r_K1);
375 Clobber(r_GP);
376 Clobber(r_FP);
377 Clobber(r_RA);
378 Clobber(r_F0);
379 Clobber(r_F1);
380 Clobber(r_F2);
381 Clobber(r_F3);
382 Clobber(r_F4);
383 Clobber(r_F5);
384 Clobber(r_F6);
385 Clobber(r_F7);
386 Clobber(r_F8);
387 Clobber(r_F9);
388 Clobber(r_F10);
389 Clobber(r_F11);
390 Clobber(r_F12);
391 Clobber(r_F13);
392 Clobber(r_F14);
393 Clobber(r_F15);
394}
395
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700396RegLocation MipsMir2Lir::GetReturnWideAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700397 UNIMPLEMENTED(FATAL) << "No GetReturnWideAlt for MIPS";
398 RegLocation res = LocCReturnWide();
399 return res;
400}
401
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700402RegLocation MipsMir2Lir::GetReturnAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700403 UNIMPLEMENTED(FATAL) << "No GetReturnAlt for MIPS";
404 RegLocation res = LocCReturn();
405 return res;
406}
407
Brian Carlstrom7940e442013-07-12 13:46:57 -0700408/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700409void MipsMir2Lir::LockCallTemps() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700410 LockTemp(rMIPS_ARG0);
411 LockTemp(rMIPS_ARG1);
412 LockTemp(rMIPS_ARG2);
413 LockTemp(rMIPS_ARG3);
414}
415
416/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700417void MipsMir2Lir::FreeCallTemps() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700418 FreeTemp(rMIPS_ARG0);
419 FreeTemp(rMIPS_ARG1);
420 FreeTemp(rMIPS_ARG2);
421 FreeTemp(rMIPS_ARG3);
422}
423
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700424void MipsMir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700425#if ANDROID_SMP != 0
426 NewLIR1(kMipsSync, 0 /* Only stype currently supported */);
427#endif
428}
429
430/*
431 * Alloc a pair of core registers, or a double. Low reg in low byte,
432 * high reg in next byte.
433 */
434int MipsMir2Lir::AllocTypedTempPair(bool fp_hint,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700435 int reg_class) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700436 int high_reg;
437 int low_reg;
438 int res = 0;
439
440 if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
441 low_reg = AllocTempDouble();
442 high_reg = low_reg + 1;
443 res = (low_reg & 0xff) | ((high_reg & 0xff) << 8);
444 return res;
445 }
446
447 low_reg = AllocTemp();
448 high_reg = AllocTemp();
449 res = (low_reg & 0xff) | ((high_reg & 0xff) << 8);
450 return res;
451}
452
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700453int MipsMir2Lir::AllocTypedTemp(bool fp_hint, int reg_class) {
454 if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700455 return AllocTempFloat();
456}
457 return AllocTemp();
458}
459
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700460void MipsMir2Lir::CompilerInitializeRegAlloc() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700461 int num_regs = sizeof(core_regs)/sizeof(*core_regs);
462 int num_reserved = sizeof(ReservedRegs)/sizeof(*ReservedRegs);
463 int num_temps = sizeof(core_temps)/sizeof(*core_temps);
464 int num_fp_regs = sizeof(FpRegs)/sizeof(*FpRegs);
465 int num_fp_temps = sizeof(fp_temps)/sizeof(*fp_temps);
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700466 reg_pool_ = static_cast<RegisterPool*>(arena_->Alloc(sizeof(*reg_pool_),
467 ArenaAllocator::kAllocRegAlloc));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700468 reg_pool_->num_core_regs = num_regs;
469 reg_pool_->core_regs = static_cast<RegisterInfo*>
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700470 (arena_->Alloc(num_regs * sizeof(*reg_pool_->core_regs), ArenaAllocator::kAllocRegAlloc));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700471 reg_pool_->num_fp_regs = num_fp_regs;
472 reg_pool_->FPRegs = static_cast<RegisterInfo*>
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700473 (arena_->Alloc(num_fp_regs * sizeof(*reg_pool_->FPRegs), ArenaAllocator::kAllocRegAlloc));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700474 CompilerInitPool(reg_pool_->core_regs, core_regs, reg_pool_->num_core_regs);
475 CompilerInitPool(reg_pool_->FPRegs, FpRegs, reg_pool_->num_fp_regs);
476 // Keep special registers from being allocated
477 for (int i = 0; i < num_reserved; i++) {
478 if (NO_SUSPEND && (ReservedRegs[i] == rMIPS_SUSPEND)) {
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700479 // To measure cost of suspend check
Brian Carlstrom7940e442013-07-12 13:46:57 -0700480 continue;
481 }
482 MarkInUse(ReservedRegs[i]);
483 }
484 // Mark temp regs - all others not in use can be used for promotion
485 for (int i = 0; i < num_temps; i++) {
486 MarkTemp(core_temps[i]);
487 }
488 for (int i = 0; i < num_fp_temps; i++) {
489 MarkTemp(fp_temps[i]);
490 }
491}
492
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700493void MipsMir2Lir::FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700494 if ((rl_free.low_reg != rl_keep.low_reg) && (rl_free.low_reg != rl_keep.high_reg) &&
495 (rl_free.high_reg != rl_keep.low_reg) && (rl_free.high_reg != rl_keep.high_reg)) {
496 // No overlap, free both
497 FreeTemp(rl_free.low_reg);
498 FreeTemp(rl_free.high_reg);
499 }
500}
501/*
502 * In the Arm code a it is typical to use the link register
503 * to hold the target address. However, for Mips we must
504 * ensure that all branch instructions can be restarted if
505 * there is a trap in the shadow. Allocate a temp register.
506 */
Ian Rogers468532e2013-08-05 10:56:33 -0700507int MipsMir2Lir::LoadHelper(ThreadOffset offset) {
508 LoadWordDisp(rMIPS_SELF, offset.Int32Value(), r_T9);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700509 return r_T9;
510}
511
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700512void MipsMir2Lir::SpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700513 if (num_core_spills_ == 0) {
514 return;
515 }
516 uint32_t mask = core_spill_mask_;
517 int offset = num_core_spills_ * 4;
518 OpRegImm(kOpSub, rMIPS_SP, offset);
519 for (int reg = 0; mask; mask >>= 1, reg++) {
520 if (mask & 0x1) {
521 offset -= 4;
522 StoreWordDisp(rMIPS_SP, offset, reg);
523 }
524 }
525}
526
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700527void MipsMir2Lir::UnSpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700528 if (num_core_spills_ == 0) {
529 return;
530 }
531 uint32_t mask = core_spill_mask_;
532 int offset = frame_size_;
533 for (int reg = 0; mask; mask >>= 1, reg++) {
534 if (mask & 0x1) {
535 offset -= 4;
536 LoadWordDisp(rMIPS_SP, offset, reg);
537 }
538 }
539 OpRegImm(kOpAdd, rMIPS_SP, frame_size_);
540}
541
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700542bool MipsMir2Lir::IsUnconditionalBranch(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700543 return (lir->opcode == kMipsB);
544}
545
546MipsMir2Lir::MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
547 : Mir2Lir(cu, mir_graph, arena) {
548 for (int i = 0; i < kMipsLast; i++) {
549 if (MipsMir2Lir::EncodingMap[i].opcode != i) {
550 LOG(FATAL) << "Encoding order for " << MipsMir2Lir::EncodingMap[i].name
551 << " is wrong: expecting " << i << ", seeing "
552 << static_cast<int>(MipsMir2Lir::EncodingMap[i].opcode);
553 }
554 }
555}
556
557Mir2Lir* MipsCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
558 ArenaAllocator* const arena) {
559 return new MipsMir2Lir(cu, mir_graph, arena);
560}
561
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700562uint64_t MipsMir2Lir::GetTargetInstFlags(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700563 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700564 return MipsMir2Lir::EncodingMap[opcode].flags;
565}
566
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700567const char* MipsMir2Lir::GetTargetInstName(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700568 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700569 return MipsMir2Lir::EncodingMap[opcode].name;
570}
571
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700572const char* MipsMir2Lir::GetTargetInstFmt(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700573 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700574 return MipsMir2Lir::EncodingMap[opcode].fmt;
575}
576
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700577} // namespace art