blob: 0ee32d4d21cf1207b6171a321ddab6ce817ab959 [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"
18#include "dex/compiler_internals.h"
19#include "dex/quick/mir_to_lir-inl.h"
20#include "mips_lir.h"
21
22#include <string>
23
24namespace art {
25
26static int core_regs[] = {r_ZERO, r_AT, r_V0, r_V1, r_A0, r_A1, r_A2, r_A3,
27 r_T0, r_T1, r_T2, r_T3, r_T4, r_T5, r_T6, r_T7,
28 r_S0, r_S1, r_S2, r_S3, r_S4, r_S5, r_S6, r_S7, r_T8,
29 r_T9, r_K0, r_K1, r_GP, r_SP, r_FP, r_RA};
30static int ReservedRegs[] = {r_ZERO, r_AT, r_S0, r_S1, r_K0, r_K1, r_GP, r_SP,
31 r_RA};
32static int core_temps[] = {r_V0, r_V1, r_A0, r_A1, r_A2, r_A3, r_T0, r_T1, r_T2,
33 r_T3, r_T4, r_T5, r_T6, r_T7, r_T8};
34static int FpRegs[] = {r_F0, r_F1, r_F2, r_F3, r_F4, r_F5, r_F6, r_F7,
35 r_F8, r_F9, r_F10, r_F11, r_F12, r_F13, r_F14, r_F15};
36static int fp_temps[] = {r_F0, r_F1, r_F2, r_F3, r_F4, r_F5, r_F6, r_F7,
37 r_F8, r_F9, r_F10, r_F11, r_F12, r_F13, r_F14, r_F15};
38
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070039RegLocation MipsMir2Lir::LocCReturn() {
Brian Carlstrom7940e442013-07-12 13:46:57 -070040 RegLocation res = MIPS_LOC_C_RETURN;
41 return res;
42}
43
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070044RegLocation MipsMir2Lir::LocCReturnWide() {
Brian Carlstrom7940e442013-07-12 13:46:57 -070045 RegLocation res = MIPS_LOC_C_RETURN_WIDE;
46 return res;
47}
48
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070049RegLocation MipsMir2Lir::LocCReturnFloat() {
Brian Carlstrom7940e442013-07-12 13:46:57 -070050 RegLocation res = MIPS_LOC_C_RETURN_FLOAT;
51 return res;
52}
53
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070054RegLocation MipsMir2Lir::LocCReturnDouble() {
Brian Carlstrom7940e442013-07-12 13:46:57 -070055 RegLocation res = MIPS_LOC_C_RETURN_DOUBLE;
56 return res;
57}
58
59// Return a target-dependent special register.
60int MipsMir2Lir::TargetReg(SpecialTargetRegister reg) {
61 int res = INVALID_REG;
62 switch (reg) {
63 case kSelf: res = rMIPS_SELF; break;
64 case kSuspend: res = rMIPS_SUSPEND; break;
65 case kLr: res = rMIPS_LR; break;
66 case kPc: res = rMIPS_PC; break;
67 case kSp: res = rMIPS_SP; break;
68 case kArg0: res = rMIPS_ARG0; break;
69 case kArg1: res = rMIPS_ARG1; break;
70 case kArg2: res = rMIPS_ARG2; break;
71 case kArg3: res = rMIPS_ARG3; break;
72 case kFArg0: res = rMIPS_FARG0; break;
73 case kFArg1: res = rMIPS_FARG1; break;
74 case kFArg2: res = rMIPS_FARG2; break;
75 case kFArg3: res = rMIPS_FARG3; break;
76 case kRet0: res = rMIPS_RET0; break;
77 case kRet1: res = rMIPS_RET1; break;
78 case kInvokeTgt: res = rMIPS_INVOKE_TGT; break;
79 case kCount: res = rMIPS_COUNT; break;
80 }
81 return res;
82}
83
84// Create a double from a pair of singles.
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070085int MipsMir2Lir::S2d(int low_reg, int high_reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070086 return MIPS_S2D(low_reg, high_reg);
87}
88
89// Return mask to strip off fp reg flags and bias.
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070090uint32_t MipsMir2Lir::FpRegMask() {
Brian Carlstrom7940e442013-07-12 13:46:57 -070091 return MIPS_FP_REG_MASK;
92}
93
94// True if both regs single, both core or both double.
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070095bool MipsMir2Lir::SameRegType(int reg1, int reg2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070096 return (MIPS_REGTYPE(reg1) == MIPS_REGTYPE(reg2));
97}
98
99/*
100 * Decode the register id.
101 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700102uint64_t MipsMir2Lir::GetRegMaskCommon(int reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700103 uint64_t seed;
104 int shift;
105 int reg_id;
106
107
108 reg_id = reg & 0x1f;
109 /* Each double register is equal to a pair of single-precision FP registers */
110 seed = MIPS_DOUBLEREG(reg) ? 3 : 1;
111 /* FP register starts at bit position 16 */
112 shift = MIPS_FPREG(reg) ? kMipsFPReg0 : 0;
113 /* Expand the double register id into single offset */
114 shift += reg_id;
115 return (seed << shift);
116}
117
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700118uint64_t MipsMir2Lir::GetPCUseDefEncoding() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700119 return ENCODE_MIPS_REG_PC;
120}
121
122
buzbeeb48819d2013-09-14 16:15:25 -0700123void MipsMir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700124 DCHECK_EQ(cu_->instruction_set, kMips);
buzbeeb48819d2013-09-14 16:15:25 -0700125 DCHECK(!lir->flags.use_def_invalid);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700126
127 // Mips-specific resource map setup here.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700128 if (flags & REG_DEF_SP) {
buzbeeb48819d2013-09-14 16:15:25 -0700129 lir->u.m.def_mask |= ENCODE_MIPS_REG_SP;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700130 }
131
132 if (flags & REG_USE_SP) {
buzbeeb48819d2013-09-14 16:15:25 -0700133 lir->u.m.use_mask |= ENCODE_MIPS_REG_SP;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700134 }
135
136 if (flags & REG_DEF_LR) {
buzbeeb48819d2013-09-14 16:15:25 -0700137 lir->u.m.def_mask |= ENCODE_MIPS_REG_LR;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700138 }
139}
140
141/* For dumping instructions */
142#define MIPS_REG_COUNT 32
143static const char *mips_reg_name[MIPS_REG_COUNT] = {
144 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
145 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
146 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
147 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
148};
149
150/*
151 * Interpret a format string and build a string no longer than size
152 * See format key in Assemble.c.
153 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700154std::string MipsMir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700155 std::string buf;
156 int i;
157 const char *fmt_end = &fmt[strlen(fmt)];
158 char tbuf[256];
159 char nc;
160 while (fmt < fmt_end) {
161 int operand;
162 if (*fmt == '!') {
163 fmt++;
164 DCHECK_LT(fmt, fmt_end);
165 nc = *fmt++;
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700166 if (nc == '!') {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700167 strcpy(tbuf, "!");
168 } else {
169 DCHECK_LT(fmt, fmt_end);
170 DCHECK_LT(static_cast<unsigned>(nc-'0'), 4u);
171 operand = lir->operands[nc-'0'];
172 switch (*fmt++) {
173 case 'b':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700174 strcpy(tbuf, "0000");
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700175 for (i = 3; i >= 0; i--) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700176 tbuf[i] += operand & 1;
177 operand >>= 1;
178 }
179 break;
180 case 's':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700181 sprintf(tbuf, "$f%d", operand & MIPS_FP_REG_MASK);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700182 break;
183 case 'S':
184 DCHECK_EQ(((operand & MIPS_FP_REG_MASK) & 1), 0);
Brian Carlstromb1eba212013-07-17 18:07:19 -0700185 sprintf(tbuf, "$f%d", operand & MIPS_FP_REG_MASK);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700186 break;
187 case 'h':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700188 sprintf(tbuf, "%04x", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700189 break;
190 case 'M':
191 case 'd':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700192 sprintf(tbuf, "%d", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700193 break;
194 case 'D':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700195 sprintf(tbuf, "%d", operand+1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700196 break;
197 case 'E':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700198 sprintf(tbuf, "%d", operand*4);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700199 break;
200 case 'F':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700201 sprintf(tbuf, "%d", operand*2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700202 break;
203 case 't':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700204 sprintf(tbuf, "0x%08x (L%p)", reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 +
Brian Carlstrom7940e442013-07-12 13:46:57 -0700205 (operand << 2), lir->target);
206 break;
207 case 'T':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700208 sprintf(tbuf, "0x%08x", operand << 2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700209 break;
210 case 'u': {
211 int offset_1 = lir->operands[0];
212 int offset_2 = NEXT_LIR(lir)->operands[0];
213 uintptr_t target =
214 (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) & ~3) +
215 (offset_1 << 21 >> 9) + (offset_2 << 1)) & 0xfffffffc;
216 sprintf(tbuf, "%p", reinterpret_cast<void*>(target));
217 break;
218 }
219
220 /* Nothing to print for BLX_2 */
221 case 'v':
222 strcpy(tbuf, "see above");
223 break;
224 case 'r':
225 DCHECK(operand >= 0 && operand < MIPS_REG_COUNT);
226 strcpy(tbuf, mips_reg_name[operand]);
227 break;
228 case 'N':
229 // Placeholder for delay slot handling
230 strcpy(tbuf, "; nop");
231 break;
232 default:
Brian Carlstromb1eba212013-07-17 18:07:19 -0700233 strcpy(tbuf, "DecodeError");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700234 break;
235 }
236 buf += tbuf;
237 }
238 } else {
239 buf += *fmt++;
240 }
241 }
242 return buf;
243}
244
245// FIXME: need to redo resource maps for MIPS - fix this at that time
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700246void MipsMir2Lir::DumpResourceMask(LIR *mips_lir, uint64_t mask, const char *prefix) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700247 char buf[256];
248 buf[0] = 0;
249
250 if (mask == ENCODE_ALL) {
251 strcpy(buf, "all");
252 } else {
253 char num[8];
254 int i;
255
256 for (i = 0; i < kMipsRegEnd; i++) {
257 if (mask & (1ULL << i)) {
258 sprintf(num, "%d ", i);
259 strcat(buf, num);
260 }
261 }
262
263 if (mask & ENCODE_CCODE) {
264 strcat(buf, "cc ");
265 }
266 if (mask & ENCODE_FP_STATUS) {
267 strcat(buf, "fpcc ");
268 }
269 /* Memory bits */
270 if (mips_lir && (mask & ENCODE_DALVIK_REG)) {
buzbeeb48819d2013-09-14 16:15:25 -0700271 sprintf(buf + strlen(buf), "dr%d%s", DECODE_ALIAS_INFO_REG(mips_lir->flags.alias_info),
272 DECODE_ALIAS_INFO_WIDE(mips_lir->flags.alias_info) ? "(+1)" : "");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700273 }
274 if (mask & ENCODE_LITERAL) {
275 strcat(buf, "lit ");
276 }
277
278 if (mask & ENCODE_HEAP_REF) {
279 strcat(buf, "heap ");
280 }
281 if (mask & ENCODE_MUST_NOT_ALIAS) {
282 strcat(buf, "noalias ");
283 }
284 }
285 if (buf[0]) {
286 LOG(INFO) << prefix << ": " << buf;
287 }
288}
289
290/*
291 * TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some
292 * instructions might call out to C/assembly helper functions. Until
293 * machinery is in place, always spill lr.
294 */
295
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700296void MipsMir2Lir::AdjustSpillMask() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700297 core_spill_mask_ |= (1 << r_RA);
298 num_core_spills_++;
299}
300
301/*
302 * Mark a callee-save fp register as promoted. Note that
303 * vpush/vpop uses contiguous register lists so we must
304 * include any holes in the mask. Associate holes with
305 * Dalvik register INVALID_VREG (0xFFFFU).
306 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700307void MipsMir2Lir::MarkPreservedSingle(int s_reg, int reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700308 LOG(FATAL) << "No support yet for promoted FP regs";
309}
310
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700311void MipsMir2Lir::FlushRegWide(int reg1, int reg2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700312 RegisterInfo* info1 = GetRegInfo(reg1);
313 RegisterInfo* info2 = GetRegInfo(reg2);
314 DCHECK(info1 && info2 && info1->pair && info2->pair &&
315 (info1->partner == info2->reg) &&
316 (info2->partner == info1->reg));
317 if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) {
318 if (!(info1->is_temp && info2->is_temp)) {
319 /* Should not happen. If it does, there's a problem in eval_loc */
320 LOG(FATAL) << "Long half-temp, half-promoted";
321 }
322
323 info1->dirty = false;
324 info2->dirty = false;
325 if (mir_graph_->SRegToVReg(info2->s_reg) < mir_graph_->SRegToVReg(info1->s_reg))
326 info1 = info2;
327 int v_reg = mir_graph_->SRegToVReg(info1->s_reg);
328 StoreBaseDispWide(rMIPS_SP, VRegOffset(v_reg), info1->reg, info1->partner);
329 }
330}
331
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700332void MipsMir2Lir::FlushReg(int reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700333 RegisterInfo* info = GetRegInfo(reg);
334 if (info->live && info->dirty) {
335 info->dirty = false;
336 int v_reg = mir_graph_->SRegToVReg(info->s_reg);
337 StoreBaseDisp(rMIPS_SP, VRegOffset(v_reg), reg, kWord);
338 }
339}
340
341/* Give access to the target-dependent FP register encoding to common code */
342bool MipsMir2Lir::IsFpReg(int reg) {
343 return MIPS_FPREG(reg);
344}
345
346/* Clobber all regs that might be used by an external C call */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700347void MipsMir2Lir::ClobberCalleeSave() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700348 Clobber(r_ZERO);
349 Clobber(r_AT);
350 Clobber(r_V0);
351 Clobber(r_V1);
352 Clobber(r_A0);
353 Clobber(r_A1);
354 Clobber(r_A2);
355 Clobber(r_A3);
356 Clobber(r_T0);
357 Clobber(r_T1);
358 Clobber(r_T2);
359 Clobber(r_T3);
360 Clobber(r_T4);
361 Clobber(r_T5);
362 Clobber(r_T6);
363 Clobber(r_T7);
364 Clobber(r_T8);
365 Clobber(r_T9);
366 Clobber(r_K0);
367 Clobber(r_K1);
368 Clobber(r_GP);
369 Clobber(r_FP);
370 Clobber(r_RA);
371 Clobber(r_F0);
372 Clobber(r_F1);
373 Clobber(r_F2);
374 Clobber(r_F3);
375 Clobber(r_F4);
376 Clobber(r_F5);
377 Clobber(r_F6);
378 Clobber(r_F7);
379 Clobber(r_F8);
380 Clobber(r_F9);
381 Clobber(r_F10);
382 Clobber(r_F11);
383 Clobber(r_F12);
384 Clobber(r_F13);
385 Clobber(r_F14);
386 Clobber(r_F15);
387}
388
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700389RegLocation MipsMir2Lir::GetReturnWideAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700390 UNIMPLEMENTED(FATAL) << "No GetReturnWideAlt for MIPS";
391 RegLocation res = LocCReturnWide();
392 return res;
393}
394
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700395RegLocation MipsMir2Lir::GetReturnAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700396 UNIMPLEMENTED(FATAL) << "No GetReturnAlt for MIPS";
397 RegLocation res = LocCReturn();
398 return res;
399}
400
Brian Carlstrom7940e442013-07-12 13:46:57 -0700401/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700402void MipsMir2Lir::LockCallTemps() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700403 LockTemp(rMIPS_ARG0);
404 LockTemp(rMIPS_ARG1);
405 LockTemp(rMIPS_ARG2);
406 LockTemp(rMIPS_ARG3);
407}
408
409/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700410void MipsMir2Lir::FreeCallTemps() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700411 FreeTemp(rMIPS_ARG0);
412 FreeTemp(rMIPS_ARG1);
413 FreeTemp(rMIPS_ARG2);
414 FreeTemp(rMIPS_ARG3);
415}
416
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700417void MipsMir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700418#if ANDROID_SMP != 0
419 NewLIR1(kMipsSync, 0 /* Only stype currently supported */);
420#endif
421}
422
423/*
424 * Alloc a pair of core registers, or a double. Low reg in low byte,
425 * high reg in next byte.
426 */
427int MipsMir2Lir::AllocTypedTempPair(bool fp_hint,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700428 int reg_class) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700429 int high_reg;
430 int low_reg;
431 int res = 0;
432
433 if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
434 low_reg = AllocTempDouble();
435 high_reg = low_reg + 1;
436 res = (low_reg & 0xff) | ((high_reg & 0xff) << 8);
437 return res;
438 }
439
440 low_reg = AllocTemp();
441 high_reg = AllocTemp();
442 res = (low_reg & 0xff) | ((high_reg & 0xff) << 8);
443 return res;
444}
445
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700446int MipsMir2Lir::AllocTypedTemp(bool fp_hint, int reg_class) {
447 if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700448 return AllocTempFloat();
449}
450 return AllocTemp();
451}
452
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700453void MipsMir2Lir::CompilerInitializeRegAlloc() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700454 int num_regs = sizeof(core_regs)/sizeof(*core_regs);
455 int num_reserved = sizeof(ReservedRegs)/sizeof(*ReservedRegs);
456 int num_temps = sizeof(core_temps)/sizeof(*core_temps);
457 int num_fp_regs = sizeof(FpRegs)/sizeof(*FpRegs);
458 int num_fp_temps = sizeof(fp_temps)/sizeof(*fp_temps);
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700459 reg_pool_ = static_cast<RegisterPool*>(arena_->Alloc(sizeof(*reg_pool_),
460 ArenaAllocator::kAllocRegAlloc));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700461 reg_pool_->num_core_regs = num_regs;
462 reg_pool_->core_regs = static_cast<RegisterInfo*>
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700463 (arena_->Alloc(num_regs * sizeof(*reg_pool_->core_regs), ArenaAllocator::kAllocRegAlloc));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700464 reg_pool_->num_fp_regs = num_fp_regs;
465 reg_pool_->FPRegs = static_cast<RegisterInfo*>
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700466 (arena_->Alloc(num_fp_regs * sizeof(*reg_pool_->FPRegs), ArenaAllocator::kAllocRegAlloc));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700467 CompilerInitPool(reg_pool_->core_regs, core_regs, reg_pool_->num_core_regs);
468 CompilerInitPool(reg_pool_->FPRegs, FpRegs, reg_pool_->num_fp_regs);
469 // Keep special registers from being allocated
470 for (int i = 0; i < num_reserved; i++) {
471 if (NO_SUSPEND && (ReservedRegs[i] == rMIPS_SUSPEND)) {
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700472 // To measure cost of suspend check
Brian Carlstrom7940e442013-07-12 13:46:57 -0700473 continue;
474 }
475 MarkInUse(ReservedRegs[i]);
476 }
477 // Mark temp regs - all others not in use can be used for promotion
478 for (int i = 0; i < num_temps; i++) {
479 MarkTemp(core_temps[i]);
480 }
481 for (int i = 0; i < num_fp_temps; i++) {
482 MarkTemp(fp_temps[i]);
483 }
484}
485
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700486void MipsMir2Lir::FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700487 if ((rl_free.low_reg != rl_keep.low_reg) && (rl_free.low_reg != rl_keep.high_reg) &&
488 (rl_free.high_reg != rl_keep.low_reg) && (rl_free.high_reg != rl_keep.high_reg)) {
489 // No overlap, free both
490 FreeTemp(rl_free.low_reg);
491 FreeTemp(rl_free.high_reg);
492 }
493}
494/*
495 * In the Arm code a it is typical to use the link register
496 * to hold the target address. However, for Mips we must
497 * ensure that all branch instructions can be restarted if
498 * there is a trap in the shadow. Allocate a temp register.
499 */
Ian Rogers468532e2013-08-05 10:56:33 -0700500int MipsMir2Lir::LoadHelper(ThreadOffset offset) {
501 LoadWordDisp(rMIPS_SELF, offset.Int32Value(), r_T9);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700502 return r_T9;
503}
504
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700505void MipsMir2Lir::SpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700506 if (num_core_spills_ == 0) {
507 return;
508 }
509 uint32_t mask = core_spill_mask_;
510 int offset = num_core_spills_ * 4;
511 OpRegImm(kOpSub, rMIPS_SP, offset);
512 for (int reg = 0; mask; mask >>= 1, reg++) {
513 if (mask & 0x1) {
514 offset -= 4;
515 StoreWordDisp(rMIPS_SP, offset, reg);
516 }
517 }
518}
519
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700520void MipsMir2Lir::UnSpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700521 if (num_core_spills_ == 0) {
522 return;
523 }
524 uint32_t mask = core_spill_mask_;
525 int offset = frame_size_;
526 for (int reg = 0; mask; mask >>= 1, reg++) {
527 if (mask & 0x1) {
528 offset -= 4;
529 LoadWordDisp(rMIPS_SP, offset, reg);
530 }
531 }
532 OpRegImm(kOpAdd, rMIPS_SP, frame_size_);
533}
534
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700535bool MipsMir2Lir::IsUnconditionalBranch(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700536 return (lir->opcode == kMipsB);
537}
538
539MipsMir2Lir::MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
540 : Mir2Lir(cu, mir_graph, arena) {
541 for (int i = 0; i < kMipsLast; i++) {
542 if (MipsMir2Lir::EncodingMap[i].opcode != i) {
543 LOG(FATAL) << "Encoding order for " << MipsMir2Lir::EncodingMap[i].name
544 << " is wrong: expecting " << i << ", seeing "
545 << static_cast<int>(MipsMir2Lir::EncodingMap[i].opcode);
546 }
547 }
548}
549
550Mir2Lir* MipsCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
551 ArenaAllocator* const arena) {
552 return new MipsMir2Lir(cu, mir_graph, arena);
553}
554
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700555uint64_t MipsMir2Lir::GetTargetInstFlags(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700556 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700557 return MipsMir2Lir::EncodingMap[opcode].flags;
558}
559
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700560const char* MipsMir2Lir::GetTargetInstName(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700561 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700562 return MipsMir2Lir::EncodingMap[opcode].name;
563}
564
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700565const char* MipsMir2Lir::GetTargetInstFmt(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700566 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700567 return MipsMir2Lir::EncodingMap[opcode].fmt;
568}
569
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700570} // namespace art