blob: 1d02cf7c0ebdf6f6f6d2d90e59596becbb082722 [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
343/*
344 * Mark a callee-save fp register as promoted. Note that
345 * vpush/vpop uses contiguous register lists so we must
346 * include any holes in the mask. Associate holes with
347 * Dalvik register INVALID_VREG (0xFFFFU).
348 */
buzbee091cc402014-03-31 10:14:40 -0700349void MipsMir2Lir::MarkPreservedSingle(int s_reg, RegStorage reg) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700350 LOG(FATAL) << "No support yet for promoted FP regs";
351}
352
buzbee091cc402014-03-31 10:14:40 -0700353void MipsMir2Lir::MarkPreservedDouble(int s_reg, RegStorage reg) {
354 LOG(FATAL) << "No support yet for promoted FP regs";
buzbee2700f7e2014-03-07 09:46:20 -0800355}
356
Brian Carlstrom7940e442013-07-12 13:46:57 -0700357/* Clobber all regs that might be used by an external C call */
Vladimir Marko31c2aac2013-12-09 16:31:19 +0000358void MipsMir2Lir::ClobberCallerSave() {
buzbee091cc402014-03-31 10:14:40 -0700359 Clobber(rs_rZERO);
360 Clobber(rs_rAT);
361 Clobber(rs_rV0);
362 Clobber(rs_rV1);
363 Clobber(rs_rA0);
364 Clobber(rs_rA1);
365 Clobber(rs_rA2);
366 Clobber(rs_rA3);
367 Clobber(rs_rT0);
368 Clobber(rs_rT1);
369 Clobber(rs_rT2);
370 Clobber(rs_rT3);
371 Clobber(rs_rT4);
372 Clobber(rs_rT5);
373 Clobber(rs_rT6);
374 Clobber(rs_rT7);
375 Clobber(rs_rT8);
376 Clobber(rs_rT9);
377 Clobber(rs_rK0);
378 Clobber(rs_rK1);
379 Clobber(rs_rGP);
380 Clobber(rs_rFP);
381 Clobber(rs_rRA);
382 Clobber(rs_rF0);
383 Clobber(rs_rF1);
384 Clobber(rs_rF2);
385 Clobber(rs_rF3);
386 Clobber(rs_rF4);
387 Clobber(rs_rF5);
388 Clobber(rs_rF6);
389 Clobber(rs_rF7);
390 Clobber(rs_rF8);
391 Clobber(rs_rF9);
392 Clobber(rs_rF10);
393 Clobber(rs_rF11);
394 Clobber(rs_rF12);
395 Clobber(rs_rF13);
396 Clobber(rs_rF14);
397 Clobber(rs_rF15);
398 Clobber(rs_rD0);
399 Clobber(rs_rD1);
400 Clobber(rs_rD2);
401 Clobber(rs_rD3);
402 Clobber(rs_rD4);
403 Clobber(rs_rD5);
404 Clobber(rs_rD6);
405 Clobber(rs_rD7);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700406}
407
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700408RegLocation MipsMir2Lir::GetReturnWideAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700409 UNIMPLEMENTED(FATAL) << "No GetReturnWideAlt for MIPS";
410 RegLocation res = LocCReturnWide();
411 return res;
412}
413
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700414RegLocation MipsMir2Lir::GetReturnAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700415 UNIMPLEMENTED(FATAL) << "No GetReturnAlt for MIPS";
416 RegLocation res = LocCReturn();
417 return res;
418}
419
Brian Carlstrom7940e442013-07-12 13:46:57 -0700420/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700421void MipsMir2Lir::LockCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700422 LockTemp(rs_rMIPS_ARG0);
423 LockTemp(rs_rMIPS_ARG1);
424 LockTemp(rs_rMIPS_ARG2);
425 LockTemp(rs_rMIPS_ARG3);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700426}
427
428/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700429void MipsMir2Lir::FreeCallTemps() {
buzbee091cc402014-03-31 10:14:40 -0700430 FreeTemp(rs_rMIPS_ARG0);
431 FreeTemp(rs_rMIPS_ARG1);
432 FreeTemp(rs_rMIPS_ARG2);
433 FreeTemp(rs_rMIPS_ARG3);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700434}
435
Andreas Gampeb14329f2014-05-15 11:16:06 -0700436bool MipsMir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700437#if ANDROID_SMP != 0
438 NewLIR1(kMipsSync, 0 /* Only stype currently supported */);
Andreas Gampeb14329f2014-05-15 11:16:06 -0700439 return true;
440#else
441 return false;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700442#endif
443}
444
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700445void MipsMir2Lir::CompilerInitializeRegAlloc() {
buzbeeb01bf152014-05-13 15:59:07 -0700446 reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs, empty_pool /* core64 */, sp_regs,
447 dp_regs, reserved_regs, empty_pool /* reserved64 */,
448 core_temps, empty_pool /* core64_temps */, sp_temps,
449 dp_temps);
buzbee091cc402014-03-31 10:14:40 -0700450
451 // Target-specific adjustments.
452
453 // Alias single precision floats to appropriate half of overlapping double.
454 GrowableArray<RegisterInfo*>::Iterator it(&reg_pool_->sp_regs_);
455 for (RegisterInfo* info = it.Next(); info != nullptr; info = it.Next()) {
456 int sp_reg_num = info->GetReg().GetRegNum();
Douglas Leung2db3e262014-06-25 16:02:55 -0700457#if (FR_BIT == 0)
458 int dp_reg_num = sp_reg_num & ~1;
459#else
buzbee091cc402014-03-31 10:14:40 -0700460 int dp_reg_num = sp_reg_num >> 1;
Douglas Leung2db3e262014-06-25 16:02:55 -0700461#endif
buzbee091cc402014-03-31 10:14:40 -0700462 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
463 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
464 // Double precision register's master storage should refer to itself.
465 DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
466 // Redirect single precision's master storage to master.
467 info->SetMaster(dp_reg_info);
468 // Singles should show a single 32-bit mask bit, at first referring to the low half.
469 DCHECK_EQ(info->StorageMask(), 0x1U);
470 if (sp_reg_num & 1) {
471 // For odd singles, change to user the high word of the backing double.
472 info->SetStorageMask(0x2);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700473 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700474 }
buzbee091cc402014-03-31 10:14:40 -0700475
476 // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
477 // TODO: adjust when we roll to hard float calling convention.
478 reg_pool_->next_core_reg_ = 2;
479 reg_pool_->next_sp_reg_ = 2;
Douglas Leung2db3e262014-06-25 16:02:55 -0700480#if (FR_BIT == 0)
481 reg_pool_->next_dp_reg_ = 2;
482#else
buzbee091cc402014-03-31 10:14:40 -0700483 reg_pool_->next_dp_reg_ = 1;
Douglas Leung2db3e262014-06-25 16:02:55 -0700484#endif
Brian Carlstrom7940e442013-07-12 13:46:57 -0700485}
486
Brian Carlstrom7940e442013-07-12 13:46:57 -0700487/*
488 * In the Arm code a it is typical to use the link register
489 * to hold the target address. However, for Mips we must
490 * ensure that all branch instructions can be restarted if
491 * there is a trap in the shadow. Allocate a temp register.
492 */
Ian Rogersdd7624d2014-03-14 17:43:00 -0700493RegStorage MipsMir2Lir::LoadHelper(ThreadOffset<4> offset) {
buzbee695d13a2014-04-19 13:32:20 -0700494 // NOTE: native pointer.
buzbee2700f7e2014-03-07 09:46:20 -0800495 LoadWordDisp(rs_rMIPS_SELF, offset.Int32Value(), rs_rT9);
496 return rs_rT9;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700497}
498
Andreas Gampe2f244e92014-05-08 03:35:25 -0700499RegStorage MipsMir2Lir::LoadHelper(ThreadOffset<8> offset) {
500 UNIMPLEMENTED(FATAL) << "Should not be called.";
501 return RegStorage::InvalidReg();
502}
503
Dave Allisonb373e092014-02-20 16:06:36 -0800504LIR* MipsMir2Lir::CheckSuspendUsingLoad() {
buzbee2700f7e2014-03-07 09:46:20 -0800505 RegStorage tmp = AllocTemp();
buzbee695d13a2014-04-19 13:32:20 -0700506 // NOTE: native pointer.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700507 LoadWordDisp(rs_rMIPS_SELF, Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
Dave Allisonb373e092014-02-20 16:06:36 -0800508 LIR *inst = LoadWordDisp(tmp, 0, tmp);
509 FreeTemp(tmp);
510 return inst;
511}
512
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700513void MipsMir2Lir::SpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700514 if (num_core_spills_ == 0) {
515 return;
516 }
517 uint32_t mask = core_spill_mask_;
518 int offset = num_core_spills_ * 4;
buzbee2700f7e2014-03-07 09:46:20 -0800519 OpRegImm(kOpSub, rs_rSP, offset);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700520 for (int reg = 0; mask; mask >>= 1, reg++) {
521 if (mask & 0x1) {
522 offset -= 4;
buzbee695d13a2014-04-19 13:32:20 -0700523 Store32Disp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700524 }
525 }
526}
527
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700528void MipsMir2Lir::UnSpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700529 if (num_core_spills_ == 0) {
530 return;
531 }
532 uint32_t mask = core_spill_mask_;
533 int offset = frame_size_;
534 for (int reg = 0; mask; mask >>= 1, reg++) {
535 if (mask & 0x1) {
536 offset -= 4;
buzbee695d13a2014-04-19 13:32:20 -0700537 Load32Disp(rs_rMIPS_SP, offset, RegStorage::Solo32(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700538 }
539 }
buzbee2700f7e2014-03-07 09:46:20 -0800540 OpRegImm(kOpAdd, rs_rSP, frame_size_);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700541}
542
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700543bool MipsMir2Lir::IsUnconditionalBranch(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700544 return (lir->opcode == kMipsB);
545}
546
Vladimir Marko674744e2014-04-24 15:18:26 +0100547bool MipsMir2Lir::SupportsVolatileLoadStore(OpSize size) {
548 // No support for 64-bit atomic load/store on mips.
549 return size != k64 && size != kDouble;
550}
551
552RegisterClass MipsMir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) {
Douglas Leung2db3e262014-06-25 16:02:55 -0700553 if (UNLIKELY(is_volatile)) {
554 // On Mips, atomic 64-bit load/store requires an fp register.
555 // Smaller aligned load/store is atomic for both core and fp registers.
556 if (size == k64 || size == kDouble) {
557 return kFPReg;
558 }
559 }
Vladimir Marko674744e2014-04-24 15:18:26 +0100560 // TODO: Verify that both core and fp registers are suitable for smaller sizes.
561 return RegClassBySize(size);
562}
563
Brian Carlstrom7940e442013-07-12 13:46:57 -0700564MipsMir2Lir::MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
565 : Mir2Lir(cu, mir_graph, arena) {
566 for (int i = 0; i < kMipsLast; i++) {
567 if (MipsMir2Lir::EncodingMap[i].opcode != i) {
568 LOG(FATAL) << "Encoding order for " << MipsMir2Lir::EncodingMap[i].name
569 << " is wrong: expecting " << i << ", seeing "
570 << static_cast<int>(MipsMir2Lir::EncodingMap[i].opcode);
571 }
572 }
573}
574
575Mir2Lir* MipsCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
576 ArenaAllocator* const arena) {
577 return new MipsMir2Lir(cu, mir_graph, arena);
578}
579
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700580uint64_t MipsMir2Lir::GetTargetInstFlags(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700581 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700582 return MipsMir2Lir::EncodingMap[opcode].flags;
583}
584
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700585const char* MipsMir2Lir::GetTargetInstName(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700586 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700587 return MipsMir2Lir::EncodingMap[opcode].name;
588}
589
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700590const char* MipsMir2Lir::GetTargetInstFmt(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700591 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700592 return MipsMir2Lir::EncodingMap[opcode].fmt;
593}
594
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700595} // namespace art