blob: 55cf4344f1355271b8377dfd9dc6b7e25d2915bd [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"
Ian Rogers107c31e2014-01-23 20:55:29 -080018
19#include <inttypes.h>
20
21#include <string>
22
Brian Carlstrom7940e442013-07-12 13:46:57 -070023#include "dex/compiler_internals.h"
24#include "dex/quick/mir_to_lir-inl.h"
25#include "mips_lir.h"
26
Brian Carlstrom7940e442013-07-12 13:46:57 -070027namespace art {
28
buzbee091cc402014-03-31 10:14:40 -070029static const RegStorage core_regs_arr[] =
30 {rs_rZERO, rs_rAT, rs_rV0, rs_rV1, rs_rA0, rs_rA1, rs_rA2, rs_rA3, rs_rT0, rs_rT1, rs_rT2,
31 rs_rT3, rs_rT4, rs_rT5, rs_rT6, rs_rT7, rs_rS0, rs_rS1, rs_rS2, rs_rS3, rs_rS4, rs_rS5,
32 rs_rS6, rs_rS7, rs_rT8, rs_rT9, rs_rK0, rs_rK1, rs_rGP, rs_rSP, rs_rFP, rs_rRA};
33static RegStorage sp_regs_arr[] =
34 {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
35 rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15};
36static RegStorage dp_regs_arr[] =
37 {rs_rD0, rs_rD1, rs_rD2, rs_rD3, rs_rD4, rs_rD5, rs_rD6, rs_rD7};
38static const RegStorage reserved_regs_arr[] =
39 {rs_rZERO, rs_rAT, rs_rS0, rs_rS1, rs_rK0, rs_rK1, rs_rGP, rs_rSP, rs_rRA};
40static RegStorage core_temps_arr[] =
41 {rs_rV0, rs_rV1, rs_rA0, rs_rA1, rs_rA2, rs_rA3, rs_rT0, rs_rT1, rs_rT2, rs_rT3, rs_rT4,
42 rs_rT5, rs_rT6, rs_rT7, rs_rT8};
43static RegStorage sp_temps_arr[] =
44 {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
45 rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15};
46static RegStorage dp_temps_arr[] =
47 {rs_rD0, rs_rD1, rs_rD2, rs_rD3, rs_rD4, rs_rD5, rs_rD6, rs_rD7};
48
buzbeeb01bf152014-05-13 15:59:07 -070049static const std::vector<RegStorage> empty_pool;
buzbee091cc402014-03-31 10:14:40 -070050static const std::vector<RegStorage> core_regs(core_regs_arr,
51 core_regs_arr + sizeof(core_regs_arr) / sizeof(core_regs_arr[0]));
52static const std::vector<RegStorage> sp_regs(sp_regs_arr,
53 sp_regs_arr + sizeof(sp_regs_arr) / sizeof(sp_regs_arr[0]));
54static const std::vector<RegStorage> dp_regs(dp_regs_arr,
55 dp_regs_arr + sizeof(dp_regs_arr) / sizeof(dp_regs_arr[0]));
56static const std::vector<RegStorage> reserved_regs(reserved_regs_arr,
57 reserved_regs_arr + sizeof(reserved_regs_arr) / sizeof(reserved_regs_arr[0]));
58static const std::vector<RegStorage> core_temps(core_temps_arr,
59 core_temps_arr + sizeof(core_temps_arr) / sizeof(core_temps_arr[0]));
60static const std::vector<RegStorage> sp_temps(sp_temps_arr,
61 sp_temps_arr + sizeof(sp_temps_arr) / sizeof(sp_temps_arr[0]));
62static const std::vector<RegStorage> dp_temps(dp_temps_arr,
63 dp_temps_arr + sizeof(dp_temps_arr) / sizeof(dp_temps_arr[0]));
Brian Carlstrom7940e442013-07-12 13:46:57 -070064
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070065RegLocation MipsMir2Lir::LocCReturn() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000066 return mips_loc_c_return;
Brian Carlstrom7940e442013-07-12 13:46:57 -070067}
68
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070069RegLocation MipsMir2Lir::LocCReturnWide() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000070 return mips_loc_c_return_wide;
Brian Carlstrom7940e442013-07-12 13:46:57 -070071}
72
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070073RegLocation MipsMir2Lir::LocCReturnFloat() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000074 return mips_loc_c_return_float;
Brian Carlstrom7940e442013-07-12 13:46:57 -070075}
76
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070077RegLocation MipsMir2Lir::LocCReturnDouble() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000078 return mips_loc_c_return_double;
Brian Carlstrom7940e442013-07-12 13:46:57 -070079}
80
81// Return a target-dependent special register.
buzbee2700f7e2014-03-07 09:46:20 -080082RegStorage MipsMir2Lir::TargetReg(SpecialTargetRegister reg) {
buzbee091cc402014-03-31 10:14:40 -070083 RegStorage res_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -070084 switch (reg) {
buzbee091cc402014-03-31 10:14:40 -070085 case kSelf: res_reg = rs_rMIPS_SELF; break;
86 case kSuspend: res_reg = rs_rMIPS_SUSPEND; break;
87 case kLr: res_reg = rs_rMIPS_LR; break;
88 case kPc: res_reg = rs_rMIPS_PC; break;
89 case kSp: res_reg = rs_rMIPS_SP; break;
90 case kArg0: res_reg = rs_rMIPS_ARG0; break;
91 case kArg1: res_reg = rs_rMIPS_ARG1; break;
92 case kArg2: res_reg = rs_rMIPS_ARG2; break;
93 case kArg3: res_reg = rs_rMIPS_ARG3; break;
94 case kFArg0: res_reg = rs_rMIPS_FARG0; break;
95 case kFArg1: res_reg = rs_rMIPS_FARG1; break;
96 case kFArg2: res_reg = rs_rMIPS_FARG2; break;
97 case kFArg3: res_reg = rs_rMIPS_FARG3; break;
98 case kRet0: res_reg = rs_rMIPS_RET0; break;
99 case kRet1: res_reg = rs_rMIPS_RET1; break;
100 case kInvokeTgt: res_reg = rs_rMIPS_INVOKE_TGT; break;
101 case kHiddenArg: res_reg = rs_rT0; break;
102 case kHiddenFpArg: res_reg = RegStorage::InvalidReg(); break;
103 case kCount: res_reg = rs_rMIPS_COUNT; break;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700104 }
buzbee091cc402014-03-31 10:14:40 -0700105 return res_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700106}
107
buzbee2700f7e2014-03-07 09:46:20 -0800108RegStorage MipsMir2Lir::GetArgMappingToPhysicalReg(int arg_num) {
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800109 // For the 32-bit internal ABI, the first 3 arguments are passed in registers.
110 switch (arg_num) {
111 case 0:
buzbee2700f7e2014-03-07 09:46:20 -0800112 return rs_rMIPS_ARG1;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800113 case 1:
buzbee2700f7e2014-03-07 09:46:20 -0800114 return rs_rMIPS_ARG2;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800115 case 2:
buzbee2700f7e2014-03-07 09:46:20 -0800116 return rs_rMIPS_ARG3;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800117 default:
buzbee2700f7e2014-03-07 09:46:20 -0800118 return RegStorage::InvalidReg();
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800119 }
120}
121
Brian Carlstrom7940e442013-07-12 13:46:57 -0700122/*
123 * Decode the register id.
124 */
buzbee091cc402014-03-31 10:14:40 -0700125uint64_t MipsMir2Lir::GetRegMaskCommon(RegStorage reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700126 uint64_t seed;
127 int shift;
buzbee091cc402014-03-31 10:14:40 -0700128 int reg_id = reg.GetRegNum();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700129 /* Each double register is equal to a pair of single-precision FP registers */
buzbee091cc402014-03-31 10:14:40 -0700130 if (reg.IsDouble()) {
131 seed = 0x3;
132 reg_id = reg_id << 1;
133 } else {
134 seed = 1;
135 }
136 /* FP register starts at bit position 32 */
137 shift = reg.IsFloat() ? kMipsFPReg0 : 0;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700138 /* Expand the double register id into single offset */
139 shift += reg_id;
140 return (seed << shift);
141}
142
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700143uint64_t MipsMir2Lir::GetPCUseDefEncoding() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700144 return ENCODE_MIPS_REG_PC;
145}
146
147
buzbeeb48819d2013-09-14 16:15:25 -0700148void MipsMir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700149 DCHECK_EQ(cu_->instruction_set, kMips);
buzbeeb48819d2013-09-14 16:15:25 -0700150 DCHECK(!lir->flags.use_def_invalid);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700151
152 // Mips-specific resource map setup here.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700153 if (flags & REG_DEF_SP) {
buzbeeb48819d2013-09-14 16:15:25 -0700154 lir->u.m.def_mask |= ENCODE_MIPS_REG_SP;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700155 }
156
157 if (flags & REG_USE_SP) {
buzbeeb48819d2013-09-14 16:15:25 -0700158 lir->u.m.use_mask |= ENCODE_MIPS_REG_SP;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700159 }
160
161 if (flags & REG_DEF_LR) {
buzbeeb48819d2013-09-14 16:15:25 -0700162 lir->u.m.def_mask |= ENCODE_MIPS_REG_LR;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700163 }
buzbee9da5c102014-03-28 12:59:18 -0700164
165 if (flags & REG_DEF_HI) {
166 lir->u.m.def_mask |= ENCODE_MIPS_REG_HI;
167 }
168
169 if (flags & REG_DEF_LO) {
170 lir->u.m.def_mask |= ENCODE_MIPS_REG_LO;
171 }
172
173 if (flags & REG_USE_HI) {
174 lir->u.m.use_mask |= ENCODE_MIPS_REG_HI;
175 }
176
177 if (flags & REG_USE_LO) {
178 lir->u.m.use_mask |= ENCODE_MIPS_REG_LO;
179 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700180}
181
182/* For dumping instructions */
183#define MIPS_REG_COUNT 32
184static const char *mips_reg_name[MIPS_REG_COUNT] = {
185 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
186 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
187 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
188 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
189};
190
191/*
192 * Interpret a format string and build a string no longer than size
193 * See format key in Assemble.c.
194 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700195std::string MipsMir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700196 std::string buf;
197 int i;
198 const char *fmt_end = &fmt[strlen(fmt)];
199 char tbuf[256];
200 char nc;
201 while (fmt < fmt_end) {
202 int operand;
203 if (*fmt == '!') {
204 fmt++;
205 DCHECK_LT(fmt, fmt_end);
206 nc = *fmt++;
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700207 if (nc == '!') {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700208 strcpy(tbuf, "!");
209 } else {
210 DCHECK_LT(fmt, fmt_end);
211 DCHECK_LT(static_cast<unsigned>(nc-'0'), 4u);
212 operand = lir->operands[nc-'0'];
213 switch (*fmt++) {
214 case 'b':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700215 strcpy(tbuf, "0000");
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700216 for (i = 3; i >= 0; i--) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700217 tbuf[i] += operand & 1;
218 operand >>= 1;
219 }
220 break;
221 case 's':
buzbee091cc402014-03-31 10:14:40 -0700222 snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700223 break;
224 case 'S':
buzbee091cc402014-03-31 10:14:40 -0700225 DCHECK_EQ(RegStorage::RegNum(operand) & 1, 0);
226 snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700227 break;
228 case 'h':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800229 snprintf(tbuf, arraysize(tbuf), "%04x", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700230 break;
231 case 'M':
232 case 'd':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800233 snprintf(tbuf, arraysize(tbuf), "%d", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700234 break;
235 case 'D':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800236 snprintf(tbuf, arraysize(tbuf), "%d", operand+1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700237 break;
238 case 'E':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800239 snprintf(tbuf, arraysize(tbuf), "%d", operand*4);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700240 break;
241 case 'F':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800242 snprintf(tbuf, arraysize(tbuf), "%d", operand*2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700243 break;
244 case 't':
Ian Rogers107c31e2014-01-23 20:55:29 -0800245 snprintf(tbuf, arraysize(tbuf), "0x%08" PRIxPTR " (L%p)",
246 reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 + (operand << 1),
247 lir->target);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700248 break;
249 case 'T':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800250 snprintf(tbuf, arraysize(tbuf), "0x%08x", operand << 2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700251 break;
252 case 'u': {
253 int offset_1 = lir->operands[0];
254 int offset_2 = NEXT_LIR(lir)->operands[0];
255 uintptr_t target =
256 (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) & ~3) +
257 (offset_1 << 21 >> 9) + (offset_2 << 1)) & 0xfffffffc;
Ian Rogers988e6ea2014-01-08 11:30:50 -0800258 snprintf(tbuf, arraysize(tbuf), "%p", reinterpret_cast<void*>(target));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700259 break;
260 }
261
262 /* Nothing to print for BLX_2 */
263 case 'v':
264 strcpy(tbuf, "see above");
265 break;
266 case 'r':
267 DCHECK(operand >= 0 && operand < MIPS_REG_COUNT);
268 strcpy(tbuf, mips_reg_name[operand]);
269 break;
270 case 'N':
271 // Placeholder for delay slot handling
272 strcpy(tbuf, "; nop");
273 break;
274 default:
Brian Carlstromb1eba212013-07-17 18:07:19 -0700275 strcpy(tbuf, "DecodeError");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700276 break;
277 }
278 buf += tbuf;
279 }
280 } else {
281 buf += *fmt++;
282 }
283 }
284 return buf;
285}
286
287// FIXME: need to redo resource maps for MIPS - fix this at that time
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700288void MipsMir2Lir::DumpResourceMask(LIR *mips_lir, uint64_t mask, const char *prefix) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700289 char buf[256];
290 buf[0] = 0;
291
292 if (mask == ENCODE_ALL) {
293 strcpy(buf, "all");
294 } else {
295 char num[8];
296 int i;
297
298 for (i = 0; i < kMipsRegEnd; i++) {
299 if (mask & (1ULL << i)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800300 snprintf(num, arraysize(num), "%d ", i);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700301 strcat(buf, num);
302 }
303 }
304
305 if (mask & ENCODE_CCODE) {
306 strcat(buf, "cc ");
307 }
308 if (mask & ENCODE_FP_STATUS) {
309 strcat(buf, "fpcc ");
310 }
311 /* Memory bits */
312 if (mips_lir && (mask & ENCODE_DALVIK_REG)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800313 snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s",
314 DECODE_ALIAS_INFO_REG(mips_lir->flags.alias_info),
315 DECODE_ALIAS_INFO_WIDE(mips_lir->flags.alias_info) ? "(+1)" : "");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700316 }
317 if (mask & ENCODE_LITERAL) {
318 strcat(buf, "lit ");
319 }
320
321 if (mask & ENCODE_HEAP_REF) {
322 strcat(buf, "heap ");
323 }
324 if (mask & ENCODE_MUST_NOT_ALIAS) {
325 strcat(buf, "noalias ");
326 }
327 }
328 if (buf[0]) {
329 LOG(INFO) << prefix << ": " << buf;
330 }
331}
332
333/*
334 * TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some
335 * instructions might call out to C/assembly helper functions. Until
336 * machinery is in place, always spill lr.
337 */
338
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700339void MipsMir2Lir::AdjustSpillMask() {
buzbee091cc402014-03-31 10:14:40 -0700340 core_spill_mask_ |= (1 << rs_rRA.GetRegNum());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700341 num_core_spills_++;
342}
343
344/*
345 * Mark a callee-save fp register as promoted. Note that
346 * vpush/vpop uses contiguous register lists so we must
347 * include any holes in the mask. Associate holes with
348 * Dalvik register INVALID_VREG (0xFFFFU).
349 */
buzbee091cc402014-03-31 10:14:40 -0700350void MipsMir2Lir::MarkPreservedSingle(int s_reg, RegStorage reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700351 LOG(FATAL) << "No support yet for promoted FP regs";
352}
353
buzbee091cc402014-03-31 10:14:40 -0700354void MipsMir2Lir::MarkPreservedDouble(int s_reg, RegStorage reg) {
355 LOG(FATAL) << "No support yet for promoted FP regs";
buzbee2700f7e2014-03-07 09:46:20 -0800356}
357
Brian Carlstrom7940e442013-07-12 13:46:57 -0700358/* Clobber all regs that might be used by an external C call */
Vladimir Marko31c2aac2013-12-09 16:31:19 +0000359void MipsMir2Lir::ClobberCallerSave() {
buzbee091cc402014-03-31 10:14:40 -0700360 Clobber(rs_rZERO);
361 Clobber(rs_rAT);
362 Clobber(rs_rV0);
363 Clobber(rs_rV1);
364 Clobber(rs_rA0);
365 Clobber(rs_rA1);
366 Clobber(rs_rA2);
367 Clobber(rs_rA3);
368 Clobber(rs_rT0);
369 Clobber(rs_rT1);
370 Clobber(rs_rT2);
371 Clobber(rs_rT3);
372 Clobber(rs_rT4);
373 Clobber(rs_rT5);
374 Clobber(rs_rT6);
375 Clobber(rs_rT7);
376 Clobber(rs_rT8);
377 Clobber(rs_rT9);
378 Clobber(rs_rK0);
379 Clobber(rs_rK1);
380 Clobber(rs_rGP);
381 Clobber(rs_rFP);
382 Clobber(rs_rRA);
383 Clobber(rs_rF0);
384 Clobber(rs_rF1);
385 Clobber(rs_rF2);
386 Clobber(rs_rF3);
387 Clobber(rs_rF4);
388 Clobber(rs_rF5);
389 Clobber(rs_rF6);
390 Clobber(rs_rF7);
391 Clobber(rs_rF8);
392 Clobber(rs_rF9);
393 Clobber(rs_rF10);
394 Clobber(rs_rF11);
395 Clobber(rs_rF12);
396 Clobber(rs_rF13);
397 Clobber(rs_rF14);
398 Clobber(rs_rF15);
399 Clobber(rs_rD0);
400 Clobber(rs_rD1);
401 Clobber(rs_rD2);
402 Clobber(rs_rD3);
403 Clobber(rs_rD4);
404 Clobber(rs_rD5);
405 Clobber(rs_rD6);
406 Clobber(rs_rD7);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700407}
408
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700409RegLocation MipsMir2Lir::GetReturnWideAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700410 UNIMPLEMENTED(FATAL) << "No GetReturnWideAlt for MIPS";
411 RegLocation res = LocCReturnWide();
412 return res;
413}
414
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700415RegLocation MipsMir2Lir::GetReturnAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700416 UNIMPLEMENTED(FATAL) << "No GetReturnAlt for MIPS";
417 RegLocation res = LocCReturn();
418 return res;
419}
420
Brian Carlstrom7940e442013-07-12 13:46:57 -0700421/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700422void MipsMir2Lir::LockCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700423 LockTemp(rs_rMIPS_ARG0);
424 LockTemp(rs_rMIPS_ARG1);
425 LockTemp(rs_rMIPS_ARG2);
426 LockTemp(rs_rMIPS_ARG3);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700427}
428
429/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700430void MipsMir2Lir::FreeCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700431 FreeTemp(rs_rMIPS_ARG0);
432 FreeTemp(rs_rMIPS_ARG1);
433 FreeTemp(rs_rMIPS_ARG2);
434 FreeTemp(rs_rMIPS_ARG3);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700435}
436
Andreas Gampeb14329f2014-05-15 11:16:06 -0700437bool MipsMir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700438#if ANDROID_SMP != 0
439 NewLIR1(kMipsSync, 0 /* Only stype currently supported */);
Andreas Gampeb14329f2014-05-15 11:16:06 -0700440 return true;
441#else
442 return false;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700443#endif
444}
445
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700446void MipsMir2Lir::CompilerInitializeRegAlloc() {
buzbeeb01bf152014-05-13 15:59:07 -0700447 reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs, empty_pool /* core64 */, sp_regs,
448 dp_regs, reserved_regs, empty_pool /* reserved64 */,
449 core_temps, empty_pool /* core64_temps */, sp_temps,
450 dp_temps);
buzbee091cc402014-03-31 10:14:40 -0700451
452 // Target-specific adjustments.
453
454 // Alias single precision floats to appropriate half of overlapping double.
455 GrowableArray<RegisterInfo*>::Iterator it(&reg_pool_->sp_regs_);
456 for (RegisterInfo* info = it.Next(); info != nullptr; info = it.Next()) {
457 int sp_reg_num = info->GetReg().GetRegNum();
458 int dp_reg_num = sp_reg_num >> 1;
459 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
460 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
461 // Double precision register's master storage should refer to itself.
462 DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
463 // Redirect single precision's master storage to master.
464 info->SetMaster(dp_reg_info);
465 // Singles should show a single 32-bit mask bit, at first referring to the low half.
466 DCHECK_EQ(info->StorageMask(), 0x1U);
467 if (sp_reg_num & 1) {
468 // For odd singles, change to user the high word of the backing double.
469 info->SetStorageMask(0x2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700470 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700471 }
buzbee091cc402014-03-31 10:14:40 -0700472
473 // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
474 // TODO: adjust when we roll to hard float calling convention.
475 reg_pool_->next_core_reg_ = 2;
476 reg_pool_->next_sp_reg_ = 2;
477 reg_pool_->next_dp_reg_ = 1;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700478}
479
Brian Carlstrom7940e442013-07-12 13:46:57 -0700480/*
481 * In the Arm code a it is typical to use the link register
482 * to hold the target address. However, for Mips we must
483 * ensure that all branch instructions can be restarted if
484 * there is a trap in the shadow. Allocate a temp register.
485 */
Ian Rogersdd7624d2014-03-14 17:43:00 -0700486RegStorage MipsMir2Lir::LoadHelper(ThreadOffset<4> offset) {
buzbee695d13a2014-04-19 13:32:20 -0700487 // NOTE: native pointer.
buzbee2700f7e2014-03-07 09:46:20 -0800488 LoadWordDisp(rs_rMIPS_SELF, offset.Int32Value(), rs_rT9);
489 return rs_rT9;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700490}
491
Andreas Gampe2f244e92014-05-08 03:35:25 -0700492RegStorage MipsMir2Lir::LoadHelper(ThreadOffset<8> offset) {
493 UNIMPLEMENTED(FATAL) << "Should not be called.";
494 return RegStorage::InvalidReg();
495}
496
Dave Allisonb373e092014-02-20 16:06:36 -0800497LIR* MipsMir2Lir::CheckSuspendUsingLoad() {
buzbee2700f7e2014-03-07 09:46:20 -0800498 RegStorage tmp = AllocTemp();
buzbee695d13a2014-04-19 13:32:20 -0700499 // NOTE: native pointer.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700500 LoadWordDisp(rs_rMIPS_SELF, Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
Dave Allisonb373e092014-02-20 16:06:36 -0800501 LIR *inst = LoadWordDisp(tmp, 0, tmp);
502 FreeTemp(tmp);
503 return inst;
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;
buzbee2700f7e2014-03-07 09:46:20 -0800512 OpRegImm(kOpSub, rs_rSP, offset);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700513 for (int reg = 0; mask; mask >>= 1, reg++) {
514 if (mask & 0x1) {
515 offset -= 4;
buzbee695d13a2014-04-19 13:32:20 -0700516 Store32Disp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700517 }
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;
buzbee695d13a2014-04-19 13:32:20 -0700530 Load32Disp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700531 }
532 }
buzbee2700f7e2014-03-07 09:46:20 -0800533 OpRegImm(kOpAdd, rs_rSP, frame_size_);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700534}
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
Vladimir Marko674744e2014-04-24 15:18:26 +0100540bool MipsMir2Lir::SupportsVolatileLoadStore(OpSize size) {
541 // No support for 64-bit atomic load/store on mips.
542 return size != k64 && size != kDouble;
543}
544
545RegisterClass MipsMir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) {
546 // No support for 64-bit atomic load/store on mips.
547 DCHECK(size != k64 && size != kDouble);
548 // TODO: Verify that both core and fp registers are suitable for smaller sizes.
549 return RegClassBySize(size);
550}
551
Brian Carlstrom7940e442013-07-12 13:46:57 -0700552MipsMir2Lir::MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
553 : Mir2Lir(cu, mir_graph, arena) {
554 for (int i = 0; i < kMipsLast; i++) {
555 if (MipsMir2Lir::EncodingMap[i].opcode != i) {
556 LOG(FATAL) << "Encoding order for " << MipsMir2Lir::EncodingMap[i].name
557 << " is wrong: expecting " << i << ", seeing "
558 << static_cast<int>(MipsMir2Lir::EncodingMap[i].opcode);
559 }
560 }
561}
562
563Mir2Lir* MipsCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
564 ArenaAllocator* const arena) {
565 return new MipsMir2Lir(cu, mir_graph, arena);
566}
567
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700568uint64_t MipsMir2Lir::GetTargetInstFlags(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700569 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700570 return MipsMir2Lir::EncodingMap[opcode].flags;
571}
572
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700573const char* MipsMir2Lir::GetTargetInstName(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700574 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700575 return MipsMir2Lir::EncodingMap[opcode].name;
576}
577
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700578const char* MipsMir2Lir::GetTargetInstFmt(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700579 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700580 return MipsMir2Lir::EncodingMap[opcode].fmt;
581}
582
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700583} // namespace art