blob: b9159ed80889318017d6a0335829848e5c93ee43 [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
buzbeefa57c472012-11-21 12:06:18 -080026static 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};
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};
buzbeefa57c472012-11-21 12:06:18 -080032static 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};
buzbeeefc63692012-11-14 16:31:52 -080034#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};
buzbeefa57c472012-11-21 12:06:18 -080037static int fp_temps[] = {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};
buzbeeefc63692012-11-14 16:31:52 -080039#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.
buzbeefa57c472012-11-21 12:06:18 -080091int S2d(int low_reg, int high_reg)
buzbeeefc63692012-11-14 16:31:52 -080092{
buzbeefa57c472012-11-21 12:06:18 -080093 return MIPS_S2D(low_reg, high_reg);
buzbeeefc63692012-11-14 16:31:52 -080094}
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 */
buzbeefa57c472012-11-21 12:06:18 -0800129uint64_t GetRegMaskCommon(CompilationUnit* cu, 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;
buzbeefa57c472012-11-21 12:06:18 -0800133 int reg_id;
buzbeeefc63692012-11-14 16:31:52 -0800134
135
buzbeefa57c472012-11-21 12:06:18 -0800136 reg_id = reg & 0x1f;
buzbeeefc63692012-11-14 16:31:52 -0800137 /* 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 */
buzbeefa57c472012-11-21 12:06:18 -0800142 shift += reg_id;
buzbeeefc63692012-11-14 16:31:52 -0800143 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
buzbeefa57c472012-11-21 12:06:18 -0800152void SetupTargetResourceMasks(CompilationUnit* cu, LIR* lir)
buzbeeefc63692012-11-14 16:31:52 -0800153{
buzbeefa57c472012-11-21 12:06:18 -0800154 DCHECK_EQ(cu->instruction_set, kMips);
buzbeeefc63692012-11-14 16:31:52 -0800155
156 // Mips-specific resource map setup here.
157 uint64_t flags = EncodingMap[lir->opcode].flags;
158
159 if (flags & REG_DEF_SP) {
buzbeefa57c472012-11-21 12:06:18 -0800160 lir->def_mask |= ENCODE_MIPS_REG_SP;
buzbeeefc63692012-11-14 16:31:52 -0800161 }
162
163 if (flags & REG_USE_SP) {
buzbeefa57c472012-11-21 12:06:18 -0800164 lir->use_mask |= ENCODE_MIPS_REG_SP;
buzbeeefc63692012-11-14 16:31:52 -0800165 }
166
167 if (flags & REG_DEF_LR) {
buzbeefa57c472012-11-21 12:06:18 -0800168 lir->def_mask |= ENCODE_MIPS_REG_LR;
buzbeeefc63692012-11-14 16:31:52 -0800169 }
170}
171
172/* For dumping instructions */
173#define MIPS_REG_COUNT 32
buzbeefa57c472012-11-21 12:06:18 -0800174static const char *mips_reg_name[MIPS_REG_COUNT] = {
buzbeeefc63692012-11-14 16:31:52 -0800175 "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 */
buzbeefa57c472012-11-21 12:06:18 -0800185std::string BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr)
buzbeeefc63692012-11-14 16:31:52 -0800186{
187 std::string buf;
188 int i;
buzbeefa57c472012-11-21 12:06:18 -0800189 const char *fmt_end = &fmt[strlen(fmt)];
buzbeeefc63692012-11-14 16:31:52 -0800190 char tbuf[256];
191 char nc;
buzbeefa57c472012-11-21 12:06:18 -0800192 while (fmt < fmt_end) {
buzbeeefc63692012-11-14 16:31:52 -0800193 int operand;
194 if (*fmt == '!') {
195 fmt++;
buzbeefa57c472012-11-21 12:06:18 -0800196 DCHECK_LT(fmt, fmt_end);
buzbeeefc63692012-11-14 16:31:52 -0800197 nc = *fmt++;
198 if (nc=='!') {
199 strcpy(tbuf, "!");
200 } else {
buzbeefa57c472012-11-21 12:06:18 -0800201 DCHECK_LT(fmt, fmt_end);
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':
buzbeefa57c472012-11-21 12:06:18 -0800236 sprintf(tbuf,"0x%08x (L%p)", reinterpret_cast<uintptr_t>(base_addr) + 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 =
buzbeefa57c472012-11-21 12:06:18 -0800246 (((reinterpret_cast<uintptr_t>(base_addr) + 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);
buzbeefa57c472012-11-21 12:06:18 -0800258 strcpy(tbuf, mips_reg_name[operand]);
buzbeeefc63692012-11-14 16:31:52 -0800259 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
buzbeefa57c472012-11-21 12:06:18 -0800278void DumpResourceMask(LIR *mips_lir, 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 */
buzbeefa57c472012-11-21 12:06:18 -0800303 if (mips_lir && (mask & ENCODE_DALVIK_REG)) {
304 sprintf(buf + strlen(buf), "dr%d%s", mips_lir->alias_info & 0xffff,
305 (mips_lir->alias_info & 0x80000000) ? "(+1)" : "");
buzbeeefc63692012-11-14 16:31:52 -0800306 }
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/*
buzbeefa57c472012-11-21 12:06:18 -0800324 * TUNING: is leaf? Can't just use "has_invoke" to determine as some
buzbeeefc63692012-11-14 16:31:52 -0800325 * instructions might call out to C/assembly helper functions. Until
326 * machinery is in place, always spill lr.
327 */
328
buzbeefa57c472012-11-21 12:06:18 -0800329void AdjustSpillMask(CompilationUnit* cu)
buzbeeefc63692012-11-14 16:31:52 -0800330{
buzbeefa57c472012-11-21 12:06:18 -0800331 cu->core_spill_mask |= (1 << r_RA);
332 cu->num_core_spills++;
buzbeeefc63692012-11-14 16:31:52 -0800333}
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 */
buzbeefa57c472012-11-21 12:06:18 -0800341void MarkPreservedSingle(CompilationUnit* cu, int s_reg, int reg)
buzbeeefc63692012-11-14 16:31:52 -0800342{
343 LOG(FATAL) << "No support yet for promoted FP regs";
344}
345
buzbeefa57c472012-11-21 12:06:18 -0800346void FlushRegWide(CompilationUnit* cu, int reg1, int reg2)
buzbeeefc63692012-11-14 16:31:52 -0800347{
buzbeefa57c472012-11-21 12:06:18 -0800348 RegisterInfo* info1 = GetRegInfo(cu, reg1);
349 RegisterInfo* info2 = GetRegInfo(cu, 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)) {
buzbeefa57c472012-11-21 12:06:18 -0800354 if (!(info1->is_temp && info2->is_temp)) {
355 /* Should not happen. If it does, there's a problem in eval_loc */
buzbeeefc63692012-11-14 16:31:52 -0800356 LOG(FATAL) << "Long half-temp, half-promoted";
357 }
358
359 info1->dirty = false;
360 info2->dirty = false;
buzbeefa57c472012-11-21 12:06:18 -0800361 if (SRegToVReg(cu, info2->s_reg) < SRegToVReg(cu, info1->s_reg))
buzbeeefc63692012-11-14 16:31:52 -0800362 info1 = info2;
buzbeefa57c472012-11-21 12:06:18 -0800363 int v_reg = SRegToVReg(cu, info1->s_reg);
364 StoreBaseDispWide(cu, rMIPS_SP, VRegOffset(cu, v_reg), info1->reg, info1->partner);
buzbeeefc63692012-11-14 16:31:52 -0800365 }
366}
367
buzbeefa57c472012-11-21 12:06:18 -0800368void FlushReg(CompilationUnit* cu, int reg)
buzbeeefc63692012-11-14 16:31:52 -0800369{
buzbeefa57c472012-11-21 12:06:18 -0800370 RegisterInfo* info = GetRegInfo(cu, reg);
buzbeeefc63692012-11-14 16:31:52 -0800371 if (info->live && info->dirty) {
372 info->dirty = false;
buzbeefa57c472012-11-21 12:06:18 -0800373 int v_reg = SRegToVReg(cu, info->s_reg);
374 StoreBaseDisp(cu, rMIPS_SP, VRegOffset(cu, v_reg), 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 */
buzbeefa57c472012-11-21 12:06:18 -0800384void ClobberCalleeSave(CompilationUnit *cu)
buzbeeefc63692012-11-14 16:31:52 -0800385{
buzbeefa57c472012-11-21 12:06:18 -0800386 Clobber(cu, r_ZERO);
387 Clobber(cu, r_AT);
388 Clobber(cu, r_V0);
389 Clobber(cu, r_V1);
390 Clobber(cu, r_A0);
391 Clobber(cu, r_A1);
392 Clobber(cu, r_A2);
393 Clobber(cu, r_A3);
394 Clobber(cu, r_T0);
395 Clobber(cu, r_T1);
396 Clobber(cu, r_T2);
397 Clobber(cu, r_T3);
398 Clobber(cu, r_T4);
399 Clobber(cu, r_T5);
400 Clobber(cu, r_T6);
401 Clobber(cu, r_T7);
402 Clobber(cu, r_T8);
403 Clobber(cu, r_T9);
404 Clobber(cu, r_K0);
405 Clobber(cu, r_K1);
406 Clobber(cu, r_GP);
407 Clobber(cu, r_FP);
408 Clobber(cu, r_RA);
409 Clobber(cu, r_F0);
410 Clobber(cu, r_F1);
411 Clobber(cu, r_F2);
412 Clobber(cu, r_F3);
413 Clobber(cu, r_F4);
414 Clobber(cu, r_F5);
415 Clobber(cu, r_F6);
416 Clobber(cu, r_F7);
417 Clobber(cu, r_F8);
418 Clobber(cu, r_F9);
419 Clobber(cu, r_F10);
420 Clobber(cu, r_F11);
421 Clobber(cu, r_F12);
422 Clobber(cu, r_F13);
423 Clobber(cu, r_F14);
424 Clobber(cu, r_F15);
buzbeeefc63692012-11-14 16:31:52 -0800425}
426
buzbeefa57c472012-11-21 12:06:18 -0800427RegLocation GetReturnWideAlt(CompilationUnit* cu)
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
buzbeefa57c472012-11-21 12:06:18 -0800434RegLocation GetReturnAlt(CompilationUnit* cu)
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
buzbeefa57c472012-11-21 12:06:18 -0800441RegisterInfo* GetRegInfo(CompilationUnit* cu, int reg)
buzbeeefc63692012-11-14 16:31:52 -0800442{
buzbeefa57c472012-11-21 12:06:18 -0800443 return MIPS_FPREG(reg) ? &cu->reg_pool->FPRegs[reg & MIPS_FP_REG_MASK]
444 : &cu->reg_pool->core_regs[reg];
buzbeeefc63692012-11-14 16:31:52 -0800445}
446
447/* To be used when explicitly managing register use */
buzbeefa57c472012-11-21 12:06:18 -0800448void LockCallTemps(CompilationUnit* cu)
buzbeeefc63692012-11-14 16:31:52 -0800449{
buzbeefa57c472012-11-21 12:06:18 -0800450 LockTemp(cu, rMIPS_ARG0);
451 LockTemp(cu, rMIPS_ARG1);
452 LockTemp(cu, rMIPS_ARG2);
453 LockTemp(cu, rMIPS_ARG3);
buzbeeefc63692012-11-14 16:31:52 -0800454}
455
456/* To be used when explicitly managing register use */
buzbeefa57c472012-11-21 12:06:18 -0800457void FreeCallTemps(CompilationUnit* cu)
buzbeeefc63692012-11-14 16:31:52 -0800458{
buzbeefa57c472012-11-21 12:06:18 -0800459 FreeTemp(cu, rMIPS_ARG0);
460 FreeTemp(cu, rMIPS_ARG1);
461 FreeTemp(cu, rMIPS_ARG2);
462 FreeTemp(cu, 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
buzbeefa57c472012-11-21 12:06:18 -0800471void GenMemBarrier(CompilationUnit *cu, MemBarrierKind barrier_kind)
buzbeeefc63692012-11-14 16:31:52 -0800472{
473#if ANDROID_SMP != 0
buzbeefa57c472012-11-21 12:06:18 -0800474 NewLIR1(cu, 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 */
buzbeefa57c472012-11-21 12:06:18 -0800482int AllocTypedTempPair(CompilationUnit *cu, bool fp_hint,
483 int reg_class)
buzbeeefc63692012-11-14 16:31:52 -0800484{
buzbeefa57c472012-11-21 12:06:18 -0800485 int high_reg;
486 int low_reg;
buzbeeefc63692012-11-14 16:31:52 -0800487 int res = 0;
488
489#ifdef __mips_hard_float
buzbeefa57c472012-11-21 12:06:18 -0800490 if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
491 low_reg = AllocTempDouble(cu);
492 high_reg = low_reg + 1;
493 res = (low_reg & 0xff) | ((high_reg & 0xff) << 8);
buzbeeefc63692012-11-14 16:31:52 -0800494 return res;
495 }
496#endif
497
buzbeefa57c472012-11-21 12:06:18 -0800498 low_reg = AllocTemp(cu);
499 high_reg = AllocTemp(cu);
500 res = (low_reg & 0xff) | ((high_reg & 0xff) << 8);
buzbeeefc63692012-11-14 16:31:52 -0800501 return res;
502}
503
buzbeefa57c472012-11-21 12:06:18 -0800504int AllocTypedTemp(CompilationUnit *cu, bool fp_hint, int reg_class)
buzbeeefc63692012-11-14 16:31:52 -0800505{
506#ifdef __mips_hard_float
buzbeefa57c472012-11-21 12:06:18 -0800507 if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg))
buzbeeefc63692012-11-14 16:31:52 -0800508{
buzbeefa57c472012-11-21 12:06:18 -0800509 return AllocTempFloat(cu);
buzbeeefc63692012-11-14 16:31:52 -0800510}
511#endif
buzbeefa57c472012-11-21 12:06:18 -0800512 return AllocTemp(cu);
buzbeeefc63692012-11-14 16:31:52 -0800513}
514
buzbeefa57c472012-11-21 12:06:18 -0800515void CompilerInitializeRegAlloc(CompilationUnit* cu)
buzbeeefc63692012-11-14 16:31:52 -0800516{
buzbeefa57c472012-11-21 12:06:18 -0800517 int num_regs = sizeof(core_regs)/sizeof(*core_regs);
518 int num_reserved = sizeof(ReservedRegs)/sizeof(*ReservedRegs);
519 int num_temps = sizeof(core_temps)/sizeof(*core_temps);
buzbeeefc63692012-11-14 16:31:52 -0800520#ifdef __mips_hard_float
buzbeefa57c472012-11-21 12:06:18 -0800521 int num_fp_regs = sizeof(FpRegs)/sizeof(*FpRegs);
522 int num_fp_temps = sizeof(fp_temps)/sizeof(*fp_temps);
buzbeeefc63692012-11-14 16:31:52 -0800523#else
buzbeefa57c472012-11-21 12:06:18 -0800524 int num_fp_regs = 0;
525 int num_fp_temps = 0;
buzbeeefc63692012-11-14 16:31:52 -0800526#endif
buzbeecbd6d442012-11-17 14:11:25 -0800527 RegisterPool *pool =
buzbeefa57c472012-11-21 12:06:18 -0800528 static_cast<RegisterPool*>(NewMem(cu, sizeof(*pool), true, kAllocRegAlloc));
529 cu->reg_pool = pool;
530 pool->num_core_regs = num_regs;
531 pool->core_regs = static_cast<RegisterInfo*>
532 (NewMem(cu, num_regs * sizeof(*cu->reg_pool->core_regs), true, kAllocRegAlloc));
533 pool->num_fp_regs = num_fp_regs;
buzbeecbd6d442012-11-17 14:11:25 -0800534 pool->FPRegs = static_cast<RegisterInfo*>
buzbeefa57c472012-11-21 12:06:18 -0800535 (NewMem(cu, num_fp_regs * sizeof(*cu->reg_pool->FPRegs), true, kAllocRegAlloc));
536 CompilerInitPool(pool->core_regs, core_regs, pool->num_core_regs);
537 CompilerInitPool(pool->FPRegs, FpRegs, pool->num_fp_regs);
buzbeeefc63692012-11-14 16:31:52 -0800538 // Keep special registers from being allocated
buzbeefa57c472012-11-21 12:06:18 -0800539 for (int i = 0; i < num_reserved; 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 }
buzbeefa57c472012-11-21 12:06:18 -0800544 MarkInUse(cu, ReservedRegs[i]);
buzbeeefc63692012-11-14 16:31:52 -0800545 }
546 // Mark temp regs - all others not in use can be used for promotion
buzbeefa57c472012-11-21 12:06:18 -0800547 for (int i = 0; i < num_temps; i++) {
548 MarkTemp(cu, core_temps[i]);
buzbeeefc63692012-11-14 16:31:52 -0800549 }
buzbeefa57c472012-11-21 12:06:18 -0800550 for (int i = 0; i < num_fp_temps; i++) {
551 MarkTemp(cu, fp_temps[i]);
buzbeeefc63692012-11-14 16:31:52 -0800552 }
553 // Construct the alias map.
buzbeefa57c472012-11-21 12:06:18 -0800554 cu->phi_alias_map = static_cast<int*>
555 (NewMem(cu, cu->num_ssa_regs * sizeof(cu->phi_alias_map[0]), false, kAllocDFInfo));
556 for (int i = 0; i < cu->num_ssa_regs; i++) {
557 cu->phi_alias_map[i] = i;
buzbeeefc63692012-11-14 16:31:52 -0800558 }
buzbeefa57c472012-11-21 12:06:18 -0800559 for (MIR* phi = cu->phi_list; phi; phi = phi->meta.phi_next) {
560 int def_reg = phi->ssa_rep->defs[0];
561 for (int i = 0; i < phi->ssa_rep->num_uses; i++) {
562 for (int j = 0; j < cu->num_ssa_regs; j++) {
563 if (cu->phi_alias_map[j] == phi->ssa_rep->uses[i]) {
564 cu->phi_alias_map[j] = def_reg;
buzbeeefc63692012-11-14 16:31:52 -0800565 }
566 }
567 }
568 }
569}
570
buzbeefa57c472012-11-21 12:06:18 -0800571void FreeRegLocTemps(CompilationUnit* cu, RegLocation rl_keep,
572 RegLocation rl_free)
buzbeeefc63692012-11-14 16:31:52 -0800573{
buzbeefa57c472012-11-21 12:06:18 -0800574 if ((rl_free.low_reg != rl_keep.low_reg) && (rl_free.low_reg != rl_keep.high_reg) &&
575 (rl_free.high_reg != rl_keep.low_reg) && (rl_free.high_reg != rl_keep.high_reg)) {
buzbeeefc63692012-11-14 16:31:52 -0800576 // No overlap, free both
buzbeefa57c472012-11-21 12:06:18 -0800577 FreeTemp(cu, rl_free.low_reg);
578 FreeTemp(cu, rl_free.high_reg);
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 */
buzbeefa57c472012-11-21 12:06:18 -0800587int LoadHelper(CompilationUnit* cu, int offset)
buzbeeefc63692012-11-14 16:31:52 -0800588{
buzbeefa57c472012-11-21 12:06:18 -0800589 LoadWordDisp(cu, rMIPS_SELF, offset, r_T9);
buzbeeefc63692012-11-14 16:31:52 -0800590 return r_T9;
591}
592
buzbeefa57c472012-11-21 12:06:18 -0800593void SpillCoreRegs(CompilationUnit* cu)
buzbeeefc63692012-11-14 16:31:52 -0800594{
buzbeefa57c472012-11-21 12:06:18 -0800595 if (cu->num_core_spills == 0) {
buzbeeefc63692012-11-14 16:31:52 -0800596 return;
597 }
buzbeefa57c472012-11-21 12:06:18 -0800598 uint32_t mask = cu->core_spill_mask;
599 int offset = cu->num_core_spills * 4;
600 OpRegImm(cu, 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;
buzbeefa57c472012-11-21 12:06:18 -0800604 StoreWordDisp(cu, rMIPS_SP, offset, reg);
buzbeeefc63692012-11-14 16:31:52 -0800605 }
606 }
607}
608
buzbeefa57c472012-11-21 12:06:18 -0800609void UnSpillCoreRegs(CompilationUnit* cu)
buzbeeefc63692012-11-14 16:31:52 -0800610{
buzbeefa57c472012-11-21 12:06:18 -0800611 if (cu->num_core_spills == 0) {
buzbeeefc63692012-11-14 16:31:52 -0800612 return;
613 }
buzbeefa57c472012-11-21 12:06:18 -0800614 uint32_t mask = cu->core_spill_mask;
615 int offset = cu->frame_size;
buzbeeefc63692012-11-14 16:31:52 -0800616 for (int reg = 0; mask; mask >>= 1, reg++) {
617 if (mask & 0x1) {
618 offset -= 4;
buzbeefa57c472012-11-21 12:06:18 -0800619 LoadWordDisp(cu, rMIPS_SP, offset, reg);
buzbeeefc63692012-11-14 16:31:52 -0800620 }
621 }
buzbeefa57c472012-11-21 12:06:18 -0800622 OpRegImm(cu, kOpAdd, rMIPS_SP, cu->frame_size);
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