blob: 8abd592c2677a19ce68ba889247df8e5bb8d852b [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};
Goran Jakovljevicfc8156a2015-07-28 14:26:12 +020052static constexpr RegStorage sp_fr0_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 Jakovljevicfc8156a2015-07-28 14:26:12 +020055static constexpr RegStorage sp_fr1_temps_arr_32[] =
56 {rs_rF0, rs_rF2, rs_rF4, rs_rF6, rs_rF8, rs_rF10, rs_rF12, rs_rF14};
Goran Jakovljevic10957932015-03-24 18:42:56 +010057static constexpr RegStorage dp_fr0_temps_arr_32[] =
Ian Rogersd582fa42014-11-05 23:46:43 -080058 {rs_rD0_fr0, rs_rD1_fr0, rs_rD2_fr0, rs_rD3_fr0, rs_rD4_fr0, rs_rD5_fr0, rs_rD6_fr0,
59 rs_rD7_fr0};
Goran Jakovljevic10957932015-03-24 18:42:56 +010060static constexpr RegStorage dp_fr1_temps_arr_32[] =
Ian Rogersd582fa42014-11-05 23:46:43 -080061 {rs_rD0_fr1, rs_rD1_fr1, rs_rD2_fr1, rs_rD3_fr1, rs_rD4_fr1, rs_rD5_fr1, rs_rD6_fr1,
62 rs_rD7_fr1};
buzbee091cc402014-03-31 10:14:40 -070063
Goran Jakovljevic10957932015-03-24 18:42:56 +010064static constexpr RegStorage core_regs_arr_64[] =
65 {rs_rZERO, rs_rAT, rs_rV0, rs_rV1, rs_rA0, rs_rA1, rs_rA2, rs_rA3, rs_rA4, rs_rA5, rs_rA6,
66 rs_rA7, rs_rT0, rs_rT1, rs_rT2, rs_rT3, rs_rS0, rs_rS1, rs_rS2, rs_rS3, rs_rS4, rs_rS5, rs_rS6,
67 rs_rS7, rs_rT8, rs_rT9, rs_rK0, rs_rK1, rs_rGP, rs_rSP, rs_rFP, rs_rRA};
68static constexpr RegStorage core_regs_arr_64d[] =
69 {rs_rZEROd, rs_rATd, rs_rV0d, rs_rV1d, rs_rA0d, rs_rA1d, rs_rA2d, rs_rA3d, rs_rA4d, rs_rA5d,
70 rs_rA6d, rs_rA7d, rs_rT0d, rs_rT1d, rs_rT2d, rs_rT3d, rs_rS0d, rs_rS1d, rs_rS2d, rs_rS3d,
71 rs_rS4d, rs_rS5d, rs_rS6d, rs_rS7d, rs_rT8d, rs_rT9d, rs_rK0d, rs_rK1d, rs_rGPd, rs_rSPd,
72 rs_rFPd, rs_rRAd};
73#if 0
74// TODO: f24-f31 must be saved before calls and restored after.
75static constexpr RegStorage sp_regs_arr_64[] =
76 {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
77 rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15, rs_rF16, rs_rF17, rs_rF18, rs_rF19, rs_rF20,
78 rs_rF21, rs_rF22, rs_rF23, rs_rF24, rs_rF25, rs_rF26, rs_rF27, rs_rF28, rs_rF29, rs_rF30,
79 rs_rF31};
80static constexpr RegStorage dp_regs_arr_64[] =
81 {rs_rD0, rs_rD1, rs_rD2, rs_rD3, rs_rD4, rs_rD5, rs_rD6, rs_rD7, rs_rD8, rs_rD9, rs_rD10,
82 rs_rD11, rs_rD12, rs_rD13, rs_rD14, rs_rD15, rs_rD16, rs_rD17, rs_rD18, rs_rD19, rs_rD20,
83 rs_rD21, rs_rD22, rs_rD23, rs_rD24, rs_rD25, rs_rD26, rs_rD27, rs_rD28, rs_rD29, rs_rD30,
84 rs_rD31};
85#else
86static constexpr RegStorage sp_regs_arr_64[] =
87 {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
88 rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15, rs_rF16, rs_rF17, rs_rF18, rs_rF19, rs_rF20,
89 rs_rF21, rs_rF22, rs_rF23};
90static constexpr RegStorage dp_regs_arr_64[] =
91 {rs_rD0, rs_rD1, rs_rD2, rs_rD3, rs_rD4, rs_rD5, rs_rD6, rs_rD7, rs_rD8, rs_rD9, rs_rD10,
92 rs_rD11, rs_rD12, rs_rD13, rs_rD14, rs_rD15, rs_rD16, rs_rD17, rs_rD18, rs_rD19, rs_rD20,
93 rs_rD21, rs_rD22, rs_rD23};
94#endif
95static constexpr RegStorage reserved_regs_arr_64[] =
96 {rs_rZERO, rs_rAT, rs_rS0, rs_rS1, rs_rT9, rs_rK0, rs_rK1, rs_rGP, rs_rSP, rs_rRA};
97static constexpr RegStorage reserved_regs_arr_64d[] =
98 {rs_rZEROd, rs_rATd, rs_rS0d, rs_rS1d, rs_rT9d, rs_rK0d, rs_rK1d, rs_rGPd, rs_rSPd, rs_rRAd};
99static constexpr RegStorage core_temps_arr_64[] =
100 {rs_rV0, rs_rV1, rs_rA0, rs_rA1, rs_rA2, rs_rA3, rs_rA4, rs_rA5, rs_rA6, rs_rA7, rs_rT0, rs_rT1,
101 rs_rT2, rs_rT3, rs_rT8};
102static constexpr RegStorage core_temps_arr_64d[] =
103 {rs_rV0d, rs_rV1d, rs_rA0d, rs_rA1d, rs_rA2d, rs_rA3d, rs_rA4d, rs_rA5d, rs_rA6d, rs_rA7d,
104 rs_rT0d, rs_rT1d, rs_rT2d, rs_rT3d, rs_rT8d};
105#if 0
106// TODO: f24-f31 must be saved before calls and restored after.
107static constexpr RegStorage sp_temps_arr_64[] =
108 {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
109 rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15, rs_rF16, rs_rF17, rs_rF18, rs_rF19, rs_rF20,
110 rs_rF21, rs_rF22, rs_rF23, rs_rF24, rs_rF25, rs_rF26, rs_rF27, rs_rF28, rs_rF29, rs_rF30,
111 rs_rF31};
112static constexpr RegStorage dp_temps_arr_64[] =
113 {rs_rD0, rs_rD1, rs_rD2, rs_rD3, rs_rD4, rs_rD5, rs_rD6, rs_rD7, rs_rD8, rs_rD9, rs_rD10,
114 rs_rD11, rs_rD12, rs_rD13, rs_rD14, rs_rD15, rs_rD16, rs_rD17, rs_rD18, rs_rD19, rs_rD20,
115 rs_rD21, rs_rD22, rs_rD23, rs_rD24, rs_rD25, rs_rD26, rs_rD27, rs_rD28, rs_rD29, rs_rD30,
116 rs_rD31};
117#else
118static constexpr RegStorage sp_temps_arr_64[] =
119 {rs_rF0, rs_rF1, rs_rF2, rs_rF3, rs_rF4, rs_rF5, rs_rF6, rs_rF7, rs_rF8, rs_rF9, rs_rF10,
120 rs_rF11, rs_rF12, rs_rF13, rs_rF14, rs_rF15, rs_rF16, rs_rF17, rs_rF18, rs_rF19, rs_rF20,
121 rs_rF21, rs_rF22, rs_rF23};
122static constexpr RegStorage dp_temps_arr_64[] =
123 {rs_rD0, rs_rD1, rs_rD2, rs_rD3, rs_rD4, rs_rD5, rs_rD6, rs_rD7, rs_rD8, rs_rD9, rs_rD10,
124 rs_rD11, rs_rD12, rs_rD13, rs_rD14, rs_rD15, rs_rD16, rs_rD17, rs_rD18, rs_rD19, rs_rD20,
125 rs_rD21, rs_rD22, rs_rD23};
126#endif
127
Vladimir Marko089142c2014-06-05 10:57:05 +0100128static constexpr ArrayRef<const RegStorage> empty_pool;
Goran Jakovljevic10957932015-03-24 18:42:56 +0100129static constexpr ArrayRef<const RegStorage> core_regs_32(core_regs_arr_32);
130static constexpr ArrayRef<const RegStorage> sp_regs_32(sp_regs_arr_32);
131static constexpr ArrayRef<const RegStorage> dp_fr0_regs_32(dp_fr0_regs_arr_32);
132static constexpr ArrayRef<const RegStorage> dp_fr1_regs_32(dp_fr1_regs_arr_32);
133static constexpr ArrayRef<const RegStorage> reserved_regs_32(reserved_regs_arr_32);
134static constexpr ArrayRef<const RegStorage> core_temps_32(core_temps_arr_32);
Goran Jakovljevicfc8156a2015-07-28 14:26:12 +0200135static constexpr ArrayRef<const RegStorage> sp_fr0_temps_32(sp_fr0_temps_arr_32);
136static constexpr ArrayRef<const RegStorage> sp_fr1_temps_32(sp_fr1_temps_arr_32);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100137static constexpr ArrayRef<const RegStorage> dp_fr0_temps_32(dp_fr0_temps_arr_32);
138static constexpr ArrayRef<const RegStorage> dp_fr1_temps_32(dp_fr1_temps_arr_32);
139
140static constexpr ArrayRef<const RegStorage> core_regs_64(core_regs_arr_64);
141static constexpr ArrayRef<const RegStorage> core_regs_64d(core_regs_arr_64d);
142static constexpr ArrayRef<const RegStorage> sp_regs_64(sp_regs_arr_64);
143static constexpr ArrayRef<const RegStorage> dp_regs_64(dp_regs_arr_64);
144static constexpr ArrayRef<const RegStorage> reserved_regs_64(reserved_regs_arr_64);
145static constexpr ArrayRef<const RegStorage> reserved_regs_64d(reserved_regs_arr_64d);
146static constexpr ArrayRef<const RegStorage> core_temps_64(core_temps_arr_64);
147static constexpr ArrayRef<const RegStorage> core_temps_64d(core_temps_arr_64d);
148static constexpr ArrayRef<const RegStorage> sp_temps_64(sp_temps_arr_64);
149static constexpr ArrayRef<const RegStorage> dp_temps_64(dp_temps_arr_64);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700150
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700151RegLocation MipsMir2Lir::LocCReturn() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000152 return mips_loc_c_return;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700153}
154
buzbeea0cd2d72014-06-01 09:33:49 -0700155RegLocation MipsMir2Lir::LocCReturnRef() {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100156 return cu_->target64 ? mips64_loc_c_return_ref : mips_loc_c_return;
buzbeea0cd2d72014-06-01 09:33:49 -0700157}
158
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700159RegLocation MipsMir2Lir::LocCReturnWide() {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100160 return cu_->target64 ? mips64_loc_c_return_wide : mips_loc_c_return_wide;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700161}
162
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700163RegLocation MipsMir2Lir::LocCReturnFloat() {
Bill Buzbee00e1ec62014-02-27 23:44:13 +0000164 return mips_loc_c_return_float;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700165}
166
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700167RegLocation MipsMir2Lir::LocCReturnDouble() {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100168 if (cu_->target64) {
169 return mips64_loc_c_return_double;
170 } else if (fpuIs32Bit_) {
171 return mips_loc_c_return_double_fr0;
Douglas Leung027f0ff2015-02-27 19:05:03 -0800172 } else {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100173 return mips_loc_c_return_double_fr1;
Douglas Leung027f0ff2015-02-27 19:05:03 -0800174 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700175}
176
Goran Jakovljevic10957932015-03-24 18:42:56 +0100177// Convert k64BitSolo into k64BitPair.
Douglas Leung2db3e262014-06-25 16:02:55 -0700178RegStorage MipsMir2Lir::Solo64ToPair64(RegStorage reg) {
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800179 DCHECK(reg.IsDouble());
Douglas Leung027f0ff2015-02-27 19:05:03 -0800180 DCHECK_EQ(reg.GetRegNum() & 1, 0);
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800181 int reg_num = (reg.GetRegNum() & ~1) | RegStorage::kFloatingPoint;
182 return RegStorage(RegStorage::k64BitPair, reg_num, reg_num + 1);
Douglas Leung2db3e262014-06-25 16:02:55 -0700183}
184
Douglas Leung027f0ff2015-02-27 19:05:03 -0800185// Convert 64bit FP (k64BitSolo or k64BitPair) into k32BitSolo.
186// This routine is only used to allow a 64bit FPU to access FP registers 32bits at a time.
187RegStorage MipsMir2Lir::Fp64ToSolo32(RegStorage reg) {
188 DCHECK(!fpuIs32Bit_);
189 DCHECK(reg.IsDouble());
190 DCHECK(!reg.IsPair());
191 int reg_num = reg.GetRegNum() | RegStorage::kFloatingPoint;
192 return RegStorage(RegStorage::k32BitSolo, reg_num);
193}
194
195// Return a target-dependent special register.
196RegStorage MipsMir2Lir::TargetReg(SpecialTargetRegister reg, WideKind wide_kind) {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100197 if (!cu_->target64 && wide_kind == kWide) {
Goran Jakovljevica29449d2015-07-22 11:08:57 +0200198 DCHECK((kArg0 <= reg && reg < kArg7) || (kFArg0 == reg) || (kFArg2 == reg) || (kRet0 == reg));
Goran Jakovljevic10957932015-03-24 18:42:56 +0100199 RegStorage ret_reg = RegStorage::MakeRegPair(TargetReg(reg),
200 TargetReg(static_cast<SpecialTargetRegister>(reg + 1)));
201 if (!fpuIs32Bit_ && ret_reg.IsFloat()) {
202 // convert 64BitPair to 64BitSolo for 64bit FPUs.
203 RegStorage low = ret_reg.GetLow();
204 ret_reg = RegStorage::FloatSolo64(low.GetRegNum());
205 }
206 return ret_reg;
207 } else if (cu_->target64 && (wide_kind == kWide || wide_kind == kRef)) {
208 return As64BitReg(TargetReg(reg));
Douglas Leung027f0ff2015-02-27 19:05:03 -0800209 } else {
210 return TargetReg(reg);
211 }
212}
213
Brian Carlstrom7940e442013-07-12 13:46:57 -0700214// Return a target-dependent special register.
buzbee2700f7e2014-03-07 09:46:20 -0800215RegStorage MipsMir2Lir::TargetReg(SpecialTargetRegister reg) {
buzbee091cc402014-03-31 10:14:40 -0700216 RegStorage res_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700217 switch (reg) {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100218 case kSelf: res_reg = rs_rS1; break;
219 case kSuspend: res_reg = rs_rS0; break;
220 case kLr: res_reg = rs_rRA; break;
221 case kPc: res_reg = RegStorage::InvalidReg(); break;
222 case kSp: res_reg = rs_rSP; break;
223 case kArg0: res_reg = rs_rA0; break;
224 case kArg1: res_reg = rs_rA1; break;
225 case kArg2: res_reg = rs_rA2; break;
226 case kArg3: res_reg = rs_rA3; break;
227 case kArg4: res_reg = cu_->target64 ? rs_rA4 : RegStorage::InvalidReg(); break;
228 case kArg5: res_reg = cu_->target64 ? rs_rA5 : RegStorage::InvalidReg(); break;
229 case kArg6: res_reg = cu_->target64 ? rs_rA6 : RegStorage::InvalidReg(); break;
230 case kArg7: res_reg = cu_->target64 ? rs_rA7 : RegStorage::InvalidReg(); break;
231 case kFArg0: res_reg = rs_rF12; break;
232 case kFArg1: res_reg = rs_rF13; break;
233 case kFArg2: res_reg = rs_rF14; break;
234 case kFArg3: res_reg = rs_rF15; break;
235 case kFArg4: res_reg = cu_->target64 ? rs_rF16 : RegStorage::InvalidReg(); break;
236 case kFArg5: res_reg = cu_->target64 ? rs_rF17 : RegStorage::InvalidReg(); break;
237 case kFArg6: res_reg = cu_->target64 ? rs_rF18 : RegStorage::InvalidReg(); break;
238 case kFArg7: res_reg = cu_->target64 ? rs_rF19 : RegStorage::InvalidReg(); break;
239 case kRet0: res_reg = rs_rV0; break;
240 case kRet1: res_reg = rs_rV1; break;
241 case kInvokeTgt: res_reg = rs_rT9; break;
242 case kHiddenArg: res_reg = cu_->target64 ? rs_rT0 : rs_rT0_32; break;
buzbee091cc402014-03-31 10:14:40 -0700243 case kHiddenFpArg: res_reg = RegStorage::InvalidReg(); break;
Goran Jakovljevic10957932015-03-24 18:42:56 +0100244 case kCount: res_reg = RegStorage::InvalidReg(); break;
Dmitry Petrochenko58994cd2014-05-17 01:02:18 +0700245 default: res_reg = RegStorage::InvalidReg();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700246 }
buzbee091cc402014-03-31 10:14:40 -0700247 return res_reg;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700248}
249
Serguei Katkov717a3e42014-11-13 17:19:42 +0600250RegStorage MipsMir2Lir::InToRegStorageMipsMapper::GetNextReg(ShortyArg arg) {
251 const SpecialTargetRegister coreArgMappingToPhysicalReg[] = {kArg1, kArg2, kArg3};
252 const size_t coreArgMappingToPhysicalRegSize = arraysize(coreArgMappingToPhysicalReg);
Goran Jakovljevica29449d2015-07-22 11:08:57 +0200253 const SpecialTargetRegister fpuArgMappingToPhysicalReg[] = {kFArg0, kFArg2};
254 const size_t fpuArgMappingToPhysicalRegSize = arraysize(fpuArgMappingToPhysicalReg);
Serguei Katkov717a3e42014-11-13 17:19:42 +0600255
256 RegStorage result = RegStorage::InvalidReg();
Goran Jakovljevica29449d2015-07-22 11:08:57 +0200257 if (arg.IsFP()) {
258 if (cur_fpu_reg_ < fpuArgMappingToPhysicalRegSize) {
259 result = m2l_->TargetReg(fpuArgMappingToPhysicalReg[cur_fpu_reg_++],
260 arg.IsWide() ? kWide : kNotWide);
261 }
262 } else {
263 if (cur_core_reg_ < coreArgMappingToPhysicalRegSize) {
264 if (arg.IsWide() && cur_core_reg_ == 0) {
265 // Don't use a1-a2 as a register pair, move to a2-a3 instead.
266 cur_core_reg_++;
267 }
268 result = m2l_->TargetReg(coreArgMappingToPhysicalReg[cur_core_reg_++],
269 arg.IsRef() ? kRef : kNotWide);
270 if (arg.IsWide() && cur_core_reg_ < coreArgMappingToPhysicalRegSize) {
271 result = RegStorage::MakeRegPair(
272 result, m2l_->TargetReg(coreArgMappingToPhysicalReg[cur_core_reg_++], kNotWide));
273 }
Serguei Katkov717a3e42014-11-13 17:19:42 +0600274 }
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800275 }
Serguei Katkov717a3e42014-11-13 17:19:42 +0600276 return result;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800277}
278
Goran Jakovljevic10957932015-03-24 18:42:56 +0100279RegStorage MipsMir2Lir::InToRegStorageMips64Mapper::GetNextReg(ShortyArg arg) {
280 const SpecialTargetRegister coreArgMappingToPhysicalReg[] =
281 {kArg1, kArg2, kArg3, kArg4, kArg5, kArg6, kArg7};
282 const size_t coreArgMappingToPhysicalRegSize = arraysize(coreArgMappingToPhysicalReg);
283 const SpecialTargetRegister fpArgMappingToPhysicalReg[] =
284 {kFArg1, kFArg2, kFArg3, kFArg4, kFArg5, kFArg6, kFArg7};
285 const size_t fpArgMappingToPhysicalRegSize = arraysize(fpArgMappingToPhysicalReg);
286
287 RegStorage result = RegStorage::InvalidReg();
288 if (arg.IsFP()) {
289 if (cur_arg_reg_ < fpArgMappingToPhysicalRegSize) {
290 DCHECK(!arg.IsRef());
291 result = m2l_->TargetReg(fpArgMappingToPhysicalReg[cur_arg_reg_++],
292 arg.IsWide() ? kWide : kNotWide);
293 }
294 } else {
295 if (cur_arg_reg_ < coreArgMappingToPhysicalRegSize) {
296 DCHECK(!(arg.IsWide() && arg.IsRef()));
297 result = m2l_->TargetReg(coreArgMappingToPhysicalReg[cur_arg_reg_++],
298 arg.IsRef() ? kRef : (arg.IsWide() ? kWide : kNotWide));
299 }
300 }
301 return result;
302}
303
Brian Carlstrom7940e442013-07-12 13:46:57 -0700304/*
305 * Decode the register id.
306 */
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100307ResourceMask MipsMir2Lir::GetRegMaskCommon(const RegStorage& reg) const {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100308 if (cu_->target64) {
309 return ResourceMask::Bit((reg.IsFloat() ? kMipsFPReg0 : 0) + reg.GetRegNum());
Ian Rogersd582fa42014-11-05 23:46:43 -0800310 } else {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100311 if (reg.IsDouble()) {
312 return ResourceMask::TwoBits((reg.GetRegNum() & ~1) + kMipsFPReg0);
313 } else if (reg.IsSingle()) {
314 return ResourceMask::Bit(reg.GetRegNum() + kMipsFPReg0);
315 } else {
316 return ResourceMask::Bit(reg.GetRegNum());
317 }
Ian Rogersd582fa42014-11-05 23:46:43 -0800318 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700319}
320
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100321ResourceMask MipsMir2Lir::GetPCUseDefEncoding() const {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100322 return cu_->target64 ? ResourceMask::Bit(kMips64RegPC) : ResourceMask::Bit(kMipsRegPC);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700323}
324
Goran Jakovljevic10957932015-03-24 18:42:56 +0100325void MipsMir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags, ResourceMask* use_mask,
326 ResourceMask* def_mask) {
buzbeeb48819d2013-09-14 16:15:25 -0700327 DCHECK(!lir->flags.use_def_invalid);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700328
329 // Mips-specific resource map setup here.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700330 if (flags & REG_DEF_SP) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100331 def_mask->SetBit(kMipsRegSP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700332 }
333
334 if (flags & REG_USE_SP) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100335 use_mask->SetBit(kMipsRegSP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700336 }
337
338 if (flags & REG_DEF_LR) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100339 def_mask->SetBit(kMipsRegLR);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700340 }
buzbee9da5c102014-03-28 12:59:18 -0700341
Goran Jakovljevic10957932015-03-24 18:42:56 +0100342 if (!cu_->target64) {
343 if (flags & REG_DEF_HI) {
344 def_mask->SetBit(kMipsRegHI);
345 }
buzbee9da5c102014-03-28 12:59:18 -0700346
Goran Jakovljevic10957932015-03-24 18:42:56 +0100347 if (flags & REG_DEF_LO) {
348 def_mask->SetBit(kMipsRegLO);
349 }
buzbee9da5c102014-03-28 12:59:18 -0700350
Goran Jakovljevic10957932015-03-24 18:42:56 +0100351 if (flags & REG_USE_HI) {
352 use_mask->SetBit(kMipsRegHI);
353 }
buzbee9da5c102014-03-28 12:59:18 -0700354
Goran Jakovljevic10957932015-03-24 18:42:56 +0100355 if (flags & REG_USE_LO) {
356 use_mask->SetBit(kMipsRegLO);
357 }
buzbee9da5c102014-03-28 12:59:18 -0700358 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700359}
360
361/* For dumping instructions */
362#define MIPS_REG_COUNT 32
363static const char *mips_reg_name[MIPS_REG_COUNT] = {
364 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
365 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
366 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
367 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
368};
369
Goran Jakovljevic10957932015-03-24 18:42:56 +0100370static const char *mips64_reg_name[MIPS_REG_COUNT] = {
371 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
372 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
373 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
374 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
375};
376
Brian Carlstrom7940e442013-07-12 13:46:57 -0700377/*
378 * Interpret a format string and build a string no longer than size
Goran Jakovljevic10957932015-03-24 18:42:56 +0100379 * See format key in assemble_mips.cc.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700380 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700381std::string MipsMir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700382 std::string buf;
383 int i;
384 const char *fmt_end = &fmt[strlen(fmt)];
385 char tbuf[256];
386 char nc;
387 while (fmt < fmt_end) {
388 int operand;
389 if (*fmt == '!') {
390 fmt++;
391 DCHECK_LT(fmt, fmt_end);
392 nc = *fmt++;
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700393 if (nc == '!') {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700394 strcpy(tbuf, "!");
395 } else {
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800396 DCHECK_LT(fmt, fmt_end);
397 DCHECK_LT(static_cast<unsigned>(nc-'0'), 4u);
398 operand = lir->operands[nc-'0'];
399 switch (*fmt++) {
400 case 'b':
401 strcpy(tbuf, "0000");
402 for (i = 3; i >= 0; i--) {
403 tbuf[i] += operand & 1;
404 operand >>= 1;
405 }
406 break;
407 case 's':
408 snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
409 break;
410 case 'S':
411 DCHECK_EQ(RegStorage::RegNum(operand) & 1, 0);
412 snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
413 break;
414 case 'h':
415 snprintf(tbuf, arraysize(tbuf), "%04x", operand);
416 break;
417 case 'M':
418 case 'd':
419 snprintf(tbuf, arraysize(tbuf), "%d", operand);
420 break;
421 case 'D':
422 snprintf(tbuf, arraysize(tbuf), "%d", operand+1);
423 break;
424 case 'E':
425 snprintf(tbuf, arraysize(tbuf), "%d", operand*4);
426 break;
427 case 'F':
428 snprintf(tbuf, arraysize(tbuf), "%d", operand*2);
429 break;
430 case 't':
431 snprintf(tbuf, arraysize(tbuf), "0x%08" PRIxPTR " (L%p)",
432 reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 + (operand << 1),
433 lir->target);
434 break;
435 case 'T':
436 snprintf(tbuf, arraysize(tbuf), "0x%08x", operand << 2);
437 break;
438 case 'u': {
439 int offset_1 = lir->operands[0];
440 int offset_2 = NEXT_LIR(lir)->operands[0];
441 uintptr_t target =
442 (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) & ~3) +
443 (offset_1 << 21 >> 9) + (offset_2 << 1)) & 0xfffffffc;
444 snprintf(tbuf, arraysize(tbuf), "%p", reinterpret_cast<void*>(target));
445 break;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700446 }
447
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800448 /* Nothing to print for BLX_2 */
449 case 'v':
450 strcpy(tbuf, "see above");
451 break;
452 case 'r':
453 DCHECK(operand >= 0 && operand < MIPS_REG_COUNT);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100454 if (cu_->target64) {
455 strcpy(tbuf, mips64_reg_name[operand]);
456 } else {
457 strcpy(tbuf, mips_reg_name[operand]);
458 }
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800459 break;
460 case 'N':
461 // Placeholder for delay slot handling
462 strcpy(tbuf, "; nop");
463 break;
464 default:
465 strcpy(tbuf, "DecodeError");
466 break;
467 }
468 buf += tbuf;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700469 }
470 } else {
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800471 buf += *fmt++;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700472 }
473 }
474 return buf;
475}
476
Goran Jakovljevic10957932015-03-24 18:42:56 +0100477// FIXME: need to redo resource maps for MIPS - fix this at that time.
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100478void MipsMir2Lir::DumpResourceMask(LIR *mips_lir, const ResourceMask& mask, const char *prefix) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700479 char buf[256];
480 buf[0] = 0;
481
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100482 if (mask.Equals(kEncodeAll)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700483 strcpy(buf, "all");
484 } else {
485 char num[8];
486 int i;
487
Goran Jakovljevic10957932015-03-24 18:42:56 +0100488 for (i = 0; i < (cu_->target64 ? kMips64RegEnd : kMipsRegEnd); i++) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100489 if (mask.HasBit(i)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800490 snprintf(num, arraysize(num), "%d ", i);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700491 strcat(buf, num);
492 }
493 }
494
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100495 if (mask.HasBit(ResourceMask::kCCode)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700496 strcat(buf, "cc ");
497 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100498 if (mask.HasBit(ResourceMask::kFPStatus)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700499 strcat(buf, "fpcc ");
500 }
Goran Jakovljevic10957932015-03-24 18:42:56 +0100501 // Memory bits.
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100502 if (mips_lir && (mask.HasBit(ResourceMask::kDalvikReg))) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800503 snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s",
504 DECODE_ALIAS_INFO_REG(mips_lir->flags.alias_info),
505 DECODE_ALIAS_INFO_WIDE(mips_lir->flags.alias_info) ? "(+1)" : "");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700506 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100507 if (mask.HasBit(ResourceMask::kLiteral)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700508 strcat(buf, "lit ");
509 }
510
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100511 if (mask.HasBit(ResourceMask::kHeapRef)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700512 strcat(buf, "heap ");
513 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100514 if (mask.HasBit(ResourceMask::kMustNotAlias)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700515 strcat(buf, "noalias ");
516 }
517 }
518 if (buf[0]) {
519 LOG(INFO) << prefix << ": " << buf;
520 }
521}
522
523/*
524 * TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some
525 * instructions might call out to C/assembly helper functions. Until
526 * machinery is in place, always spill lr.
527 */
528
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700529void MipsMir2Lir::AdjustSpillMask() {
buzbee091cc402014-03-31 10:14:40 -0700530 core_spill_mask_ |= (1 << rs_rRA.GetRegNum());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700531 num_core_spills_++;
532}
533
Brian Carlstrom7940e442013-07-12 13:46:57 -0700534/* Clobber all regs that might be used by an external C call */
Vladimir Marko31c2aac2013-12-09 16:31:19 +0000535void MipsMir2Lir::ClobberCallerSave() {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100536 if (cu_->target64) {
537 Clobber(rs_rZEROd);
538 Clobber(rs_rATd);
539 Clobber(rs_rV0d);
540 Clobber(rs_rV1d);
541 Clobber(rs_rA0d);
542 Clobber(rs_rA1d);
543 Clobber(rs_rA2d);
544 Clobber(rs_rA3d);
545 Clobber(rs_rA4d);
546 Clobber(rs_rA5d);
547 Clobber(rs_rA6d);
548 Clobber(rs_rA7d);
549 Clobber(rs_rT0d);
550 Clobber(rs_rT1d);
551 Clobber(rs_rT2d);
552 Clobber(rs_rT3d);
553 Clobber(rs_rT8d);
554 Clobber(rs_rT9d);
555 Clobber(rs_rK0d);
556 Clobber(rs_rK1d);
557 Clobber(rs_rGPd);
558 Clobber(rs_rFPd);
559 Clobber(rs_rRAd);
560
561 Clobber(rs_rF0);
562 Clobber(rs_rF1);
563 Clobber(rs_rF2);
564 Clobber(rs_rF3);
565 Clobber(rs_rF4);
566 Clobber(rs_rF5);
567 Clobber(rs_rF6);
568 Clobber(rs_rF7);
569 Clobber(rs_rF8);
570 Clobber(rs_rF9);
571 Clobber(rs_rF10);
572 Clobber(rs_rF11);
573 Clobber(rs_rF12);
574 Clobber(rs_rF13);
575 Clobber(rs_rF14);
576 Clobber(rs_rF15);
577 Clobber(rs_rD0);
578 Clobber(rs_rD1);
579 Clobber(rs_rD2);
580 Clobber(rs_rD3);
581 Clobber(rs_rD4);
582 Clobber(rs_rD5);
583 Clobber(rs_rD6);
584 Clobber(rs_rD7);
Ian Rogersd582fa42014-11-05 23:46:43 -0800585 } else {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100586 Clobber(rs_rZERO);
587 Clobber(rs_rAT);
588 Clobber(rs_rV0);
589 Clobber(rs_rV1);
590 Clobber(rs_rA0);
591 Clobber(rs_rA1);
592 Clobber(rs_rA2);
593 Clobber(rs_rA3);
594 Clobber(rs_rT0_32);
595 Clobber(rs_rT1_32);
596 Clobber(rs_rT2_32);
597 Clobber(rs_rT3_32);
598 Clobber(rs_rT4_32);
599 Clobber(rs_rT5_32);
600 Clobber(rs_rT6_32);
601 Clobber(rs_rT7_32);
602 Clobber(rs_rT8);
603 Clobber(rs_rT9);
604 Clobber(rs_rK0);
605 Clobber(rs_rK1);
606 Clobber(rs_rGP);
607 Clobber(rs_rFP);
608 Clobber(rs_rRA);
609 Clobber(rs_rF0);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100610 Clobber(rs_rF2);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100611 Clobber(rs_rF4);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100612 Clobber(rs_rF6);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100613 Clobber(rs_rF8);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100614 Clobber(rs_rF10);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100615 Clobber(rs_rF12);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100616 Clobber(rs_rF14);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100617 if (fpuIs32Bit_) {
Goran Jakovljevicfc8156a2015-07-28 14:26:12 +0200618 Clobber(rs_rF1);
619 Clobber(rs_rF3);
620 Clobber(rs_rF5);
621 Clobber(rs_rF7);
622 Clobber(rs_rF9);
623 Clobber(rs_rF11);
624 Clobber(rs_rF13);
625 Clobber(rs_rF15);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100626 Clobber(rs_rD0_fr0);
627 Clobber(rs_rD1_fr0);
628 Clobber(rs_rD2_fr0);
629 Clobber(rs_rD3_fr0);
630 Clobber(rs_rD4_fr0);
631 Clobber(rs_rD5_fr0);
632 Clobber(rs_rD6_fr0);
633 Clobber(rs_rD7_fr0);
634 } else {
635 Clobber(rs_rD0_fr1);
636 Clobber(rs_rD1_fr1);
637 Clobber(rs_rD2_fr1);
638 Clobber(rs_rD3_fr1);
639 Clobber(rs_rD4_fr1);
640 Clobber(rs_rD5_fr1);
641 Clobber(rs_rD6_fr1);
642 Clobber(rs_rD7_fr1);
643 }
Ian Rogersd582fa42014-11-05 23:46:43 -0800644 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700645}
646
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700647RegLocation MipsMir2Lir::GetReturnWideAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700648 UNIMPLEMENTED(FATAL) << "No GetReturnWideAlt for MIPS";
649 RegLocation res = LocCReturnWide();
650 return res;
651}
652
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700653RegLocation MipsMir2Lir::GetReturnAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700654 UNIMPLEMENTED(FATAL) << "No GetReturnAlt for MIPS";
655 RegLocation res = LocCReturn();
656 return res;
657}
658
Brian Carlstrom7940e442013-07-12 13:46:57 -0700659/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700660void MipsMir2Lir::LockCallTemps() {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100661 LockTemp(TargetReg(kArg0));
662 LockTemp(TargetReg(kArg1));
663 LockTemp(TargetReg(kArg2));
664 LockTemp(TargetReg(kArg3));
665 if (cu_->target64) {
666 LockTemp(TargetReg(kArg4));
667 LockTemp(TargetReg(kArg5));
668 LockTemp(TargetReg(kArg6));
669 LockTemp(TargetReg(kArg7));
Goran Jakovljevica29449d2015-07-22 11:08:57 +0200670 } else {
671 LockTemp(TargetReg(kFArg0));
672 LockTemp(TargetReg(kFArg1));
673 LockTemp(TargetReg(kFArg2));
674 LockTemp(TargetReg(kFArg3));
675 if (fpuIs32Bit_) {
676 LockTemp(rs_rD6_fr0);
677 LockTemp(rs_rD7_fr0);
678 } else {
679 LockTemp(rs_rD6_fr1);
680 LockTemp(rs_rD7_fr1);
681 }
Goran Jakovljevic10957932015-03-24 18:42:56 +0100682 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700683}
684
685/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700686void MipsMir2Lir::FreeCallTemps() {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100687 FreeTemp(TargetReg(kArg0));
688 FreeTemp(TargetReg(kArg1));
689 FreeTemp(TargetReg(kArg2));
690 FreeTemp(TargetReg(kArg3));
691 if (cu_->target64) {
692 FreeTemp(TargetReg(kArg4));
693 FreeTemp(TargetReg(kArg5));
694 FreeTemp(TargetReg(kArg6));
695 FreeTemp(TargetReg(kArg7));
Goran Jakovljevica29449d2015-07-22 11:08:57 +0200696 } else {
697 FreeTemp(TargetReg(kFArg0));
698 FreeTemp(TargetReg(kFArg1));
699 FreeTemp(TargetReg(kFArg2));
700 FreeTemp(TargetReg(kFArg3));
701 if (fpuIs32Bit_) {
702 FreeTemp(rs_rD6_fr0);
703 FreeTemp(rs_rD7_fr0);
704 } else {
705 FreeTemp(rs_rD6_fr1);
706 FreeTemp(rs_rD7_fr1);
707 }
Goran Jakovljevic10957932015-03-24 18:42:56 +0100708 }
Vladimir Markobfe400b2014-12-19 19:27:26 +0000709 FreeTemp(TargetReg(kHiddenArg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700710}
711
Ian Rogersd582fa42014-11-05 23:46:43 -0800712bool MipsMir2Lir::GenMemBarrier(MemBarrierKind barrier_kind ATTRIBUTE_UNUSED) {
Andreas Gampe0b9203e2015-01-22 20:39:27 -0800713 if (cu_->compiler_driver->GetInstructionSetFeatures()->IsSmp()) {
Ian Rogersd582fa42014-11-05 23:46:43 -0800714 NewLIR1(kMipsSync, 0 /* Only stype currently supported */);
715 return true;
716 } else {
717 return false;
718 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700719}
720
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700721void MipsMir2Lir::CompilerInitializeRegAlloc() {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100722 if (cu_->target64) {
723 reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs_64, core_regs_64d, sp_regs_64,
724 dp_regs_64, reserved_regs_64, reserved_regs_64d,
725 core_temps_64, core_temps_64d, sp_temps_64,
726 dp_temps_64));
buzbee091cc402014-03-31 10:14:40 -0700727
Goran Jakovljevic10957932015-03-24 18:42:56 +0100728 // Alias single precision floats to appropriate half of overlapping double.
729 for (RegisterInfo* info : reg_pool_->sp_regs_) {
730 int sp_reg_num = info->GetReg().GetRegNum();
731 int dp_reg_num = sp_reg_num;
732 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
733 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
734 // Double precision register's master storage should refer to itself.
735 DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
736 // Redirect single precision's master storage to master.
737 info->SetMaster(dp_reg_info);
738 // Singles should show a single 32-bit mask bit, at first referring to the low half.
739 DCHECK_EQ(info->StorageMask(), 0x1U);
740 }
buzbee091cc402014-03-31 10:14:40 -0700741
Goran Jakovljevic10957932015-03-24 18:42:56 +0100742 // Alias 32bit W registers to corresponding 64bit X registers.
743 for (RegisterInfo* info : reg_pool_->core_regs_) {
744 int d_reg_num = info->GetReg().GetRegNum();
745 RegStorage d_reg = RegStorage::Solo64(d_reg_num);
746 RegisterInfo* d_reg_info = GetRegInfo(d_reg);
747 // 64bit D register's master storage should refer to itself.
748 DCHECK_EQ(d_reg_info, d_reg_info->Master());
749 // Redirect 32bit master storage to 64bit D.
750 info->SetMaster(d_reg_info);
751 // 32bit should show a single 32-bit mask bit, at first referring to the low half.
752 DCHECK_EQ(info->StorageMask(), 0x1U);
753 }
754 } else {
755 reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs_32, empty_pool, // core64
756 sp_regs_32,
757 fpuIs32Bit_ ? dp_fr0_regs_32 : dp_fr1_regs_32,
758 reserved_regs_32, empty_pool, // reserved64
759 core_temps_32, empty_pool, // core64_temps
Goran Jakovljevicfc8156a2015-07-28 14:26:12 +0200760 fpuIs32Bit_ ? sp_fr0_temps_32 : sp_fr1_temps_32,
Goran Jakovljevic10957932015-03-24 18:42:56 +0100761 fpuIs32Bit_ ? dp_fr0_temps_32 : dp_fr1_temps_32));
762
763 // Alias single precision floats to appropriate half of overlapping double.
764 for (RegisterInfo* info : reg_pool_->sp_regs_) {
765 int sp_reg_num = info->GetReg().GetRegNum();
766 int dp_reg_num = sp_reg_num & ~1;
Goran Jakovljevicfc8156a2015-07-28 14:26:12 +0200767 if (fpuIs32Bit_ || (sp_reg_num == dp_reg_num)) {
768 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
769 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
770 // Double precision register's master storage should refer to itself.
771 DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
772 // Redirect single precision's master storage to master.
773 info->SetMaster(dp_reg_info);
774 // Singles should show a single 32-bit mask bit, at first referring to the low half.
775 DCHECK_EQ(info->StorageMask(), 0x1U);
776 if (sp_reg_num & 1) {
777 // For odd singles, change to user the high word of the backing double.
778 info->SetStorageMask(0x2);
779 }
Goran Jakovljevic10957932015-03-24 18:42:56 +0100780 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700781 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700782 }
buzbee091cc402014-03-31 10:14:40 -0700783
784 // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
785 // TODO: adjust when we roll to hard float calling convention.
786 reg_pool_->next_core_reg_ = 2;
787 reg_pool_->next_sp_reg_ = 2;
Goran Jakovljevic10957932015-03-24 18:42:56 +0100788 if (cu_->target64) {
789 reg_pool_->next_dp_reg_ = 1;
790 } else {
791 reg_pool_->next_dp_reg_ = 2;
792 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700793}
794
Brian Carlstrom7940e442013-07-12 13:46:57 -0700795/*
796 * In the Arm code a it is typical to use the link register
797 * to hold the target address. However, for Mips we must
798 * ensure that all branch instructions can be restarted if
799 * there is a trap in the shadow. Allocate a temp register.
800 */
Andreas Gampe98430592014-07-27 19:44:50 -0700801RegStorage MipsMir2Lir::LoadHelper(QuickEntrypointEnum trampoline) {
buzbee695d13a2014-04-19 13:32:20 -0700802 // NOTE: native pointer.
Goran Jakovljevic10957932015-03-24 18:42:56 +0100803 if (cu_->target64) {
804 LoadWordDisp(TargetPtrReg(kSelf), GetThreadOffset<8>(trampoline).Int32Value(),
805 TargetPtrReg(kInvokeTgt));
806 } else {
807 LoadWordDisp(TargetPtrReg(kSelf), GetThreadOffset<4>(trampoline).Int32Value(),
808 TargetPtrReg(kInvokeTgt));
809 }
810 return TargetPtrReg(kInvokeTgt);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700811}
812
Dave Allisonb373e092014-02-20 16:06:36 -0800813LIR* MipsMir2Lir::CheckSuspendUsingLoad() {
buzbee2700f7e2014-03-07 09:46:20 -0800814 RegStorage tmp = AllocTemp();
buzbee695d13a2014-04-19 13:32:20 -0700815 // NOTE: native pointer.
Goran Jakovljevic10957932015-03-24 18:42:56 +0100816 if (cu_->target64) {
817 LoadWordDisp(TargetPtrReg(kSelf), Thread::ThreadSuspendTriggerOffset<8>().Int32Value(), tmp);
818 } else {
819 LoadWordDisp(TargetPtrReg(kSelf), Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
820 }
Dave Allisonb373e092014-02-20 16:06:36 -0800821 LIR *inst = LoadWordDisp(tmp, 0, tmp);
822 FreeTemp(tmp);
823 return inst;
824}
825
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700826LIR* MipsMir2Lir::GenAtomic64Load(RegStorage r_base, int displacement, RegStorage r_dest) {
827 DCHECK(!r_dest.IsFloat()); // See RegClassForFieldLoadStore().
Goran Jakovljevic10957932015-03-24 18:42:56 +0100828 if (!cu_->target64) {
829 DCHECK(r_dest.IsPair());
830 }
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700831 ClobberCallerSave();
Goran Jakovljevic10957932015-03-24 18:42:56 +0100832 LockCallTemps(); // Using fixed registers.
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700833 RegStorage reg_ptr = TargetReg(kArg0);
834 OpRegRegImm(kOpAdd, reg_ptr, r_base, displacement);
Andreas Gampe98430592014-07-27 19:44:50 -0700835 RegStorage r_tgt = LoadHelper(kQuickA64Load);
Douglas Leung22bb5a22015-07-02 16:42:08 -0700836 ForceImplicitNullCheck(reg_ptr, 0, true); // is_wide = true
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700837 LIR *ret = OpReg(kOpBlx, r_tgt);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100838 RegStorage reg_ret;
839 if (cu_->target64) {
840 OpRegCopy(r_dest, TargetReg(kRet0));
841 } else {
842 reg_ret = RegStorage::MakeRegPair(TargetReg(kRet0), TargetReg(kRet1));
843 OpRegCopyWide(r_dest, reg_ret);
844 }
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700845 return ret;
846}
847
848LIR* MipsMir2Lir::GenAtomic64Store(RegStorage r_base, int displacement, RegStorage r_src) {
849 DCHECK(!r_src.IsFloat()); // See RegClassForFieldLoadStore().
Goran Jakovljevic10957932015-03-24 18:42:56 +0100850 if (cu_->target64) {
851 DCHECK(!r_src.IsPair());
852 } else {
853 DCHECK(r_src.IsPair());
854 }
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700855 ClobberCallerSave();
Goran Jakovljevic10957932015-03-24 18:42:56 +0100856 LockCallTemps(); // Using fixed registers.
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700857 RegStorage temp_ptr = AllocTemp();
858 OpRegRegImm(kOpAdd, temp_ptr, r_base, displacement);
Douglas Leung22bb5a22015-07-02 16:42:08 -0700859 ForceImplicitNullCheck(temp_ptr, 0, true); // is_wide = true
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700860 RegStorage temp_value = AllocTempWide();
861 OpRegCopyWide(temp_value, r_src);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100862 if (cu_->target64) {
863 OpRegCopyWide(TargetReg(kArg0, kWide), temp_ptr);
864 OpRegCopyWide(TargetReg(kArg1, kWide), temp_value);
865 } else {
866 RegStorage reg_ptr = TargetReg(kArg0);
867 OpRegCopy(reg_ptr, temp_ptr);
868 RegStorage reg_value = RegStorage::MakeRegPair(TargetReg(kArg2), TargetReg(kArg3));
869 OpRegCopyWide(reg_value, temp_value);
870 }
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700871 FreeTemp(temp_ptr);
872 FreeTemp(temp_value);
Andreas Gampe98430592014-07-27 19:44:50 -0700873 RegStorage r_tgt = LoadHelper(kQuickA64Store);
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700874 return OpReg(kOpBlx, r_tgt);
875}
876
David Srbecky1109fb32015-04-07 20:21:06 +0100877static dwarf::Reg DwarfCoreReg(int num) {
878 return dwarf::Reg::MipsCore(num);
879}
880
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700881void MipsMir2Lir::SpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700882 if (num_core_spills_ == 0) {
883 return;
884 }
885 uint32_t mask = core_spill_mask_;
Goran Jakovljevic10957932015-03-24 18:42:56 +0100886 int ptr_size = cu_->target64 ? 8 : 4;
887 int offset = num_core_spills_ * ptr_size;
888 const RegStorage rs_sp = TargetPtrReg(kSp);
889 OpRegImm(kOpSub, rs_sp, offset);
David Srbecky1109fb32015-04-07 20:21:06 +0100890 cfi_.AdjustCFAOffset(offset);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700891 for (int reg = 0; mask; mask >>= 1, reg++) {
892 if (mask & 0x1) {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100893 offset -= ptr_size;
894 StoreWordDisp(rs_sp, offset,
895 cu_->target64 ? RegStorage::Solo64(reg) : RegStorage::Solo32(reg));
David Srbecky1109fb32015-04-07 20:21:06 +0100896 cfi_.RelOffset(DwarfCoreReg(reg), offset);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700897 }
898 }
899}
900
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700901void MipsMir2Lir::UnSpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700902 if (num_core_spills_ == 0) {
903 return;
904 }
905 uint32_t mask = core_spill_mask_;
Goran Jakovljevic10957932015-03-24 18:42:56 +0100906 int offset = frame_size_;
907 int ptr_size = cu_->target64 ? 8 : 4;
908 const RegStorage rs_sp = TargetPtrReg(kSp);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700909 for (int reg = 0; mask; mask >>= 1, reg++) {
910 if (mask & 0x1) {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100911 offset -= ptr_size;
912 LoadWordDisp(rs_sp, offset,
913 cu_->target64 ? RegStorage::Solo64(reg) : RegStorage::Solo32(reg));
David Srbecky1109fb32015-04-07 20:21:06 +0100914 cfi_.Restore(DwarfCoreReg(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700915 }
916 }
Goran Jakovljevic10957932015-03-24 18:42:56 +0100917 OpRegImm(kOpAdd, rs_sp, frame_size_);
David Srbecky1109fb32015-04-07 20:21:06 +0100918 cfi_.AdjustCFAOffset(-frame_size_);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700919}
920
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700921bool MipsMir2Lir::IsUnconditionalBranch(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700922 return (lir->opcode == kMipsB);
923}
924
Vladimir Marko674744e2014-04-24 15:18:26 +0100925RegisterClass MipsMir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) {
Douglas Leung2db3e262014-06-25 16:02:55 -0700926 if (UNLIKELY(is_volatile)) {
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700927 // On Mips, atomic 64-bit load/store requires a core register.
Douglas Leung2db3e262014-06-25 16:02:55 -0700928 // Smaller aligned load/store is atomic for both core and fp registers.
929 if (size == k64 || size == kDouble) {
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700930 return kCoreReg;
Douglas Leung2db3e262014-06-25 16:02:55 -0700931 }
932 }
Vladimir Marko674744e2014-04-24 15:18:26 +0100933 // TODO: Verify that both core and fp registers are suitable for smaller sizes.
934 return RegClassBySize(size);
935}
936
Brian Carlstrom7940e442013-07-12 13:46:57 -0700937MipsMir2Lir::MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
Goran Jakovljevic10957932015-03-24 18:42:56 +0100938 : Mir2Lir(cu, mir_graph, arena), in_to_reg_storage_mips64_mapper_(this),
939 in_to_reg_storage_mips_mapper_(this),
940 isaIsR6_(cu_->target64 ? true : cu->compiler_driver->GetInstructionSetFeatures()
941 ->AsMipsInstructionSetFeatures()->IsR6()),
942 fpuIs32Bit_(cu_->target64 ? false : cu->compiler_driver->GetInstructionSetFeatures()
943 ->AsMipsInstructionSetFeatures()->Is32BitFloatingPoint()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700944 for (int i = 0; i < kMipsLast; i++) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700945 DCHECK_EQ(MipsMir2Lir::EncodingMap[i].opcode, i)
946 << "Encoding order for " << MipsMir2Lir::EncodingMap[i].name
947 << " is wrong: expecting " << i << ", seeing "
948 << static_cast<int>(MipsMir2Lir::EncodingMap[i].opcode);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700949 }
950}
951
952Mir2Lir* MipsCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
953 ArenaAllocator* const arena) {
954 return new MipsMir2Lir(cu, mir_graph, arena);
955}
956
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700957uint64_t MipsMir2Lir::GetTargetInstFlags(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700958 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700959 return MipsMir2Lir::EncodingMap[opcode].flags;
960}
961
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700962const char* MipsMir2Lir::GetTargetInstName(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700963 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700964 return MipsMir2Lir::EncodingMap[opcode].name;
965}
966
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700967const char* MipsMir2Lir::GetTargetInstFmt(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700968 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700969 return MipsMir2Lir::EncodingMap[opcode].fmt;
970}
971
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700972} // namespace art