blob: 8e768dcf182b657e497d8d9139ec998666964310 [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
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700123void MipsMir2Lir::SetupTargetResourceMasks(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700124 DCHECK_EQ(cu_->instruction_set, kMips);
125
126 // Mips-specific resource map setup here.
127 uint64_t flags = MipsMir2Lir::EncodingMap[lir->opcode].flags;
128
129 if (flags & REG_DEF_SP) {
130 lir->def_mask |= ENCODE_MIPS_REG_SP;
131 }
132
133 if (flags & REG_USE_SP) {
134 lir->use_mask |= ENCODE_MIPS_REG_SP;
135 }
136
137 if (flags & REG_DEF_LR) {
138 lir->def_mask |= ENCODE_MIPS_REG_LR;
139 }
140}
141
142/* For dumping instructions */
143#define MIPS_REG_COUNT 32
144static const char *mips_reg_name[MIPS_REG_COUNT] = {
145 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
146 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
147 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
148 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
149};
150
151/*
152 * Interpret a format string and build a string no longer than size
153 * See format key in Assemble.c.
154 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700155std::string MipsMir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700156 std::string buf;
157 int i;
158 const char *fmt_end = &fmt[strlen(fmt)];
159 char tbuf[256];
160 char nc;
161 while (fmt < fmt_end) {
162 int operand;
163 if (*fmt == '!') {
164 fmt++;
165 DCHECK_LT(fmt, fmt_end);
166 nc = *fmt++;
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700167 if (nc == '!') {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700168 strcpy(tbuf, "!");
169 } else {
170 DCHECK_LT(fmt, fmt_end);
171 DCHECK_LT(static_cast<unsigned>(nc-'0'), 4u);
172 operand = lir->operands[nc-'0'];
173 switch (*fmt++) {
174 case 'b':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700175 strcpy(tbuf, "0000");
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700176 for (i = 3; i >= 0; i--) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700177 tbuf[i] += operand & 1;
178 operand >>= 1;
179 }
180 break;
181 case 's':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700182 sprintf(tbuf, "$f%d", operand & MIPS_FP_REG_MASK);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700183 break;
184 case 'S':
185 DCHECK_EQ(((operand & MIPS_FP_REG_MASK) & 1), 0);
Brian Carlstromb1eba212013-07-17 18:07:19 -0700186 sprintf(tbuf, "$f%d", operand & MIPS_FP_REG_MASK);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700187 break;
188 case 'h':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700189 sprintf(tbuf, "%04x", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700190 break;
191 case 'M':
192 case 'd':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700193 sprintf(tbuf, "%d", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700194 break;
195 case 'D':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700196 sprintf(tbuf, "%d", operand+1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700197 break;
198 case 'E':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700199 sprintf(tbuf, "%d", operand*4);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700200 break;
201 case 'F':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700202 sprintf(tbuf, "%d", operand*2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700203 break;
204 case 't':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700205 sprintf(tbuf, "0x%08x (L%p)", reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 +
Brian Carlstrom7940e442013-07-12 13:46:57 -0700206 (operand << 2), lir->target);
207 break;
208 case 'T':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700209 sprintf(tbuf, "0x%08x", operand << 2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700210 break;
211 case 'u': {
212 int offset_1 = lir->operands[0];
213 int offset_2 = NEXT_LIR(lir)->operands[0];
214 uintptr_t target =
215 (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) & ~3) +
216 (offset_1 << 21 >> 9) + (offset_2 << 1)) & 0xfffffffc;
217 sprintf(tbuf, "%p", reinterpret_cast<void*>(target));
218 break;
219 }
220
221 /* Nothing to print for BLX_2 */
222 case 'v':
223 strcpy(tbuf, "see above");
224 break;
225 case 'r':
226 DCHECK(operand >= 0 && operand < MIPS_REG_COUNT);
227 strcpy(tbuf, mips_reg_name[operand]);
228 break;
229 case 'N':
230 // Placeholder for delay slot handling
231 strcpy(tbuf, "; nop");
232 break;
233 default:
Brian Carlstromb1eba212013-07-17 18:07:19 -0700234 strcpy(tbuf, "DecodeError");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700235 break;
236 }
237 buf += tbuf;
238 }
239 } else {
240 buf += *fmt++;
241 }
242 }
243 return buf;
244}
245
246// FIXME: need to redo resource maps for MIPS - fix this at that time
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700247void MipsMir2Lir::DumpResourceMask(LIR *mips_lir, uint64_t mask, const char *prefix) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700248 char buf[256];
249 buf[0] = 0;
250
251 if (mask == ENCODE_ALL) {
252 strcpy(buf, "all");
253 } else {
254 char num[8];
255 int i;
256
257 for (i = 0; i < kMipsRegEnd; i++) {
258 if (mask & (1ULL << i)) {
259 sprintf(num, "%d ", i);
260 strcat(buf, num);
261 }
262 }
263
264 if (mask & ENCODE_CCODE) {
265 strcat(buf, "cc ");
266 }
267 if (mask & ENCODE_FP_STATUS) {
268 strcat(buf, "fpcc ");
269 }
270 /* Memory bits */
271 if (mips_lir && (mask & ENCODE_DALVIK_REG)) {
272 sprintf(buf + strlen(buf), "dr%d%s", mips_lir->alias_info & 0xffff,
273 (mips_lir->alias_info & 0x80000000) ? "(+1)" : "");
274 }
275 if (mask & ENCODE_LITERAL) {
276 strcat(buf, "lit ");
277 }
278
279 if (mask & ENCODE_HEAP_REF) {
280 strcat(buf, "heap ");
281 }
282 if (mask & ENCODE_MUST_NOT_ALIAS) {
283 strcat(buf, "noalias ");
284 }
285 }
286 if (buf[0]) {
287 LOG(INFO) << prefix << ": " << buf;
288 }
289}
290
291/*
292 * TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some
293 * instructions might call out to C/assembly helper functions. Until
294 * machinery is in place, always spill lr.
295 */
296
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700297void MipsMir2Lir::AdjustSpillMask() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700298 core_spill_mask_ |= (1 << r_RA);
299 num_core_spills_++;
300}
301
302/*
303 * Mark a callee-save fp register as promoted. Note that
304 * vpush/vpop uses contiguous register lists so we must
305 * include any holes in the mask. Associate holes with
306 * Dalvik register INVALID_VREG (0xFFFFU).
307 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700308void MipsMir2Lir::MarkPreservedSingle(int s_reg, int reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700309 LOG(FATAL) << "No support yet for promoted FP regs";
310}
311
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700312void MipsMir2Lir::FlushRegWide(int reg1, int reg2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700313 RegisterInfo* info1 = GetRegInfo(reg1);
314 RegisterInfo* info2 = GetRegInfo(reg2);
315 DCHECK(info1 && info2 && info1->pair && info2->pair &&
316 (info1->partner == info2->reg) &&
317 (info2->partner == info1->reg));
318 if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) {
319 if (!(info1->is_temp && info2->is_temp)) {
320 /* Should not happen. If it does, there's a problem in eval_loc */
321 LOG(FATAL) << "Long half-temp, half-promoted";
322 }
323
324 info1->dirty = false;
325 info2->dirty = false;
326 if (mir_graph_->SRegToVReg(info2->s_reg) < mir_graph_->SRegToVReg(info1->s_reg))
327 info1 = info2;
328 int v_reg = mir_graph_->SRegToVReg(info1->s_reg);
329 StoreBaseDispWide(rMIPS_SP, VRegOffset(v_reg), info1->reg, info1->partner);
330 }
331}
332
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700333void MipsMir2Lir::FlushReg(int reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700334 RegisterInfo* info = GetRegInfo(reg);
335 if (info->live && info->dirty) {
336 info->dirty = false;
337 int v_reg = mir_graph_->SRegToVReg(info->s_reg);
338 StoreBaseDisp(rMIPS_SP, VRegOffset(v_reg), reg, kWord);
339 }
340}
341
342/* Give access to the target-dependent FP register encoding to common code */
343bool MipsMir2Lir::IsFpReg(int reg) {
344 return MIPS_FPREG(reg);
345}
346
347/* Clobber all regs that might be used by an external C call */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700348void MipsMir2Lir::ClobberCalleeSave() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700349 Clobber(r_ZERO);
350 Clobber(r_AT);
351 Clobber(r_V0);
352 Clobber(r_V1);
353 Clobber(r_A0);
354 Clobber(r_A1);
355 Clobber(r_A2);
356 Clobber(r_A3);
357 Clobber(r_T0);
358 Clobber(r_T1);
359 Clobber(r_T2);
360 Clobber(r_T3);
361 Clobber(r_T4);
362 Clobber(r_T5);
363 Clobber(r_T6);
364 Clobber(r_T7);
365 Clobber(r_T8);
366 Clobber(r_T9);
367 Clobber(r_K0);
368 Clobber(r_K1);
369 Clobber(r_GP);
370 Clobber(r_FP);
371 Clobber(r_RA);
372 Clobber(r_F0);
373 Clobber(r_F1);
374 Clobber(r_F2);
375 Clobber(r_F3);
376 Clobber(r_F4);
377 Clobber(r_F5);
378 Clobber(r_F6);
379 Clobber(r_F7);
380 Clobber(r_F8);
381 Clobber(r_F9);
382 Clobber(r_F10);
383 Clobber(r_F11);
384 Clobber(r_F12);
385 Clobber(r_F13);
386 Clobber(r_F14);
387 Clobber(r_F15);
388}
389
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700390RegLocation MipsMir2Lir::GetReturnWideAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700391 UNIMPLEMENTED(FATAL) << "No GetReturnWideAlt for MIPS";
392 RegLocation res = LocCReturnWide();
393 return res;
394}
395
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700396RegLocation MipsMir2Lir::GetReturnAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700397 UNIMPLEMENTED(FATAL) << "No GetReturnAlt for MIPS";
398 RegLocation res = LocCReturn();
399 return res;
400}
401
Brian Carlstrom7940e442013-07-12 13:46:57 -0700402/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700403void MipsMir2Lir::LockCallTemps() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700404 LockTemp(rMIPS_ARG0);
405 LockTemp(rMIPS_ARG1);
406 LockTemp(rMIPS_ARG2);
407 LockTemp(rMIPS_ARG3);
408}
409
410/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700411void MipsMir2Lir::FreeCallTemps() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700412 FreeTemp(rMIPS_ARG0);
413 FreeTemp(rMIPS_ARG1);
414 FreeTemp(rMIPS_ARG2);
415 FreeTemp(rMIPS_ARG3);
416}
417
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700418void MipsMir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700419#if ANDROID_SMP != 0
420 NewLIR1(kMipsSync, 0 /* Only stype currently supported */);
421#endif
422}
423
424/*
425 * Alloc a pair of core registers, or a double. Low reg in low byte,
426 * high reg in next byte.
427 */
428int MipsMir2Lir::AllocTypedTempPair(bool fp_hint,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700429 int reg_class) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700430 int high_reg;
431 int low_reg;
432 int res = 0;
433
434 if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
435 low_reg = AllocTempDouble();
436 high_reg = low_reg + 1;
437 res = (low_reg & 0xff) | ((high_reg & 0xff) << 8);
438 return res;
439 }
440
441 low_reg = AllocTemp();
442 high_reg = AllocTemp();
443 res = (low_reg & 0xff) | ((high_reg & 0xff) << 8);
444 return res;
445}
446
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700447int MipsMir2Lir::AllocTypedTemp(bool fp_hint, int reg_class) {
448 if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700449 return AllocTempFloat();
450}
451 return AllocTemp();
452}
453
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700454void MipsMir2Lir::CompilerInitializeRegAlloc() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700455 int num_regs = sizeof(core_regs)/sizeof(*core_regs);
456 int num_reserved = sizeof(ReservedRegs)/sizeof(*ReservedRegs);
457 int num_temps = sizeof(core_temps)/sizeof(*core_temps);
458 int num_fp_regs = sizeof(FpRegs)/sizeof(*FpRegs);
459 int num_fp_temps = sizeof(fp_temps)/sizeof(*fp_temps);
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700460 reg_pool_ = static_cast<RegisterPool*>(arena_->Alloc(sizeof(*reg_pool_),
461 ArenaAllocator::kAllocRegAlloc));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700462 reg_pool_->num_core_regs = num_regs;
463 reg_pool_->core_regs = static_cast<RegisterInfo*>
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700464 (arena_->Alloc(num_regs * sizeof(*reg_pool_->core_regs), ArenaAllocator::kAllocRegAlloc));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700465 reg_pool_->num_fp_regs = num_fp_regs;
466 reg_pool_->FPRegs = static_cast<RegisterInfo*>
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700467 (arena_->Alloc(num_fp_regs * sizeof(*reg_pool_->FPRegs), ArenaAllocator::kAllocRegAlloc));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700468 CompilerInitPool(reg_pool_->core_regs, core_regs, reg_pool_->num_core_regs);
469 CompilerInitPool(reg_pool_->FPRegs, FpRegs, reg_pool_->num_fp_regs);
470 // Keep special registers from being allocated
471 for (int i = 0; i < num_reserved; i++) {
472 if (NO_SUSPEND && (ReservedRegs[i] == rMIPS_SUSPEND)) {
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700473 // To measure cost of suspend check
Brian Carlstrom7940e442013-07-12 13:46:57 -0700474 continue;
475 }
476 MarkInUse(ReservedRegs[i]);
477 }
478 // Mark temp regs - all others not in use can be used for promotion
479 for (int i = 0; i < num_temps; i++) {
480 MarkTemp(core_temps[i]);
481 }
482 for (int i = 0; i < num_fp_temps; i++) {
483 MarkTemp(fp_temps[i]);
484 }
485}
486
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700487void MipsMir2Lir::FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700488 if ((rl_free.low_reg != rl_keep.low_reg) && (rl_free.low_reg != rl_keep.high_reg) &&
489 (rl_free.high_reg != rl_keep.low_reg) && (rl_free.high_reg != rl_keep.high_reg)) {
490 // No overlap, free both
491 FreeTemp(rl_free.low_reg);
492 FreeTemp(rl_free.high_reg);
493 }
494}
495/*
496 * In the Arm code a it is typical to use the link register
497 * to hold the target address. However, for Mips we must
498 * ensure that all branch instructions can be restarted if
499 * there is a trap in the shadow. Allocate a temp register.
500 */
Ian Rogers468532e2013-08-05 10:56:33 -0700501int MipsMir2Lir::LoadHelper(ThreadOffset offset) {
502 LoadWordDisp(rMIPS_SELF, offset.Int32Value(), r_T9);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700503 return r_T9;
504}
505
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700506void MipsMir2Lir::SpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700507 if (num_core_spills_ == 0) {
508 return;
509 }
510 uint32_t mask = core_spill_mask_;
511 int offset = num_core_spills_ * 4;
512 OpRegImm(kOpSub, rMIPS_SP, offset);
513 for (int reg = 0; mask; mask >>= 1, reg++) {
514 if (mask & 0x1) {
515 offset -= 4;
516 StoreWordDisp(rMIPS_SP, offset, reg);
517 }
518 }
519}
520
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700521void MipsMir2Lir::UnSpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700522 if (num_core_spills_ == 0) {
523 return;
524 }
525 uint32_t mask = core_spill_mask_;
526 int offset = frame_size_;
527 for (int reg = 0; mask; mask >>= 1, reg++) {
528 if (mask & 0x1) {
529 offset -= 4;
530 LoadWordDisp(rMIPS_SP, offset, reg);
531 }
532 }
533 OpRegImm(kOpAdd, rMIPS_SP, frame_size_);
534}
535
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700536bool MipsMir2Lir::IsUnconditionalBranch(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700537 return (lir->opcode == kMipsB);
538}
539
540MipsMir2Lir::MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
541 : Mir2Lir(cu, mir_graph, arena) {
542 for (int i = 0; i < kMipsLast; i++) {
543 if (MipsMir2Lir::EncodingMap[i].opcode != i) {
544 LOG(FATAL) << "Encoding order for " << MipsMir2Lir::EncodingMap[i].name
545 << " is wrong: expecting " << i << ", seeing "
546 << static_cast<int>(MipsMir2Lir::EncodingMap[i].opcode);
547 }
548 }
549}
550
551Mir2Lir* MipsCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
552 ArenaAllocator* const arena) {
553 return new MipsMir2Lir(cu, mir_graph, arena);
554}
555
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700556uint64_t MipsMir2Lir::GetTargetInstFlags(int 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) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700561 return MipsMir2Lir::EncodingMap[opcode].name;
562}
563
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700564const char* MipsMir2Lir::GetTargetInstFmt(int opcode) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700565 return MipsMir2Lir::EncodingMap[opcode].fmt;
566}
567
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700568} // namespace art