blob: 4c0bd8378b887c2355b412d5effb7f3f8f0717b7 [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
Ian Rogersd582fa42014-11-05 23:46:43 -080023#include "arch/mips/instruction_set_features_mips.h"
Andreas Gampe53c913b2014-08-12 23:19:23 -070024#include "backend_mips.h"
Andreas Gampe0b9203e2015-01-22 20:39:27 -080025#include "base/logging.h"
26#include "dex/compiler_ir.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070027#include "dex/quick/mir_to_lir-inl.h"
Andreas Gampe0b9203e2015-01-22 20:39:27 -080028#include "driver/compiler_driver.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070029#include "mips_lir.h"
30
Brian Carlstrom7940e442013-07-12 13:46:57 -070031namespace art {
32
Goran Jakovljevic10957932015-03-24 18:42:56 +010033static constexpr RegStorage core_regs_arr_32[] =
34 {rs_rZERO, rs_rAT, rs_rV0, rs_rV1, rs_rA0, rs_rA1, rs_rA2, rs_rA3, rs_rT0_32, rs_rT1_32,
35 rs_rT2_32, rs_rT3_32, rs_rT4_32, rs_rT5_32, rs_rT6_32, rs_rT7_32, rs_rS0, rs_rS1, rs_rS2,
36 rs_rS3, rs_rS4, rs_rS5, rs_rS6, rs_rS7, rs_rT8, rs_rT9, rs_rK0, rs_rK1, rs_rGP, rs_rSP, rs_rFP,
37 rs_rRA};
38static constexpr RegStorage sp_regs_arr_32[] =
buzbee091cc402014-03-31 10:14:40 -070039 {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
40 rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15};
Goran Jakovljevic10957932015-03-24 18:42:56 +010041static constexpr RegStorage dp_fr0_regs_arr_32[] =
Ian Rogersd582fa42014-11-05 23:46:43 -080042 {rs_rD0_fr0, rs_rD1_fr0, rs_rD2_fr0, rs_rD3_fr0, rs_rD4_fr0, rs_rD5_fr0, rs_rD6_fr0,
43 rs_rD7_fr0};
Goran Jakovljevic10957932015-03-24 18:42:56 +010044static constexpr RegStorage dp_fr1_regs_arr_32[] =
Ian Rogersd582fa42014-11-05 23:46:43 -080045 {rs_rD0_fr1, rs_rD1_fr1, rs_rD2_fr1, rs_rD3_fr1, rs_rD4_fr1, rs_rD5_fr1, rs_rD6_fr1,
46 rs_rD7_fr1};
Goran Jakovljevic10957932015-03-24 18:42:56 +010047static constexpr RegStorage reserved_regs_arr_32[] =
buzbee091cc402014-03-31 10:14:40 -070048 {rs_rZERO, rs_rAT, rs_rS0, rs_rS1, rs_rK0, rs_rK1, rs_rGP, rs_rSP, rs_rRA};
Goran Jakovljevic10957932015-03-24 18:42:56 +010049static constexpr RegStorage core_temps_arr_32[] =
50 {rs_rV0, rs_rV1, rs_rA0, rs_rA1, rs_rA2, rs_rA3, rs_rT0_32, rs_rT1_32, rs_rT2_32, rs_rT3_32,
51 rs_rT4_32, rs_rT5_32, rs_rT6_32, rs_rT7_32, rs_rT8};
52static constexpr RegStorage sp_temps_arr_32[] =
buzbee091cc402014-03-31 10:14:40 -070053 {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
54 rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15};
Goran Jakovljevic10957932015-03-24 18:42:56 +010055static constexpr RegStorage dp_fr0_temps_arr_32[] =
Ian Rogersd582fa42014-11-05 23:46:43 -080056 {rs_rD0_fr0, rs_rD1_fr0, rs_rD2_fr0, rs_rD3_fr0, rs_rD4_fr0, rs_rD5_fr0, rs_rD6_fr0,
57 rs_rD7_fr0};
Goran Jakovljevic10957932015-03-24 18:42:56 +010058static constexpr RegStorage dp_fr1_temps_arr_32[] =
Ian Rogersd582fa42014-11-05 23:46:43 -080059 {rs_rD0_fr1, rs_rD1_fr1, rs_rD2_fr1, rs_rD3_fr1, rs_rD4_fr1, rs_rD5_fr1, rs_rD6_fr1,
60 rs_rD7_fr1};
buzbee091cc402014-03-31 10:14:40 -070061
Goran Jakovljevic10957932015-03-24 18:42:56 +010062static constexpr RegStorage core_regs_arr_64[] =
63 {rs_rZERO, rs_rAT, rs_rV0, rs_rV1, rs_rA0, rs_rA1, rs_rA2, rs_rA3, rs_rA4, rs_rA5, rs_rA6,
64 rs_rA7, rs_rT0, rs_rT1, rs_rT2, rs_rT3, rs_rS0, rs_rS1, rs_rS2, rs_rS3, rs_rS4, rs_rS5, rs_rS6,
65 rs_rS7, rs_rT8, rs_rT9, rs_rK0, rs_rK1, rs_rGP, rs_rSP, rs_rFP, rs_rRA};
66static constexpr RegStorage core_regs_arr_64d[] =
67 {rs_rZEROd, rs_rATd, rs_rV0d, rs_rV1d, rs_rA0d, rs_rA1d, rs_rA2d, rs_rA3d, rs_rA4d, rs_rA5d,
68 rs_rA6d, rs_rA7d, rs_rT0d, rs_rT1d, rs_rT2d, rs_rT3d, rs_rS0d, rs_rS1d, rs_rS2d, rs_rS3d,
69 rs_rS4d, rs_rS5d, rs_rS6d, rs_rS7d, rs_rT8d, rs_rT9d, rs_rK0d, rs_rK1d, rs_rGPd, rs_rSPd,
70 rs_rFPd, rs_rRAd};
71#if 0
72// TODO: f24-f31 must be saved before calls and restored after.
73static constexpr RegStorage sp_regs_arr_64[] =
74 {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
75 rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15, rs_rF16, rs_rF17, rs_rF18, rs_rF19, rs_rF20,
76 rs_rF21, rs_rF22, rs_rF23, rs_rF24, rs_rF25, rs_rF26, rs_rF27, rs_rF28, rs_rF29, rs_rF30,
77 rs_rF31};
78static constexpr RegStorage dp_regs_arr_64[] =
79 {rs_rD0, rs_rD1, rs_rD2, rs_rD3, rs_rD4, rs_rD5, rs_rD6, rs_rD7, rs_rD8, rs_rD9, rs_rD10,
80 rs_rD11, rs_rD12, rs_rD13, rs_rD14, rs_rD15, rs_rD16, rs_rD17, rs_rD18, rs_rD19, rs_rD20,
81 rs_rD21, rs_rD22, rs_rD23, rs_rD24, rs_rD25, rs_rD26, rs_rD27, rs_rD28, rs_rD29, rs_rD30,
82 rs_rD31};
83#else
84static constexpr RegStorage sp_regs_arr_64[] =
85 {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
86 rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15, rs_rF16, rs_rF17, rs_rF18, rs_rF19, rs_rF20,
87 rs_rF21, rs_rF22, rs_rF23};
88static constexpr RegStorage dp_regs_arr_64[] =
89 {rs_rD0, rs_rD1, rs_rD2, rs_rD3, rs_rD4, rs_rD5, rs_rD6, rs_rD7, rs_rD8, rs_rD9, rs_rD10,
90 rs_rD11, rs_rD12, rs_rD13, rs_rD14, rs_rD15, rs_rD16, rs_rD17, rs_rD18, rs_rD19, rs_rD20,
91 rs_rD21, rs_rD22, rs_rD23};
92#endif
93static constexpr RegStorage reserved_regs_arr_64[] =
94 {rs_rZERO, rs_rAT, rs_rS0, rs_rS1, rs_rT9, rs_rK0, rs_rK1, rs_rGP, rs_rSP, rs_rRA};
95static constexpr RegStorage reserved_regs_arr_64d[] =
96 {rs_rZEROd, rs_rATd, rs_rS0d, rs_rS1d, rs_rT9d, rs_rK0d, rs_rK1d, rs_rGPd, rs_rSPd, rs_rRAd};
97static constexpr RegStorage core_temps_arr_64[] =
98 {rs_rV0, rs_rV1, rs_rA0, rs_rA1, rs_rA2, rs_rA3, rs_rA4, rs_rA5, rs_rA6, rs_rA7, rs_rT0, rs_rT1,
99 rs_rT2, rs_rT3, rs_rT8};
100static constexpr RegStorage core_temps_arr_64d[] =
101 {rs_rV0d, rs_rV1d, rs_rA0d, rs_rA1d, rs_rA2d, rs_rA3d, rs_rA4d, rs_rA5d, rs_rA6d, rs_rA7d,
102 rs_rT0d, rs_rT1d, rs_rT2d, rs_rT3d, rs_rT8d};
103#if 0
104// TODO: f24-f31 must be saved before calls and restored after.
105static constexpr RegStorage sp_temps_arr_64[] =
106 {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
107 rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15, rs_rF16, rs_rF17, rs_rF18, rs_rF19, rs_rF20,
108 rs_rF21, rs_rF22, rs_rF23, rs_rF24, rs_rF25, rs_rF26, rs_rF27, rs_rF28, rs_rF29, rs_rF30,
109 rs_rF31};
110static constexpr RegStorage dp_temps_arr_64[] =
111 {rs_rD0, rs_rD1, rs_rD2, rs_rD3, rs_rD4, rs_rD5, rs_rD6, rs_rD7, rs_rD8, rs_rD9, rs_rD10,
112 rs_rD11, rs_rD12, rs_rD13, rs_rD14, rs_rD15, rs_rD16, rs_rD17, rs_rD18, rs_rD19, rs_rD20,
113 rs_rD21, rs_rD22, rs_rD23, rs_rD24, rs_rD25, rs_rD26, rs_rD27, rs_rD28, rs_rD29, rs_rD30,
114 rs_rD31};
115#else
116static constexpr RegStorage sp_temps_arr_64[] =
117 {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
118 rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15, rs_rF16, rs_rF17, rs_rF18, rs_rF19, rs_rF20,
119 rs_rF21, rs_rF22, rs_rF23};
120static constexpr RegStorage dp_temps_arr_64[] =
121 {rs_rD0, rs_rD1, rs_rD2, rs_rD3, rs_rD4, rs_rD5, rs_rD6, rs_rD7, rs_rD8, rs_rD9, rs_rD10,
122 rs_rD11, rs_rD12, rs_rD13, rs_rD14, rs_rD15, rs_rD16, rs_rD17, rs_rD18, rs_rD19, rs_rD20,
123 rs_rD21, rs_rD22, rs_rD23};
124#endif
125
Vladimir Marko089142c2014-06-05 10:57:05 +0100126static constexpr ArrayRef<const RegStorage> empty_pool;
Goran Jakovljevic10957932015-03-24 18:42:56 +0100127static constexpr ArrayRef<const RegStorage> core_regs_32(core_regs_arr_32);
128static constexpr ArrayRef<const RegStorage> sp_regs_32(sp_regs_arr_32);
129static constexpr ArrayRef<const RegStorage> dp_fr0_regs_32(dp_fr0_regs_arr_32);
130static constexpr ArrayRef<const RegStorage> dp_fr1_regs_32(dp_fr1_regs_arr_32);
131static constexpr ArrayRef<const RegStorage> reserved_regs_32(reserved_regs_arr_32);
132static constexpr ArrayRef<const RegStorage> core_temps_32(core_temps_arr_32);
133static constexpr ArrayRef<const RegStorage> sp_temps_32(sp_temps_arr_32);
134static constexpr ArrayRef<const RegStorage> dp_fr0_temps_32(dp_fr0_temps_arr_32);
135static constexpr ArrayRef<const RegStorage> dp_fr1_temps_32(dp_fr1_temps_arr_32);
136
137static constexpr ArrayRef<const RegStorage> core_regs_64(core_regs_arr_64);
138static constexpr ArrayRef<const RegStorage> core_regs_64d(core_regs_arr_64d);
139static constexpr ArrayRef<const RegStorage> sp_regs_64(sp_regs_arr_64);
140static constexpr ArrayRef<const RegStorage> dp_regs_64(dp_regs_arr_64);
141static constexpr ArrayRef<const RegStorage> reserved_regs_64(reserved_regs_arr_64);
142static constexpr ArrayRef<const RegStorage> reserved_regs_64d(reserved_regs_arr_64d);
143static constexpr ArrayRef<const RegStorage> core_temps_64(core_temps_arr_64);
144static constexpr ArrayRef<const RegStorage> core_temps_64d(core_temps_arr_64d);
145static constexpr ArrayRef<const RegStorage> sp_temps_64(sp_temps_arr_64);
146static constexpr ArrayRef<const RegStorage> dp_temps_64(dp_temps_arr_64);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700147
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700148RegLocation MipsMir2Lir::LocCReturn() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000149 return mips_loc_c_return;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700150}
151
buzbeea0cd2d72014-06-01 09:33:49 -0700152RegLocation MipsMir2Lir::LocCReturnRef() {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100153 return cu_->target64 ? mips64_loc_c_return_ref : mips_loc_c_return;
buzbeea0cd2d72014-06-01 09:33:49 -0700154}
155
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700156RegLocation MipsMir2Lir::LocCReturnWide() {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100157 return cu_->target64 ? mips64_loc_c_return_wide : mips_loc_c_return_wide;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700158}
159
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700160RegLocation MipsMir2Lir::LocCReturnFloat() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000161 return mips_loc_c_return_float;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700162}
163
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700164RegLocation MipsMir2Lir::LocCReturnDouble() {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100165 if (cu_->target64) {
166 return mips64_loc_c_return_double;
167 } else if (fpuIs32Bit_) {
168 return mips_loc_c_return_double_fr0;
Douglas Leung027f0ff2015-02-27 19:05:03 -0800169 } else {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100170 return mips_loc_c_return_double_fr1;
Douglas Leung027f0ff2015-02-27 19:05:03 -0800171 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700172}
173
Goran Jakovljevic10957932015-03-24 18:42:56 +0100174// Convert k64BitSolo into k64BitPair.
Douglas Leung2db3e262014-06-25 16:02:55 -0700175RegStorage MipsMir2Lir::Solo64ToPair64(RegStorage reg) {
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800176 DCHECK(reg.IsDouble());
Douglas Leung027f0ff2015-02-27 19:05:03 -0800177 DCHECK_EQ(reg.GetRegNum() & 1, 0);
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800178 int reg_num = (reg.GetRegNum() & ~1) | RegStorage::kFloatingPoint;
179 return RegStorage(RegStorage::k64BitPair, reg_num, reg_num + 1);
Douglas Leung2db3e262014-06-25 16:02:55 -0700180}
181
Douglas Leung027f0ff2015-02-27 19:05:03 -0800182// Convert 64bit FP (k64BitSolo or k64BitPair) into k32BitSolo.
183// This routine is only used to allow a 64bit FPU to access FP registers 32bits at a time.
184RegStorage MipsMir2Lir::Fp64ToSolo32(RegStorage reg) {
185 DCHECK(!fpuIs32Bit_);
186 DCHECK(reg.IsDouble());
187 DCHECK(!reg.IsPair());
188 int reg_num = reg.GetRegNum() | RegStorage::kFloatingPoint;
189 return RegStorage(RegStorage::k32BitSolo, reg_num);
190}
191
192// Return a target-dependent special register.
193RegStorage MipsMir2Lir::TargetReg(SpecialTargetRegister reg, WideKind wide_kind) {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100194 if (!cu_->target64 && wide_kind == kWide) {
195 DCHECK((kArg0 <= reg && reg < kArg7) || (kFArg0 <= reg && reg < kFArg15) || (kRet0 == reg));
196 RegStorage ret_reg = RegStorage::MakeRegPair(TargetReg(reg),
197 TargetReg(static_cast<SpecialTargetRegister>(reg + 1)));
198 if (!fpuIs32Bit_ && ret_reg.IsFloat()) {
199 // convert 64BitPair to 64BitSolo for 64bit FPUs.
200 RegStorage low = ret_reg.GetLow();
201 ret_reg = RegStorage::FloatSolo64(low.GetRegNum());
202 }
203 return ret_reg;
204 } else if (cu_->target64 && (wide_kind == kWide || wide_kind == kRef)) {
205 return As64BitReg(TargetReg(reg));
Douglas Leung027f0ff2015-02-27 19:05:03 -0800206 } else {
207 return TargetReg(reg);
208 }
209}
210
Brian Carlstrom7940e442013-07-12 13:46:57 -0700211// Return a target-dependent special register.
buzbee2700f7e2014-03-07 09:46:20 -0800212RegStorage MipsMir2Lir::TargetReg(SpecialTargetRegister reg) {
buzbee091cc402014-03-31 10:14:40 -0700213 RegStorage res_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700214 switch (reg) {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100215 case kSelf: res_reg = rs_rS1; break;
216 case kSuspend: res_reg = rs_rS0; break;
217 case kLr: res_reg = rs_rRA; break;
218 case kPc: res_reg = RegStorage::InvalidReg(); break;
219 case kSp: res_reg = rs_rSP; break;
220 case kArg0: res_reg = rs_rA0; break;
221 case kArg1: res_reg = rs_rA1; break;
222 case kArg2: res_reg = rs_rA2; break;
223 case kArg3: res_reg = rs_rA3; break;
224 case kArg4: res_reg = cu_->target64 ? rs_rA4 : RegStorage::InvalidReg(); break;
225 case kArg5: res_reg = cu_->target64 ? rs_rA5 : RegStorage::InvalidReg(); break;
226 case kArg6: res_reg = cu_->target64 ? rs_rA6 : RegStorage::InvalidReg(); break;
227 case kArg7: res_reg = cu_->target64 ? rs_rA7 : RegStorage::InvalidReg(); break;
228 case kFArg0: res_reg = rs_rF12; break;
229 case kFArg1: res_reg = rs_rF13; break;
230 case kFArg2: res_reg = rs_rF14; break;
231 case kFArg3: res_reg = rs_rF15; break;
232 case kFArg4: res_reg = cu_->target64 ? rs_rF16 : RegStorage::InvalidReg(); break;
233 case kFArg5: res_reg = cu_->target64 ? rs_rF17 : RegStorage::InvalidReg(); break;
234 case kFArg6: res_reg = cu_->target64 ? rs_rF18 : RegStorage::InvalidReg(); break;
235 case kFArg7: res_reg = cu_->target64 ? rs_rF19 : RegStorage::InvalidReg(); break;
236 case kRet0: res_reg = rs_rV0; break;
237 case kRet1: res_reg = rs_rV1; break;
238 case kInvokeTgt: res_reg = rs_rT9; break;
239 case kHiddenArg: res_reg = cu_->target64 ? rs_rT0 : rs_rT0_32; break;
buzbee091cc402014-03-31 10:14:40 -0700240 case kHiddenFpArg: res_reg = RegStorage::InvalidReg(); break;
Goran Jakovljevic10957932015-03-24 18:42:56 +0100241 case kCount: res_reg = RegStorage::InvalidReg(); break;
Dmitry Petrochenko58994cd2014-05-17 01:02:18 +0700242 default: res_reg = RegStorage::InvalidReg();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700243 }
buzbee091cc402014-03-31 10:14:40 -0700244 return res_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700245}
246
Serguei Katkov717a3e42014-11-13 17:19:42 +0600247RegStorage MipsMir2Lir::InToRegStorageMipsMapper::GetNextReg(ShortyArg arg) {
248 const SpecialTargetRegister coreArgMappingToPhysicalReg[] = {kArg1, kArg2, kArg3};
249 const size_t coreArgMappingToPhysicalRegSize = arraysize(coreArgMappingToPhysicalReg);
250
251 RegStorage result = RegStorage::InvalidReg();
252 if (cur_core_reg_ < coreArgMappingToPhysicalRegSize) {
253 result = m2l_->TargetReg(coreArgMappingToPhysicalReg[cur_core_reg_++],
254 arg.IsRef() ? kRef : kNotWide);
255 if (arg.IsWide() && cur_core_reg_ < coreArgMappingToPhysicalRegSize) {
256 result = RegStorage::MakeRegPair(
257 result, m2l_->TargetReg(coreArgMappingToPhysicalReg[cur_core_reg_++], kNotWide));
258 }
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800259 }
Serguei Katkov717a3e42014-11-13 17:19:42 +0600260 return result;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800261}
262
Goran Jakovljevic10957932015-03-24 18:42:56 +0100263RegStorage MipsMir2Lir::InToRegStorageMips64Mapper::GetNextReg(ShortyArg arg) {
264 const SpecialTargetRegister coreArgMappingToPhysicalReg[] =
265 {kArg1, kArg2, kArg3, kArg4, kArg5, kArg6, kArg7};
266 const size_t coreArgMappingToPhysicalRegSize = arraysize(coreArgMappingToPhysicalReg);
267 const SpecialTargetRegister fpArgMappingToPhysicalReg[] =
268 {kFArg1, kFArg2, kFArg3, kFArg4, kFArg5, kFArg6, kFArg7};
269 const size_t fpArgMappingToPhysicalRegSize = arraysize(fpArgMappingToPhysicalReg);
270
271 RegStorage result = RegStorage::InvalidReg();
272 if (arg.IsFP()) {
273 if (cur_arg_reg_ < fpArgMappingToPhysicalRegSize) {
274 DCHECK(!arg.IsRef());
275 result = m2l_->TargetReg(fpArgMappingToPhysicalReg[cur_arg_reg_++],
276 arg.IsWide() ? kWide : kNotWide);
277 }
278 } else {
279 if (cur_arg_reg_ < coreArgMappingToPhysicalRegSize) {
280 DCHECK(!(arg.IsWide() && arg.IsRef()));
281 result = m2l_->TargetReg(coreArgMappingToPhysicalReg[cur_arg_reg_++],
282 arg.IsRef() ? kRef : (arg.IsWide() ? kWide : kNotWide));
283 }
284 }
285 return result;
286}
287
Brian Carlstrom7940e442013-07-12 13:46:57 -0700288/*
289 * Decode the register id.
290 */
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100291ResourceMask MipsMir2Lir::GetRegMaskCommon(const RegStorage& reg) const {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100292 if (cu_->target64) {
293 return ResourceMask::Bit((reg.IsFloat() ? kMipsFPReg0 : 0) + reg.GetRegNum());
Ian Rogersd582fa42014-11-05 23:46:43 -0800294 } else {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100295 if (reg.IsDouble()) {
296 return ResourceMask::TwoBits((reg.GetRegNum() & ~1) + kMipsFPReg0);
297 } else if (reg.IsSingle()) {
298 return ResourceMask::Bit(reg.GetRegNum() + kMipsFPReg0);
299 } else {
300 return ResourceMask::Bit(reg.GetRegNum());
301 }
Ian Rogersd582fa42014-11-05 23:46:43 -0800302 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700303}
304
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100305ResourceMask MipsMir2Lir::GetPCUseDefEncoding() const {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100306 return cu_->target64 ? ResourceMask::Bit(kMips64RegPC) : ResourceMask::Bit(kMipsRegPC);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700307}
308
Goran Jakovljevic10957932015-03-24 18:42:56 +0100309void MipsMir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags, ResourceMask* use_mask,
310 ResourceMask* def_mask) {
buzbeeb48819d2013-09-14 16:15:25 -0700311 DCHECK(!lir->flags.use_def_invalid);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700312
313 // Mips-specific resource map setup here.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700314 if (flags & REG_DEF_SP) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100315 def_mask->SetBit(kMipsRegSP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700316 }
317
318 if (flags & REG_USE_SP) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100319 use_mask->SetBit(kMipsRegSP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700320 }
321
322 if (flags & REG_DEF_LR) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100323 def_mask->SetBit(kMipsRegLR);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700324 }
buzbee9da5c102014-03-28 12:59:18 -0700325
Goran Jakovljevic10957932015-03-24 18:42:56 +0100326 if (!cu_->target64) {
327 if (flags & REG_DEF_HI) {
328 def_mask->SetBit(kMipsRegHI);
329 }
buzbee9da5c102014-03-28 12:59:18 -0700330
Goran Jakovljevic10957932015-03-24 18:42:56 +0100331 if (flags & REG_DEF_LO) {
332 def_mask->SetBit(kMipsRegLO);
333 }
buzbee9da5c102014-03-28 12:59:18 -0700334
Goran Jakovljevic10957932015-03-24 18:42:56 +0100335 if (flags & REG_USE_HI) {
336 use_mask->SetBit(kMipsRegHI);
337 }
buzbee9da5c102014-03-28 12:59:18 -0700338
Goran Jakovljevic10957932015-03-24 18:42:56 +0100339 if (flags & REG_USE_LO) {
340 use_mask->SetBit(kMipsRegLO);
341 }
buzbee9da5c102014-03-28 12:59:18 -0700342 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700343}
344
345/* For dumping instructions */
346#define MIPS_REG_COUNT 32
347static const char *mips_reg_name[MIPS_REG_COUNT] = {
348 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
349 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
350 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
351 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
352};
353
Goran Jakovljevic10957932015-03-24 18:42:56 +0100354static const char *mips64_reg_name[MIPS_REG_COUNT] = {
355 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
356 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
357 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
358 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
359};
360
Brian Carlstrom7940e442013-07-12 13:46:57 -0700361/*
362 * Interpret a format string and build a string no longer than size
Goran Jakovljevic10957932015-03-24 18:42:56 +0100363 * See format key in assemble_mips.cc.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700364 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700365std::string MipsMir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700366 std::string buf;
367 int i;
368 const char *fmt_end = &fmt[strlen(fmt)];
369 char tbuf[256];
370 char nc;
371 while (fmt < fmt_end) {
372 int operand;
373 if (*fmt == '!') {
374 fmt++;
375 DCHECK_LT(fmt, fmt_end);
376 nc = *fmt++;
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700377 if (nc == '!') {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700378 strcpy(tbuf, "!");
379 } else {
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800380 DCHECK_LT(fmt, fmt_end);
381 DCHECK_LT(static_cast<unsigned>(nc-'0'), 4u);
382 operand = lir->operands[nc-'0'];
383 switch (*fmt++) {
384 case 'b':
385 strcpy(tbuf, "0000");
386 for (i = 3; i >= 0; i--) {
387 tbuf[i] += operand & 1;
388 operand >>= 1;
389 }
390 break;
391 case 's':
392 snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
393 break;
394 case 'S':
395 DCHECK_EQ(RegStorage::RegNum(operand) & 1, 0);
396 snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
397 break;
398 case 'h':
399 snprintf(tbuf, arraysize(tbuf), "%04x", operand);
400 break;
401 case 'M':
402 case 'd':
403 snprintf(tbuf, arraysize(tbuf), "%d", operand);
404 break;
405 case 'D':
406 snprintf(tbuf, arraysize(tbuf), "%d", operand+1);
407 break;
408 case 'E':
409 snprintf(tbuf, arraysize(tbuf), "%d", operand*4);
410 break;
411 case 'F':
412 snprintf(tbuf, arraysize(tbuf), "%d", operand*2);
413 break;
414 case 't':
415 snprintf(tbuf, arraysize(tbuf), "0x%08" PRIxPTR " (L%p)",
416 reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 + (operand << 1),
417 lir->target);
418 break;
419 case 'T':
420 snprintf(tbuf, arraysize(tbuf), "0x%08x", operand << 2);
421 break;
422 case 'u': {
423 int offset_1 = lir->operands[0];
424 int offset_2 = NEXT_LIR(lir)->operands[0];
425 uintptr_t target =
426 (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) & ~3) +
427 (offset_1 << 21 >> 9) + (offset_2 << 1)) & 0xfffffffc;
428 snprintf(tbuf, arraysize(tbuf), "%p", reinterpret_cast<void*>(target));
429 break;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700430 }
431
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800432 /* Nothing to print for BLX_2 */
433 case 'v':
434 strcpy(tbuf, "see above");
435 break;
436 case 'r':
437 DCHECK(operand >= 0 && operand < MIPS_REG_COUNT);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100438 if (cu_->target64) {
439 strcpy(tbuf, mips64_reg_name[operand]);
440 } else {
441 strcpy(tbuf, mips_reg_name[operand]);
442 }
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800443 break;
444 case 'N':
445 // Placeholder for delay slot handling
446 strcpy(tbuf, "; nop");
447 break;
448 default:
449 strcpy(tbuf, "DecodeError");
450 break;
451 }
452 buf += tbuf;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700453 }
454 } else {
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800455 buf += *fmt++;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700456 }
457 }
458 return buf;
459}
460
Goran Jakovljevic10957932015-03-24 18:42:56 +0100461// FIXME: need to redo resource maps for MIPS - fix this at that time.
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100462void MipsMir2Lir::DumpResourceMask(LIR *mips_lir, const ResourceMask& mask, const char *prefix) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700463 char buf[256];
464 buf[0] = 0;
465
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100466 if (mask.Equals(kEncodeAll)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700467 strcpy(buf, "all");
468 } else {
469 char num[8];
470 int i;
471
Goran Jakovljevic10957932015-03-24 18:42:56 +0100472 for (i = 0; i < (cu_->target64 ? kMips64RegEnd : kMipsRegEnd); i++) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100473 if (mask.HasBit(i)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800474 snprintf(num, arraysize(num), "%d ", i);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700475 strcat(buf, num);
476 }
477 }
478
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100479 if (mask.HasBit(ResourceMask::kCCode)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700480 strcat(buf, "cc ");
481 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100482 if (mask.HasBit(ResourceMask::kFPStatus)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700483 strcat(buf, "fpcc ");
484 }
Goran Jakovljevic10957932015-03-24 18:42:56 +0100485 // Memory bits.
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100486 if (mips_lir && (mask.HasBit(ResourceMask::kDalvikReg))) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800487 snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s",
488 DECODE_ALIAS_INFO_REG(mips_lir->flags.alias_info),
489 DECODE_ALIAS_INFO_WIDE(mips_lir->flags.alias_info) ? "(+1)" : "");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700490 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100491 if (mask.HasBit(ResourceMask::kLiteral)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700492 strcat(buf, "lit ");
493 }
494
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100495 if (mask.HasBit(ResourceMask::kHeapRef)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700496 strcat(buf, "heap ");
497 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100498 if (mask.HasBit(ResourceMask::kMustNotAlias)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700499 strcat(buf, "noalias ");
500 }
501 }
502 if (buf[0]) {
503 LOG(INFO) << prefix << ": " << buf;
504 }
505}
506
507/*
508 * TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some
509 * instructions might call out to C/assembly helper functions. Until
510 * machinery is in place, always spill lr.
511 */
512
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700513void MipsMir2Lir::AdjustSpillMask() {
buzbee091cc402014-03-31 10:14:40 -0700514 core_spill_mask_ |= (1 << rs_rRA.GetRegNum());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700515 num_core_spills_++;
516}
517
Brian Carlstrom7940e442013-07-12 13:46:57 -0700518/* Clobber all regs that might be used by an external C call */
Vladimir Marko31c2aac2013-12-09 16:31:19 +0000519void MipsMir2Lir::ClobberCallerSave() {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100520 if (cu_->target64) {
521 Clobber(rs_rZEROd);
522 Clobber(rs_rATd);
523 Clobber(rs_rV0d);
524 Clobber(rs_rV1d);
525 Clobber(rs_rA0d);
526 Clobber(rs_rA1d);
527 Clobber(rs_rA2d);
528 Clobber(rs_rA3d);
529 Clobber(rs_rA4d);
530 Clobber(rs_rA5d);
531 Clobber(rs_rA6d);
532 Clobber(rs_rA7d);
533 Clobber(rs_rT0d);
534 Clobber(rs_rT1d);
535 Clobber(rs_rT2d);
536 Clobber(rs_rT3d);
537 Clobber(rs_rT8d);
538 Clobber(rs_rT9d);
539 Clobber(rs_rK0d);
540 Clobber(rs_rK1d);
541 Clobber(rs_rGPd);
542 Clobber(rs_rFPd);
543 Clobber(rs_rRAd);
544
545 Clobber(rs_rF0);
546 Clobber(rs_rF1);
547 Clobber(rs_rF2);
548 Clobber(rs_rF3);
549 Clobber(rs_rF4);
550 Clobber(rs_rF5);
551 Clobber(rs_rF6);
552 Clobber(rs_rF7);
553 Clobber(rs_rF8);
554 Clobber(rs_rF9);
555 Clobber(rs_rF10);
556 Clobber(rs_rF11);
557 Clobber(rs_rF12);
558 Clobber(rs_rF13);
559 Clobber(rs_rF14);
560 Clobber(rs_rF15);
561 Clobber(rs_rD0);
562 Clobber(rs_rD1);
563 Clobber(rs_rD2);
564 Clobber(rs_rD3);
565 Clobber(rs_rD4);
566 Clobber(rs_rD5);
567 Clobber(rs_rD6);
568 Clobber(rs_rD7);
Ian Rogersd582fa42014-11-05 23:46:43 -0800569 } else {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100570 Clobber(rs_rZERO);
571 Clobber(rs_rAT);
572 Clobber(rs_rV0);
573 Clobber(rs_rV1);
574 Clobber(rs_rA0);
575 Clobber(rs_rA1);
576 Clobber(rs_rA2);
577 Clobber(rs_rA3);
578 Clobber(rs_rT0_32);
579 Clobber(rs_rT1_32);
580 Clobber(rs_rT2_32);
581 Clobber(rs_rT3_32);
582 Clobber(rs_rT4_32);
583 Clobber(rs_rT5_32);
584 Clobber(rs_rT6_32);
585 Clobber(rs_rT7_32);
586 Clobber(rs_rT8);
587 Clobber(rs_rT9);
588 Clobber(rs_rK0);
589 Clobber(rs_rK1);
590 Clobber(rs_rGP);
591 Clobber(rs_rFP);
592 Clobber(rs_rRA);
593 Clobber(rs_rF0);
594 Clobber(rs_rF1);
595 Clobber(rs_rF2);
596 Clobber(rs_rF3);
597 Clobber(rs_rF4);
598 Clobber(rs_rF5);
599 Clobber(rs_rF6);
600 Clobber(rs_rF7);
601 Clobber(rs_rF8);
602 Clobber(rs_rF9);
603 Clobber(rs_rF10);
604 Clobber(rs_rF11);
605 Clobber(rs_rF12);
606 Clobber(rs_rF13);
607 Clobber(rs_rF14);
608 Clobber(rs_rF15);
609 if (fpuIs32Bit_) {
610 Clobber(rs_rD0_fr0);
611 Clobber(rs_rD1_fr0);
612 Clobber(rs_rD2_fr0);
613 Clobber(rs_rD3_fr0);
614 Clobber(rs_rD4_fr0);
615 Clobber(rs_rD5_fr0);
616 Clobber(rs_rD6_fr0);
617 Clobber(rs_rD7_fr0);
618 } else {
619 Clobber(rs_rD0_fr1);
620 Clobber(rs_rD1_fr1);
621 Clobber(rs_rD2_fr1);
622 Clobber(rs_rD3_fr1);
623 Clobber(rs_rD4_fr1);
624 Clobber(rs_rD5_fr1);
625 Clobber(rs_rD6_fr1);
626 Clobber(rs_rD7_fr1);
627 }
Ian Rogersd582fa42014-11-05 23:46:43 -0800628 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700629}
630
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700631RegLocation MipsMir2Lir::GetReturnWideAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700632 UNIMPLEMENTED(FATAL) << "No GetReturnWideAlt for MIPS";
633 RegLocation res = LocCReturnWide();
634 return res;
635}
636
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700637RegLocation MipsMir2Lir::GetReturnAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700638 UNIMPLEMENTED(FATAL) << "No GetReturnAlt for MIPS";
639 RegLocation res = LocCReturn();
640 return res;
641}
642
Brian Carlstrom7940e442013-07-12 13:46:57 -0700643/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700644void MipsMir2Lir::LockCallTemps() {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100645 LockTemp(TargetReg(kArg0));
646 LockTemp(TargetReg(kArg1));
647 LockTemp(TargetReg(kArg2));
648 LockTemp(TargetReg(kArg3));
649 if (cu_->target64) {
650 LockTemp(TargetReg(kArg4));
651 LockTemp(TargetReg(kArg5));
652 LockTemp(TargetReg(kArg6));
653 LockTemp(TargetReg(kArg7));
654 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700655}
656
657/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700658void MipsMir2Lir::FreeCallTemps() {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100659 FreeTemp(TargetReg(kArg0));
660 FreeTemp(TargetReg(kArg1));
661 FreeTemp(TargetReg(kArg2));
662 FreeTemp(TargetReg(kArg3));
663 if (cu_->target64) {
664 FreeTemp(TargetReg(kArg4));
665 FreeTemp(TargetReg(kArg5));
666 FreeTemp(TargetReg(kArg6));
667 FreeTemp(TargetReg(kArg7));
668 }
Vladimir Markobfe400b2014-12-19 19:27:26 +0000669 FreeTemp(TargetReg(kHiddenArg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700670}
671
Ian Rogersd582fa42014-11-05 23:46:43 -0800672bool MipsMir2Lir::GenMemBarrier(MemBarrierKind barrier_kind ATTRIBUTE_UNUSED) {
Andreas Gampe0b9203e2015-01-22 20:39:27 -0800673 if (cu_->compiler_driver->GetInstructionSetFeatures()->IsSmp()) {
Ian Rogersd582fa42014-11-05 23:46:43 -0800674 NewLIR1(kMipsSync, 0 /* Only stype currently supported */);
675 return true;
676 } else {
677 return false;
678 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700679}
680
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700681void MipsMir2Lir::CompilerInitializeRegAlloc() {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100682 if (cu_->target64) {
683 reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs_64, core_regs_64d, sp_regs_64,
684 dp_regs_64, reserved_regs_64, reserved_regs_64d,
685 core_temps_64, core_temps_64d, sp_temps_64,
686 dp_temps_64));
buzbee091cc402014-03-31 10:14:40 -0700687
Goran Jakovljevic10957932015-03-24 18:42:56 +0100688 // Alias single precision floats to appropriate half of overlapping double.
689 for (RegisterInfo* info : reg_pool_->sp_regs_) {
690 int sp_reg_num = info->GetReg().GetRegNum();
691 int dp_reg_num = sp_reg_num;
692 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
693 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
694 // Double precision register's master storage should refer to itself.
695 DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
696 // Redirect single precision's master storage to master.
697 info->SetMaster(dp_reg_info);
698 // Singles should show a single 32-bit mask bit, at first referring to the low half.
699 DCHECK_EQ(info->StorageMask(), 0x1U);
700 }
buzbee091cc402014-03-31 10:14:40 -0700701
Goran Jakovljevic10957932015-03-24 18:42:56 +0100702 // Alias 32bit W registers to corresponding 64bit X registers.
703 for (RegisterInfo* info : reg_pool_->core_regs_) {
704 int d_reg_num = info->GetReg().GetRegNum();
705 RegStorage d_reg = RegStorage::Solo64(d_reg_num);
706 RegisterInfo* d_reg_info = GetRegInfo(d_reg);
707 // 64bit D register's master storage should refer to itself.
708 DCHECK_EQ(d_reg_info, d_reg_info->Master());
709 // Redirect 32bit master storage to 64bit D.
710 info->SetMaster(d_reg_info);
711 // 32bit should show a single 32-bit mask bit, at first referring to the low half.
712 DCHECK_EQ(info->StorageMask(), 0x1U);
713 }
714 } else {
715 reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs_32, empty_pool, // core64
716 sp_regs_32,
717 fpuIs32Bit_ ? dp_fr0_regs_32 : dp_fr1_regs_32,
718 reserved_regs_32, empty_pool, // reserved64
719 core_temps_32, empty_pool, // core64_temps
720 sp_temps_32,
721 fpuIs32Bit_ ? dp_fr0_temps_32 : dp_fr1_temps_32));
722
723 // Alias single precision floats to appropriate half of overlapping double.
724 for (RegisterInfo* info : reg_pool_->sp_regs_) {
725 int sp_reg_num = info->GetReg().GetRegNum();
726 int dp_reg_num = sp_reg_num & ~1;
727 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
728 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
729 // Double precision register's master storage should refer to itself.
730 DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
731 // Redirect single precision's master storage to master.
732 info->SetMaster(dp_reg_info);
733 // Singles should show a single 32-bit mask bit, at first referring to the low half.
734 DCHECK_EQ(info->StorageMask(), 0x1U);
735 if (sp_reg_num & 1) {
736 // For odd singles, change to user the high word of the backing double.
737 info->SetStorageMask(0x2);
738 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700739 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700740 }
buzbee091cc402014-03-31 10:14:40 -0700741
742 // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
743 // TODO: adjust when we roll to hard float calling convention.
744 reg_pool_->next_core_reg_ = 2;
745 reg_pool_->next_sp_reg_ = 2;
Goran Jakovljevic10957932015-03-24 18:42:56 +0100746 if (cu_->target64) {
747 reg_pool_->next_dp_reg_ = 1;
748 } else {
749 reg_pool_->next_dp_reg_ = 2;
750 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700751}
752
Brian Carlstrom7940e442013-07-12 13:46:57 -0700753/*
754 * In the Arm code a it is typical to use the link register
755 * to hold the target address. However, for Mips we must
756 * ensure that all branch instructions can be restarted if
757 * there is a trap in the shadow. Allocate a temp register.
758 */
Andreas Gampe98430592014-07-27 19:44:50 -0700759RegStorage MipsMir2Lir::LoadHelper(QuickEntrypointEnum trampoline) {
buzbee695d13a2014-04-19 13:32:20 -0700760 // NOTE: native pointer.
Goran Jakovljevic10957932015-03-24 18:42:56 +0100761 if (cu_->target64) {
762 LoadWordDisp(TargetPtrReg(kSelf), GetThreadOffset<8>(trampoline).Int32Value(),
763 TargetPtrReg(kInvokeTgt));
764 } else {
765 LoadWordDisp(TargetPtrReg(kSelf), GetThreadOffset<4>(trampoline).Int32Value(),
766 TargetPtrReg(kInvokeTgt));
767 }
768 return TargetPtrReg(kInvokeTgt);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700769}
770
Dave Allisonb373e092014-02-20 16:06:36 -0800771LIR* MipsMir2Lir::CheckSuspendUsingLoad() {
buzbee2700f7e2014-03-07 09:46:20 -0800772 RegStorage tmp = AllocTemp();
buzbee695d13a2014-04-19 13:32:20 -0700773 // NOTE: native pointer.
Goran Jakovljevic10957932015-03-24 18:42:56 +0100774 if (cu_->target64) {
775 LoadWordDisp(TargetPtrReg(kSelf), Thread::ThreadSuspendTriggerOffset<8>().Int32Value(), tmp);
776 } else {
777 LoadWordDisp(TargetPtrReg(kSelf), Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
778 }
Dave Allisonb373e092014-02-20 16:06:36 -0800779 LIR *inst = LoadWordDisp(tmp, 0, tmp);
780 FreeTemp(tmp);
781 return inst;
782}
783
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700784LIR* MipsMir2Lir::GenAtomic64Load(RegStorage r_base, int displacement, RegStorage r_dest) {
785 DCHECK(!r_dest.IsFloat()); // See RegClassForFieldLoadStore().
Goran Jakovljevic10957932015-03-24 18:42:56 +0100786 if (!cu_->target64) {
787 DCHECK(r_dest.IsPair());
788 }
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700789 ClobberCallerSave();
Goran Jakovljevic10957932015-03-24 18:42:56 +0100790 LockCallTemps(); // Using fixed registers.
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700791 RegStorage reg_ptr = TargetReg(kArg0);
792 OpRegRegImm(kOpAdd, reg_ptr, r_base, displacement);
Andreas Gampe98430592014-07-27 19:44:50 -0700793 RegStorage r_tgt = LoadHelper(kQuickA64Load);
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700794 LIR *ret = OpReg(kOpBlx, r_tgt);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100795 RegStorage reg_ret;
796 if (cu_->target64) {
797 OpRegCopy(r_dest, TargetReg(kRet0));
798 } else {
799 reg_ret = RegStorage::MakeRegPair(TargetReg(kRet0), TargetReg(kRet1));
800 OpRegCopyWide(r_dest, reg_ret);
801 }
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700802 return ret;
803}
804
805LIR* MipsMir2Lir::GenAtomic64Store(RegStorage r_base, int displacement, RegStorage r_src) {
806 DCHECK(!r_src.IsFloat()); // See RegClassForFieldLoadStore().
Goran Jakovljevic10957932015-03-24 18:42:56 +0100807 if (cu_->target64) {
808 DCHECK(!r_src.IsPair());
809 } else {
810 DCHECK(r_src.IsPair());
811 }
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700812 ClobberCallerSave();
Goran Jakovljevic10957932015-03-24 18:42:56 +0100813 LockCallTemps(); // Using fixed registers.
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700814 RegStorage temp_ptr = AllocTemp();
815 OpRegRegImm(kOpAdd, temp_ptr, r_base, displacement);
816 RegStorage temp_value = AllocTempWide();
817 OpRegCopyWide(temp_value, r_src);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100818 if (cu_->target64) {
819 OpRegCopyWide(TargetReg(kArg0, kWide), temp_ptr);
820 OpRegCopyWide(TargetReg(kArg1, kWide), temp_value);
821 } else {
822 RegStorage reg_ptr = TargetReg(kArg0);
823 OpRegCopy(reg_ptr, temp_ptr);
824 RegStorage reg_value = RegStorage::MakeRegPair(TargetReg(kArg2), TargetReg(kArg3));
825 OpRegCopyWide(reg_value, temp_value);
826 }
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700827 FreeTemp(temp_ptr);
828 FreeTemp(temp_value);
Andreas Gampe98430592014-07-27 19:44:50 -0700829 RegStorage r_tgt = LoadHelper(kQuickA64Store);
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700830 return OpReg(kOpBlx, r_tgt);
831}
832
David Srbecky1109fb32015-04-07 20:21:06 +0100833static dwarf::Reg DwarfCoreReg(int num) {
834 return dwarf::Reg::MipsCore(num);
835}
836
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700837void MipsMir2Lir::SpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700838 if (num_core_spills_ == 0) {
839 return;
840 }
841 uint32_t mask = core_spill_mask_;
Goran Jakovljevic10957932015-03-24 18:42:56 +0100842 int ptr_size = cu_->target64 ? 8 : 4;
843 int offset = num_core_spills_ * ptr_size;
844 const RegStorage rs_sp = TargetPtrReg(kSp);
845 OpRegImm(kOpSub, rs_sp, offset);
David Srbecky1109fb32015-04-07 20:21:06 +0100846 cfi_.AdjustCFAOffset(offset);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700847 for (int reg = 0; mask; mask >>= 1, reg++) {
848 if (mask & 0x1) {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100849 offset -= ptr_size;
850 StoreWordDisp(rs_sp, offset,
851 cu_->target64 ? RegStorage::Solo64(reg) : RegStorage::Solo32(reg));
David Srbecky1109fb32015-04-07 20:21:06 +0100852 cfi_.RelOffset(DwarfCoreReg(reg), offset);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700853 }
854 }
855}
856
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700857void MipsMir2Lir::UnSpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700858 if (num_core_spills_ == 0) {
859 return;
860 }
861 uint32_t mask = core_spill_mask_;
Goran Jakovljevic10957932015-03-24 18:42:56 +0100862 int offset = frame_size_;
863 int ptr_size = cu_->target64 ? 8 : 4;
864 const RegStorage rs_sp = TargetPtrReg(kSp);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700865 for (int reg = 0; mask; mask >>= 1, reg++) {
866 if (mask & 0x1) {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100867 offset -= ptr_size;
868 LoadWordDisp(rs_sp, offset,
869 cu_->target64 ? RegStorage::Solo64(reg) : RegStorage::Solo32(reg));
David Srbecky1109fb32015-04-07 20:21:06 +0100870 cfi_.Restore(DwarfCoreReg(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700871 }
872 }
Goran Jakovljevic10957932015-03-24 18:42:56 +0100873 OpRegImm(kOpAdd, rs_sp, frame_size_);
David Srbecky1109fb32015-04-07 20:21:06 +0100874 cfi_.AdjustCFAOffset(-frame_size_);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700875}
876
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700877bool MipsMir2Lir::IsUnconditionalBranch(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700878 return (lir->opcode == kMipsB);
879}
880
Vladimir Marko674744e2014-04-24 15:18:26 +0100881RegisterClass MipsMir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) {
Douglas Leung2db3e262014-06-25 16:02:55 -0700882 if (UNLIKELY(is_volatile)) {
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700883 // On Mips, atomic 64-bit load/store requires a core register.
Douglas Leung2db3e262014-06-25 16:02:55 -0700884 // Smaller aligned load/store is atomic for both core and fp registers.
885 if (size == k64 || size == kDouble) {
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700886 return kCoreReg;
Douglas Leung2db3e262014-06-25 16:02:55 -0700887 }
888 }
Vladimir Marko674744e2014-04-24 15:18:26 +0100889 // TODO: Verify that both core and fp registers are suitable for smaller sizes.
890 return RegClassBySize(size);
891}
892
Brian Carlstrom7940e442013-07-12 13:46:57 -0700893MipsMir2Lir::MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
Goran Jakovljevic10957932015-03-24 18:42:56 +0100894 : Mir2Lir(cu, mir_graph, arena), in_to_reg_storage_mips64_mapper_(this),
895 in_to_reg_storage_mips_mapper_(this),
896 isaIsR6_(cu_->target64 ? true : cu->compiler_driver->GetInstructionSetFeatures()
897 ->AsMipsInstructionSetFeatures()->IsR6()),
898 fpuIs32Bit_(cu_->target64 ? false : cu->compiler_driver->GetInstructionSetFeatures()
899 ->AsMipsInstructionSetFeatures()->Is32BitFloatingPoint()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700900 for (int i = 0; i < kMipsLast; i++) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700901 DCHECK_EQ(MipsMir2Lir::EncodingMap[i].opcode, i)
902 << "Encoding order for " << MipsMir2Lir::EncodingMap[i].name
903 << " is wrong: expecting " << i << ", seeing "
904 << static_cast<int>(MipsMir2Lir::EncodingMap[i].opcode);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700905 }
906}
907
908Mir2Lir* MipsCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
909 ArenaAllocator* const arena) {
910 return new MipsMir2Lir(cu, mir_graph, arena);
911}
912
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700913uint64_t MipsMir2Lir::GetTargetInstFlags(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700914 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700915 return MipsMir2Lir::EncodingMap[opcode].flags;
916}
917
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700918const char* MipsMir2Lir::GetTargetInstName(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700919 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700920 return MipsMir2Lir::EncodingMap[opcode].name;
921}
922
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700923const char* MipsMir2Lir::GetTargetInstFmt(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700924 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700925 return MipsMir2Lir::EncodingMap[opcode].fmt;
926}
927
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700928} // namespace art