blob: 381c7ce0aa818efc4fd82ba0be330992b3feb68b [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;
Dmitry Petrochenko58994cd2014-05-17 01:02:18 +0700101 default: res_reg = RegStorage::InvalidReg();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700102 }
buzbee091cc402014-03-31 10:14:40 -0700103 return res_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700104}
105
buzbee2700f7e2014-03-07 09:46:20 -0800106RegStorage MipsMir2Lir::GetArgMappingToPhysicalReg(int arg_num) {
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800107 // For the 32-bit internal ABI, the first 3 arguments are passed in registers.
108 switch (arg_num) {
109 case 0:
buzbee2700f7e2014-03-07 09:46:20 -0800110 return rs_rMIPS_ARG1;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800111 case 1:
buzbee2700f7e2014-03-07 09:46:20 -0800112 return rs_rMIPS_ARG2;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800113 case 2:
buzbee2700f7e2014-03-07 09:46:20 -0800114 return rs_rMIPS_ARG3;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800115 default:
buzbee2700f7e2014-03-07 09:46:20 -0800116 return RegStorage::InvalidReg();
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800117 }
118}
119
Brian Carlstrom7940e442013-07-12 13:46:57 -0700120/*
121 * Decode the register id.
122 */
buzbee091cc402014-03-31 10:14:40 -0700123uint64_t MipsMir2Lir::GetRegMaskCommon(RegStorage reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700124 uint64_t seed;
125 int shift;
buzbee091cc402014-03-31 10:14:40 -0700126 int reg_id = reg.GetRegNum();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700127 /* Each double register is equal to a pair of single-precision FP registers */
buzbee091cc402014-03-31 10:14:40 -0700128 if (reg.IsDouble()) {
129 seed = 0x3;
130 reg_id = reg_id << 1;
131 } else {
132 seed = 1;
133 }
134 /* FP register starts at bit position 32 */
135 shift = reg.IsFloat() ? kMipsFPReg0 : 0;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700136 /* Expand the double register id into single offset */
137 shift += reg_id;
138 return (seed << shift);
139}
140
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700141uint64_t MipsMir2Lir::GetPCUseDefEncoding() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700142 return ENCODE_MIPS_REG_PC;
143}
144
145
buzbeeb48819d2013-09-14 16:15:25 -0700146void MipsMir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700147 DCHECK_EQ(cu_->instruction_set, kMips);
buzbeeb48819d2013-09-14 16:15:25 -0700148 DCHECK(!lir->flags.use_def_invalid);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700149
150 // Mips-specific resource map setup here.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700151 if (flags & REG_DEF_SP) {
buzbeeb48819d2013-09-14 16:15:25 -0700152 lir->u.m.def_mask |= ENCODE_MIPS_REG_SP;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700153 }
154
155 if (flags & REG_USE_SP) {
buzbeeb48819d2013-09-14 16:15:25 -0700156 lir->u.m.use_mask |= ENCODE_MIPS_REG_SP;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700157 }
158
159 if (flags & REG_DEF_LR) {
buzbeeb48819d2013-09-14 16:15:25 -0700160 lir->u.m.def_mask |= ENCODE_MIPS_REG_LR;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700161 }
buzbee9da5c102014-03-28 12:59:18 -0700162
163 if (flags & REG_DEF_HI) {
164 lir->u.m.def_mask |= ENCODE_MIPS_REG_HI;
165 }
166
167 if (flags & REG_DEF_LO) {
168 lir->u.m.def_mask |= ENCODE_MIPS_REG_LO;
169 }
170
171 if (flags & REG_USE_HI) {
172 lir->u.m.use_mask |= ENCODE_MIPS_REG_HI;
173 }
174
175 if (flags & REG_USE_LO) {
176 lir->u.m.use_mask |= ENCODE_MIPS_REG_LO;
177 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700178}
179
180/* For dumping instructions */
181#define MIPS_REG_COUNT 32
182static const char *mips_reg_name[MIPS_REG_COUNT] = {
183 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
184 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
185 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
186 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
187};
188
189/*
190 * Interpret a format string and build a string no longer than size
191 * See format key in Assemble.c.
192 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700193std::string MipsMir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700194 std::string buf;
195 int i;
196 const char *fmt_end = &fmt[strlen(fmt)];
197 char tbuf[256];
198 char nc;
199 while (fmt < fmt_end) {
200 int operand;
201 if (*fmt == '!') {
202 fmt++;
203 DCHECK_LT(fmt, fmt_end);
204 nc = *fmt++;
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700205 if (nc == '!') {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700206 strcpy(tbuf, "!");
207 } else {
208 DCHECK_LT(fmt, fmt_end);
209 DCHECK_LT(static_cast<unsigned>(nc-'0'), 4u);
210 operand = lir->operands[nc-'0'];
211 switch (*fmt++) {
212 case 'b':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700213 strcpy(tbuf, "0000");
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700214 for (i = 3; i >= 0; i--) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700215 tbuf[i] += operand & 1;
216 operand >>= 1;
217 }
218 break;
219 case 's':
buzbee091cc402014-03-31 10:14:40 -0700220 snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700221 break;
222 case 'S':
buzbee091cc402014-03-31 10:14:40 -0700223 DCHECK_EQ(RegStorage::RegNum(operand) & 1, 0);
224 snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700225 break;
226 case 'h':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800227 snprintf(tbuf, arraysize(tbuf), "%04x", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700228 break;
229 case 'M':
230 case 'd':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800231 snprintf(tbuf, arraysize(tbuf), "%d", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700232 break;
233 case 'D':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800234 snprintf(tbuf, arraysize(tbuf), "%d", operand+1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700235 break;
236 case 'E':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800237 snprintf(tbuf, arraysize(tbuf), "%d", operand*4);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700238 break;
239 case 'F':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800240 snprintf(tbuf, arraysize(tbuf), "%d", operand*2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700241 break;
242 case 't':
Ian Rogers107c31e2014-01-23 20:55:29 -0800243 snprintf(tbuf, arraysize(tbuf), "0x%08" PRIxPTR " (L%p)",
244 reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 + (operand << 1),
245 lir->target);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700246 break;
247 case 'T':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800248 snprintf(tbuf, arraysize(tbuf), "0x%08x", operand << 2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700249 break;
250 case 'u': {
251 int offset_1 = lir->operands[0];
252 int offset_2 = NEXT_LIR(lir)->operands[0];
253 uintptr_t target =
254 (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) & ~3) +
255 (offset_1 << 21 >> 9) + (offset_2 << 1)) & 0xfffffffc;
Ian Rogers988e6ea2014-01-08 11:30:50 -0800256 snprintf(tbuf, arraysize(tbuf), "%p", reinterpret_cast<void*>(target));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700257 break;
258 }
259
260 /* Nothing to print for BLX_2 */
261 case 'v':
262 strcpy(tbuf, "see above");
263 break;
264 case 'r':
265 DCHECK(operand >= 0 && operand < MIPS_REG_COUNT);
266 strcpy(tbuf, mips_reg_name[operand]);
267 break;
268 case 'N':
269 // Placeholder for delay slot handling
270 strcpy(tbuf, "; nop");
271 break;
272 default:
Brian Carlstromb1eba212013-07-17 18:07:19 -0700273 strcpy(tbuf, "DecodeError");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700274 break;
275 }
276 buf += tbuf;
277 }
278 } else {
279 buf += *fmt++;
280 }
281 }
282 return buf;
283}
284
285// FIXME: need to redo resource maps for MIPS - fix this at that time
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700286void MipsMir2Lir::DumpResourceMask(LIR *mips_lir, uint64_t mask, const char *prefix) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700287 char buf[256];
288 buf[0] = 0;
289
290 if (mask == ENCODE_ALL) {
291 strcpy(buf, "all");
292 } else {
293 char num[8];
294 int i;
295
296 for (i = 0; i < kMipsRegEnd; i++) {
297 if (mask & (1ULL << i)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800298 snprintf(num, arraysize(num), "%d ", i);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700299 strcat(buf, num);
300 }
301 }
302
303 if (mask & ENCODE_CCODE) {
304 strcat(buf, "cc ");
305 }
306 if (mask & ENCODE_FP_STATUS) {
307 strcat(buf, "fpcc ");
308 }
309 /* Memory bits */
310 if (mips_lir && (mask & ENCODE_DALVIK_REG)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800311 snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s",
312 DECODE_ALIAS_INFO_REG(mips_lir->flags.alias_info),
313 DECODE_ALIAS_INFO_WIDE(mips_lir->flags.alias_info) ? "(+1)" : "");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700314 }
315 if (mask & ENCODE_LITERAL) {
316 strcat(buf, "lit ");
317 }
318
319 if (mask & ENCODE_HEAP_REF) {
320 strcat(buf, "heap ");
321 }
322 if (mask & ENCODE_MUST_NOT_ALIAS) {
323 strcat(buf, "noalias ");
324 }
325 }
326 if (buf[0]) {
327 LOG(INFO) << prefix << ": " << buf;
328 }
329}
330
331/*
332 * TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some
333 * instructions might call out to C/assembly helper functions. Until
334 * machinery is in place, always spill lr.
335 */
336
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700337void MipsMir2Lir::AdjustSpillMask() {
buzbee091cc402014-03-31 10:14:40 -0700338 core_spill_mask_ |= (1 << rs_rRA.GetRegNum());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700339 num_core_spills_++;
340}
341
342/*
343 * Mark a callee-save fp register as promoted. Note that
344 * vpush/vpop uses contiguous register lists so we must
345 * include any holes in the mask. Associate holes with
346 * Dalvik register INVALID_VREG (0xFFFFU).
347 */
buzbee091cc402014-03-31 10:14:40 -0700348void MipsMir2Lir::MarkPreservedSingle(int s_reg, RegStorage reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700349 LOG(FATAL) << "No support yet for promoted FP regs";
350}
351
buzbee091cc402014-03-31 10:14:40 -0700352void MipsMir2Lir::MarkPreservedDouble(int s_reg, RegStorage reg) {
353 LOG(FATAL) << "No support yet for promoted FP regs";
buzbee2700f7e2014-03-07 09:46:20 -0800354}
355
Brian Carlstrom7940e442013-07-12 13:46:57 -0700356/* Clobber all regs that might be used by an external C call */
Vladimir Marko31c2aac2013-12-09 16:31:19 +0000357void MipsMir2Lir::ClobberCallerSave() {
buzbee091cc402014-03-31 10:14:40 -0700358 Clobber(rs_rZERO);
359 Clobber(rs_rAT);
360 Clobber(rs_rV0);
361 Clobber(rs_rV1);
362 Clobber(rs_rA0);
363 Clobber(rs_rA1);
364 Clobber(rs_rA2);
365 Clobber(rs_rA3);
366 Clobber(rs_rT0);
367 Clobber(rs_rT1);
368 Clobber(rs_rT2);
369 Clobber(rs_rT3);
370 Clobber(rs_rT4);
371 Clobber(rs_rT5);
372 Clobber(rs_rT6);
373 Clobber(rs_rT7);
374 Clobber(rs_rT8);
375 Clobber(rs_rT9);
376 Clobber(rs_rK0);
377 Clobber(rs_rK1);
378 Clobber(rs_rGP);
379 Clobber(rs_rFP);
380 Clobber(rs_rRA);
381 Clobber(rs_rF0);
382 Clobber(rs_rF1);
383 Clobber(rs_rF2);
384 Clobber(rs_rF3);
385 Clobber(rs_rF4);
386 Clobber(rs_rF5);
387 Clobber(rs_rF6);
388 Clobber(rs_rF7);
389 Clobber(rs_rF8);
390 Clobber(rs_rF9);
391 Clobber(rs_rF10);
392 Clobber(rs_rF11);
393 Clobber(rs_rF12);
394 Clobber(rs_rF13);
395 Clobber(rs_rF14);
396 Clobber(rs_rF15);
397 Clobber(rs_rD0);
398 Clobber(rs_rD1);
399 Clobber(rs_rD2);
400 Clobber(rs_rD3);
401 Clobber(rs_rD4);
402 Clobber(rs_rD5);
403 Clobber(rs_rD6);
404 Clobber(rs_rD7);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700405}
406
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700407RegLocation MipsMir2Lir::GetReturnWideAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700408 UNIMPLEMENTED(FATAL) << "No GetReturnWideAlt for MIPS";
409 RegLocation res = LocCReturnWide();
410 return res;
411}
412
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700413RegLocation MipsMir2Lir::GetReturnAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700414 UNIMPLEMENTED(FATAL) << "No GetReturnAlt for MIPS";
415 RegLocation res = LocCReturn();
416 return res;
417}
418
Brian Carlstrom7940e442013-07-12 13:46:57 -0700419/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700420void MipsMir2Lir::LockCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700421 LockTemp(rs_rMIPS_ARG0);
422 LockTemp(rs_rMIPS_ARG1);
423 LockTemp(rs_rMIPS_ARG2);
424 LockTemp(rs_rMIPS_ARG3);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700425}
426
427/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700428void MipsMir2Lir::FreeCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700429 FreeTemp(rs_rMIPS_ARG0);
430 FreeTemp(rs_rMIPS_ARG1);
431 FreeTemp(rs_rMIPS_ARG2);
432 FreeTemp(rs_rMIPS_ARG3);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700433}
434
Andreas Gampeb14329f2014-05-15 11:16:06 -0700435bool MipsMir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700436#if ANDROID_SMP != 0
437 NewLIR1(kMipsSync, 0 /* Only stype currently supported */);
Andreas Gampeb14329f2014-05-15 11:16:06 -0700438 return true;
439#else
440 return false;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700441#endif
442}
443
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700444void MipsMir2Lir::CompilerInitializeRegAlloc() {
buzbeeb01bf152014-05-13 15:59:07 -0700445 reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs, empty_pool /* core64 */, sp_regs,
446 dp_regs, reserved_regs, empty_pool /* reserved64 */,
447 core_temps, empty_pool /* core64_temps */, sp_temps,
448 dp_temps);
buzbee091cc402014-03-31 10:14:40 -0700449
450 // Target-specific adjustments.
451
452 // Alias single precision floats to appropriate half of overlapping double.
453 GrowableArray<RegisterInfo*>::Iterator it(&reg_pool_->sp_regs_);
454 for (RegisterInfo* info = it.Next(); info != nullptr; info = it.Next()) {
455 int sp_reg_num = info->GetReg().GetRegNum();
456 int dp_reg_num = sp_reg_num >> 1;
457 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
458 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
459 // Double precision register's master storage should refer to itself.
460 DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
461 // Redirect single precision's master storage to master.
462 info->SetMaster(dp_reg_info);
463 // Singles should show a single 32-bit mask bit, at first referring to the low half.
464 DCHECK_EQ(info->StorageMask(), 0x1U);
465 if (sp_reg_num & 1) {
466 // For odd singles, change to user the high word of the backing double.
467 info->SetStorageMask(0x2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700468 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700469 }
buzbee091cc402014-03-31 10:14:40 -0700470
471 // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
472 // TODO: adjust when we roll to hard float calling convention.
473 reg_pool_->next_core_reg_ = 2;
474 reg_pool_->next_sp_reg_ = 2;
475 reg_pool_->next_dp_reg_ = 1;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700476}
477
Brian Carlstrom7940e442013-07-12 13:46:57 -0700478/*
479 * In the Arm code a it is typical to use the link register
480 * to hold the target address. However, for Mips we must
481 * ensure that all branch instructions can be restarted if
482 * there is a trap in the shadow. Allocate a temp register.
483 */
Ian Rogersdd7624d2014-03-14 17:43:00 -0700484RegStorage MipsMir2Lir::LoadHelper(ThreadOffset<4> offset) {
buzbee695d13a2014-04-19 13:32:20 -0700485 // NOTE: native pointer.
buzbee2700f7e2014-03-07 09:46:20 -0800486 LoadWordDisp(rs_rMIPS_SELF, offset.Int32Value(), rs_rT9);
487 return rs_rT9;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700488}
489
Andreas Gampe2f244e92014-05-08 03:35:25 -0700490RegStorage MipsMir2Lir::LoadHelper(ThreadOffset<8> offset) {
491 UNIMPLEMENTED(FATAL) << "Should not be called.";
492 return RegStorage::InvalidReg();
493}
494
Dave Allisonb373e092014-02-20 16:06:36 -0800495LIR* MipsMir2Lir::CheckSuspendUsingLoad() {
buzbee2700f7e2014-03-07 09:46:20 -0800496 RegStorage tmp = AllocTemp();
buzbee695d13a2014-04-19 13:32:20 -0700497 // NOTE: native pointer.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700498 LoadWordDisp(rs_rMIPS_SELF, Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
Dave Allisonb373e092014-02-20 16:06:36 -0800499 LIR *inst = LoadWordDisp(tmp, 0, tmp);
500 FreeTemp(tmp);
501 return inst;
502}
503
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700504void MipsMir2Lir::SpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700505 if (num_core_spills_ == 0) {
506 return;
507 }
508 uint32_t mask = core_spill_mask_;
509 int offset = num_core_spills_ * 4;
buzbee2700f7e2014-03-07 09:46:20 -0800510 OpRegImm(kOpSub, rs_rSP, offset);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700511 for (int reg = 0; mask; mask >>= 1, reg++) {
512 if (mask & 0x1) {
513 offset -= 4;
buzbee695d13a2014-04-19 13:32:20 -0700514 Store32Disp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700515 }
516 }
517}
518
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700519void MipsMir2Lir::UnSpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700520 if (num_core_spills_ == 0) {
521 return;
522 }
523 uint32_t mask = core_spill_mask_;
524 int offset = frame_size_;
525 for (int reg = 0; mask; mask >>= 1, reg++) {
526 if (mask & 0x1) {
527 offset -= 4;
buzbee695d13a2014-04-19 13:32:20 -0700528 Load32Disp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700529 }
530 }
buzbee2700f7e2014-03-07 09:46:20 -0800531 OpRegImm(kOpAdd, rs_rSP, frame_size_);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700532}
533
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700534bool MipsMir2Lir::IsUnconditionalBranch(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700535 return (lir->opcode == kMipsB);
536}
537
Vladimir Marko674744e2014-04-24 15:18:26 +0100538bool MipsMir2Lir::SupportsVolatileLoadStore(OpSize size) {
539 // No support for 64-bit atomic load/store on mips.
540 return size != k64 && size != kDouble;
541}
542
543RegisterClass MipsMir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) {
544 // No support for 64-bit atomic load/store on mips.
545 DCHECK(size != k64 && size != kDouble);
546 // TODO: Verify that both core and fp registers are suitable for smaller sizes.
547 return RegClassBySize(size);
548}
549
Brian Carlstrom7940e442013-07-12 13:46:57 -0700550MipsMir2Lir::MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
551 : Mir2Lir(cu, mir_graph, arena) {
552 for (int i = 0; i < kMipsLast; i++) {
553 if (MipsMir2Lir::EncodingMap[i].opcode != i) {
554 LOG(FATAL) << "Encoding order for " << MipsMir2Lir::EncodingMap[i].name
555 << " is wrong: expecting " << i << ", seeing "
556 << static_cast<int>(MipsMir2Lir::EncodingMap[i].opcode);
557 }
558 }
559}
560
561Mir2Lir* MipsCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
562 ArenaAllocator* const arena) {
563 return new MipsMir2Lir(cu, mir_graph, arena);
564}
565
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700566uint64_t MipsMir2Lir::GetTargetInstFlags(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700567 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700568 return MipsMir2Lir::EncodingMap[opcode].flags;
569}
570
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700571const char* MipsMir2Lir::GetTargetInstName(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700572 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700573 return MipsMir2Lir::EncodingMap[opcode].name;
574}
575
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700576const char* MipsMir2Lir::GetTargetInstFmt(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700577 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700578 return MipsMir2Lir::EncodingMap[opcode].fmt;
579}
580
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700581} // namespace art