blob: 7a3da717c24a81795630ee7d3e6bc81218b1e5ef [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
49static const std::vector<RegStorage> core_regs(core_regs_arr,
50 core_regs_arr + sizeof(core_regs_arr) / sizeof(core_regs_arr[0]));
51static const std::vector<RegStorage> sp_regs(sp_regs_arr,
52 sp_regs_arr + sizeof(sp_regs_arr) / sizeof(sp_regs_arr[0]));
53static const std::vector<RegStorage> dp_regs(dp_regs_arr,
54 dp_regs_arr + sizeof(dp_regs_arr) / sizeof(dp_regs_arr[0]));
55static const std::vector<RegStorage> reserved_regs(reserved_regs_arr,
56 reserved_regs_arr + sizeof(reserved_regs_arr) / sizeof(reserved_regs_arr[0]));
57static const std::vector<RegStorage> core_temps(core_temps_arr,
58 core_temps_arr + sizeof(core_temps_arr) / sizeof(core_temps_arr[0]));
59static const std::vector<RegStorage> sp_temps(sp_temps_arr,
60 sp_temps_arr + sizeof(sp_temps_arr) / sizeof(sp_temps_arr[0]));
61static const std::vector<RegStorage> dp_temps(dp_temps_arr,
62 dp_temps_arr + sizeof(dp_temps_arr) / sizeof(dp_temps_arr[0]));
Brian Carlstrom7940e442013-07-12 13:46:57 -070063
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070064RegLocation MipsMir2Lir::LocCReturn() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000065 return mips_loc_c_return;
Brian Carlstrom7940e442013-07-12 13:46:57 -070066}
67
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070068RegLocation MipsMir2Lir::LocCReturnWide() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000069 return mips_loc_c_return_wide;
Brian Carlstrom7940e442013-07-12 13:46:57 -070070}
71
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070072RegLocation MipsMir2Lir::LocCReturnFloat() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000073 return mips_loc_c_return_float;
Brian Carlstrom7940e442013-07-12 13:46:57 -070074}
75
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070076RegLocation MipsMir2Lir::LocCReturnDouble() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000077 return mips_loc_c_return_double;
Brian Carlstrom7940e442013-07-12 13:46:57 -070078}
79
80// Return a target-dependent special register.
buzbee2700f7e2014-03-07 09:46:20 -080081RegStorage MipsMir2Lir::TargetReg(SpecialTargetRegister reg) {
buzbee091cc402014-03-31 10:14:40 -070082 RegStorage res_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -070083 switch (reg) {
buzbee091cc402014-03-31 10:14:40 -070084 case kSelf: res_reg = rs_rMIPS_SELF; break;
85 case kSuspend: res_reg = rs_rMIPS_SUSPEND; break;
86 case kLr: res_reg = rs_rMIPS_LR; break;
87 case kPc: res_reg = rs_rMIPS_PC; break;
88 case kSp: res_reg = rs_rMIPS_SP; break;
89 case kArg0: res_reg = rs_rMIPS_ARG0; break;
90 case kArg1: res_reg = rs_rMIPS_ARG1; break;
91 case kArg2: res_reg = rs_rMIPS_ARG2; break;
92 case kArg3: res_reg = rs_rMIPS_ARG3; break;
93 case kFArg0: res_reg = rs_rMIPS_FARG0; break;
94 case kFArg1: res_reg = rs_rMIPS_FARG1; break;
95 case kFArg2: res_reg = rs_rMIPS_FARG2; break;
96 case kFArg3: res_reg = rs_rMIPS_FARG3; break;
97 case kRet0: res_reg = rs_rMIPS_RET0; break;
98 case kRet1: res_reg = rs_rMIPS_RET1; break;
99 case kInvokeTgt: res_reg = rs_rMIPS_INVOKE_TGT; break;
100 case kHiddenArg: res_reg = rs_rT0; break;
101 case kHiddenFpArg: res_reg = RegStorage::InvalidReg(); break;
102 case kCount: res_reg = rs_rMIPS_COUNT; break;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700103 }
buzbee091cc402014-03-31 10:14:40 -0700104 return res_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700105}
106
buzbee2700f7e2014-03-07 09:46:20 -0800107RegStorage MipsMir2Lir::GetArgMappingToPhysicalReg(int arg_num) {
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800108 // For the 32-bit internal ABI, the first 3 arguments are passed in registers.
109 switch (arg_num) {
110 case 0:
buzbee2700f7e2014-03-07 09:46:20 -0800111 return rs_rMIPS_ARG1;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800112 case 1:
buzbee2700f7e2014-03-07 09:46:20 -0800113 return rs_rMIPS_ARG2;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800114 case 2:
buzbee2700f7e2014-03-07 09:46:20 -0800115 return rs_rMIPS_ARG3;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800116 default:
buzbee2700f7e2014-03-07 09:46:20 -0800117 return RegStorage::InvalidReg();
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800118 }
119}
120
Brian Carlstrom7940e442013-07-12 13:46:57 -0700121/*
122 * Decode the register id.
123 */
buzbee091cc402014-03-31 10:14:40 -0700124uint64_t MipsMir2Lir::GetRegMaskCommon(RegStorage reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700125 uint64_t seed;
126 int shift;
buzbee091cc402014-03-31 10:14:40 -0700127 int reg_id = reg.GetRegNum();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700128 /* Each double register is equal to a pair of single-precision FP registers */
buzbee091cc402014-03-31 10:14:40 -0700129 if (reg.IsDouble()) {
130 seed = 0x3;
131 reg_id = reg_id << 1;
132 } else {
133 seed = 1;
134 }
135 /* FP register starts at bit position 32 */
136 shift = reg.IsFloat() ? kMipsFPReg0 : 0;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700137 /* Expand the double register id into single offset */
138 shift += reg_id;
139 return (seed << shift);
140}
141
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700142uint64_t MipsMir2Lir::GetPCUseDefEncoding() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700143 return ENCODE_MIPS_REG_PC;
144}
145
146
buzbeeb48819d2013-09-14 16:15:25 -0700147void MipsMir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700148 DCHECK_EQ(cu_->instruction_set, kMips);
buzbeeb48819d2013-09-14 16:15:25 -0700149 DCHECK(!lir->flags.use_def_invalid);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700150
151 // Mips-specific resource map setup here.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700152 if (flags & REG_DEF_SP) {
buzbeeb48819d2013-09-14 16:15:25 -0700153 lir->u.m.def_mask |= ENCODE_MIPS_REG_SP;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700154 }
155
156 if (flags & REG_USE_SP) {
buzbeeb48819d2013-09-14 16:15:25 -0700157 lir->u.m.use_mask |= ENCODE_MIPS_REG_SP;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700158 }
159
160 if (flags & REG_DEF_LR) {
buzbeeb48819d2013-09-14 16:15:25 -0700161 lir->u.m.def_mask |= ENCODE_MIPS_REG_LR;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700162 }
buzbee9da5c102014-03-28 12:59:18 -0700163
164 if (flags & REG_DEF_HI) {
165 lir->u.m.def_mask |= ENCODE_MIPS_REG_HI;
166 }
167
168 if (flags & REG_DEF_LO) {
169 lir->u.m.def_mask |= ENCODE_MIPS_REG_LO;
170 }
171
172 if (flags & REG_USE_HI) {
173 lir->u.m.use_mask |= ENCODE_MIPS_REG_HI;
174 }
175
176 if (flags & REG_USE_LO) {
177 lir->u.m.use_mask |= ENCODE_MIPS_REG_LO;
178 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700179}
180
181/* For dumping instructions */
182#define MIPS_REG_COUNT 32
183static const char *mips_reg_name[MIPS_REG_COUNT] = {
184 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
185 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
186 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
187 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
188};
189
190/*
191 * Interpret a format string and build a string no longer than size
192 * See format key in Assemble.c.
193 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700194std::string MipsMir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700195 std::string buf;
196 int i;
197 const char *fmt_end = &fmt[strlen(fmt)];
198 char tbuf[256];
199 char nc;
200 while (fmt < fmt_end) {
201 int operand;
202 if (*fmt == '!') {
203 fmt++;
204 DCHECK_LT(fmt, fmt_end);
205 nc = *fmt++;
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700206 if (nc == '!') {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700207 strcpy(tbuf, "!");
208 } else {
209 DCHECK_LT(fmt, fmt_end);
210 DCHECK_LT(static_cast<unsigned>(nc-'0'), 4u);
211 operand = lir->operands[nc-'0'];
212 switch (*fmt++) {
213 case 'b':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700214 strcpy(tbuf, "0000");
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700215 for (i = 3; i >= 0; i--) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700216 tbuf[i] += operand & 1;
217 operand >>= 1;
218 }
219 break;
220 case 's':
buzbee091cc402014-03-31 10:14:40 -0700221 snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700222 break;
223 case 'S':
buzbee091cc402014-03-31 10:14:40 -0700224 DCHECK_EQ(RegStorage::RegNum(operand) & 1, 0);
225 snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700226 break;
227 case 'h':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800228 snprintf(tbuf, arraysize(tbuf), "%04x", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700229 break;
230 case 'M':
231 case 'd':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800232 snprintf(tbuf, arraysize(tbuf), "%d", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700233 break;
234 case 'D':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800235 snprintf(tbuf, arraysize(tbuf), "%d", operand+1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700236 break;
237 case 'E':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800238 snprintf(tbuf, arraysize(tbuf), "%d", operand*4);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700239 break;
240 case 'F':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800241 snprintf(tbuf, arraysize(tbuf), "%d", operand*2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700242 break;
243 case 't':
Ian Rogers107c31e2014-01-23 20:55:29 -0800244 snprintf(tbuf, arraysize(tbuf), "0x%08" PRIxPTR " (L%p)",
245 reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 + (operand << 1),
246 lir->target);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700247 break;
248 case 'T':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800249 snprintf(tbuf, arraysize(tbuf), "0x%08x", operand << 2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700250 break;
251 case 'u': {
252 int offset_1 = lir->operands[0];
253 int offset_2 = NEXT_LIR(lir)->operands[0];
254 uintptr_t target =
255 (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) & ~3) +
256 (offset_1 << 21 >> 9) + (offset_2 << 1)) & 0xfffffffc;
Ian Rogers988e6ea2014-01-08 11:30:50 -0800257 snprintf(tbuf, arraysize(tbuf), "%p", reinterpret_cast<void*>(target));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700258 break;
259 }
260
261 /* Nothing to print for BLX_2 */
262 case 'v':
263 strcpy(tbuf, "see above");
264 break;
265 case 'r':
266 DCHECK(operand >= 0 && operand < MIPS_REG_COUNT);
267 strcpy(tbuf, mips_reg_name[operand]);
268 break;
269 case 'N':
270 // Placeholder for delay slot handling
271 strcpy(tbuf, "; nop");
272 break;
273 default:
Brian Carlstromb1eba212013-07-17 18:07:19 -0700274 strcpy(tbuf, "DecodeError");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700275 break;
276 }
277 buf += tbuf;
278 }
279 } else {
280 buf += *fmt++;
281 }
282 }
283 return buf;
284}
285
286// FIXME: need to redo resource maps for MIPS - fix this at that time
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700287void MipsMir2Lir::DumpResourceMask(LIR *mips_lir, uint64_t mask, const char *prefix) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700288 char buf[256];
289 buf[0] = 0;
290
291 if (mask == ENCODE_ALL) {
292 strcpy(buf, "all");
293 } else {
294 char num[8];
295 int i;
296
297 for (i = 0; i < kMipsRegEnd; i++) {
298 if (mask & (1ULL << i)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800299 snprintf(num, arraysize(num), "%d ", i);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700300 strcat(buf, num);
301 }
302 }
303
304 if (mask & ENCODE_CCODE) {
305 strcat(buf, "cc ");
306 }
307 if (mask & ENCODE_FP_STATUS) {
308 strcat(buf, "fpcc ");
309 }
310 /* Memory bits */
311 if (mips_lir && (mask & ENCODE_DALVIK_REG)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800312 snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s",
313 DECODE_ALIAS_INFO_REG(mips_lir->flags.alias_info),
314 DECODE_ALIAS_INFO_WIDE(mips_lir->flags.alias_info) ? "(+1)" : "");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700315 }
316 if (mask & ENCODE_LITERAL) {
317 strcat(buf, "lit ");
318 }
319
320 if (mask & ENCODE_HEAP_REF) {
321 strcat(buf, "heap ");
322 }
323 if (mask & ENCODE_MUST_NOT_ALIAS) {
324 strcat(buf, "noalias ");
325 }
326 }
327 if (buf[0]) {
328 LOG(INFO) << prefix << ": " << buf;
329 }
330}
331
332/*
333 * TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some
334 * instructions might call out to C/assembly helper functions. Until
335 * machinery is in place, always spill lr.
336 */
337
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700338void MipsMir2Lir::AdjustSpillMask() {
buzbee091cc402014-03-31 10:14:40 -0700339 core_spill_mask_ |= (1 << rs_rRA.GetRegNum());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700340 num_core_spills_++;
341}
342
343/*
344 * Mark a callee-save fp register as promoted. Note that
345 * vpush/vpop uses contiguous register lists so we must
346 * include any holes in the mask. Associate holes with
347 * Dalvik register INVALID_VREG (0xFFFFU).
348 */
buzbee091cc402014-03-31 10:14:40 -0700349void MipsMir2Lir::MarkPreservedSingle(int s_reg, RegStorage reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700350 LOG(FATAL) << "No support yet for promoted FP regs";
351}
352
buzbee091cc402014-03-31 10:14:40 -0700353void MipsMir2Lir::MarkPreservedDouble(int s_reg, RegStorage reg) {
354 LOG(FATAL) << "No support yet for promoted FP regs";
buzbee2700f7e2014-03-07 09:46:20 -0800355}
356
Brian Carlstrom7940e442013-07-12 13:46:57 -0700357/* Clobber all regs that might be used by an external C call */
Vladimir Marko31c2aac2013-12-09 16:31:19 +0000358void MipsMir2Lir::ClobberCallerSave() {
buzbee091cc402014-03-31 10:14:40 -0700359 Clobber(rs_rZERO);
360 Clobber(rs_rAT);
361 Clobber(rs_rV0);
362 Clobber(rs_rV1);
363 Clobber(rs_rA0);
364 Clobber(rs_rA1);
365 Clobber(rs_rA2);
366 Clobber(rs_rA3);
367 Clobber(rs_rT0);
368 Clobber(rs_rT1);
369 Clobber(rs_rT2);
370 Clobber(rs_rT3);
371 Clobber(rs_rT4);
372 Clobber(rs_rT5);
373 Clobber(rs_rT6);
374 Clobber(rs_rT7);
375 Clobber(rs_rT8);
376 Clobber(rs_rT9);
377 Clobber(rs_rK0);
378 Clobber(rs_rK1);
379 Clobber(rs_rGP);
380 Clobber(rs_rFP);
381 Clobber(rs_rRA);
382 Clobber(rs_rF0);
383 Clobber(rs_rF1);
384 Clobber(rs_rF2);
385 Clobber(rs_rF3);
386 Clobber(rs_rF4);
387 Clobber(rs_rF5);
388 Clobber(rs_rF6);
389 Clobber(rs_rF7);
390 Clobber(rs_rF8);
391 Clobber(rs_rF9);
392 Clobber(rs_rF10);
393 Clobber(rs_rF11);
394 Clobber(rs_rF12);
395 Clobber(rs_rF13);
396 Clobber(rs_rF14);
397 Clobber(rs_rF15);
398 Clobber(rs_rD0);
399 Clobber(rs_rD1);
400 Clobber(rs_rD2);
401 Clobber(rs_rD3);
402 Clobber(rs_rD4);
403 Clobber(rs_rD5);
404 Clobber(rs_rD6);
405 Clobber(rs_rD7);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700406}
407
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700408RegLocation MipsMir2Lir::GetReturnWideAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700409 UNIMPLEMENTED(FATAL) << "No GetReturnWideAlt for MIPS";
410 RegLocation res = LocCReturnWide();
411 return res;
412}
413
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700414RegLocation MipsMir2Lir::GetReturnAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700415 UNIMPLEMENTED(FATAL) << "No GetReturnAlt for MIPS";
416 RegLocation res = LocCReturn();
417 return res;
418}
419
Brian Carlstrom7940e442013-07-12 13:46:57 -0700420/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700421void MipsMir2Lir::LockCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700422 LockTemp(rs_rMIPS_ARG0);
423 LockTemp(rs_rMIPS_ARG1);
424 LockTemp(rs_rMIPS_ARG2);
425 LockTemp(rs_rMIPS_ARG3);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700426}
427
428/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700429void MipsMir2Lir::FreeCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700430 FreeTemp(rs_rMIPS_ARG0);
431 FreeTemp(rs_rMIPS_ARG1);
432 FreeTemp(rs_rMIPS_ARG2);
433 FreeTemp(rs_rMIPS_ARG3);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700434}
435
Andreas Gampeb14329f2014-05-15 11:16:06 -0700436bool MipsMir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700437#if ANDROID_SMP != 0
438 NewLIR1(kMipsSync, 0 /* Only stype currently supported */);
Andreas Gampeb14329f2014-05-15 11:16:06 -0700439 return true;
440#else
441 return false;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700442#endif
443}
444
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000445// Alloc a pair of core registers, or a double.
446RegStorage MipsMir2Lir::AllocTypedTempWide(bool fp_hint, int reg_class) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700447 if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
buzbee2700f7e2014-03-07 09:46:20 -0800448 return AllocTempDouble();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700449 }
450
buzbee091cc402014-03-31 10:14:40 -0700451 RegStorage low_reg = AllocTemp();
452 RegStorage high_reg = AllocTemp();
453 return RegStorage::MakeRegPair(low_reg, high_reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700454}
455
buzbee2700f7e2014-03-07 09:46:20 -0800456RegStorage MipsMir2Lir::AllocTypedTemp(bool fp_hint, int reg_class) {
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700457 if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
buzbee091cc402014-03-31 10:14:40 -0700458 return AllocTempSingle();
459 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700460 return AllocTemp();
461}
462
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700463void MipsMir2Lir::CompilerInitializeRegAlloc() {
buzbee091cc402014-03-31 10:14:40 -0700464 reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs, sp_regs, dp_regs, reserved_regs,
465 core_temps, sp_temps, dp_temps);
466
467 // Target-specific adjustments.
468
469 // Alias single precision floats to appropriate half of overlapping double.
470 GrowableArray<RegisterInfo*>::Iterator it(&reg_pool_->sp_regs_);
471 for (RegisterInfo* info = it.Next(); info != nullptr; info = it.Next()) {
472 int sp_reg_num = info->GetReg().GetRegNum();
473 int dp_reg_num = sp_reg_num >> 1;
474 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
475 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
476 // Double precision register's master storage should refer to itself.
477 DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
478 // Redirect single precision's master storage to master.
479 info->SetMaster(dp_reg_info);
480 // Singles should show a single 32-bit mask bit, at first referring to the low half.
481 DCHECK_EQ(info->StorageMask(), 0x1U);
482 if (sp_reg_num & 1) {
483 // For odd singles, change to user the high word of the backing double.
484 info->SetStorageMask(0x2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700485 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700486 }
buzbee091cc402014-03-31 10:14:40 -0700487
488 // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
489 // TODO: adjust when we roll to hard float calling convention.
490 reg_pool_->next_core_reg_ = 2;
491 reg_pool_->next_sp_reg_ = 2;
492 reg_pool_->next_dp_reg_ = 1;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700493}
494
Brian Carlstrom7940e442013-07-12 13:46:57 -0700495/*
496 * In the Arm code a it is typical to use the link register
497 * to hold the target address. However, for Mips we must
498 * ensure that all branch instructions can be restarted if
499 * there is a trap in the shadow. Allocate a temp register.
500 */
Ian Rogersdd7624d2014-03-14 17:43:00 -0700501RegStorage MipsMir2Lir::LoadHelper(ThreadOffset<4> offset) {
buzbee695d13a2014-04-19 13:32:20 -0700502 // NOTE: native pointer.
buzbee2700f7e2014-03-07 09:46:20 -0800503 LoadWordDisp(rs_rMIPS_SELF, offset.Int32Value(), rs_rT9);
504 return rs_rT9;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700505}
506
Andreas Gampe2f244e92014-05-08 03:35:25 -0700507RegStorage MipsMir2Lir::LoadHelper(ThreadOffset<8> offset) {
508 UNIMPLEMENTED(FATAL) << "Should not be called.";
509 return RegStorage::InvalidReg();
510}
511
Dave Allisonb373e092014-02-20 16:06:36 -0800512LIR* MipsMir2Lir::CheckSuspendUsingLoad() {
buzbee2700f7e2014-03-07 09:46:20 -0800513 RegStorage tmp = AllocTemp();
buzbee695d13a2014-04-19 13:32:20 -0700514 // NOTE: native pointer.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700515 LoadWordDisp(rs_rMIPS_SELF, Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
Dave Allisonb373e092014-02-20 16:06:36 -0800516 LIR *inst = LoadWordDisp(tmp, 0, tmp);
517 FreeTemp(tmp);
518 return inst;
519}
520
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700521void MipsMir2Lir::SpillCoreRegs() {
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 = num_core_spills_ * 4;
buzbee2700f7e2014-03-07 09:46:20 -0800527 OpRegImm(kOpSub, rs_rSP, offset);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700528 for (int reg = 0; mask; mask >>= 1, reg++) {
529 if (mask & 0x1) {
530 offset -= 4;
buzbee695d13a2014-04-19 13:32:20 -0700531 Store32Disp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700532 }
533 }
534}
535
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700536void MipsMir2Lir::UnSpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700537 if (num_core_spills_ == 0) {
538 return;
539 }
540 uint32_t mask = core_spill_mask_;
541 int offset = frame_size_;
542 for (int reg = 0; mask; mask >>= 1, reg++) {
543 if (mask & 0x1) {
544 offset -= 4;
buzbee695d13a2014-04-19 13:32:20 -0700545 Load32Disp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700546 }
547 }
buzbee2700f7e2014-03-07 09:46:20 -0800548 OpRegImm(kOpAdd, rs_rSP, frame_size_);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700549}
550
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700551bool MipsMir2Lir::IsUnconditionalBranch(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700552 return (lir->opcode == kMipsB);
553}
554
Vladimir Marko674744e2014-04-24 15:18:26 +0100555bool MipsMir2Lir::SupportsVolatileLoadStore(OpSize size) {
556 // No support for 64-bit atomic load/store on mips.
557 return size != k64 && size != kDouble;
558}
559
560RegisterClass MipsMir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) {
561 // No support for 64-bit atomic load/store on mips.
562 DCHECK(size != k64 && size != kDouble);
563 // TODO: Verify that both core and fp registers are suitable for smaller sizes.
564 return RegClassBySize(size);
565}
566
Brian Carlstrom7940e442013-07-12 13:46:57 -0700567MipsMir2Lir::MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
568 : Mir2Lir(cu, mir_graph, arena) {
569 for (int i = 0; i < kMipsLast; i++) {
570 if (MipsMir2Lir::EncodingMap[i].opcode != i) {
571 LOG(FATAL) << "Encoding order for " << MipsMir2Lir::EncodingMap[i].name
572 << " is wrong: expecting " << i << ", seeing "
573 << static_cast<int>(MipsMir2Lir::EncodingMap[i].opcode);
574 }
575 }
576}
577
578Mir2Lir* MipsCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
579 ArenaAllocator* const arena) {
580 return new MipsMir2Lir(cu, mir_graph, arena);
581}
582
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700583uint64_t MipsMir2Lir::GetTargetInstFlags(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700584 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700585 return MipsMir2Lir::EncodingMap[opcode].flags;
586}
587
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700588const char* MipsMir2Lir::GetTargetInstName(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700589 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700590 return MipsMir2Lir::EncodingMap[opcode].name;
591}
592
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700593const char* MipsMir2Lir::GetTargetInstFmt(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700594 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700595 return MipsMir2Lir::EncodingMap[opcode].fmt;
596}
597
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700598} // namespace art