blob: 36238003714f1a5c9b798c5ca43d28ceaa959be0 [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};
buzbee52a77fc2012-11-20 19:50:46 -080030static int ReservedRegs[] = {r_ZERO, r_AT, r_S0, r_S1, r_K0, r_K1, r_GP, r_SP,
buzbeeefc63692012-11-14 16:31:52 -080031 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
buzbee52a77fc2012-11-20 19:50:46 -080035static int FpRegs[] = {r_F0, r_F1, r_F2, r_F3, r_F4, r_F5, r_F6, r_F7,
buzbeeefc63692012-11-14 16:31:52 -080036 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
buzbee52a77fc2012-11-20 19:50:46 -080041RegLocation LocCReturn()
buzbeeefc63692012-11-14 16:31:52 -080042{
43 RegLocation res = MIPS_LOC_C_RETURN;
44 return res;
45}
46
buzbee52a77fc2012-11-20 19:50:46 -080047RegLocation LocCReturnWide()
buzbeeefc63692012-11-14 16:31:52 -080048{
49 RegLocation res = MIPS_LOC_C_RETURN_WIDE;
50 return res;
51}
52
buzbee52a77fc2012-11-20 19:50:46 -080053RegLocation LocCReturnFloat()
buzbeeefc63692012-11-14 16:31:52 -080054{
55 RegLocation res = MIPS_LOC_C_RETURN_FLOAT;
56 return res;
57}
58
buzbee52a77fc2012-11-20 19:50:46 -080059RegLocation LocCReturnDouble()
buzbeeefc63692012-11-14 16:31:52 -080060{
61 RegLocation res = MIPS_LOC_C_RETURN_DOUBLE;
62 return res;
63}
64
65// Return a target-dependent special register.
buzbee52a77fc2012-11-20 19:50:46 -080066int TargetReg(SpecialTargetRegister reg) {
buzbeeefc63692012-11-14 16:31:52 -080067 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.
buzbee52a77fc2012-11-20 19:50:46 -080091int S2d(int lowReg, int highReg)
buzbeeefc63692012-11-14 16:31:52 -080092{
93 return MIPS_S2D(lowReg, highReg);
94}
95
96// Is reg a single or double?
buzbee52a77fc2012-11-20 19:50:46 -080097bool FpReg(int reg)
buzbeeefc63692012-11-14 16:31:52 -080098{
99 return MIPS_FPREG(reg);
100}
101
102// Is reg a single?
buzbee52a77fc2012-11-20 19:50:46 -0800103bool SingleReg(int reg)
buzbeeefc63692012-11-14 16:31:52 -0800104{
105 return MIPS_SINGLEREG(reg);
106}
107
108// Is reg a double?
buzbee52a77fc2012-11-20 19:50:46 -0800109bool DoubleReg(int reg)
buzbeeefc63692012-11-14 16:31:52 -0800110{
111 return MIPS_DOUBLEREG(reg);
112}
113
114// Return mask to strip off fp reg flags and bias.
buzbee52a77fc2012-11-20 19:50:46 -0800115uint32_t FpRegMask()
buzbeeefc63692012-11-14 16:31:52 -0800116{
117 return MIPS_FP_REG_MASK;
118}
119
120// True if both regs single, both core or both double.
buzbee52a77fc2012-11-20 19:50:46 -0800121bool SameRegType(int reg1, int reg2)
buzbeeefc63692012-11-14 16:31:52 -0800122{
123 return (MIPS_REGTYPE(reg1) == MIPS_REGTYPE(reg2));
124}
125
126/*
127 * Decode the register id.
128 */
buzbee52a77fc2012-11-20 19:50:46 -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
buzbee52a77fc2012-11-20 19:50:46 -0800146uint64_t GetPCUseDefEncoding()
buzbeeefc63692012-11-14 16:31:52 -0800147{
148 return ENCODE_MIPS_REG_PC;
149}
150
151
buzbee52a77fc2012-11-20 19:50:46 -0800152void SetupTargetResourceMasks(CompilationUnit* cUnit, LIR* lir)
buzbeeefc63692012-11-14 16:31:52 -0800153{
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 */
buzbee52a77fc2012-11-20 19:50:46 -0800185std::string BuildInsnString(const char *fmt, LIR *lir, unsigned char* baseAddr)
buzbeeefc63692012-11-14 16:31:52 -0800186{
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
buzbee52a77fc2012-11-20 19:50:46 -0800278void DumpResourceMask(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
buzbee52a77fc2012-11-20 19:50:46 -0800329void AdjustSpillMask(CompilationUnit* cUnit)
buzbeeefc63692012-11-14 16:31:52 -0800330{
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 */
buzbee52a77fc2012-11-20 19:50:46 -0800341void MarkPreservedSingle(CompilationUnit* cUnit, int sReg, int reg)
buzbeeefc63692012-11-14 16:31:52 -0800342{
343 LOG(FATAL) << "No support yet for promoted FP regs";
344}
345
buzbee52a77fc2012-11-20 19:50:46 -0800346void FlushRegWide(CompilationUnit* cUnit, int reg1, int reg2)
buzbeeefc63692012-11-14 16:31:52 -0800347{
buzbee52a77fc2012-11-20 19:50:46 -0800348 RegisterInfo* info1 = GetRegInfo(cUnit, reg1);
349 RegisterInfo* info2 = GetRegInfo(cUnit, reg2);
buzbeeefc63692012-11-14 16:31:52 -0800350 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);
buzbee52a77fc2012-11-20 19:50:46 -0800364 StoreBaseDispWide(cUnit, rMIPS_SP, VRegOffset(cUnit, vReg), info1->reg, info1->partner);
buzbeeefc63692012-11-14 16:31:52 -0800365 }
366}
367
buzbee52a77fc2012-11-20 19:50:46 -0800368void FlushReg(CompilationUnit* cUnit, int reg)
buzbeeefc63692012-11-14 16:31:52 -0800369{
buzbee52a77fc2012-11-20 19:50:46 -0800370 RegisterInfo* info = GetRegInfo(cUnit, reg);
buzbeeefc63692012-11-14 16:31:52 -0800371 if (info->live && info->dirty) {
372 info->dirty = false;
373 int vReg = SRegToVReg(cUnit, info->sReg);
buzbee52a77fc2012-11-20 19:50:46 -0800374 StoreBaseDisp(cUnit, rMIPS_SP, VRegOffset(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 */
buzbee52a77fc2012-11-20 19:50:46 -0800379bool IsFpReg(int reg) {
buzbeeefc63692012-11-14 16:31:52 -0800380 return MIPS_FPREG(reg);
381}
382
buzbeeefc63692012-11-14 16:31:52 -0800383/* Clobber all regs that might be used by an external C call */
buzbee52a77fc2012-11-20 19:50:46 -0800384extern void ClobberCalleeSave(CompilationUnit *cUnit)
buzbeeefc63692012-11-14 16:31:52 -0800385{
buzbee52a77fc2012-11-20 19:50:46 -0800386 Clobber(cUnit, r_ZERO);
387 Clobber(cUnit, r_AT);
388 Clobber(cUnit, r_V0);
389 Clobber(cUnit, r_V1);
390 Clobber(cUnit, r_A0);
391 Clobber(cUnit, r_A1);
392 Clobber(cUnit, r_A2);
393 Clobber(cUnit, r_A3);
394 Clobber(cUnit, r_T0);
395 Clobber(cUnit, r_T1);
396 Clobber(cUnit, r_T2);
397 Clobber(cUnit, r_T3);
398 Clobber(cUnit, r_T4);
399 Clobber(cUnit, r_T5);
400 Clobber(cUnit, r_T6);
401 Clobber(cUnit, r_T7);
402 Clobber(cUnit, r_T8);
403 Clobber(cUnit, r_T9);
404 Clobber(cUnit, r_K0);
405 Clobber(cUnit, r_K1);
406 Clobber(cUnit, r_GP);
407 Clobber(cUnit, r_FP);
408 Clobber(cUnit, r_RA);
409 Clobber(cUnit, r_F0);
410 Clobber(cUnit, r_F1);
411 Clobber(cUnit, r_F2);
412 Clobber(cUnit, r_F3);
413 Clobber(cUnit, r_F4);
414 Clobber(cUnit, r_F5);
415 Clobber(cUnit, r_F6);
416 Clobber(cUnit, r_F7);
417 Clobber(cUnit, r_F8);
418 Clobber(cUnit, r_F9);
419 Clobber(cUnit, r_F10);
420 Clobber(cUnit, r_F11);
421 Clobber(cUnit, r_F12);
422 Clobber(cUnit, r_F13);
423 Clobber(cUnit, r_F14);
424 Clobber(cUnit, r_F15);
buzbeeefc63692012-11-14 16:31:52 -0800425}
426
buzbee52a77fc2012-11-20 19:50:46 -0800427extern RegLocation GetReturnWideAlt(CompilationUnit* cUnit)
buzbeeefc63692012-11-14 16:31:52 -0800428{
buzbee52a77fc2012-11-20 19:50:46 -0800429 UNIMPLEMENTED(FATAL) << "No GetReturnWideAlt for MIPS";
430 RegLocation res = LocCReturnWide();
buzbeeefc63692012-11-14 16:31:52 -0800431 return res;
432}
433
buzbee52a77fc2012-11-20 19:50:46 -0800434extern RegLocation GetReturnAlt(CompilationUnit* cUnit)
buzbeeefc63692012-11-14 16:31:52 -0800435{
buzbee52a77fc2012-11-20 19:50:46 -0800436 UNIMPLEMENTED(FATAL) << "No GetReturnAlt for MIPS";
437 RegLocation res = LocCReturn();
buzbeeefc63692012-11-14 16:31:52 -0800438 return res;
439}
440
buzbee52a77fc2012-11-20 19:50:46 -0800441extern RegisterInfo* GetRegInfo(CompilationUnit* cUnit, int reg)
buzbeeefc63692012-11-14 16:31:52 -0800442{
443 return MIPS_FPREG(reg) ? &cUnit->regPool->FPRegs[reg & MIPS_FP_REG_MASK]
444 : &cUnit->regPool->coreRegs[reg];
445}
446
447/* To be used when explicitly managing register use */
buzbee52a77fc2012-11-20 19:50:46 -0800448extern void LockCallTemps(CompilationUnit* cUnit)
buzbeeefc63692012-11-14 16:31:52 -0800449{
buzbee52a77fc2012-11-20 19:50:46 -0800450 LockTemp(cUnit, rMIPS_ARG0);
451 LockTemp(cUnit, rMIPS_ARG1);
452 LockTemp(cUnit, rMIPS_ARG2);
453 LockTemp(cUnit, rMIPS_ARG3);
buzbeeefc63692012-11-14 16:31:52 -0800454}
455
456/* To be used when explicitly managing register use */
buzbee52a77fc2012-11-20 19:50:46 -0800457extern void FreeCallTemps(CompilationUnit* cUnit)
buzbeeefc63692012-11-14 16:31:52 -0800458{
buzbee52a77fc2012-11-20 19:50:46 -0800459 FreeTemp(cUnit, rMIPS_ARG0);
460 FreeTemp(cUnit, rMIPS_ARG1);
461 FreeTemp(cUnit, rMIPS_ARG2);
462 FreeTemp(cUnit, rMIPS_ARG3);
buzbeeefc63692012-11-14 16:31:52 -0800463}
464
465/* Architecture-specific initializations and checks go here */
buzbee52a77fc2012-11-20 19:50:46 -0800466bool ArchVariantInit(void)
buzbeeefc63692012-11-14 16:31:52 -0800467{
468 return true;
469}
470
buzbee52a77fc2012-11-20 19:50:46 -0800471void GenMemBarrier(CompilationUnit *cUnit, MemBarrierKind barrierKind)
buzbeeefc63692012-11-14 16:31:52 -0800472{
473#if ANDROID_SMP != 0
buzbee52a77fc2012-11-20 19:50:46 -0800474 NewLIR1(cUnit, kMipsSync, 0 /* Only stype currently supported */);
buzbeeefc63692012-11-14 16:31:52 -0800475#endif
476}
477
478/*
479 * Alloc a pair of core registers, or a double. Low reg in low byte,
480 * high reg in next byte.
481 */
buzbee52a77fc2012-11-20 19:50:46 -0800482int AllocTypedTempPair(CompilationUnit *cUnit, bool fpHint,
buzbeeefc63692012-11-14 16:31:52 -0800483 int regClass)
484{
485 int highReg;
486 int lowReg;
487 int res = 0;
488
489#ifdef __mips_hard_float
490 if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg)) {
buzbee52a77fc2012-11-20 19:50:46 -0800491 lowReg = AllocTempDouble(cUnit);
buzbeeefc63692012-11-14 16:31:52 -0800492 highReg = lowReg + 1;
493 res = (lowReg & 0xff) | ((highReg & 0xff) << 8);
494 return res;
495 }
496#endif
497
buzbee52a77fc2012-11-20 19:50:46 -0800498 lowReg = AllocTemp(cUnit);
499 highReg = AllocTemp(cUnit);
buzbeeefc63692012-11-14 16:31:52 -0800500 res = (lowReg & 0xff) | ((highReg & 0xff) << 8);
501 return res;
502}
503
buzbee52a77fc2012-11-20 19:50:46 -0800504int AllocTypedTemp(CompilationUnit *cUnit, bool fpHint, int regClass)
buzbeeefc63692012-11-14 16:31:52 -0800505{
506#ifdef __mips_hard_float
507 if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg))
508{
buzbee52a77fc2012-11-20 19:50:46 -0800509 return AllocTempFloat(cUnit);
buzbeeefc63692012-11-14 16:31:52 -0800510}
511#endif
buzbee52a77fc2012-11-20 19:50:46 -0800512 return AllocTemp(cUnit);
buzbeeefc63692012-11-14 16:31:52 -0800513}
514
buzbee52a77fc2012-11-20 19:50:46 -0800515void CompilerInitializeRegAlloc(CompilationUnit* cUnit)
buzbeeefc63692012-11-14 16:31:52 -0800516{
517 int numRegs = sizeof(coreRegs)/sizeof(*coreRegs);
buzbee52a77fc2012-11-20 19:50:46 -0800518 int numReserved = sizeof(ReservedRegs)/sizeof(*ReservedRegs);
buzbeeefc63692012-11-14 16:31:52 -0800519 int numTemps = sizeof(coreTemps)/sizeof(*coreTemps);
520#ifdef __mips_hard_float
buzbee52a77fc2012-11-20 19:50:46 -0800521 int numFPRegs = sizeof(FpRegs)/sizeof(*FpRegs);
buzbeeefc63692012-11-14 16:31:52 -0800522 int numFPTemps = sizeof(fpTemps)/sizeof(*fpTemps);
523#else
524 int numFPRegs = 0;
525 int numFPTemps = 0;
526#endif
buzbeecbd6d442012-11-17 14:11:25 -0800527 RegisterPool *pool =
buzbee52a77fc2012-11-20 19:50:46 -0800528 static_cast<RegisterPool*>(NewMem(cUnit, sizeof(*pool), true, kAllocRegAlloc));
buzbeeefc63692012-11-14 16:31:52 -0800529 cUnit->regPool = pool;
530 pool->numCoreRegs = numRegs;
buzbeecbd6d442012-11-17 14:11:25 -0800531 pool->coreRegs = static_cast<RegisterInfo*>
buzbee52a77fc2012-11-20 19:50:46 -0800532 (NewMem(cUnit, numRegs * sizeof(*cUnit->regPool->coreRegs), true, kAllocRegAlloc));
buzbeeefc63692012-11-14 16:31:52 -0800533 pool->numFPRegs = numFPRegs;
buzbeecbd6d442012-11-17 14:11:25 -0800534 pool->FPRegs = static_cast<RegisterInfo*>
buzbee52a77fc2012-11-20 19:50:46 -0800535 (NewMem(cUnit, numFPRegs * sizeof(*cUnit->regPool->FPRegs), true, kAllocRegAlloc));
536 CompilerInitPool(pool->coreRegs, coreRegs, pool->numCoreRegs);
537 CompilerInitPool(pool->FPRegs, FpRegs, pool->numFPRegs);
buzbeeefc63692012-11-14 16:31:52 -0800538 // Keep special registers from being allocated
539 for (int i = 0; i < numReserved; i++) {
buzbee52a77fc2012-11-20 19:50:46 -0800540 if (NO_SUSPEND && (ReservedRegs[i] == rMIPS_SUSPEND)) {
buzbeeefc63692012-11-14 16:31:52 -0800541 //To measure cost of suspend check
542 continue;
543 }
buzbee52a77fc2012-11-20 19:50:46 -0800544 MarkInUse(cUnit, ReservedRegs[i]);
buzbeeefc63692012-11-14 16:31:52 -0800545 }
546 // Mark temp regs - all others not in use can be used for promotion
547 for (int i = 0; i < numTemps; i++) {
buzbee52a77fc2012-11-20 19:50:46 -0800548 MarkTemp(cUnit, coreTemps[i]);
buzbeeefc63692012-11-14 16:31:52 -0800549 }
550 for (int i = 0; i < numFPTemps; i++) {
buzbee52a77fc2012-11-20 19:50:46 -0800551 MarkTemp(cUnit, fpTemps[i]);
buzbeeefc63692012-11-14 16:31:52 -0800552 }
553 // Construct the alias map.
buzbeecbd6d442012-11-17 14:11:25 -0800554 cUnit->phiAliasMap = static_cast<int*>
buzbee52a77fc2012-11-20 19:50:46 -0800555 (NewMem(cUnit, cUnit->numSSARegs * sizeof(cUnit->phiAliasMap[0]), false, kAllocDFInfo));
buzbeeefc63692012-11-14 16:31:52 -0800556 for (int i = 0; i < cUnit->numSSARegs; i++) {
557 cUnit->phiAliasMap[i] = i;
558 }
559 for (MIR* phi = cUnit->phiList; phi; phi = phi->meta.phiNext) {
560 int defReg = phi->ssaRep->defs[0];
561 for (int i = 0; i < phi->ssaRep->numUses; i++) {
562 for (int j = 0; j < cUnit->numSSARegs; j++) {
563 if (cUnit->phiAliasMap[j] == phi->ssaRep->uses[i]) {
564 cUnit->phiAliasMap[j] = defReg;
565 }
566 }
567 }
568 }
569}
570
buzbee52a77fc2012-11-20 19:50:46 -0800571void FreeRegLocTemps(CompilationUnit* cUnit, RegLocation rlKeep,
buzbeeefc63692012-11-14 16:31:52 -0800572 RegLocation rlFree)
573{
574 if ((rlFree.lowReg != rlKeep.lowReg) && (rlFree.lowReg != rlKeep.highReg) &&
575 (rlFree.highReg != rlKeep.lowReg) && (rlFree.highReg != rlKeep.highReg)) {
576 // No overlap, free both
buzbee52a77fc2012-11-20 19:50:46 -0800577 FreeTemp(cUnit, rlFree.lowReg);
578 FreeTemp(cUnit, rlFree.highReg);
buzbeeefc63692012-11-14 16:31:52 -0800579 }
580}
581/*
582 * In the Arm code a it is typical to use the link register
583 * to hold the target address. However, for Mips we must
584 * ensure that all branch instructions can be restarted if
585 * there is a trap in the shadow. Allocate a temp register.
586 */
buzbee52a77fc2012-11-20 19:50:46 -0800587int LoadHelper(CompilationUnit* cUnit, int offset)
buzbeeefc63692012-11-14 16:31:52 -0800588{
buzbee52a77fc2012-11-20 19:50:46 -0800589 LoadWordDisp(cUnit, rMIPS_SELF, offset, r_T9);
buzbeeefc63692012-11-14 16:31:52 -0800590 return r_T9;
591}
592
buzbee52a77fc2012-11-20 19:50:46 -0800593void SpillCoreRegs(CompilationUnit* cUnit)
buzbeeefc63692012-11-14 16:31:52 -0800594{
595 if (cUnit->numCoreSpills == 0) {
596 return;
597 }
598 uint32_t mask = cUnit->coreSpillMask;
599 int offset = cUnit->numCoreSpills * 4;
buzbee52a77fc2012-11-20 19:50:46 -0800600 OpRegImm(cUnit, kOpSub, rMIPS_SP, offset);
buzbeeefc63692012-11-14 16:31:52 -0800601 for (int reg = 0; mask; mask >>= 1, reg++) {
602 if (mask & 0x1) {
603 offset -= 4;
buzbee52a77fc2012-11-20 19:50:46 -0800604 StoreWordDisp(cUnit, rMIPS_SP, offset, reg);
buzbeeefc63692012-11-14 16:31:52 -0800605 }
606 }
607}
608
buzbee52a77fc2012-11-20 19:50:46 -0800609void UnSpillCoreRegs(CompilationUnit* cUnit)
buzbeeefc63692012-11-14 16:31:52 -0800610{
611 if (cUnit->numCoreSpills == 0) {
612 return;
613 }
614 uint32_t mask = cUnit->coreSpillMask;
615 int offset = cUnit->frameSize;
616 for (int reg = 0; mask; mask >>= 1, reg++) {
617 if (mask & 0x1) {
618 offset -= 4;
buzbee52a77fc2012-11-20 19:50:46 -0800619 LoadWordDisp(cUnit, rMIPS_SP, offset, reg);
buzbeeefc63692012-11-14 16:31:52 -0800620 }
621 }
buzbee52a77fc2012-11-20 19:50:46 -0800622 OpRegImm(cUnit, kOpAdd, rMIPS_SP, cUnit->frameSize);
buzbeeefc63692012-11-14 16:31:52 -0800623}
624
buzbee52a77fc2012-11-20 19:50:46 -0800625bool BranchUnconditional(LIR* lir)
buzbeeefc63692012-11-14 16:31:52 -0800626{
buzbeecbd6d442012-11-17 14:11:25 -0800627 return (lir->opcode == kMipsB);
buzbeeefc63692012-11-14 16:31:52 -0800628}
629
buzbeeefc63692012-11-14 16:31:52 -0800630/* Common initialization routine for an architecture family */
buzbee52a77fc2012-11-20 19:50:46 -0800631bool ArchInit()
buzbeeefc63692012-11-14 16:31:52 -0800632{
633 int i;
634
635 for (i = 0; i < kMipsLast; i++) {
636 if (EncodingMap[i].opcode != i) {
637 LOG(FATAL) << "Encoding order for " << EncodingMap[i].name <<
buzbeecbd6d442012-11-17 14:11:25 -0800638 " is wrong: expecting " << i << ", seeing " << static_cast<int>(EncodingMap[i].opcode);
buzbeeefc63692012-11-14 16:31:52 -0800639 }
640 }
641
buzbee52a77fc2012-11-20 19:50:46 -0800642 return ArchVariantInit();
buzbeeefc63692012-11-14 16:31:52 -0800643}
644
buzbee52a77fc2012-11-20 19:50:46 -0800645uint64_t GetTargetInstFlags(int opcode)
buzbee1bc37c62012-11-20 13:35:41 -0800646{
647 return EncodingMap[opcode].flags;
648}
649
buzbee52a77fc2012-11-20 19:50:46 -0800650const char* GetTargetInstName(int opcode)
buzbee1bc37c62012-11-20 13:35:41 -0800651{
652 return EncodingMap[opcode].name;
653}
654
buzbee52a77fc2012-11-20 19:50:46 -0800655const char* GetTargetInstFmt(int opcode)
buzbee1bc37c62012-11-20 13:35:41 -0800656{
657 return EncodingMap[opcode].fmt;
658}
659
buzbeeefc63692012-11-14 16:31:52 -0800660} // namespace art