blob: 76b5243a1289f2712a1da84427fb96bc5e895a4e [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 */
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100123ResourceMask MipsMir2Lir::GetRegMaskCommon(const RegStorage& reg) const {
124 return reg.IsDouble()
125 /* Each double register is equal to a pair of single-precision FP registers */
126 ? ResourceMask::TwoBits(reg.GetRegNum() * 2 + kMipsFPReg0)
127 : ResourceMask::Bit(reg.IsSingle() ? reg.GetRegNum() + kMipsFPReg0 : reg.GetRegNum());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700128}
129
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100130ResourceMask MipsMir2Lir::GetPCUseDefEncoding() const {
131 return ResourceMask::Bit(kMipsRegPC);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700132}
133
134
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100135void MipsMir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags,
136 ResourceMask* use_mask, ResourceMask* def_mask) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700137 DCHECK_EQ(cu_->instruction_set, kMips);
buzbeeb48819d2013-09-14 16:15:25 -0700138 DCHECK(!lir->flags.use_def_invalid);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700139
140 // Mips-specific resource map setup here.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700141 if (flags & REG_DEF_SP) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100142 def_mask->SetBit(kMipsRegSP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700143 }
144
145 if (flags & REG_USE_SP) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100146 use_mask->SetBit(kMipsRegSP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700147 }
148
149 if (flags & REG_DEF_LR) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100150 def_mask->SetBit(kMipsRegLR);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700151 }
buzbee9da5c102014-03-28 12:59:18 -0700152
153 if (flags & REG_DEF_HI) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100154 def_mask->SetBit(kMipsRegHI);
buzbee9da5c102014-03-28 12:59:18 -0700155 }
156
157 if (flags & REG_DEF_LO) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100158 def_mask->SetBit(kMipsRegLO);
buzbee9da5c102014-03-28 12:59:18 -0700159 }
160
161 if (flags & REG_USE_HI) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100162 use_mask->SetBit(kMipsRegHI);
buzbee9da5c102014-03-28 12:59:18 -0700163 }
164
165 if (flags & REG_USE_LO) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100166 use_mask->SetBit(kMipsRegLO);
buzbee9da5c102014-03-28 12:59:18 -0700167 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700168}
169
170/* For dumping instructions */
171#define MIPS_REG_COUNT 32
172static const char *mips_reg_name[MIPS_REG_COUNT] = {
173 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
174 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
175 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
176 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
177};
178
179/*
180 * Interpret a format string and build a string no longer than size
181 * See format key in Assemble.c.
182 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700183std::string MipsMir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700184 std::string buf;
185 int i;
186 const char *fmt_end = &fmt[strlen(fmt)];
187 char tbuf[256];
188 char nc;
189 while (fmt < fmt_end) {
190 int operand;
191 if (*fmt == '!') {
192 fmt++;
193 DCHECK_LT(fmt, fmt_end);
194 nc = *fmt++;
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700195 if (nc == '!') {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700196 strcpy(tbuf, "!");
197 } else {
198 DCHECK_LT(fmt, fmt_end);
199 DCHECK_LT(static_cast<unsigned>(nc-'0'), 4u);
200 operand = lir->operands[nc-'0'];
201 switch (*fmt++) {
202 case 'b':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700203 strcpy(tbuf, "0000");
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700204 for (i = 3; i >= 0; i--) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700205 tbuf[i] += operand & 1;
206 operand >>= 1;
207 }
208 break;
209 case 's':
buzbee091cc402014-03-31 10:14:40 -0700210 snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700211 break;
212 case 'S':
buzbee091cc402014-03-31 10:14:40 -0700213 DCHECK_EQ(RegStorage::RegNum(operand) & 1, 0);
214 snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700215 break;
216 case 'h':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800217 snprintf(tbuf, arraysize(tbuf), "%04x", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700218 break;
219 case 'M':
220 case 'd':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800221 snprintf(tbuf, arraysize(tbuf), "%d", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700222 break;
223 case 'D':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800224 snprintf(tbuf, arraysize(tbuf), "%d", operand+1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700225 break;
226 case 'E':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800227 snprintf(tbuf, arraysize(tbuf), "%d", operand*4);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700228 break;
229 case 'F':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800230 snprintf(tbuf, arraysize(tbuf), "%d", operand*2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700231 break;
232 case 't':
Ian Rogers107c31e2014-01-23 20:55:29 -0800233 snprintf(tbuf, arraysize(tbuf), "0x%08" PRIxPTR " (L%p)",
234 reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 + (operand << 1),
235 lir->target);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700236 break;
237 case 'T':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800238 snprintf(tbuf, arraysize(tbuf), "0x%08x", operand << 2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700239 break;
240 case 'u': {
241 int offset_1 = lir->operands[0];
242 int offset_2 = NEXT_LIR(lir)->operands[0];
243 uintptr_t target =
244 (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) & ~3) +
245 (offset_1 << 21 >> 9) + (offset_2 << 1)) & 0xfffffffc;
Ian Rogers988e6ea2014-01-08 11:30:50 -0800246 snprintf(tbuf, arraysize(tbuf), "%p", reinterpret_cast<void*>(target));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700247 break;
248 }
249
250 /* Nothing to print for BLX_2 */
251 case 'v':
252 strcpy(tbuf, "see above");
253 break;
254 case 'r':
255 DCHECK(operand >= 0 && operand < MIPS_REG_COUNT);
256 strcpy(tbuf, mips_reg_name[operand]);
257 break;
258 case 'N':
259 // Placeholder for delay slot handling
260 strcpy(tbuf, "; nop");
261 break;
262 default:
Brian Carlstromb1eba212013-07-17 18:07:19 -0700263 strcpy(tbuf, "DecodeError");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700264 break;
265 }
266 buf += tbuf;
267 }
268 } else {
269 buf += *fmt++;
270 }
271 }
272 return buf;
273}
274
275// FIXME: need to redo resource maps for MIPS - fix this at that time
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100276void MipsMir2Lir::DumpResourceMask(LIR *mips_lir, const ResourceMask& mask, const char *prefix) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700277 char buf[256];
278 buf[0] = 0;
279
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100280 if (mask.Equals(kEncodeAll)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700281 strcpy(buf, "all");
282 } else {
283 char num[8];
284 int i;
285
286 for (i = 0; i < kMipsRegEnd; i++) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100287 if (mask.HasBit(i)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800288 snprintf(num, arraysize(num), "%d ", i);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700289 strcat(buf, num);
290 }
291 }
292
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100293 if (mask.HasBit(ResourceMask::kCCode)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700294 strcat(buf, "cc ");
295 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100296 if (mask.HasBit(ResourceMask::kFPStatus)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700297 strcat(buf, "fpcc ");
298 }
299 /* Memory bits */
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100300 if (mips_lir && (mask.HasBit(ResourceMask::kDalvikReg))) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800301 snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s",
302 DECODE_ALIAS_INFO_REG(mips_lir->flags.alias_info),
303 DECODE_ALIAS_INFO_WIDE(mips_lir->flags.alias_info) ? "(+1)" : "");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700304 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100305 if (mask.HasBit(ResourceMask::kLiteral)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700306 strcat(buf, "lit ");
307 }
308
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100309 if (mask.HasBit(ResourceMask::kHeapRef)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700310 strcat(buf, "heap ");
311 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100312 if (mask.HasBit(ResourceMask::kMustNotAlias)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700313 strcat(buf, "noalias ");
314 }
315 }
316 if (buf[0]) {
317 LOG(INFO) << prefix << ": " << buf;
318 }
319}
320
321/*
322 * TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some
323 * instructions might call out to C/assembly helper functions. Until
324 * machinery is in place, always spill lr.
325 */
326
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700327void MipsMir2Lir::AdjustSpillMask() {
buzbee091cc402014-03-31 10:14:40 -0700328 core_spill_mask_ |= (1 << rs_rRA.GetRegNum());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700329 num_core_spills_++;
330}
331
332/*
333 * Mark a callee-save fp register as promoted. Note that
334 * vpush/vpop uses contiguous register lists so we must
335 * include any holes in the mask. Associate holes with
336 * Dalvik register INVALID_VREG (0xFFFFU).
337 */
buzbee091cc402014-03-31 10:14:40 -0700338void MipsMir2Lir::MarkPreservedSingle(int s_reg, RegStorage reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700339 LOG(FATAL) << "No support yet for promoted FP regs";
340}
341
buzbee091cc402014-03-31 10:14:40 -0700342void MipsMir2Lir::MarkPreservedDouble(int s_reg, RegStorage reg) {
343 LOG(FATAL) << "No support yet for promoted FP regs";
buzbee2700f7e2014-03-07 09:46:20 -0800344}
345
Brian Carlstrom7940e442013-07-12 13:46:57 -0700346/* Clobber all regs that might be used by an external C call */
Vladimir Marko31c2aac2013-12-09 16:31:19 +0000347void MipsMir2Lir::ClobberCallerSave() {
buzbee091cc402014-03-31 10:14:40 -0700348 Clobber(rs_rZERO);
349 Clobber(rs_rAT);
350 Clobber(rs_rV0);
351 Clobber(rs_rV1);
352 Clobber(rs_rA0);
353 Clobber(rs_rA1);
354 Clobber(rs_rA2);
355 Clobber(rs_rA3);
356 Clobber(rs_rT0);
357 Clobber(rs_rT1);
358 Clobber(rs_rT2);
359 Clobber(rs_rT3);
360 Clobber(rs_rT4);
361 Clobber(rs_rT5);
362 Clobber(rs_rT6);
363 Clobber(rs_rT7);
364 Clobber(rs_rT8);
365 Clobber(rs_rT9);
366 Clobber(rs_rK0);
367 Clobber(rs_rK1);
368 Clobber(rs_rGP);
369 Clobber(rs_rFP);
370 Clobber(rs_rRA);
371 Clobber(rs_rF0);
372 Clobber(rs_rF1);
373 Clobber(rs_rF2);
374 Clobber(rs_rF3);
375 Clobber(rs_rF4);
376 Clobber(rs_rF5);
377 Clobber(rs_rF6);
378 Clobber(rs_rF7);
379 Clobber(rs_rF8);
380 Clobber(rs_rF9);
381 Clobber(rs_rF10);
382 Clobber(rs_rF11);
383 Clobber(rs_rF12);
384 Clobber(rs_rF13);
385 Clobber(rs_rF14);
386 Clobber(rs_rF15);
387 Clobber(rs_rD0);
388 Clobber(rs_rD1);
389 Clobber(rs_rD2);
390 Clobber(rs_rD3);
391 Clobber(rs_rD4);
392 Clobber(rs_rD5);
393 Clobber(rs_rD6);
394 Clobber(rs_rD7);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700395}
396
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700397RegLocation MipsMir2Lir::GetReturnWideAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700398 UNIMPLEMENTED(FATAL) << "No GetReturnWideAlt for MIPS";
399 RegLocation res = LocCReturnWide();
400 return res;
401}
402
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700403RegLocation MipsMir2Lir::GetReturnAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700404 UNIMPLEMENTED(FATAL) << "No GetReturnAlt for MIPS";
405 RegLocation res = LocCReturn();
406 return res;
407}
408
Brian Carlstrom7940e442013-07-12 13:46:57 -0700409/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700410void MipsMir2Lir::LockCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700411 LockTemp(rs_rMIPS_ARG0);
412 LockTemp(rs_rMIPS_ARG1);
413 LockTemp(rs_rMIPS_ARG2);
414 LockTemp(rs_rMIPS_ARG3);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700415}
416
417/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700418void MipsMir2Lir::FreeCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700419 FreeTemp(rs_rMIPS_ARG0);
420 FreeTemp(rs_rMIPS_ARG1);
421 FreeTemp(rs_rMIPS_ARG2);
422 FreeTemp(rs_rMIPS_ARG3);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700423}
424
Andreas Gampeb14329f2014-05-15 11:16:06 -0700425bool MipsMir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700426#if ANDROID_SMP != 0
427 NewLIR1(kMipsSync, 0 /* Only stype currently supported */);
Andreas Gampeb14329f2014-05-15 11:16:06 -0700428 return true;
429#else
430 return false;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700431#endif
432}
433
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700434void MipsMir2Lir::CompilerInitializeRegAlloc() {
buzbeeb01bf152014-05-13 15:59:07 -0700435 reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs, empty_pool /* core64 */, sp_regs,
436 dp_regs, reserved_regs, empty_pool /* reserved64 */,
437 core_temps, empty_pool /* core64_temps */, sp_temps,
438 dp_temps);
buzbee091cc402014-03-31 10:14:40 -0700439
440 // Target-specific adjustments.
441
442 // Alias single precision floats to appropriate half of overlapping double.
443 GrowableArray<RegisterInfo*>::Iterator it(&reg_pool_->sp_regs_);
444 for (RegisterInfo* info = it.Next(); info != nullptr; info = it.Next()) {
445 int sp_reg_num = info->GetReg().GetRegNum();
446 int dp_reg_num = sp_reg_num >> 1;
447 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
448 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
449 // Double precision register's master storage should refer to itself.
450 DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
451 // Redirect single precision's master storage to master.
452 info->SetMaster(dp_reg_info);
453 // Singles should show a single 32-bit mask bit, at first referring to the low half.
454 DCHECK_EQ(info->StorageMask(), 0x1U);
455 if (sp_reg_num & 1) {
456 // For odd singles, change to user the high word of the backing double.
457 info->SetStorageMask(0x2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700458 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700459 }
buzbee091cc402014-03-31 10:14:40 -0700460
461 // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
462 // TODO: adjust when we roll to hard float calling convention.
463 reg_pool_->next_core_reg_ = 2;
464 reg_pool_->next_sp_reg_ = 2;
465 reg_pool_->next_dp_reg_ = 1;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700466}
467
Brian Carlstrom7940e442013-07-12 13:46:57 -0700468/*
469 * In the Arm code a it is typical to use the link register
470 * to hold the target address. However, for Mips we must
471 * ensure that all branch instructions can be restarted if
472 * there is a trap in the shadow. Allocate a temp register.
473 */
Ian Rogersdd7624d2014-03-14 17:43:00 -0700474RegStorage MipsMir2Lir::LoadHelper(ThreadOffset<4> offset) {
buzbee695d13a2014-04-19 13:32:20 -0700475 // NOTE: native pointer.
buzbee2700f7e2014-03-07 09:46:20 -0800476 LoadWordDisp(rs_rMIPS_SELF, offset.Int32Value(), rs_rT9);
477 return rs_rT9;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700478}
479
Andreas Gampe2f244e92014-05-08 03:35:25 -0700480RegStorage MipsMir2Lir::LoadHelper(ThreadOffset<8> offset) {
481 UNIMPLEMENTED(FATAL) << "Should not be called.";
482 return RegStorage::InvalidReg();
483}
484
Dave Allisonb373e092014-02-20 16:06:36 -0800485LIR* MipsMir2Lir::CheckSuspendUsingLoad() {
buzbee2700f7e2014-03-07 09:46:20 -0800486 RegStorage tmp = AllocTemp();
buzbee695d13a2014-04-19 13:32:20 -0700487 // NOTE: native pointer.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700488 LoadWordDisp(rs_rMIPS_SELF, Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
Dave Allisonb373e092014-02-20 16:06:36 -0800489 LIR *inst = LoadWordDisp(tmp, 0, tmp);
490 FreeTemp(tmp);
491 return inst;
492}
493
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700494void MipsMir2Lir::SpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700495 if (num_core_spills_ == 0) {
496 return;
497 }
498 uint32_t mask = core_spill_mask_;
499 int offset = num_core_spills_ * 4;
buzbee2700f7e2014-03-07 09:46:20 -0800500 OpRegImm(kOpSub, rs_rSP, offset);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700501 for (int reg = 0; mask; mask >>= 1, reg++) {
502 if (mask & 0x1) {
503 offset -= 4;
buzbee695d13a2014-04-19 13:32:20 -0700504 Store32Disp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700505 }
506 }
507}
508
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700509void MipsMir2Lir::UnSpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700510 if (num_core_spills_ == 0) {
511 return;
512 }
513 uint32_t mask = core_spill_mask_;
514 int offset = frame_size_;
515 for (int reg = 0; mask; mask >>= 1, reg++) {
516 if (mask & 0x1) {
517 offset -= 4;
buzbee695d13a2014-04-19 13:32:20 -0700518 Load32Disp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700519 }
520 }
buzbee2700f7e2014-03-07 09:46:20 -0800521 OpRegImm(kOpAdd, rs_rSP, frame_size_);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700522}
523
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700524bool MipsMir2Lir::IsUnconditionalBranch(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700525 return (lir->opcode == kMipsB);
526}
527
Vladimir Marko674744e2014-04-24 15:18:26 +0100528bool MipsMir2Lir::SupportsVolatileLoadStore(OpSize size) {
529 // No support for 64-bit atomic load/store on mips.
530 return size != k64 && size != kDouble;
531}
532
533RegisterClass MipsMir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) {
534 // No support for 64-bit atomic load/store on mips.
535 DCHECK(size != k64 && size != kDouble);
536 // TODO: Verify that both core and fp registers are suitable for smaller sizes.
537 return RegClassBySize(size);
538}
539
Brian Carlstrom7940e442013-07-12 13:46:57 -0700540MipsMir2Lir::MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
541 : Mir2Lir(cu, mir_graph, arena) {
542 for (int i = 0; i < kMipsLast; i++) {
543 if (MipsMir2Lir::EncodingMap[i].opcode != i) {
544 LOG(FATAL) << "Encoding order for " << MipsMir2Lir::EncodingMap[i].name
545 << " is wrong: expecting " << i << ", seeing "
546 << static_cast<int>(MipsMir2Lir::EncodingMap[i].opcode);
547 }
548 }
549}
550
551Mir2Lir* MipsCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
552 ArenaAllocator* const arena) {
553 return new MipsMir2Lir(cu, mir_graph, arena);
554}
555
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700556uint64_t MipsMir2Lir::GetTargetInstFlags(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700557 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700558 return MipsMir2Lir::EncodingMap[opcode].flags;
559}
560
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700561const char* MipsMir2Lir::GetTargetInstName(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700562 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700563 return MipsMir2Lir::EncodingMap[opcode].name;
564}
565
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700566const char* MipsMir2Lir::GetTargetInstFmt(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700567 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700568 return MipsMir2Lir::EncodingMap[opcode].fmt;
569}
570
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700571} // namespace art