blob: c1a7c990f0e8a78916b0e5940a8370858a975936 [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
Vladimir Marko089142c2014-06-05 10:57:05 +010029static constexpr RegStorage core_regs_arr[] =
buzbee091cc402014-03-31 10:14:40 -070030 {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};
Vladimir Marko089142c2014-06-05 10:57:05 +010033static constexpr RegStorage sp_regs_arr[] =
buzbee091cc402014-03-31 10:14:40 -070034 {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};
Vladimir Marko089142c2014-06-05 10:57:05 +010036static constexpr RegStorage dp_regs_arr[] =
buzbee091cc402014-03-31 10:14:40 -070037 {rs_rD0, rs_rD1, rs_rD2, rs_rD3, rs_rD4, rs_rD5, rs_rD6, rs_rD7};
Vladimir Marko089142c2014-06-05 10:57:05 +010038static constexpr RegStorage reserved_regs_arr[] =
buzbee091cc402014-03-31 10:14:40 -070039 {rs_rZERO, rs_rAT, rs_rS0, rs_rS1, rs_rK0, rs_rK1, rs_rGP, rs_rSP, rs_rRA};
Vladimir Marko089142c2014-06-05 10:57:05 +010040static constexpr RegStorage core_temps_arr[] =
buzbee091cc402014-03-31 10:14:40 -070041 {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};
Vladimir Marko089142c2014-06-05 10:57:05 +010043static constexpr RegStorage sp_temps_arr[] =
buzbee091cc402014-03-31 10:14:40 -070044 {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};
Vladimir Marko089142c2014-06-05 10:57:05 +010046static constexpr RegStorage dp_temps_arr[] =
buzbee091cc402014-03-31 10:14:40 -070047 {rs_rD0, rs_rD1, rs_rD2, rs_rD3, rs_rD4, rs_rD5, rs_rD6, rs_rD7};
48
Vladimir Marko089142c2014-06-05 10:57:05 +010049static constexpr ArrayRef<const RegStorage> empty_pool;
50static constexpr ArrayRef<const RegStorage> core_regs(core_regs_arr);
51static constexpr ArrayRef<const RegStorage> sp_regs(sp_regs_arr);
52static constexpr ArrayRef<const RegStorage> dp_regs(dp_regs_arr);
53static constexpr ArrayRef<const RegStorage> reserved_regs(reserved_regs_arr);
54static constexpr ArrayRef<const RegStorage> core_temps(core_temps_arr);
55static constexpr ArrayRef<const RegStorage> sp_temps(sp_temps_arr);
56static constexpr ArrayRef<const RegStorage> dp_temps(dp_temps_arr);
Brian Carlstrom7940e442013-07-12 13:46:57 -070057
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070058RegLocation MipsMir2Lir::LocCReturn() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000059 return mips_loc_c_return;
Brian Carlstrom7940e442013-07-12 13:46:57 -070060}
61
buzbeea0cd2d72014-06-01 09:33:49 -070062RegLocation MipsMir2Lir::LocCReturnRef() {
63 return mips_loc_c_return;
64}
65
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070066RegLocation MipsMir2Lir::LocCReturnWide() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000067 return mips_loc_c_return_wide;
Brian Carlstrom7940e442013-07-12 13:46:57 -070068}
69
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070070RegLocation MipsMir2Lir::LocCReturnFloat() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000071 return mips_loc_c_return_float;
Brian Carlstrom7940e442013-07-12 13:46:57 -070072}
73
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070074RegLocation MipsMir2Lir::LocCReturnDouble() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +000075 return mips_loc_c_return_double;
Brian Carlstrom7940e442013-07-12 13:46:57 -070076}
77
78// Return a target-dependent special register.
buzbee2700f7e2014-03-07 09:46:20 -080079RegStorage MipsMir2Lir::TargetReg(SpecialTargetRegister reg) {
buzbee091cc402014-03-31 10:14:40 -070080 RegStorage res_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -070081 switch (reg) {
buzbee091cc402014-03-31 10:14:40 -070082 case kSelf: res_reg = rs_rMIPS_SELF; break;
83 case kSuspend: res_reg = rs_rMIPS_SUSPEND; break;
84 case kLr: res_reg = rs_rMIPS_LR; break;
85 case kPc: res_reg = rs_rMIPS_PC; break;
86 case kSp: res_reg = rs_rMIPS_SP; break;
87 case kArg0: res_reg = rs_rMIPS_ARG0; break;
88 case kArg1: res_reg = rs_rMIPS_ARG1; break;
89 case kArg2: res_reg = rs_rMIPS_ARG2; break;
90 case kArg3: res_reg = rs_rMIPS_ARG3; break;
91 case kFArg0: res_reg = rs_rMIPS_FARG0; break;
92 case kFArg1: res_reg = rs_rMIPS_FARG1; break;
93 case kFArg2: res_reg = rs_rMIPS_FARG2; break;
94 case kFArg3: res_reg = rs_rMIPS_FARG3; break;
95 case kRet0: res_reg = rs_rMIPS_RET0; break;
96 case kRet1: res_reg = rs_rMIPS_RET1; break;
97 case kInvokeTgt: res_reg = rs_rMIPS_INVOKE_TGT; break;
98 case kHiddenArg: res_reg = rs_rT0; break;
99 case kHiddenFpArg: res_reg = RegStorage::InvalidReg(); break;
100 case kCount: res_reg = rs_rMIPS_COUNT; break;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700101 }
buzbee091cc402014-03-31 10:14:40 -0700102 return res_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700103}
104
buzbee2700f7e2014-03-07 09:46:20 -0800105RegStorage MipsMir2Lir::GetArgMappingToPhysicalReg(int arg_num) {
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800106 // For the 32-bit internal ABI, the first 3 arguments are passed in registers.
107 switch (arg_num) {
108 case 0:
buzbee2700f7e2014-03-07 09:46:20 -0800109 return rs_rMIPS_ARG1;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800110 case 1:
buzbee2700f7e2014-03-07 09:46:20 -0800111 return rs_rMIPS_ARG2;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800112 case 2:
buzbee2700f7e2014-03-07 09:46:20 -0800113 return rs_rMIPS_ARG3;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800114 default:
buzbee2700f7e2014-03-07 09:46:20 -0800115 return RegStorage::InvalidReg();
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800116 }
117}
118
Brian Carlstrom7940e442013-07-12 13:46:57 -0700119/*
120 * Decode the register id.
121 */
buzbee091cc402014-03-31 10:14:40 -0700122uint64_t MipsMir2Lir::GetRegMaskCommon(RegStorage reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700123 uint64_t seed;
124 int shift;
buzbee091cc402014-03-31 10:14:40 -0700125 int reg_id = reg.GetRegNum();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700126 /* Each double register is equal to a pair of single-precision FP registers */
buzbee091cc402014-03-31 10:14:40 -0700127 if (reg.IsDouble()) {
128 seed = 0x3;
129 reg_id = reg_id << 1;
130 } else {
131 seed = 1;
132 }
133 /* FP register starts at bit position 32 */
134 shift = reg.IsFloat() ? kMipsFPReg0 : 0;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700135 /* Expand the double register id into single offset */
136 shift += reg_id;
137 return (seed << shift);
138}
139
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700140uint64_t MipsMir2Lir::GetPCUseDefEncoding() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700141 return ENCODE_MIPS_REG_PC;
142}
143
144
buzbeeb48819d2013-09-14 16:15:25 -0700145void MipsMir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700146 DCHECK_EQ(cu_->instruction_set, kMips);
buzbeeb48819d2013-09-14 16:15:25 -0700147 DCHECK(!lir->flags.use_def_invalid);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700148
149 // Mips-specific resource map setup here.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700150 if (flags & REG_DEF_SP) {
buzbeeb48819d2013-09-14 16:15:25 -0700151 lir->u.m.def_mask |= ENCODE_MIPS_REG_SP;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700152 }
153
154 if (flags & REG_USE_SP) {
buzbeeb48819d2013-09-14 16:15:25 -0700155 lir->u.m.use_mask |= ENCODE_MIPS_REG_SP;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700156 }
157
158 if (flags & REG_DEF_LR) {
buzbeeb48819d2013-09-14 16:15:25 -0700159 lir->u.m.def_mask |= ENCODE_MIPS_REG_LR;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700160 }
buzbee9da5c102014-03-28 12:59:18 -0700161
162 if (flags & REG_DEF_HI) {
163 lir->u.m.def_mask |= ENCODE_MIPS_REG_HI;
164 }
165
166 if (flags & REG_DEF_LO) {
167 lir->u.m.def_mask |= ENCODE_MIPS_REG_LO;
168 }
169
170 if (flags & REG_USE_HI) {
171 lir->u.m.use_mask |= ENCODE_MIPS_REG_HI;
172 }
173
174 if (flags & REG_USE_LO) {
175 lir->u.m.use_mask |= ENCODE_MIPS_REG_LO;
176 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700177}
178
179/* For dumping instructions */
180#define MIPS_REG_COUNT 32
181static const char *mips_reg_name[MIPS_REG_COUNT] = {
182 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
183 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
184 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
185 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
186};
187
188/*
189 * Interpret a format string and build a string no longer than size
190 * See format key in Assemble.c.
191 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700192std::string MipsMir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700193 std::string buf;
194 int i;
195 const char *fmt_end = &fmt[strlen(fmt)];
196 char tbuf[256];
197 char nc;
198 while (fmt < fmt_end) {
199 int operand;
200 if (*fmt == '!') {
201 fmt++;
202 DCHECK_LT(fmt, fmt_end);
203 nc = *fmt++;
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700204 if (nc == '!') {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700205 strcpy(tbuf, "!");
206 } else {
207 DCHECK_LT(fmt, fmt_end);
208 DCHECK_LT(static_cast<unsigned>(nc-'0'), 4u);
209 operand = lir->operands[nc-'0'];
210 switch (*fmt++) {
211 case 'b':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700212 strcpy(tbuf, "0000");
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700213 for (i = 3; i >= 0; i--) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700214 tbuf[i] += operand & 1;
215 operand >>= 1;
216 }
217 break;
218 case 's':
buzbee091cc402014-03-31 10:14:40 -0700219 snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700220 break;
221 case 'S':
buzbee091cc402014-03-31 10:14:40 -0700222 DCHECK_EQ(RegStorage::RegNum(operand) & 1, 0);
223 snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700224 break;
225 case 'h':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800226 snprintf(tbuf, arraysize(tbuf), "%04x", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700227 break;
228 case 'M':
229 case 'd':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800230 snprintf(tbuf, arraysize(tbuf), "%d", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700231 break;
232 case 'D':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800233 snprintf(tbuf, arraysize(tbuf), "%d", operand+1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700234 break;
235 case 'E':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800236 snprintf(tbuf, arraysize(tbuf), "%d", operand*4);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700237 break;
238 case 'F':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800239 snprintf(tbuf, arraysize(tbuf), "%d", operand*2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700240 break;
241 case 't':
Ian Rogers107c31e2014-01-23 20:55:29 -0800242 snprintf(tbuf, arraysize(tbuf), "0x%08" PRIxPTR " (L%p)",
243 reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 + (operand << 1),
244 lir->target);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700245 break;
246 case 'T':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800247 snprintf(tbuf, arraysize(tbuf), "0x%08x", operand << 2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700248 break;
249 case 'u': {
250 int offset_1 = lir->operands[0];
251 int offset_2 = NEXT_LIR(lir)->operands[0];
252 uintptr_t target =
253 (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) & ~3) +
254 (offset_1 << 21 >> 9) + (offset_2 << 1)) & 0xfffffffc;
Ian Rogers988e6ea2014-01-08 11:30:50 -0800255 snprintf(tbuf, arraysize(tbuf), "%p", reinterpret_cast<void*>(target));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700256 break;
257 }
258
259 /* Nothing to print for BLX_2 */
260 case 'v':
261 strcpy(tbuf, "see above");
262 break;
263 case 'r':
264 DCHECK(operand >= 0 && operand < MIPS_REG_COUNT);
265 strcpy(tbuf, mips_reg_name[operand]);
266 break;
267 case 'N':
268 // Placeholder for delay slot handling
269 strcpy(tbuf, "; nop");
270 break;
271 default:
Brian Carlstromb1eba212013-07-17 18:07:19 -0700272 strcpy(tbuf, "DecodeError");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700273 break;
274 }
275 buf += tbuf;
276 }
277 } else {
278 buf += *fmt++;
279 }
280 }
281 return buf;
282}
283
284// FIXME: need to redo resource maps for MIPS - fix this at that time
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700285void MipsMir2Lir::DumpResourceMask(LIR *mips_lir, uint64_t mask, const char *prefix) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700286 char buf[256];
287 buf[0] = 0;
288
289 if (mask == ENCODE_ALL) {
290 strcpy(buf, "all");
291 } else {
292 char num[8];
293 int i;
294
295 for (i = 0; i < kMipsRegEnd; i++) {
296 if (mask & (1ULL << i)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800297 snprintf(num, arraysize(num), "%d ", i);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700298 strcat(buf, num);
299 }
300 }
301
302 if (mask & ENCODE_CCODE) {
303 strcat(buf, "cc ");
304 }
305 if (mask & ENCODE_FP_STATUS) {
306 strcat(buf, "fpcc ");
307 }
308 /* Memory bits */
309 if (mips_lir && (mask & ENCODE_DALVIK_REG)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800310 snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s",
311 DECODE_ALIAS_INFO_REG(mips_lir->flags.alias_info),
312 DECODE_ALIAS_INFO_WIDE(mips_lir->flags.alias_info) ? "(+1)" : "");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700313 }
314 if (mask & ENCODE_LITERAL) {
315 strcat(buf, "lit ");
316 }
317
318 if (mask & ENCODE_HEAP_REF) {
319 strcat(buf, "heap ");
320 }
321 if (mask & ENCODE_MUST_NOT_ALIAS) {
322 strcat(buf, "noalias ");
323 }
324 }
325 if (buf[0]) {
326 LOG(INFO) << prefix << ": " << buf;
327 }
328}
329
330/*
331 * TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some
332 * instructions might call out to C/assembly helper functions. Until
333 * machinery is in place, always spill lr.
334 */
335
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700336void MipsMir2Lir::AdjustSpillMask() {
buzbee091cc402014-03-31 10:14:40 -0700337 core_spill_mask_ |= (1 << rs_rRA.GetRegNum());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700338 num_core_spills_++;
339}
340
341/*
342 * Mark a callee-save fp register as promoted. Note that
343 * vpush/vpop uses contiguous register lists so we must
344 * include any holes in the mask. Associate holes with
345 * Dalvik register INVALID_VREG (0xFFFFU).
346 */
buzbee091cc402014-03-31 10:14:40 -0700347void MipsMir2Lir::MarkPreservedSingle(int s_reg, RegStorage reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700348 LOG(FATAL) << "No support yet for promoted FP regs";
349}
350
buzbee091cc402014-03-31 10:14:40 -0700351void MipsMir2Lir::MarkPreservedDouble(int s_reg, RegStorage reg) {
352 LOG(FATAL) << "No support yet for promoted FP regs";
buzbee2700f7e2014-03-07 09:46:20 -0800353}
354
Brian Carlstrom7940e442013-07-12 13:46:57 -0700355/* Clobber all regs that might be used by an external C call */
Vladimir Marko31c2aac2013-12-09 16:31:19 +0000356void MipsMir2Lir::ClobberCallerSave() {
buzbee091cc402014-03-31 10:14:40 -0700357 Clobber(rs_rZERO);
358 Clobber(rs_rAT);
359 Clobber(rs_rV0);
360 Clobber(rs_rV1);
361 Clobber(rs_rA0);
362 Clobber(rs_rA1);
363 Clobber(rs_rA2);
364 Clobber(rs_rA3);
365 Clobber(rs_rT0);
366 Clobber(rs_rT1);
367 Clobber(rs_rT2);
368 Clobber(rs_rT3);
369 Clobber(rs_rT4);
370 Clobber(rs_rT5);
371 Clobber(rs_rT6);
372 Clobber(rs_rT7);
373 Clobber(rs_rT8);
374 Clobber(rs_rT9);
375 Clobber(rs_rK0);
376 Clobber(rs_rK1);
377 Clobber(rs_rGP);
378 Clobber(rs_rFP);
379 Clobber(rs_rRA);
380 Clobber(rs_rF0);
381 Clobber(rs_rF1);
382 Clobber(rs_rF2);
383 Clobber(rs_rF3);
384 Clobber(rs_rF4);
385 Clobber(rs_rF5);
386 Clobber(rs_rF6);
387 Clobber(rs_rF7);
388 Clobber(rs_rF8);
389 Clobber(rs_rF9);
390 Clobber(rs_rF10);
391 Clobber(rs_rF11);
392 Clobber(rs_rF12);
393 Clobber(rs_rF13);
394 Clobber(rs_rF14);
395 Clobber(rs_rF15);
396 Clobber(rs_rD0);
397 Clobber(rs_rD1);
398 Clobber(rs_rD2);
399 Clobber(rs_rD3);
400 Clobber(rs_rD4);
401 Clobber(rs_rD5);
402 Clobber(rs_rD6);
403 Clobber(rs_rD7);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700404}
405
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700406RegLocation MipsMir2Lir::GetReturnWideAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700407 UNIMPLEMENTED(FATAL) << "No GetReturnWideAlt for MIPS";
408 RegLocation res = LocCReturnWide();
409 return res;
410}
411
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700412RegLocation MipsMir2Lir::GetReturnAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700413 UNIMPLEMENTED(FATAL) << "No GetReturnAlt for MIPS";
414 RegLocation res = LocCReturn();
415 return res;
416}
417
Brian Carlstrom7940e442013-07-12 13:46:57 -0700418/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700419void MipsMir2Lir::LockCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700420 LockTemp(rs_rMIPS_ARG0);
421 LockTemp(rs_rMIPS_ARG1);
422 LockTemp(rs_rMIPS_ARG2);
423 LockTemp(rs_rMIPS_ARG3);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700424}
425
426/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700427void MipsMir2Lir::FreeCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700428 FreeTemp(rs_rMIPS_ARG0);
429 FreeTemp(rs_rMIPS_ARG1);
430 FreeTemp(rs_rMIPS_ARG2);
431 FreeTemp(rs_rMIPS_ARG3);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700432}
433
Andreas Gampeb14329f2014-05-15 11:16:06 -0700434bool MipsMir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700435#if ANDROID_SMP != 0
436 NewLIR1(kMipsSync, 0 /* Only stype currently supported */);
Andreas Gampeb14329f2014-05-15 11:16:06 -0700437 return true;
438#else
439 return false;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700440#endif
441}
442
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700443void MipsMir2Lir::CompilerInitializeRegAlloc() {
buzbeeb01bf152014-05-13 15:59:07 -0700444 reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs, empty_pool /* core64 */, sp_regs,
445 dp_regs, reserved_regs, empty_pool /* reserved64 */,
446 core_temps, empty_pool /* core64_temps */, sp_temps,
447 dp_temps);
buzbee091cc402014-03-31 10:14:40 -0700448
449 // Target-specific adjustments.
450
451 // Alias single precision floats to appropriate half of overlapping double.
452 GrowableArray<RegisterInfo*>::Iterator it(&reg_pool_->sp_regs_);
453 for (RegisterInfo* info = it.Next(); info != nullptr; info = it.Next()) {
454 int sp_reg_num = info->GetReg().GetRegNum();
455 int dp_reg_num = sp_reg_num >> 1;
456 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
457 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
458 // Double precision register's master storage should refer to itself.
459 DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
460 // Redirect single precision's master storage to master.
461 info->SetMaster(dp_reg_info);
462 // Singles should show a single 32-bit mask bit, at first referring to the low half.
463 DCHECK_EQ(info->StorageMask(), 0x1U);
464 if (sp_reg_num & 1) {
465 // For odd singles, change to user the high word of the backing double.
466 info->SetStorageMask(0x2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700467 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700468 }
buzbee091cc402014-03-31 10:14:40 -0700469
470 // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
471 // TODO: adjust when we roll to hard float calling convention.
472 reg_pool_->next_core_reg_ = 2;
473 reg_pool_->next_sp_reg_ = 2;
474 reg_pool_->next_dp_reg_ = 1;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700475}
476
Brian Carlstrom7940e442013-07-12 13:46:57 -0700477/*
478 * In the Arm code a it is typical to use the link register
479 * to hold the target address. However, for Mips we must
480 * ensure that all branch instructions can be restarted if
481 * there is a trap in the shadow. Allocate a temp register.
482 */
Ian Rogersdd7624d2014-03-14 17:43:00 -0700483RegStorage MipsMir2Lir::LoadHelper(ThreadOffset<4> offset) {
buzbee695d13a2014-04-19 13:32:20 -0700484 // NOTE: native pointer.
buzbee2700f7e2014-03-07 09:46:20 -0800485 LoadWordDisp(rs_rMIPS_SELF, offset.Int32Value(), rs_rT9);
486 return rs_rT9;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700487}
488
Andreas Gampe2f244e92014-05-08 03:35:25 -0700489RegStorage MipsMir2Lir::LoadHelper(ThreadOffset<8> offset) {
490 UNIMPLEMENTED(FATAL) << "Should not be called.";
491 return RegStorage::InvalidReg();
492}
493
Dave Allisonb373e092014-02-20 16:06:36 -0800494LIR* MipsMir2Lir::CheckSuspendUsingLoad() {
buzbee2700f7e2014-03-07 09:46:20 -0800495 RegStorage tmp = AllocTemp();
buzbee695d13a2014-04-19 13:32:20 -0700496 // NOTE: native pointer.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700497 LoadWordDisp(rs_rMIPS_SELF, Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
Dave Allisonb373e092014-02-20 16:06:36 -0800498 LIR *inst = LoadWordDisp(tmp, 0, tmp);
499 FreeTemp(tmp);
500 return inst;
501}
502
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700503void MipsMir2Lir::SpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700504 if (num_core_spills_ == 0) {
505 return;
506 }
507 uint32_t mask = core_spill_mask_;
508 int offset = num_core_spills_ * 4;
buzbee2700f7e2014-03-07 09:46:20 -0800509 OpRegImm(kOpSub, rs_rSP, offset);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700510 for (int reg = 0; mask; mask >>= 1, reg++) {
511 if (mask & 0x1) {
512 offset -= 4;
buzbee695d13a2014-04-19 13:32:20 -0700513 Store32Disp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700514 }
515 }
516}
517
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700518void MipsMir2Lir::UnSpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700519 if (num_core_spills_ == 0) {
520 return;
521 }
522 uint32_t mask = core_spill_mask_;
523 int offset = frame_size_;
524 for (int reg = 0; mask; mask >>= 1, reg++) {
525 if (mask & 0x1) {
526 offset -= 4;
buzbee695d13a2014-04-19 13:32:20 -0700527 Load32Disp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700528 }
529 }
buzbee2700f7e2014-03-07 09:46:20 -0800530 OpRegImm(kOpAdd, rs_rSP, frame_size_);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700531}
532
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700533bool MipsMir2Lir::IsUnconditionalBranch(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700534 return (lir->opcode == kMipsB);
535}
536
Vladimir Marko674744e2014-04-24 15:18:26 +0100537bool MipsMir2Lir::SupportsVolatileLoadStore(OpSize size) {
538 // No support for 64-bit atomic load/store on mips.
539 return size != k64 && size != kDouble;
540}
541
542RegisterClass MipsMir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) {
543 // No support for 64-bit atomic load/store on mips.
544 DCHECK(size != k64 && size != kDouble);
545 // TODO: Verify that both core and fp registers are suitable for smaller sizes.
546 return RegClassBySize(size);
547}
548
Brian Carlstrom7940e442013-07-12 13:46:57 -0700549MipsMir2Lir::MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
550 : Mir2Lir(cu, mir_graph, arena) {
551 for (int i = 0; i < kMipsLast; i++) {
552 if (MipsMir2Lir::EncodingMap[i].opcode != i) {
553 LOG(FATAL) << "Encoding order for " << MipsMir2Lir::EncodingMap[i].name
554 << " is wrong: expecting " << i << ", seeing "
555 << static_cast<int>(MipsMir2Lir::EncodingMap[i].opcode);
556 }
557 }
558}
559
560Mir2Lir* MipsCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
561 ArenaAllocator* const arena) {
562 return new MipsMir2Lir(cu, mir_graph, arena);
563}
564
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700565uint64_t MipsMir2Lir::GetTargetInstFlags(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700566 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700567 return MipsMir2Lir::EncodingMap[opcode].flags;
568}
569
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700570const char* MipsMir2Lir::GetTargetInstName(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700571 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700572 return MipsMir2Lir::EncodingMap[opcode].name;
573}
574
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700575const char* MipsMir2Lir::GetTargetInstFmt(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700576 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700577 return MipsMir2Lir::EncodingMap[opcode].fmt;
578}
579
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700580} // namespace art