blob: a5b7824cf69eca1f45246895134f3dd3b630cd6f [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
Douglas Leung2db3e262014-06-25 16:02:55 -070078// Convert k64BitSolo into k64BitPair
79RegStorage MipsMir2Lir::Solo64ToPair64(RegStorage reg) {
80 DCHECK(reg.IsDouble());
81 int reg_num = (reg.GetRegNum() & ~1) | RegStorage::kFloatingPoint;
82 return RegStorage(RegStorage::k64BitPair, reg_num, reg_num + 1);
83}
84
Brian Carlstrom7940e442013-07-12 13:46:57 -070085// 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;
Dmitry Petrochenko58994cd2014-05-17 01:02:18 +0700108 default: res_reg = RegStorage::InvalidReg();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700109 }
buzbee091cc402014-03-31 10:14:40 -0700110 return res_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700111}
112
buzbee2700f7e2014-03-07 09:46:20 -0800113RegStorage MipsMir2Lir::GetArgMappingToPhysicalReg(int arg_num) {
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800114 // For the 32-bit internal ABI, the first 3 arguments are passed in registers.
115 switch (arg_num) {
116 case 0:
buzbee2700f7e2014-03-07 09:46:20 -0800117 return rs_rMIPS_ARG1;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800118 case 1:
buzbee2700f7e2014-03-07 09:46:20 -0800119 return rs_rMIPS_ARG2;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800120 case 2:
buzbee2700f7e2014-03-07 09:46:20 -0800121 return rs_rMIPS_ARG3;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800122 default:
buzbee2700f7e2014-03-07 09:46:20 -0800123 return RegStorage::InvalidReg();
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800124 }
125}
126
Brian Carlstrom7940e442013-07-12 13:46:57 -0700127/*
128 * Decode the register id.
129 */
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100130ResourceMask MipsMir2Lir::GetRegMaskCommon(const RegStorage& reg) const {
131 return reg.IsDouble()
132 /* Each double register is equal to a pair of single-precision FP registers */
Douglas Leung2db3e262014-06-25 16:02:55 -0700133#if (FR_BIT == 0)
134 ? ResourceMask::TwoBits((reg.GetRegNum() & ~1) + kMipsFPReg0)
135#else
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100136 ? ResourceMask::TwoBits(reg.GetRegNum() * 2 + kMipsFPReg0)
Douglas Leung2db3e262014-06-25 16:02:55 -0700137#endif
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100138 : ResourceMask::Bit(reg.IsSingle() ? reg.GetRegNum() + kMipsFPReg0 : reg.GetRegNum());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700139}
140
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100141ResourceMask MipsMir2Lir::GetPCUseDefEncoding() const {
142 return ResourceMask::Bit(kMipsRegPC);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700143}
144
145
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100146void MipsMir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags,
147 ResourceMask* use_mask, ResourceMask* def_mask) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700148 DCHECK_EQ(cu_->instruction_set, kMips);
buzbeeb48819d2013-09-14 16:15:25 -0700149 DCHECK(!lir->flags.use_def_invalid);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700150
151 // Mips-specific resource map setup here.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700152 if (flags & REG_DEF_SP) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100153 def_mask->SetBit(kMipsRegSP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700154 }
155
156 if (flags & REG_USE_SP) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100157 use_mask->SetBit(kMipsRegSP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700158 }
159
160 if (flags & REG_DEF_LR) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100161 def_mask->SetBit(kMipsRegLR);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700162 }
buzbee9da5c102014-03-28 12:59:18 -0700163
164 if (flags & REG_DEF_HI) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100165 def_mask->SetBit(kMipsRegHI);
buzbee9da5c102014-03-28 12:59:18 -0700166 }
167
168 if (flags & REG_DEF_LO) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100169 def_mask->SetBit(kMipsRegLO);
buzbee9da5c102014-03-28 12:59:18 -0700170 }
171
172 if (flags & REG_USE_HI) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100173 use_mask->SetBit(kMipsRegHI);
buzbee9da5c102014-03-28 12:59:18 -0700174 }
175
176 if (flags & REG_USE_LO) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100177 use_mask->SetBit(kMipsRegLO);
buzbee9da5c102014-03-28 12:59:18 -0700178 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700179}
180
181/* For dumping instructions */
182#define MIPS_REG_COUNT 32
183static const char *mips_reg_name[MIPS_REG_COUNT] = {
184 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
185 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
186 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
187 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
188};
189
190/*
191 * Interpret a format string and build a string no longer than size
192 * See format key in Assemble.c.
193 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700194std::string MipsMir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700195 std::string buf;
196 int i;
197 const char *fmt_end = &fmt[strlen(fmt)];
198 char tbuf[256];
199 char nc;
200 while (fmt < fmt_end) {
201 int operand;
202 if (*fmt == '!') {
203 fmt++;
204 DCHECK_LT(fmt, fmt_end);
205 nc = *fmt++;
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700206 if (nc == '!') {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700207 strcpy(tbuf, "!");
208 } else {
209 DCHECK_LT(fmt, fmt_end);
210 DCHECK_LT(static_cast<unsigned>(nc-'0'), 4u);
211 operand = lir->operands[nc-'0'];
212 switch (*fmt++) {
213 case 'b':
Brian Carlstromb1eba212013-07-17 18:07:19 -0700214 strcpy(tbuf, "0000");
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700215 for (i = 3; i >= 0; i--) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700216 tbuf[i] += operand & 1;
217 operand >>= 1;
218 }
219 break;
220 case 's':
buzbee091cc402014-03-31 10:14:40 -0700221 snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700222 break;
223 case 'S':
buzbee091cc402014-03-31 10:14:40 -0700224 DCHECK_EQ(RegStorage::RegNum(operand) & 1, 0);
225 snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700226 break;
227 case 'h':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800228 snprintf(tbuf, arraysize(tbuf), "%04x", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700229 break;
230 case 'M':
231 case 'd':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800232 snprintf(tbuf, arraysize(tbuf), "%d", operand);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700233 break;
234 case 'D':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800235 snprintf(tbuf, arraysize(tbuf), "%d", operand+1);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700236 break;
237 case 'E':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800238 snprintf(tbuf, arraysize(tbuf), "%d", operand*4);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700239 break;
240 case 'F':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800241 snprintf(tbuf, arraysize(tbuf), "%d", operand*2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700242 break;
243 case 't':
Ian Rogers107c31e2014-01-23 20:55:29 -0800244 snprintf(tbuf, arraysize(tbuf), "0x%08" PRIxPTR " (L%p)",
245 reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 + (operand << 1),
246 lir->target);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700247 break;
248 case 'T':
Ian Rogers988e6ea2014-01-08 11:30:50 -0800249 snprintf(tbuf, arraysize(tbuf), "0x%08x", operand << 2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700250 break;
251 case 'u': {
252 int offset_1 = lir->operands[0];
253 int offset_2 = NEXT_LIR(lir)->operands[0];
254 uintptr_t target =
255 (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) & ~3) +
256 (offset_1 << 21 >> 9) + (offset_2 << 1)) & 0xfffffffc;
Ian Rogers988e6ea2014-01-08 11:30:50 -0800257 snprintf(tbuf, arraysize(tbuf), "%p", reinterpret_cast<void*>(target));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700258 break;
259 }
260
261 /* Nothing to print for BLX_2 */
262 case 'v':
263 strcpy(tbuf, "see above");
264 break;
265 case 'r':
266 DCHECK(operand >= 0 && operand < MIPS_REG_COUNT);
267 strcpy(tbuf, mips_reg_name[operand]);
268 break;
269 case 'N':
270 // Placeholder for delay slot handling
271 strcpy(tbuf, "; nop");
272 break;
273 default:
Brian Carlstromb1eba212013-07-17 18:07:19 -0700274 strcpy(tbuf, "DecodeError");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700275 break;
276 }
277 buf += tbuf;
278 }
279 } else {
280 buf += *fmt++;
281 }
282 }
283 return buf;
284}
285
286// FIXME: need to redo resource maps for MIPS - fix this at that time
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100287void MipsMir2Lir::DumpResourceMask(LIR *mips_lir, const ResourceMask& mask, const char *prefix) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700288 char buf[256];
289 buf[0] = 0;
290
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100291 if (mask.Equals(kEncodeAll)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700292 strcpy(buf, "all");
293 } else {
294 char num[8];
295 int i;
296
297 for (i = 0; i < kMipsRegEnd; i++) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100298 if (mask.HasBit(i)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800299 snprintf(num, arraysize(num), "%d ", i);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700300 strcat(buf, num);
301 }
302 }
303
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100304 if (mask.HasBit(ResourceMask::kCCode)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700305 strcat(buf, "cc ");
306 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100307 if (mask.HasBit(ResourceMask::kFPStatus)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700308 strcat(buf, "fpcc ");
309 }
310 /* Memory bits */
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100311 if (mips_lir && (mask.HasBit(ResourceMask::kDalvikReg))) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800312 snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s",
313 DECODE_ALIAS_INFO_REG(mips_lir->flags.alias_info),
314 DECODE_ALIAS_INFO_WIDE(mips_lir->flags.alias_info) ? "(+1)" : "");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700315 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100316 if (mask.HasBit(ResourceMask::kLiteral)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700317 strcat(buf, "lit ");
318 }
319
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100320 if (mask.HasBit(ResourceMask::kHeapRef)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700321 strcat(buf, "heap ");
322 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100323 if (mask.HasBit(ResourceMask::kMustNotAlias)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700324 strcat(buf, "noalias ");
325 }
326 }
327 if (buf[0]) {
328 LOG(INFO) << prefix << ": " << buf;
329 }
330}
331
332/*
333 * TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some
334 * instructions might call out to C/assembly helper functions. Until
335 * machinery is in place, always spill lr.
336 */
337
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700338void MipsMir2Lir::AdjustSpillMask() {
buzbee091cc402014-03-31 10:14:40 -0700339 core_spill_mask_ |= (1 << rs_rRA.GetRegNum());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700340 num_core_spills_++;
341}
342
Brian Carlstrom7940e442013-07-12 13:46:57 -0700343/* Clobber all regs that might be used by an external C call */
Vladimir Marko31c2aac2013-12-09 16:31:19 +0000344void MipsMir2Lir::ClobberCallerSave() {
buzbee091cc402014-03-31 10:14:40 -0700345 Clobber(rs_rZERO);
346 Clobber(rs_rAT);
347 Clobber(rs_rV0);
348 Clobber(rs_rV1);
349 Clobber(rs_rA0);
350 Clobber(rs_rA1);
351 Clobber(rs_rA2);
352 Clobber(rs_rA3);
353 Clobber(rs_rT0);
354 Clobber(rs_rT1);
355 Clobber(rs_rT2);
356 Clobber(rs_rT3);
357 Clobber(rs_rT4);
358 Clobber(rs_rT5);
359 Clobber(rs_rT6);
360 Clobber(rs_rT7);
361 Clobber(rs_rT8);
362 Clobber(rs_rT9);
363 Clobber(rs_rK0);
364 Clobber(rs_rK1);
365 Clobber(rs_rGP);
366 Clobber(rs_rFP);
367 Clobber(rs_rRA);
368 Clobber(rs_rF0);
369 Clobber(rs_rF1);
370 Clobber(rs_rF2);
371 Clobber(rs_rF3);
372 Clobber(rs_rF4);
373 Clobber(rs_rF5);
374 Clobber(rs_rF6);
375 Clobber(rs_rF7);
376 Clobber(rs_rF8);
377 Clobber(rs_rF9);
378 Clobber(rs_rF10);
379 Clobber(rs_rF11);
380 Clobber(rs_rF12);
381 Clobber(rs_rF13);
382 Clobber(rs_rF14);
383 Clobber(rs_rF15);
384 Clobber(rs_rD0);
385 Clobber(rs_rD1);
386 Clobber(rs_rD2);
387 Clobber(rs_rD3);
388 Clobber(rs_rD4);
389 Clobber(rs_rD5);
390 Clobber(rs_rD6);
391 Clobber(rs_rD7);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700392}
393
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700394RegLocation MipsMir2Lir::GetReturnWideAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700395 UNIMPLEMENTED(FATAL) << "No GetReturnWideAlt for MIPS";
396 RegLocation res = LocCReturnWide();
397 return res;
398}
399
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700400RegLocation MipsMir2Lir::GetReturnAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700401 UNIMPLEMENTED(FATAL) << "No GetReturnAlt for MIPS";
402 RegLocation res = LocCReturn();
403 return res;
404}
405
Brian Carlstrom7940e442013-07-12 13:46:57 -0700406/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700407void MipsMir2Lir::LockCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700408 LockTemp(rs_rMIPS_ARG0);
409 LockTemp(rs_rMIPS_ARG1);
410 LockTemp(rs_rMIPS_ARG2);
411 LockTemp(rs_rMIPS_ARG3);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700412}
413
414/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700415void MipsMir2Lir::FreeCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700416 FreeTemp(rs_rMIPS_ARG0);
417 FreeTemp(rs_rMIPS_ARG1);
418 FreeTemp(rs_rMIPS_ARG2);
419 FreeTemp(rs_rMIPS_ARG3);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700420}
421
Andreas Gampeb14329f2014-05-15 11:16:06 -0700422bool MipsMir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700423#if ANDROID_SMP != 0
424 NewLIR1(kMipsSync, 0 /* Only stype currently supported */);
Andreas Gampeb14329f2014-05-15 11:16:06 -0700425 return true;
426#else
427 return false;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700428#endif
429}
430
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700431void MipsMir2Lir::CompilerInitializeRegAlloc() {
buzbeeb01bf152014-05-13 15:59:07 -0700432 reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs, empty_pool /* core64 */, sp_regs,
433 dp_regs, reserved_regs, empty_pool /* reserved64 */,
434 core_temps, empty_pool /* core64_temps */, sp_temps,
435 dp_temps);
buzbee091cc402014-03-31 10:14:40 -0700436
437 // Target-specific adjustments.
438
439 // Alias single precision floats to appropriate half of overlapping double.
440 GrowableArray<RegisterInfo*>::Iterator it(&reg_pool_->sp_regs_);
441 for (RegisterInfo* info = it.Next(); info != nullptr; info = it.Next()) {
442 int sp_reg_num = info->GetReg().GetRegNum();
Douglas Leung2db3e262014-06-25 16:02:55 -0700443#if (FR_BIT == 0)
444 int dp_reg_num = sp_reg_num & ~1;
445#else
buzbee091cc402014-03-31 10:14:40 -0700446 int dp_reg_num = sp_reg_num >> 1;
Douglas Leung2db3e262014-06-25 16:02:55 -0700447#endif
buzbee091cc402014-03-31 10:14:40 -0700448 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
449 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
450 // Double precision register's master storage should refer to itself.
451 DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
452 // Redirect single precision's master storage to master.
453 info->SetMaster(dp_reg_info);
454 // Singles should show a single 32-bit mask bit, at first referring to the low half.
455 DCHECK_EQ(info->StorageMask(), 0x1U);
456 if (sp_reg_num & 1) {
457 // For odd singles, change to user the high word of the backing double.
458 info->SetStorageMask(0x2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700459 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700460 }
buzbee091cc402014-03-31 10:14:40 -0700461
462 // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
463 // TODO: adjust when we roll to hard float calling convention.
464 reg_pool_->next_core_reg_ = 2;
465 reg_pool_->next_sp_reg_ = 2;
Douglas Leung2db3e262014-06-25 16:02:55 -0700466#if (FR_BIT == 0)
467 reg_pool_->next_dp_reg_ = 2;
468#else
buzbee091cc402014-03-31 10:14:40 -0700469 reg_pool_->next_dp_reg_ = 1;
Douglas Leung2db3e262014-06-25 16:02:55 -0700470#endif
Brian Carlstrom7940e442013-07-12 13:46:57 -0700471}
472
Brian Carlstrom7940e442013-07-12 13:46:57 -0700473/*
474 * In the Arm code a it is typical to use the link register
475 * to hold the target address. However, for Mips we must
476 * ensure that all branch instructions can be restarted if
477 * there is a trap in the shadow. Allocate a temp register.
478 */
Ian Rogersdd7624d2014-03-14 17:43:00 -0700479RegStorage MipsMir2Lir::LoadHelper(ThreadOffset<4> offset) {
buzbee695d13a2014-04-19 13:32:20 -0700480 // NOTE: native pointer.
buzbee2700f7e2014-03-07 09:46:20 -0800481 LoadWordDisp(rs_rMIPS_SELF, offset.Int32Value(), rs_rT9);
482 return rs_rT9;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700483}
484
Andreas Gampe2f244e92014-05-08 03:35:25 -0700485RegStorage MipsMir2Lir::LoadHelper(ThreadOffset<8> offset) {
486 UNIMPLEMENTED(FATAL) << "Should not be called.";
487 return RegStorage::InvalidReg();
488}
489
Dave Allisonb373e092014-02-20 16:06:36 -0800490LIR* MipsMir2Lir::CheckSuspendUsingLoad() {
buzbee2700f7e2014-03-07 09:46:20 -0800491 RegStorage tmp = AllocTemp();
buzbee695d13a2014-04-19 13:32:20 -0700492 // NOTE: native pointer.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700493 LoadWordDisp(rs_rMIPS_SELF, Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
Dave Allisonb373e092014-02-20 16:06:36 -0800494 LIR *inst = LoadWordDisp(tmp, 0, tmp);
495 FreeTemp(tmp);
496 return inst;
497}
498
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700499void MipsMir2Lir::SpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700500 if (num_core_spills_ == 0) {
501 return;
502 }
503 uint32_t mask = core_spill_mask_;
504 int offset = num_core_spills_ * 4;
buzbee2700f7e2014-03-07 09:46:20 -0800505 OpRegImm(kOpSub, rs_rSP, offset);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700506 for (int reg = 0; mask; mask >>= 1, reg++) {
507 if (mask & 0x1) {
508 offset -= 4;
buzbee695d13a2014-04-19 13:32:20 -0700509 Store32Disp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700510 }
511 }
512}
513
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700514void MipsMir2Lir::UnSpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700515 if (num_core_spills_ == 0) {
516 return;
517 }
518 uint32_t mask = core_spill_mask_;
519 int offset = frame_size_;
520 for (int reg = 0; mask; mask >>= 1, reg++) {
521 if (mask & 0x1) {
522 offset -= 4;
buzbee695d13a2014-04-19 13:32:20 -0700523 Load32Disp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700524 }
525 }
buzbee2700f7e2014-03-07 09:46:20 -0800526 OpRegImm(kOpAdd, rs_rSP, frame_size_);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700527}
528
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700529bool MipsMir2Lir::IsUnconditionalBranch(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700530 return (lir->opcode == kMipsB);
531}
532
Vladimir Marko674744e2014-04-24 15:18:26 +0100533bool MipsMir2Lir::SupportsVolatileLoadStore(OpSize size) {
534 // No support for 64-bit atomic load/store on mips.
535 return size != k64 && size != kDouble;
536}
537
538RegisterClass MipsMir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) {
Douglas Leung2db3e262014-06-25 16:02:55 -0700539 if (UNLIKELY(is_volatile)) {
540 // On Mips, atomic 64-bit load/store requires an fp register.
541 // Smaller aligned load/store is atomic for both core and fp registers.
542 if (size == k64 || size == kDouble) {
543 return kFPReg;
544 }
545 }
Vladimir Marko674744e2014-04-24 15:18:26 +0100546 // 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