blob: a3621f5d5263841d142f80398efb62cc01ebce02 [file] [log] [blame]
buzbeeefc63692012-11-14 16:31:52 -08001/*
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 "../../compiler_internals.h"
18#include "mips_lir.h"
buzbeeeaf09bc2012-11-15 14:51:41 -080019#include "../ralloc_util.h"
20#include "../codegen_util.h"
buzbeeefc63692012-11-14 16:31:52 -080021
22#include <string>
23
24namespace art {
25
26static int coreRegs[] = {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 coreTemps[] = {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};
34#ifdef __mips_hard_float
35static int fpRegs[] = {r_F0, r_F1, r_F2, r_F3, r_F4, r_F5, r_F6, r_F7,
36 r_F8, r_F9, r_F10, r_F11, r_F12, r_F13, r_F14, r_F15};
37static int fpTemps[] = {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};
39#endif
40
41RegLocation locCReturn()
42{
43 RegLocation res = MIPS_LOC_C_RETURN;
44 return res;
45}
46
47RegLocation locCReturnWide()
48{
49 RegLocation res = MIPS_LOC_C_RETURN_WIDE;
50 return res;
51}
52
53RegLocation locCReturnFloat()
54{
55 RegLocation res = MIPS_LOC_C_RETURN_FLOAT;
56 return res;
57}
58
59RegLocation locCReturnDouble()
60{
61 RegLocation res = MIPS_LOC_C_RETURN_DOUBLE;
62 return res;
63}
64
65// Return a target-dependent special register.
66int targetReg(SpecialTargetRegister reg) {
67 int res = INVALID_REG;
68 switch (reg) {
69 case kSelf: res = rMIPS_SELF; break;
70 case kSuspend: res = rMIPS_SUSPEND; break;
71 case kLr: res = rMIPS_LR; break;
72 case kPc: res = rMIPS_PC; break;
73 case kSp: res = rMIPS_SP; break;
74 case kArg0: res = rMIPS_ARG0; break;
75 case kArg1: res = rMIPS_ARG1; break;
76 case kArg2: res = rMIPS_ARG2; break;
77 case kArg3: res = rMIPS_ARG3; break;
78 case kFArg0: res = rMIPS_FARG0; break;
79 case kFArg1: res = rMIPS_FARG1; break;
80 case kFArg2: res = rMIPS_FARG2; break;
81 case kFArg3: res = rMIPS_FARG3; break;
82 case kRet0: res = rMIPS_RET0; break;
83 case kRet1: res = rMIPS_RET1; break;
84 case kInvokeTgt: res = rMIPS_INVOKE_TGT; break;
85 case kCount: res = rMIPS_COUNT; break;
86 }
87 return res;
88}
89
90// Create a double from a pair of singles.
91int s2d(int lowReg, int highReg)
92{
93 return MIPS_S2D(lowReg, highReg);
94}
95
96// Is reg a single or double?
97bool fpReg(int reg)
98{
99 return MIPS_FPREG(reg);
100}
101
102// Is reg a single?
103bool singleReg(int reg)
104{
105 return MIPS_SINGLEREG(reg);
106}
107
108// Is reg a double?
109bool doubleReg(int reg)
110{
111 return MIPS_DOUBLEREG(reg);
112}
113
114// Return mask to strip off fp reg flags and bias.
115uint32_t fpRegMask()
116{
117 return MIPS_FP_REG_MASK;
118}
119
120// True if both regs single, both core or both double.
121bool sameRegType(int reg1, int reg2)
122{
123 return (MIPS_REGTYPE(reg1) == MIPS_REGTYPE(reg2));
124}
125
126/*
127 * Decode the register id.
128 */
buzbeeeaf09bc2012-11-15 14:51:41 -0800129uint64_t getRegMaskCommon(CompilationUnit* cUnit, int reg)
buzbeeefc63692012-11-14 16:31:52 -0800130{
buzbeeeaf09bc2012-11-15 14:51:41 -0800131 uint64_t seed;
buzbeeefc63692012-11-14 16:31:52 -0800132 int shift;
133 int regId;
134
135
136 regId = reg & 0x1f;
137 /* Each double register is equal to a pair of single-precision FP registers */
138 seed = MIPS_DOUBLEREG(reg) ? 3 : 1;
139 /* FP register starts at bit position 16 */
140 shift = MIPS_FPREG(reg) ? kMipsFPReg0 : 0;
141 /* Expand the double register id into single offset */
142 shift += regId;
143 return (seed << shift);
144}
145
146uint64_t getPCUseDefEncoding()
147{
148 return ENCODE_MIPS_REG_PC;
149}
150
151
152void setupTargetResourceMasks(CompilationUnit* cUnit, LIR* lir)
153{
154 DCHECK_EQ(cUnit->instructionSet, kMips);
155
156 // Mips-specific resource map setup here.
157 uint64_t flags = EncodingMap[lir->opcode].flags;
158
159 if (flags & REG_DEF_SP) {
160 lir->defMask |= ENCODE_MIPS_REG_SP;
161 }
162
163 if (flags & REG_USE_SP) {
164 lir->useMask |= ENCODE_MIPS_REG_SP;
165 }
166
167 if (flags & REG_DEF_LR) {
168 lir->defMask |= ENCODE_MIPS_REG_LR;
169 }
170}
171
172/* For dumping instructions */
173#define MIPS_REG_COUNT 32
174static const char *mipsRegName[MIPS_REG_COUNT] = {
175 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
176 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
177 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
178 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
179};
180
181/*
182 * Interpret a format string and build a string no longer than size
183 * See format key in Assemble.c.
184 */
185std::string buildInsnString(const char *fmt, LIR *lir, unsigned char* baseAddr)
186{
187 std::string buf;
188 int i;
189 const char *fmtEnd = &fmt[strlen(fmt)];
190 char tbuf[256];
191 char nc;
192 while (fmt < fmtEnd) {
193 int operand;
194 if (*fmt == '!') {
195 fmt++;
196 DCHECK_LT(fmt, fmtEnd);
197 nc = *fmt++;
198 if (nc=='!') {
199 strcpy(tbuf, "!");
200 } else {
201 DCHECK_LT(fmt, fmtEnd);
buzbeecbd6d442012-11-17 14:11:25 -0800202 DCHECK_LT(static_cast<unsigned>(nc-'0'), 4u);
buzbeeefc63692012-11-14 16:31:52 -0800203 operand = lir->operands[nc-'0'];
204 switch (*fmt++) {
205 case 'b':
206 strcpy(tbuf,"0000");
207 for (i=3; i>= 0; i--) {
208 tbuf[i] += operand & 1;
209 operand >>= 1;
210 }
211 break;
212 case 's':
213 sprintf(tbuf,"$f%d",operand & MIPS_FP_REG_MASK);
214 break;
215 case 'S':
216 DCHECK_EQ(((operand & MIPS_FP_REG_MASK) & 1), 0);
217 sprintf(tbuf,"$f%d",operand & MIPS_FP_REG_MASK);
218 break;
219 case 'h':
220 sprintf(tbuf,"%04x", operand);
221 break;
222 case 'M':
223 case 'd':
224 sprintf(tbuf,"%d", operand);
225 break;
226 case 'D':
227 sprintf(tbuf,"%d", operand+1);
228 break;
229 case 'E':
230 sprintf(tbuf,"%d", operand*4);
231 break;
232 case 'F':
233 sprintf(tbuf,"%d", operand*2);
234 break;
235 case 't':
buzbeecbd6d442012-11-17 14:11:25 -0800236 sprintf(tbuf,"0x%08x (L%p)", reinterpret_cast<uintptr_t>(baseAddr) + lir->offset + 4 +
buzbeeefc63692012-11-14 16:31:52 -0800237 (operand << 2), lir->target);
238 break;
239 case 'T':
buzbeecbd6d442012-11-17 14:11:25 -0800240 sprintf(tbuf,"0x%08x", operand << 2);
buzbeeefc63692012-11-14 16:31:52 -0800241 break;
242 case 'u': {
243 int offset_1 = lir->operands[0];
244 int offset_2 = NEXT_LIR(lir)->operands[0];
buzbeecbd6d442012-11-17 14:11:25 -0800245 uintptr_t target =
246 (((reinterpret_cast<uintptr_t>(baseAddr) + lir->offset + 4) & ~3) +
buzbeeefc63692012-11-14 16:31:52 -0800247 (offset_1 << 21 >> 9) + (offset_2 << 1)) & 0xfffffffc;
buzbeecbd6d442012-11-17 14:11:25 -0800248 sprintf(tbuf, "%p", reinterpret_cast<void*>(target));
buzbeeefc63692012-11-14 16:31:52 -0800249 break;
250 }
251
252 /* Nothing to print for BLX_2 */
253 case 'v':
254 strcpy(tbuf, "see above");
255 break;
256 case 'r':
257 DCHECK(operand >= 0 && operand < MIPS_REG_COUNT);
258 strcpy(tbuf, mipsRegName[operand]);
259 break;
260 case 'N':
261 // Placeholder for delay slot handling
262 strcpy(tbuf, "; nop");
263 break;
264 default:
265 strcpy(tbuf,"DecodeError");
266 break;
267 }
268 buf += tbuf;
269 }
270 } else {
271 buf += *fmt++;
272 }
273 }
274 return buf;
275}
276
277// FIXME: need to redo resource maps for MIPS - fix this at that time
buzbeecbd6d442012-11-17 14:11:25 -0800278void oatDumpResourceMask(LIR *mipsLIR, uint64_t mask, const char *prefix)
buzbeeefc63692012-11-14 16:31:52 -0800279{
280 char buf[256];
281 buf[0] = 0;
buzbeeefc63692012-11-14 16:31:52 -0800282
283 if (mask == ENCODE_ALL) {
284 strcpy(buf, "all");
285 } else {
286 char num[8];
287 int i;
288
289 for (i = 0; i < kMipsRegEnd; i++) {
290 if (mask & (1ULL << i)) {
291 sprintf(num, "%d ", i);
292 strcat(buf, num);
293 }
294 }
295
296 if (mask & ENCODE_CCODE) {
297 strcat(buf, "cc ");
298 }
299 if (mask & ENCODE_FP_STATUS) {
300 strcat(buf, "fpcc ");
301 }
302 /* Memory bits */
303 if (mipsLIR && (mask & ENCODE_DALVIK_REG)) {
304 sprintf(buf + strlen(buf), "dr%d%s", mipsLIR->aliasInfo & 0xffff,
305 (mipsLIR->aliasInfo & 0x80000000) ? "(+1)" : "");
306 }
307 if (mask & ENCODE_LITERAL) {
308 strcat(buf, "lit ");
309 }
310
311 if (mask & ENCODE_HEAP_REF) {
312 strcat(buf, "heap ");
313 }
314 if (mask & ENCODE_MUST_NOT_ALIAS) {
315 strcat(buf, "noalias ");
316 }
317 }
318 if (buf[0]) {
319 LOG(INFO) << prefix << ": " << buf;
320 }
321}
322
323/*
324 * TUNING: is leaf? Can't just use "hasInvoke" to determine as some
325 * instructions might call out to C/assembly helper functions. Until
326 * machinery is in place, always spill lr.
327 */
328
329void oatAdjustSpillMask(CompilationUnit* cUnit)
330{
331 cUnit->coreSpillMask |= (1 << r_RA);
332 cUnit->numCoreSpills++;
333}
334
335/*
336 * Mark a callee-save fp register as promoted. Note that
337 * vpush/vpop uses contiguous register lists so we must
338 * include any holes in the mask. Associate holes with
339 * Dalvik register INVALID_VREG (0xFFFFU).
340 */
341void oatMarkPreservedSingle(CompilationUnit* cUnit, int sReg, int reg)
342{
343 LOG(FATAL) << "No support yet for promoted FP regs";
344}
345
346void oatFlushRegWide(CompilationUnit* cUnit, int reg1, int reg2)
347{
348 RegisterInfo* info1 = oatGetRegInfo(cUnit, reg1);
349 RegisterInfo* info2 = oatGetRegInfo(cUnit, reg2);
350 DCHECK(info1 && info2 && info1->pair && info2->pair &&
351 (info1->partner == info2->reg) &&
352 (info2->partner == info1->reg));
353 if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) {
354 if (!(info1->isTemp && info2->isTemp)) {
355 /* Should not happen. If it does, there's a problem in evalLoc */
356 LOG(FATAL) << "Long half-temp, half-promoted";
357 }
358
359 info1->dirty = false;
360 info2->dirty = false;
361 if (SRegToVReg(cUnit, info2->sReg) < SRegToVReg(cUnit, info1->sReg))
362 info1 = info2;
363 int vReg = SRegToVReg(cUnit, info1->sReg);
buzbeeeaf09bc2012-11-15 14:51:41 -0800364 storeBaseDispWide(cUnit, rMIPS_SP, oatVRegOffset(cUnit, vReg), info1->reg, info1->partner);
buzbeeefc63692012-11-14 16:31:52 -0800365 }
366}
367
368void oatFlushReg(CompilationUnit* cUnit, int reg)
369{
370 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
371 if (info->live && info->dirty) {
372 info->dirty = false;
373 int vReg = SRegToVReg(cUnit, info->sReg);
buzbeeeaf09bc2012-11-15 14:51:41 -0800374 storeBaseDisp(cUnit, rMIPS_SP, oatVRegOffset(cUnit, vReg), reg, kWord);
buzbeeefc63692012-11-14 16:31:52 -0800375 }
376}
377
378/* Give access to the target-dependent FP register encoding to common code */
379bool oatIsFpReg(int reg) {
380 return MIPS_FPREG(reg);
381}
382
383uint32_t oatFpRegMask() {
384 return MIPS_FP_REG_MASK;
385}
386
387/* Clobber all regs that might be used by an external C call */
388extern void oatClobberCalleeSave(CompilationUnit *cUnit)
389{
390 oatClobber(cUnit, r_ZERO);
391 oatClobber(cUnit, r_AT);
392 oatClobber(cUnit, r_V0);
393 oatClobber(cUnit, r_V1);
394 oatClobber(cUnit, r_A0);
395 oatClobber(cUnit, r_A1);
396 oatClobber(cUnit, r_A2);
397 oatClobber(cUnit, r_A3);
398 oatClobber(cUnit, r_T0);
399 oatClobber(cUnit, r_T1);
400 oatClobber(cUnit, r_T2);
401 oatClobber(cUnit, r_T3);
402 oatClobber(cUnit, r_T4);
403 oatClobber(cUnit, r_T5);
404 oatClobber(cUnit, r_T6);
405 oatClobber(cUnit, r_T7);
406 oatClobber(cUnit, r_T8);
407 oatClobber(cUnit, r_T9);
408 oatClobber(cUnit, r_K0);
409 oatClobber(cUnit, r_K1);
410 oatClobber(cUnit, r_GP);
411 oatClobber(cUnit, r_FP);
412 oatClobber(cUnit, r_RA);
413 oatClobber(cUnit, r_F0);
414 oatClobber(cUnit, r_F1);
415 oatClobber(cUnit, r_F2);
416 oatClobber(cUnit, r_F3);
417 oatClobber(cUnit, r_F4);
418 oatClobber(cUnit, r_F5);
419 oatClobber(cUnit, r_F6);
420 oatClobber(cUnit, r_F7);
421 oatClobber(cUnit, r_F8);
422 oatClobber(cUnit, r_F9);
423 oatClobber(cUnit, r_F10);
424 oatClobber(cUnit, r_F11);
425 oatClobber(cUnit, r_F12);
426 oatClobber(cUnit, r_F13);
427 oatClobber(cUnit, r_F14);
428 oatClobber(cUnit, r_F15);
429}
430
431extern RegLocation oatGetReturnWideAlt(CompilationUnit* cUnit)
432{
433 UNIMPLEMENTED(FATAL) << "No oatGetReturnWideAlt for MIPS";
434 RegLocation res = locCReturnWide();
435 return res;
436}
437
438extern RegLocation oatGetReturnAlt(CompilationUnit* cUnit)
439{
440 UNIMPLEMENTED(FATAL) << "No oatGetReturnAlt for MIPS";
441 RegLocation res = locCReturn();
442 return res;
443}
444
445extern RegisterInfo* oatGetRegInfo(CompilationUnit* cUnit, int reg)
446{
447 return MIPS_FPREG(reg) ? &cUnit->regPool->FPRegs[reg & MIPS_FP_REG_MASK]
448 : &cUnit->regPool->coreRegs[reg];
449}
450
451/* To be used when explicitly managing register use */
452extern void oatLockCallTemps(CompilationUnit* cUnit)
453{
454 oatLockTemp(cUnit, rMIPS_ARG0);
455 oatLockTemp(cUnit, rMIPS_ARG1);
456 oatLockTemp(cUnit, rMIPS_ARG2);
457 oatLockTemp(cUnit, rMIPS_ARG3);
458}
459
460/* To be used when explicitly managing register use */
461extern void oatFreeCallTemps(CompilationUnit* cUnit)
462{
463 oatFreeTemp(cUnit, rMIPS_ARG0);
464 oatFreeTemp(cUnit, rMIPS_ARG1);
465 oatFreeTemp(cUnit, rMIPS_ARG2);
466 oatFreeTemp(cUnit, rMIPS_ARG3);
467}
468
buzbeeefc63692012-11-14 16:31:52 -0800469/*
470 * Determine the initial instruction set to be used for this trace.
471 * Later components may decide to change this.
472 */
473InstructionSet oatInstructionSet()
474{
475 return kMips;
476}
477
478/* Architecture-specific initializations and checks go here */
479bool oatArchVariantInit(void)
480{
481 return true;
482}
483
buzbee1bc37c62012-11-20 13:35:41 -0800484void oatGenMemBarrier(CompilationUnit *cUnit, MemBarrierKind barrierKind)
buzbeeefc63692012-11-14 16:31:52 -0800485{
486#if ANDROID_SMP != 0
buzbee1bc37c62012-11-20 13:35:41 -0800487 newLIR1(cUnit, kMipsSync, 0 /* Only stype currently supported */);
buzbeeefc63692012-11-14 16:31:52 -0800488#endif
489}
490
491/*
492 * Alloc a pair of core registers, or a double. Low reg in low byte,
493 * high reg in next byte.
494 */
495int oatAllocTypedTempPair(CompilationUnit *cUnit, bool fpHint,
496 int regClass)
497{
498 int highReg;
499 int lowReg;
500 int res = 0;
501
502#ifdef __mips_hard_float
503 if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg)) {
504 lowReg = oatAllocTempDouble(cUnit);
505 highReg = lowReg + 1;
506 res = (lowReg & 0xff) | ((highReg & 0xff) << 8);
507 return res;
508 }
509#endif
510
511 lowReg = oatAllocTemp(cUnit);
512 highReg = oatAllocTemp(cUnit);
513 res = (lowReg & 0xff) | ((highReg & 0xff) << 8);
514 return res;
515}
516
517int oatAllocTypedTemp(CompilationUnit *cUnit, bool fpHint, int regClass)
518{
519#ifdef __mips_hard_float
520 if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg))
521{
522 return oatAllocTempFloat(cUnit);
523}
524#endif
525 return oatAllocTemp(cUnit);
526}
527
528void oatInitializeRegAlloc(CompilationUnit* cUnit)
529{
530 int numRegs = sizeof(coreRegs)/sizeof(*coreRegs);
531 int numReserved = sizeof(reservedRegs)/sizeof(*reservedRegs);
532 int numTemps = sizeof(coreTemps)/sizeof(*coreTemps);
533#ifdef __mips_hard_float
534 int numFPRegs = sizeof(fpRegs)/sizeof(*fpRegs);
535 int numFPTemps = sizeof(fpTemps)/sizeof(*fpTemps);
536#else
537 int numFPRegs = 0;
538 int numFPTemps = 0;
539#endif
buzbeecbd6d442012-11-17 14:11:25 -0800540 RegisterPool *pool =
541 static_cast<RegisterPool*>(oatNew(cUnit, sizeof(*pool), true, kAllocRegAlloc));
buzbeeefc63692012-11-14 16:31:52 -0800542 cUnit->regPool = pool;
543 pool->numCoreRegs = numRegs;
buzbeecbd6d442012-11-17 14:11:25 -0800544 pool->coreRegs = static_cast<RegisterInfo*>
545 (oatNew(cUnit, numRegs * sizeof(*cUnit->regPool->coreRegs), true, kAllocRegAlloc));
buzbeeefc63692012-11-14 16:31:52 -0800546 pool->numFPRegs = numFPRegs;
buzbeecbd6d442012-11-17 14:11:25 -0800547 pool->FPRegs = static_cast<RegisterInfo*>
548 (oatNew(cUnit, numFPRegs * sizeof(*cUnit->regPool->FPRegs), true, kAllocRegAlloc));
buzbeeefc63692012-11-14 16:31:52 -0800549 oatInitPool(pool->coreRegs, coreRegs, pool->numCoreRegs);
550 oatInitPool(pool->FPRegs, fpRegs, pool->numFPRegs);
551 // Keep special registers from being allocated
552 for (int i = 0; i < numReserved; i++) {
553 if (NO_SUSPEND && (reservedRegs[i] == rMIPS_SUSPEND)) {
554 //To measure cost of suspend check
555 continue;
556 }
557 oatMarkInUse(cUnit, reservedRegs[i]);
558 }
559 // Mark temp regs - all others not in use can be used for promotion
560 for (int i = 0; i < numTemps; i++) {
561 oatMarkTemp(cUnit, coreTemps[i]);
562 }
563 for (int i = 0; i < numFPTemps; i++) {
564 oatMarkTemp(cUnit, fpTemps[i]);
565 }
566 // Construct the alias map.
buzbeecbd6d442012-11-17 14:11:25 -0800567 cUnit->phiAliasMap = static_cast<int*>
568 (oatNew(cUnit, cUnit->numSSARegs * sizeof(cUnit->phiAliasMap[0]), false, kAllocDFInfo));
buzbeeefc63692012-11-14 16:31:52 -0800569 for (int i = 0; i < cUnit->numSSARegs; i++) {
570 cUnit->phiAliasMap[i] = i;
571 }
572 for (MIR* phi = cUnit->phiList; phi; phi = phi->meta.phiNext) {
573 int defReg = phi->ssaRep->defs[0];
574 for (int i = 0; i < phi->ssaRep->numUses; i++) {
575 for (int j = 0; j < cUnit->numSSARegs; j++) {
576 if (cUnit->phiAliasMap[j] == phi->ssaRep->uses[i]) {
577 cUnit->phiAliasMap[j] = defReg;
578 }
579 }
580 }
581 }
582}
583
584void freeRegLocTemps(CompilationUnit* cUnit, RegLocation rlKeep,
585 RegLocation rlFree)
586{
587 if ((rlFree.lowReg != rlKeep.lowReg) && (rlFree.lowReg != rlKeep.highReg) &&
588 (rlFree.highReg != rlKeep.lowReg) && (rlFree.highReg != rlKeep.highReg)) {
589 // No overlap, free both
590 oatFreeTemp(cUnit, rlFree.lowReg);
591 oatFreeTemp(cUnit, rlFree.highReg);
592 }
593}
594/*
595 * In the Arm code a it is typical to use the link register
596 * to hold the target address. However, for Mips we must
597 * ensure that all branch instructions can be restarted if
598 * there is a trap in the shadow. Allocate a temp register.
599 */
600int loadHelper(CompilationUnit* cUnit, int offset)
601{
602 loadWordDisp(cUnit, rMIPS_SELF, offset, r_T9);
603 return r_T9;
604}
605
606void spillCoreRegs(CompilationUnit* cUnit)
607{
608 if (cUnit->numCoreSpills == 0) {
609 return;
610 }
611 uint32_t mask = cUnit->coreSpillMask;
612 int offset = cUnit->numCoreSpills * 4;
613 opRegImm(cUnit, kOpSub, rMIPS_SP, offset);
614 for (int reg = 0; mask; mask >>= 1, reg++) {
615 if (mask & 0x1) {
616 offset -= 4;
617 storeWordDisp(cUnit, rMIPS_SP, offset, reg);
618 }
619 }
620}
621
622void unSpillCoreRegs(CompilationUnit* cUnit)
623{
624 if (cUnit->numCoreSpills == 0) {
625 return;
626 }
627 uint32_t mask = cUnit->coreSpillMask;
628 int offset = cUnit->frameSize;
629 for (int reg = 0; mask; mask >>= 1, reg++) {
630 if (mask & 0x1) {
631 offset -= 4;
632 loadWordDisp(cUnit, rMIPS_SP, offset, reg);
633 }
634 }
635 opRegImm(cUnit, kOpAdd, rMIPS_SP, cUnit->frameSize);
636}
637
buzbeecbd6d442012-11-17 14:11:25 -0800638bool branchUnconditional(LIR* lir)
buzbeeefc63692012-11-14 16:31:52 -0800639{
buzbeecbd6d442012-11-17 14:11:25 -0800640 return (lir->opcode == kMipsB);
buzbeeefc63692012-11-14 16:31:52 -0800641}
642
buzbeeefc63692012-11-14 16:31:52 -0800643/* Common initialization routine for an architecture family */
644bool oatArchInit()
645{
646 int i;
647
648 for (i = 0; i < kMipsLast; i++) {
649 if (EncodingMap[i].opcode != i) {
650 LOG(FATAL) << "Encoding order for " << EncodingMap[i].name <<
buzbeecbd6d442012-11-17 14:11:25 -0800651 " is wrong: expecting " << i << ", seeing " << static_cast<int>(EncodingMap[i].opcode);
buzbeeefc63692012-11-14 16:31:52 -0800652 }
653 }
654
655 return oatArchVariantInit();
656}
657
buzbee1bc37c62012-11-20 13:35:41 -0800658uint64_t getTargetInstFlags(int opcode)
659{
660 return EncodingMap[opcode].flags;
661}
662
663const char* getTargetInstName(int opcode)
664{
665 return EncodingMap[opcode].name;
666}
667
668const char* getTargetInstFmt(int opcode)
669{
670 return EncodingMap[opcode].fmt;
671}
672
buzbeeefc63692012-11-14 16:31:52 -0800673} // namespace art