blob: 570c220dbf0fbd77227864dcc59980004ea93a24 [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
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700436void 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 */);
439#endif
440}
441
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000442// Alloc a pair of core registers, or a double.
443RegStorage MipsMir2Lir::AllocTypedTempWide(bool fp_hint, int reg_class) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700444 if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
buzbee2700f7e2014-03-07 09:46:20 -0800445 return AllocTempDouble();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700446 }
447
buzbee091cc402014-03-31 10:14:40 -0700448 RegStorage low_reg = AllocTemp();
449 RegStorage high_reg = AllocTemp();
450 return RegStorage::MakeRegPair(low_reg, high_reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700451}
452
buzbee2700f7e2014-03-07 09:46:20 -0800453RegStorage MipsMir2Lir::AllocTypedTemp(bool fp_hint, int reg_class) {
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700454 if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) {
buzbee091cc402014-03-31 10:14:40 -0700455 return AllocTempSingle();
456 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700457 return AllocTemp();
458}
459
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700460void MipsMir2Lir::CompilerInitializeRegAlloc() {
buzbee091cc402014-03-31 10:14:40 -0700461 reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs, sp_regs, dp_regs, reserved_regs,
462 core_temps, sp_temps, dp_temps);
463
464 // Target-specific adjustments.
465
466 // Alias single precision floats to appropriate half of overlapping double.
467 GrowableArray<RegisterInfo*>::Iterator it(&reg_pool_->sp_regs_);
468 for (RegisterInfo* info = it.Next(); info != nullptr; info = it.Next()) {
469 int sp_reg_num = info->GetReg().GetRegNum();
470 int dp_reg_num = sp_reg_num >> 1;
471 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
472 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
473 // Double precision register's master storage should refer to itself.
474 DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
475 // Redirect single precision's master storage to master.
476 info->SetMaster(dp_reg_info);
477 // Singles should show a single 32-bit mask bit, at first referring to the low half.
478 DCHECK_EQ(info->StorageMask(), 0x1U);
479 if (sp_reg_num & 1) {
480 // For odd singles, change to user the high word of the backing double.
481 info->SetStorageMask(0x2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700482 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700483 }
buzbee091cc402014-03-31 10:14:40 -0700484
485 // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
486 // TODO: adjust when we roll to hard float calling convention.
487 reg_pool_->next_core_reg_ = 2;
488 reg_pool_->next_sp_reg_ = 2;
489 reg_pool_->next_dp_reg_ = 1;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700490}
491
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700492void MipsMir2Lir::FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) {
buzbee2700f7e2014-03-07 09:46:20 -0800493 DCHECK(rl_keep.wide);
494 DCHECK(rl_free.wide);
495 if ((rl_free.reg.GetLowReg() != rl_keep.reg.GetLowReg()) &&
496 (rl_free.reg.GetLowReg() != rl_keep.reg.GetHighReg()) &&
497 (rl_free.reg.GetHighReg() != rl_keep.reg.GetLowReg()) &&
498 (rl_free.reg.GetHighReg() != rl_keep.reg.GetHighReg())) {
499 // No overlap, free.
500 FreeTemp(rl_free.reg);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700501 }
502}
503/*
504 * In the Arm code a it is typical to use the link register
505 * to hold the target address. However, for Mips we must
506 * ensure that all branch instructions can be restarted if
507 * there is a trap in the shadow. Allocate a temp register.
508 */
Ian Rogersdd7624d2014-03-14 17:43:00 -0700509RegStorage MipsMir2Lir::LoadHelper(ThreadOffset<4> offset) {
buzbee695d13a2014-04-19 13:32:20 -0700510 // NOTE: native pointer.
buzbee2700f7e2014-03-07 09:46:20 -0800511 LoadWordDisp(rs_rMIPS_SELF, offset.Int32Value(), rs_rT9);
512 return rs_rT9;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700513}
514
Dave Allisonb373e092014-02-20 16:06:36 -0800515LIR* MipsMir2Lir::CheckSuspendUsingLoad() {
buzbee2700f7e2014-03-07 09:46:20 -0800516 RegStorage tmp = AllocTemp();
buzbee695d13a2014-04-19 13:32:20 -0700517 // NOTE: native pointer.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700518 LoadWordDisp(rs_rMIPS_SELF, Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
Dave Allisonb373e092014-02-20 16:06:36 -0800519 LIR *inst = LoadWordDisp(tmp, 0, tmp);
520 FreeTemp(tmp);
521 return inst;
522}
523
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700524void MipsMir2Lir::SpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700525 if (num_core_spills_ == 0) {
526 return;
527 }
528 uint32_t mask = core_spill_mask_;
529 int offset = num_core_spills_ * 4;
buzbee2700f7e2014-03-07 09:46:20 -0800530 OpRegImm(kOpSub, rs_rSP, offset);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700531 for (int reg = 0; mask; mask >>= 1, reg++) {
532 if (mask & 0x1) {
533 offset -= 4;
buzbee695d13a2014-04-19 13:32:20 -0700534 Store32Disp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700535 }
536 }
537}
538
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700539void MipsMir2Lir::UnSpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700540 if (num_core_spills_ == 0) {
541 return;
542 }
543 uint32_t mask = core_spill_mask_;
544 int offset = frame_size_;
545 for (int reg = 0; mask; mask >>= 1, reg++) {
546 if (mask & 0x1) {
547 offset -= 4;
buzbee695d13a2014-04-19 13:32:20 -0700548 Load32Disp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700549 }
550 }
buzbee2700f7e2014-03-07 09:46:20 -0800551 OpRegImm(kOpAdd, rs_rSP, frame_size_);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700552}
553
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700554bool MipsMir2Lir::IsUnconditionalBranch(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700555 return (lir->opcode == kMipsB);
556}
557
Vladimir Marko674744e2014-04-24 15:18:26 +0100558bool MipsMir2Lir::SupportsVolatileLoadStore(OpSize size) {
559 // No support for 64-bit atomic load/store on mips.
560 return size != k64 && size != kDouble;
561}
562
563RegisterClass MipsMir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) {
564 // No support for 64-bit atomic load/store on mips.
565 DCHECK(size != k64 && size != kDouble);
566 // TODO: Verify that both core and fp registers are suitable for smaller sizes.
567 return RegClassBySize(size);
568}
569
Brian Carlstrom7940e442013-07-12 13:46:57 -0700570MipsMir2Lir::MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
571 : Mir2Lir(cu, mir_graph, arena) {
572 for (int i = 0; i < kMipsLast; i++) {
573 if (MipsMir2Lir::EncodingMap[i].opcode != i) {
574 LOG(FATAL) << "Encoding order for " << MipsMir2Lir::EncodingMap[i].name
575 << " is wrong: expecting " << i << ", seeing "
576 << static_cast<int>(MipsMir2Lir::EncodingMap[i].opcode);
577 }
578 }
579}
580
581Mir2Lir* MipsCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
582 ArenaAllocator* const arena) {
583 return new MipsMir2Lir(cu, mir_graph, arena);
584}
585
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700586uint64_t MipsMir2Lir::GetTargetInstFlags(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700587 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700588 return MipsMir2Lir::EncodingMap[opcode].flags;
589}
590
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700591const char* MipsMir2Lir::GetTargetInstName(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700592 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700593 return MipsMir2Lir::EncodingMap[opcode].name;
594}
595
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700596const char* MipsMir2Lir::GetTargetInstFmt(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700597 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700598 return MipsMir2Lir::EncodingMap[opcode].fmt;
599}
600
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700601} // namespace art