blob: fcf5f94159f1d748e990502841002c0a817f5744 [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
buzbeea0cd2d72014-06-01 09:33:49 -070069RegLocation MipsMir2Lir::LocCReturnRef() {
70 return mips_loc_c_return;
71}
72
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070073RegLocation MipsMir2Lir::LocCReturnWide() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000074 return mips_loc_c_return_wide;
Brian Carlstrom7940e442013-07-12 13:46:57 -070075}
76
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070077RegLocation MipsMir2Lir::LocCReturnFloat() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000078 return mips_loc_c_return_float;
Brian Carlstrom7940e442013-07-12 13:46:57 -070079}
80
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070081RegLocation MipsMir2Lir::LocCReturnDouble() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000082 return mips_loc_c_return_double;
Brian Carlstrom7940e442013-07-12 13:46:57 -070083}
84
85// Return a target-dependent special register.
buzbee2700f7e2014-03-07 09:46:20 -080086RegStorage MipsMir2Lir::TargetReg(SpecialTargetRegister reg) {
buzbee091cc402014-03-31 10:14:40 -070087 RegStorage res_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -070088 switch (reg) {
buzbee091cc402014-03-31 10:14:40 -070089 case kSelf: res_reg = rs_rMIPS_SELF; break;
90 case kSuspend: res_reg = rs_rMIPS_SUSPEND; break;
91 case kLr: res_reg = rs_rMIPS_LR; break;
92 case kPc: res_reg = rs_rMIPS_PC; break;
93 case kSp: res_reg = rs_rMIPS_SP; break;
94 case kArg0: res_reg = rs_rMIPS_ARG0; break;
95 case kArg1: res_reg = rs_rMIPS_ARG1; break;
96 case kArg2: res_reg = rs_rMIPS_ARG2; break;
97 case kArg3: res_reg = rs_rMIPS_ARG3; break;
98 case kFArg0: res_reg = rs_rMIPS_FARG0; break;
99 case kFArg1: res_reg = rs_rMIPS_FARG1; break;
100 case kFArg2: res_reg = rs_rMIPS_FARG2; break;
101 case kFArg3: res_reg = rs_rMIPS_FARG3; break;
102 case kRet0: res_reg = rs_rMIPS_RET0; break;
103 case kRet1: res_reg = rs_rMIPS_RET1; break;
104 case kInvokeTgt: res_reg = rs_rMIPS_INVOKE_TGT; break;
105 case kHiddenArg: res_reg = rs_rT0; break;
106 case kHiddenFpArg: res_reg = RegStorage::InvalidReg(); break;
107 case kCount: res_reg = rs_rMIPS_COUNT; break;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700108 }
buzbee091cc402014-03-31 10:14:40 -0700109 return res_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700110}
111
buzbee2700f7e2014-03-07 09:46:20 -0800112RegStorage MipsMir2Lir::GetArgMappingToPhysicalReg(int arg_num) {
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800113 // For the 32-bit internal ABI, the first 3 arguments are passed in registers.
114 switch (arg_num) {
115 case 0:
buzbee2700f7e2014-03-07 09:46:20 -0800116 return rs_rMIPS_ARG1;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800117 case 1:
buzbee2700f7e2014-03-07 09:46:20 -0800118 return rs_rMIPS_ARG2;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800119 case 2:
buzbee2700f7e2014-03-07 09:46:20 -0800120 return rs_rMIPS_ARG3;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800121 default:
buzbee2700f7e2014-03-07 09:46:20 -0800122 return RegStorage::InvalidReg();
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800123 }
124}
125
Brian Carlstrom7940e442013-07-12 13:46:57 -0700126/*
127 * Decode the register id.
128 */
buzbee091cc402014-03-31 10:14:40 -0700129uint64_t MipsMir2Lir::GetRegMaskCommon(RegStorage reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700130 uint64_t seed;
131 int shift;
buzbee091cc402014-03-31 10:14:40 -0700132 int reg_id = reg.GetRegNum();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700133 /* Each double register is equal to a pair of single-precision FP registers */
buzbee091cc402014-03-31 10:14:40 -0700134 if (reg.IsDouble()) {
135 seed = 0x3;
136 reg_id = reg_id << 1;
137 } else {
138 seed = 1;
139 }
140 /* FP register starts at bit position 32 */
141 shift = reg.IsFloat() ? kMipsFPReg0 : 0;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700142 /* Expand the double register id into single offset */
143 shift += reg_id;
144 return (seed << shift);
145}
146
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700147uint64_t MipsMir2Lir::GetPCUseDefEncoding() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700148 return ENCODE_MIPS_REG_PC;
149}
150
151
buzbeeb48819d2013-09-14 16:15:25 -0700152void MipsMir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700153 DCHECK_EQ(cu_->instruction_set, kMips);
buzbeeb48819d2013-09-14 16:15:25 -0700154 DCHECK(!lir->flags.use_def_invalid);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700155
156 // Mips-specific resource map setup here.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700157 if (flags & REG_DEF_SP) {
buzbeeb48819d2013-09-14 16:15:25 -0700158 lir->u.m.def_mask |= ENCODE_MIPS_REG_SP;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700159 }
160
161 if (flags & REG_USE_SP) {
buzbeeb48819d2013-09-14 16:15:25 -0700162 lir->u.m.use_mask |= ENCODE_MIPS_REG_SP;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700163 }
164
165 if (flags & REG_DEF_LR) {
buzbeeb48819d2013-09-14 16:15:25 -0700166 lir->u.m.def_mask |= ENCODE_MIPS_REG_LR;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700167 }
buzbee9da5c102014-03-28 12:59:18 -0700168
169 if (flags & REG_DEF_HI) {
170 lir->u.m.def_mask |= ENCODE_MIPS_REG_HI;
171 }
172
173 if (flags & REG_DEF_LO) {
174 lir->u.m.def_mask |= ENCODE_MIPS_REG_LO;
175 }
176
177 if (flags & REG_USE_HI) {
178 lir->u.m.use_mask |= ENCODE_MIPS_REG_HI;
179 }
180
181 if (flags & REG_USE_LO) {
182 lir->u.m.use_mask |= ENCODE_MIPS_REG_LO;
183 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700184}
185
186/* For dumping instructions */
187#define MIPS_REG_COUNT 32
188static const char *mips_reg_name[MIPS_REG_COUNT] = {
189 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
190 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
191 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
192 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
193};
194
195/*
196 * Interpret a format string and build a string no longer than size
197 * See format key in Assemble.c.
198 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700199std::string MipsMir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700200 std::string buf;
201 int i;
202 const char *fmt_end = &fmt[strlen(fmt)];
203 char tbuf[256];
204 char nc;
205 while (fmt < fmt_end) {
206 int operand;
207 if (*fmt == '!') {
208 fmt++;
209 DCHECK_LT(fmt, fmt_end);
210 nc = *fmt++;
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700211 if (nc == '!') {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700212 strcpy(tbuf, "!");
213 } else {
214 DCHECK_LT(fmt, fmt_end);
215 DCHECK_LT(static_cast<unsigned>(nc-'0'), 4u);
216 operand = lir->operands[nc-'0'];
217 switch (*fmt++) {
218 case 'b':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700219 strcpy(tbuf, "0000");
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700220 for (i = 3; i >= 0; i--) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700221 tbuf[i] += operand & 1;
222 operand >>= 1;
223 }
224 break;
225 case 's':
buzbee091cc402014-03-31 10:14:40 -0700226 snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700227 break;
228 case 'S':
buzbee091cc402014-03-31 10:14:40 -0700229 DCHECK_EQ(RegStorage::RegNum(operand) & 1, 0);
230 snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700231 break;
232 case 'h':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800233 snprintf(tbuf, arraysize(tbuf), "%04x", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700234 break;
235 case 'M':
236 case 'd':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800237 snprintf(tbuf, arraysize(tbuf), "%d", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700238 break;
239 case 'D':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800240 snprintf(tbuf, arraysize(tbuf), "%d", operand+1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700241 break;
242 case 'E':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800243 snprintf(tbuf, arraysize(tbuf), "%d", operand*4);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700244 break;
245 case 'F':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800246 snprintf(tbuf, arraysize(tbuf), "%d", operand*2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700247 break;
248 case 't':
Ian Rogers107c31e2014-01-23 20:55:29 -0800249 snprintf(tbuf, arraysize(tbuf), "0x%08" PRIxPTR " (L%p)",
250 reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 + (operand << 1),
251 lir->target);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700252 break;
253 case 'T':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800254 snprintf(tbuf, arraysize(tbuf), "0x%08x", operand << 2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700255 break;
256 case 'u': {
257 int offset_1 = lir->operands[0];
258 int offset_2 = NEXT_LIR(lir)->operands[0];
259 uintptr_t target =
260 (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) & ~3) +
261 (offset_1 << 21 >> 9) + (offset_2 << 1)) & 0xfffffffc;
Ian Rogers988e6ea2014-01-08 11:30:50 -0800262 snprintf(tbuf, arraysize(tbuf), "%p", reinterpret_cast<void*>(target));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700263 break;
264 }
265
266 /* Nothing to print for BLX_2 */
267 case 'v':
268 strcpy(tbuf, "see above");
269 break;
270 case 'r':
271 DCHECK(operand >= 0 && operand < MIPS_REG_COUNT);
272 strcpy(tbuf, mips_reg_name[operand]);
273 break;
274 case 'N':
275 // Placeholder for delay slot handling
276 strcpy(tbuf, "; nop");
277 break;
278 default:
Brian Carlstromb1eba212013-07-17 18:07:19 -0700279 strcpy(tbuf, "DecodeError");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700280 break;
281 }
282 buf += tbuf;
283 }
284 } else {
285 buf += *fmt++;
286 }
287 }
288 return buf;
289}
290
291// FIXME: need to redo resource maps for MIPS - fix this at that time
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700292void MipsMir2Lir::DumpResourceMask(LIR *mips_lir, uint64_t mask, const char *prefix) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700293 char buf[256];
294 buf[0] = 0;
295
296 if (mask == ENCODE_ALL) {
297 strcpy(buf, "all");
298 } else {
299 char num[8];
300 int i;
301
302 for (i = 0; i < kMipsRegEnd; i++) {
303 if (mask & (1ULL << i)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800304 snprintf(num, arraysize(num), "%d ", i);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700305 strcat(buf, num);
306 }
307 }
308
309 if (mask & ENCODE_CCODE) {
310 strcat(buf, "cc ");
311 }
312 if (mask & ENCODE_FP_STATUS) {
313 strcat(buf, "fpcc ");
314 }
315 /* Memory bits */
316 if (mips_lir && (mask & ENCODE_DALVIK_REG)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800317 snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s",
318 DECODE_ALIAS_INFO_REG(mips_lir->flags.alias_info),
319 DECODE_ALIAS_INFO_WIDE(mips_lir->flags.alias_info) ? "(+1)" : "");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700320 }
321 if (mask & ENCODE_LITERAL) {
322 strcat(buf, "lit ");
323 }
324
325 if (mask & ENCODE_HEAP_REF) {
326 strcat(buf, "heap ");
327 }
328 if (mask & ENCODE_MUST_NOT_ALIAS) {
329 strcat(buf, "noalias ");
330 }
331 }
332 if (buf[0]) {
333 LOG(INFO) << prefix << ": " << buf;
334 }
335}
336
337/*
338 * TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some
339 * instructions might call out to C/assembly helper functions. Until
340 * machinery is in place, always spill lr.
341 */
342
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700343void MipsMir2Lir::AdjustSpillMask() {
buzbee091cc402014-03-31 10:14:40 -0700344 core_spill_mask_ |= (1 << rs_rRA.GetRegNum());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700345 num_core_spills_++;
346}
347
348/*
349 * Mark a callee-save fp register as promoted. Note that
350 * vpush/vpop uses contiguous register lists so we must
351 * include any holes in the mask. Associate holes with
352 * Dalvik register INVALID_VREG (0xFFFFU).
353 */
buzbee091cc402014-03-31 10:14:40 -0700354void MipsMir2Lir::MarkPreservedSingle(int s_reg, RegStorage reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700355 LOG(FATAL) << "No support yet for promoted FP regs";
356}
357
buzbee091cc402014-03-31 10:14:40 -0700358void MipsMir2Lir::MarkPreservedDouble(int s_reg, RegStorage reg) {
359 LOG(FATAL) << "No support yet for promoted FP regs";
buzbee2700f7e2014-03-07 09:46:20 -0800360}
361
Brian Carlstrom7940e442013-07-12 13:46:57 -0700362/* Clobber all regs that might be used by an external C call */
Vladimir Marko31c2aac2013-12-09 16:31:19 +0000363void MipsMir2Lir::ClobberCallerSave() {
buzbee091cc402014-03-31 10:14:40 -0700364 Clobber(rs_rZERO);
365 Clobber(rs_rAT);
366 Clobber(rs_rV0);
367 Clobber(rs_rV1);
368 Clobber(rs_rA0);
369 Clobber(rs_rA1);
370 Clobber(rs_rA2);
371 Clobber(rs_rA3);
372 Clobber(rs_rT0);
373 Clobber(rs_rT1);
374 Clobber(rs_rT2);
375 Clobber(rs_rT3);
376 Clobber(rs_rT4);
377 Clobber(rs_rT5);
378 Clobber(rs_rT6);
379 Clobber(rs_rT7);
380 Clobber(rs_rT8);
381 Clobber(rs_rT9);
382 Clobber(rs_rK0);
383 Clobber(rs_rK1);
384 Clobber(rs_rGP);
385 Clobber(rs_rFP);
386 Clobber(rs_rRA);
387 Clobber(rs_rF0);
388 Clobber(rs_rF1);
389 Clobber(rs_rF2);
390 Clobber(rs_rF3);
391 Clobber(rs_rF4);
392 Clobber(rs_rF5);
393 Clobber(rs_rF6);
394 Clobber(rs_rF7);
395 Clobber(rs_rF8);
396 Clobber(rs_rF9);
397 Clobber(rs_rF10);
398 Clobber(rs_rF11);
399 Clobber(rs_rF12);
400 Clobber(rs_rF13);
401 Clobber(rs_rF14);
402 Clobber(rs_rF15);
403 Clobber(rs_rD0);
404 Clobber(rs_rD1);
405 Clobber(rs_rD2);
406 Clobber(rs_rD3);
407 Clobber(rs_rD4);
408 Clobber(rs_rD5);
409 Clobber(rs_rD6);
410 Clobber(rs_rD7);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700411}
412
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700413RegLocation MipsMir2Lir::GetReturnWideAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700414 UNIMPLEMENTED(FATAL) << "No GetReturnWideAlt for MIPS";
415 RegLocation res = LocCReturnWide();
416 return res;
417}
418
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700419RegLocation MipsMir2Lir::GetReturnAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700420 UNIMPLEMENTED(FATAL) << "No GetReturnAlt for MIPS";
421 RegLocation res = LocCReturn();
422 return res;
423}
424
Brian Carlstrom7940e442013-07-12 13:46:57 -0700425/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700426void MipsMir2Lir::LockCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700427 LockTemp(rs_rMIPS_ARG0);
428 LockTemp(rs_rMIPS_ARG1);
429 LockTemp(rs_rMIPS_ARG2);
430 LockTemp(rs_rMIPS_ARG3);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700431}
432
433/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700434void MipsMir2Lir::FreeCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700435 FreeTemp(rs_rMIPS_ARG0);
436 FreeTemp(rs_rMIPS_ARG1);
437 FreeTemp(rs_rMIPS_ARG2);
438 FreeTemp(rs_rMIPS_ARG3);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700439}
440
Andreas Gampeb14329f2014-05-15 11:16:06 -0700441bool MipsMir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700442#if ANDROID_SMP != 0
443 NewLIR1(kMipsSync, 0 /* Only stype currently supported */);
Andreas Gampeb14329f2014-05-15 11:16:06 -0700444 return true;
445#else
446 return false;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700447#endif
448}
449
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700450void MipsMir2Lir::CompilerInitializeRegAlloc() {
buzbeeb01bf152014-05-13 15:59:07 -0700451 reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs, empty_pool /* core64 */, sp_regs,
452 dp_regs, reserved_regs, empty_pool /* reserved64 */,
453 core_temps, empty_pool /* core64_temps */, sp_temps,
454 dp_temps);
buzbee091cc402014-03-31 10:14:40 -0700455
456 // Target-specific adjustments.
457
458 // Alias single precision floats to appropriate half of overlapping double.
459 GrowableArray<RegisterInfo*>::Iterator it(&reg_pool_->sp_regs_);
460 for (RegisterInfo* info = it.Next(); info != nullptr; info = it.Next()) {
461 int sp_reg_num = info->GetReg().GetRegNum();
462 int dp_reg_num = sp_reg_num >> 1;
463 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
464 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
465 // Double precision register's master storage should refer to itself.
466 DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
467 // Redirect single precision's master storage to master.
468 info->SetMaster(dp_reg_info);
469 // Singles should show a single 32-bit mask bit, at first referring to the low half.
470 DCHECK_EQ(info->StorageMask(), 0x1U);
471 if (sp_reg_num & 1) {
472 // For odd singles, change to user the high word of the backing double.
473 info->SetStorageMask(0x2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700474 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700475 }
buzbee091cc402014-03-31 10:14:40 -0700476
477 // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
478 // TODO: adjust when we roll to hard float calling convention.
479 reg_pool_->next_core_reg_ = 2;
480 reg_pool_->next_sp_reg_ = 2;
481 reg_pool_->next_dp_reg_ = 1;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700482}
483
Brian Carlstrom7940e442013-07-12 13:46:57 -0700484/*
485 * In the Arm code a it is typical to use the link register
486 * to hold the target address. However, for Mips we must
487 * ensure that all branch instructions can be restarted if
488 * there is a trap in the shadow. Allocate a temp register.
489 */
Ian Rogersdd7624d2014-03-14 17:43:00 -0700490RegStorage MipsMir2Lir::LoadHelper(ThreadOffset<4> offset) {
buzbee695d13a2014-04-19 13:32:20 -0700491 // NOTE: native pointer.
buzbee2700f7e2014-03-07 09:46:20 -0800492 LoadWordDisp(rs_rMIPS_SELF, offset.Int32Value(), rs_rT9);
493 return rs_rT9;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700494}
495
Andreas Gampe2f244e92014-05-08 03:35:25 -0700496RegStorage MipsMir2Lir::LoadHelper(ThreadOffset<8> offset) {
497 UNIMPLEMENTED(FATAL) << "Should not be called.";
498 return RegStorage::InvalidReg();
499}
500
Dave Allisonb373e092014-02-20 16:06:36 -0800501LIR* MipsMir2Lir::CheckSuspendUsingLoad() {
buzbee2700f7e2014-03-07 09:46:20 -0800502 RegStorage tmp = AllocTemp();
buzbee695d13a2014-04-19 13:32:20 -0700503 // NOTE: native pointer.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700504 LoadWordDisp(rs_rMIPS_SELF, Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
Dave Allisonb373e092014-02-20 16:06:36 -0800505 LIR *inst = LoadWordDisp(tmp, 0, tmp);
506 FreeTemp(tmp);
507 return inst;
508}
509
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700510void MipsMir2Lir::SpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700511 if (num_core_spills_ == 0) {
512 return;
513 }
514 uint32_t mask = core_spill_mask_;
515 int offset = num_core_spills_ * 4;
buzbee2700f7e2014-03-07 09:46:20 -0800516 OpRegImm(kOpSub, rs_rSP, offset);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700517 for (int reg = 0; mask; mask >>= 1, reg++) {
518 if (mask & 0x1) {
519 offset -= 4;
buzbee695d13a2014-04-19 13:32:20 -0700520 Store32Disp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700521 }
522 }
523}
524
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700525void MipsMir2Lir::UnSpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700526 if (num_core_spills_ == 0) {
527 return;
528 }
529 uint32_t mask = core_spill_mask_;
530 int offset = frame_size_;
531 for (int reg = 0; mask; mask >>= 1, reg++) {
532 if (mask & 0x1) {
533 offset -= 4;
buzbee695d13a2014-04-19 13:32:20 -0700534 Load32Disp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700535 }
536 }
buzbee2700f7e2014-03-07 09:46:20 -0800537 OpRegImm(kOpAdd, rs_rSP, frame_size_);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700538}
539
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700540bool MipsMir2Lir::IsUnconditionalBranch(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700541 return (lir->opcode == kMipsB);
542}
543
Vladimir Marko674744e2014-04-24 15:18:26 +0100544bool MipsMir2Lir::SupportsVolatileLoadStore(OpSize size) {
545 // No support for 64-bit atomic load/store on mips.
546 return size != k64 && size != kDouble;
547}
548
549RegisterClass MipsMir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) {
550 // No support for 64-bit atomic load/store on mips.
551 DCHECK(size != k64 && size != kDouble);
552 // TODO: Verify that both core and fp registers are suitable for smaller sizes.
553 return RegClassBySize(size);
554}
555
Brian Carlstrom7940e442013-07-12 13:46:57 -0700556MipsMir2Lir::MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
557 : Mir2Lir(cu, mir_graph, arena) {
558 for (int i = 0; i < kMipsLast; i++) {
559 if (MipsMir2Lir::EncodingMap[i].opcode != i) {
560 LOG(FATAL) << "Encoding order for " << MipsMir2Lir::EncodingMap[i].name
561 << " is wrong: expecting " << i << ", seeing "
562 << static_cast<int>(MipsMir2Lir::EncodingMap[i].opcode);
563 }
564 }
565}
566
567Mir2Lir* MipsCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
568 ArenaAllocator* const arena) {
569 return new MipsMir2Lir(cu, mir_graph, arena);
570}
571
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700572uint64_t MipsMir2Lir::GetTargetInstFlags(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700573 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700574 return MipsMir2Lir::EncodingMap[opcode].flags;
575}
576
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700577const char* MipsMir2Lir::GetTargetInstName(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700578 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700579 return MipsMir2Lir::EncodingMap[opcode].name;
580}
581
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700582const char* MipsMir2Lir::GetTargetInstFmt(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700583 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700584 return MipsMir2Lir::EncodingMap[opcode].fmt;
585}
586
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700587} // namespace art