blob: 09d37f8dbf521559f5c07b164fd5a83cea8ccc9a [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 Jakovljevicff734982015-08-24 12:58:55 +0000198 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 Jakovljevicff734982015-08-24 12:58:55 +0000253 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 Jakovljevicff734982015-08-24 12:58:55 +0000257 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 Jakovljevicff734982015-08-24 12:58:55 +0000670 } else {
671 if (fpuIs32Bit_) {
672 LockTemp(TargetReg(kFArg0));
673 LockTemp(TargetReg(kFArg1));
674 LockTemp(TargetReg(kFArg2));
675 LockTemp(TargetReg(kFArg3));
676 LockTemp(rs_rD6_fr0);
677 LockTemp(rs_rD7_fr0);
678 } else {
679 LockTemp(TargetReg(kFArg0));
680 LockTemp(TargetReg(kFArg2));
681 LockTemp(rs_rD6_fr1);
682 LockTemp(rs_rD7_fr1);
683 }
Goran Jakovljevic10957932015-03-24 18:42:56 +0100684 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700685}
686
687/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700688void MipsMir2Lir::FreeCallTemps() {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100689 FreeTemp(TargetReg(kArg0));
690 FreeTemp(TargetReg(kArg1));
691 FreeTemp(TargetReg(kArg2));
692 FreeTemp(TargetReg(kArg3));
693 if (cu_->target64) {
694 FreeTemp(TargetReg(kArg4));
695 FreeTemp(TargetReg(kArg5));
696 FreeTemp(TargetReg(kArg6));
697 FreeTemp(TargetReg(kArg7));
Goran Jakovljevicff734982015-08-24 12:58:55 +0000698 } else {
699 if (fpuIs32Bit_) {
700 FreeTemp(TargetReg(kFArg0));
701 FreeTemp(TargetReg(kFArg1));
702 FreeTemp(TargetReg(kFArg2));
703 FreeTemp(TargetReg(kFArg3));
704 FreeTemp(rs_rD6_fr0);
705 FreeTemp(rs_rD7_fr0);
706 } else {
707 FreeTemp(TargetReg(kFArg0));
708 FreeTemp(TargetReg(kFArg2));
709 FreeTemp(rs_rD6_fr1);
710 FreeTemp(rs_rD7_fr1);
711 }
Goran Jakovljevic10957932015-03-24 18:42:56 +0100712 }
Vladimir Markobfe400b2014-12-19 19:27:26 +0000713 FreeTemp(TargetReg(kHiddenArg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700714}
715
Ian Rogersd582fa42014-11-05 23:46:43 -0800716bool MipsMir2Lir::GenMemBarrier(MemBarrierKind barrier_kind ATTRIBUTE_UNUSED) {
Andreas Gampe0b9203e2015-01-22 20:39:27 -0800717 if (cu_->compiler_driver->GetInstructionSetFeatures()->IsSmp()) {
Ian Rogersd582fa42014-11-05 23:46:43 -0800718 NewLIR1(kMipsSync, 0 /* Only stype currently supported */);
719 return true;
720 } else {
721 return false;
722 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700723}
724
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700725void MipsMir2Lir::CompilerInitializeRegAlloc() {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100726 if (cu_->target64) {
727 reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs_64, core_regs_64d, sp_regs_64,
728 dp_regs_64, reserved_regs_64, reserved_regs_64d,
729 core_temps_64, core_temps_64d, sp_temps_64,
730 dp_temps_64));
buzbee091cc402014-03-31 10:14:40 -0700731
Goran Jakovljevic10957932015-03-24 18:42:56 +0100732 // Alias single precision floats to appropriate half of overlapping double.
733 for (RegisterInfo* info : reg_pool_->sp_regs_) {
734 int sp_reg_num = info->GetReg().GetRegNum();
735 int dp_reg_num = sp_reg_num;
736 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
737 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
738 // Double precision register's master storage should refer to itself.
739 DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
740 // Redirect single precision's master storage to master.
741 info->SetMaster(dp_reg_info);
742 // Singles should show a single 32-bit mask bit, at first referring to the low half.
743 DCHECK_EQ(info->StorageMask(), 0x1U);
744 }
buzbee091cc402014-03-31 10:14:40 -0700745
Goran Jakovljevic10957932015-03-24 18:42:56 +0100746 // Alias 32bit W registers to corresponding 64bit X registers.
747 for (RegisterInfo* info : reg_pool_->core_regs_) {
748 int d_reg_num = info->GetReg().GetRegNum();
749 RegStorage d_reg = RegStorage::Solo64(d_reg_num);
750 RegisterInfo* d_reg_info = GetRegInfo(d_reg);
751 // 64bit D register's master storage should refer to itself.
752 DCHECK_EQ(d_reg_info, d_reg_info->Master());
753 // Redirect 32bit master storage to 64bit D.
754 info->SetMaster(d_reg_info);
755 // 32bit should show a single 32-bit mask bit, at first referring to the low half.
756 DCHECK_EQ(info->StorageMask(), 0x1U);
757 }
758 } else {
759 reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs_32, empty_pool, // core64
760 sp_regs_32,
761 fpuIs32Bit_ ? dp_fr0_regs_32 : dp_fr1_regs_32,
762 reserved_regs_32, empty_pool, // reserved64
763 core_temps_32, empty_pool, // core64_temps
Goran Jakovljevicfc8156a2015-07-28 14:26:12 +0200764 fpuIs32Bit_ ? sp_fr0_temps_32 : sp_fr1_temps_32,
Goran Jakovljevic10957932015-03-24 18:42:56 +0100765 fpuIs32Bit_ ? dp_fr0_temps_32 : dp_fr1_temps_32));
766
767 // Alias single precision floats to appropriate half of overlapping double.
768 for (RegisterInfo* info : reg_pool_->sp_regs_) {
769 int sp_reg_num = info->GetReg().GetRegNum();
770 int dp_reg_num = sp_reg_num & ~1;
Goran Jakovljevicfc8156a2015-07-28 14:26:12 +0200771 if (fpuIs32Bit_ || (sp_reg_num == dp_reg_num)) {
772 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
773 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
774 // Double precision register's master storage should refer to itself.
775 DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
776 // Redirect single precision's master storage to master.
777 info->SetMaster(dp_reg_info);
778 // Singles should show a single 32-bit mask bit, at first referring to the low half.
779 DCHECK_EQ(info->StorageMask(), 0x1U);
780 if (sp_reg_num & 1) {
781 // For odd singles, change to user the high word of the backing double.
782 info->SetStorageMask(0x2);
783 }
Goran Jakovljevic10957932015-03-24 18:42:56 +0100784 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700785 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700786 }
buzbee091cc402014-03-31 10:14:40 -0700787
788 // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
789 // TODO: adjust when we roll to hard float calling convention.
790 reg_pool_->next_core_reg_ = 2;
791 reg_pool_->next_sp_reg_ = 2;
Goran Jakovljevic10957932015-03-24 18:42:56 +0100792 if (cu_->target64) {
793 reg_pool_->next_dp_reg_ = 1;
794 } else {
795 reg_pool_->next_dp_reg_ = 2;
796 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700797}
798
Brian Carlstrom7940e442013-07-12 13:46:57 -0700799/*
800 * In the Arm code a it is typical to use the link register
801 * to hold the target address. However, for Mips we must
802 * ensure that all branch instructions can be restarted if
803 * there is a trap in the shadow. Allocate a temp register.
804 */
Andreas Gampe98430592014-07-27 19:44:50 -0700805RegStorage MipsMir2Lir::LoadHelper(QuickEntrypointEnum trampoline) {
buzbee695d13a2014-04-19 13:32:20 -0700806 // NOTE: native pointer.
Goran Jakovljevic10957932015-03-24 18:42:56 +0100807 if (cu_->target64) {
808 LoadWordDisp(TargetPtrReg(kSelf), GetThreadOffset<8>(trampoline).Int32Value(),
809 TargetPtrReg(kInvokeTgt));
810 } else {
811 LoadWordDisp(TargetPtrReg(kSelf), GetThreadOffset<4>(trampoline).Int32Value(),
812 TargetPtrReg(kInvokeTgt));
813 }
814 return TargetPtrReg(kInvokeTgt);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700815}
816
Dave Allisonb373e092014-02-20 16:06:36 -0800817LIR* MipsMir2Lir::CheckSuspendUsingLoad() {
buzbee2700f7e2014-03-07 09:46:20 -0800818 RegStorage tmp = AllocTemp();
buzbee695d13a2014-04-19 13:32:20 -0700819 // NOTE: native pointer.
Goran Jakovljevic10957932015-03-24 18:42:56 +0100820 if (cu_->target64) {
821 LoadWordDisp(TargetPtrReg(kSelf), Thread::ThreadSuspendTriggerOffset<8>().Int32Value(), tmp);
822 } else {
823 LoadWordDisp(TargetPtrReg(kSelf), Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
824 }
Dave Allisonb373e092014-02-20 16:06:36 -0800825 LIR *inst = LoadWordDisp(tmp, 0, tmp);
826 FreeTemp(tmp);
827 return inst;
828}
829
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700830LIR* MipsMir2Lir::GenAtomic64Load(RegStorage r_base, int displacement, RegStorage r_dest) {
831 DCHECK(!r_dest.IsFloat()); // See RegClassForFieldLoadStore().
Goran Jakovljevic10957932015-03-24 18:42:56 +0100832 if (!cu_->target64) {
833 DCHECK(r_dest.IsPair());
834 }
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700835 ClobberCallerSave();
Goran Jakovljevic10957932015-03-24 18:42:56 +0100836 LockCallTemps(); // Using fixed registers.
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700837 RegStorage reg_ptr = TargetReg(kArg0);
838 OpRegRegImm(kOpAdd, reg_ptr, r_base, displacement);
Andreas Gampe98430592014-07-27 19:44:50 -0700839 RegStorage r_tgt = LoadHelper(kQuickA64Load);
Douglas Leung22bb5a22015-07-02 16:42:08 -0700840 ForceImplicitNullCheck(reg_ptr, 0, true); // is_wide = true
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700841 LIR *ret = OpReg(kOpBlx, r_tgt);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100842 RegStorage reg_ret;
843 if (cu_->target64) {
844 OpRegCopy(r_dest, TargetReg(kRet0));
845 } else {
846 reg_ret = RegStorage::MakeRegPair(TargetReg(kRet0), TargetReg(kRet1));
847 OpRegCopyWide(r_dest, reg_ret);
848 }
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700849 return ret;
850}
851
852LIR* MipsMir2Lir::GenAtomic64Store(RegStorage r_base, int displacement, RegStorage r_src) {
853 DCHECK(!r_src.IsFloat()); // See RegClassForFieldLoadStore().
Goran Jakovljevic10957932015-03-24 18:42:56 +0100854 if (cu_->target64) {
855 DCHECK(!r_src.IsPair());
856 } else {
857 DCHECK(r_src.IsPair());
858 }
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700859 ClobberCallerSave();
Goran Jakovljevic10957932015-03-24 18:42:56 +0100860 LockCallTemps(); // Using fixed registers.
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700861 RegStorage temp_ptr = AllocTemp();
862 OpRegRegImm(kOpAdd, temp_ptr, r_base, displacement);
Douglas Leung22bb5a22015-07-02 16:42:08 -0700863 ForceImplicitNullCheck(temp_ptr, 0, true); // is_wide = true
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700864 RegStorage temp_value = AllocTempWide();
865 OpRegCopyWide(temp_value, r_src);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100866 if (cu_->target64) {
867 OpRegCopyWide(TargetReg(kArg0, kWide), temp_ptr);
868 OpRegCopyWide(TargetReg(kArg1, kWide), temp_value);
869 } else {
870 RegStorage reg_ptr = TargetReg(kArg0);
871 OpRegCopy(reg_ptr, temp_ptr);
872 RegStorage reg_value = RegStorage::MakeRegPair(TargetReg(kArg2), TargetReg(kArg3));
873 OpRegCopyWide(reg_value, temp_value);
874 }
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700875 FreeTemp(temp_ptr);
876 FreeTemp(temp_value);
Andreas Gampe98430592014-07-27 19:44:50 -0700877 RegStorage r_tgt = LoadHelper(kQuickA64Store);
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700878 return OpReg(kOpBlx, r_tgt);
879}
880
David Srbecky1109fb32015-04-07 20:21:06 +0100881static dwarf::Reg DwarfCoreReg(int num) {
882 return dwarf::Reg::MipsCore(num);
883}
884
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700885void MipsMir2Lir::SpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700886 if (num_core_spills_ == 0) {
887 return;
888 }
889 uint32_t mask = core_spill_mask_;
Goran Jakovljevic10957932015-03-24 18:42:56 +0100890 int ptr_size = cu_->target64 ? 8 : 4;
891 int offset = num_core_spills_ * ptr_size;
892 const RegStorage rs_sp = TargetPtrReg(kSp);
893 OpRegImm(kOpSub, rs_sp, offset);
David Srbecky1109fb32015-04-07 20:21:06 +0100894 cfi_.AdjustCFAOffset(offset);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700895 for (int reg = 0; mask; mask >>= 1, reg++) {
896 if (mask & 0x1) {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100897 offset -= ptr_size;
898 StoreWordDisp(rs_sp, offset,
899 cu_->target64 ? RegStorage::Solo64(reg) : RegStorage::Solo32(reg));
David Srbecky1109fb32015-04-07 20:21:06 +0100900 cfi_.RelOffset(DwarfCoreReg(reg), offset);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700901 }
902 }
903}
904
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700905void MipsMir2Lir::UnSpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700906 if (num_core_spills_ == 0) {
907 return;
908 }
909 uint32_t mask = core_spill_mask_;
Goran Jakovljevic10957932015-03-24 18:42:56 +0100910 int offset = frame_size_;
911 int ptr_size = cu_->target64 ? 8 : 4;
912 const RegStorage rs_sp = TargetPtrReg(kSp);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700913 for (int reg = 0; mask; mask >>= 1, reg++) {
914 if (mask & 0x1) {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100915 offset -= ptr_size;
916 LoadWordDisp(rs_sp, offset,
917 cu_->target64 ? RegStorage::Solo64(reg) : RegStorage::Solo32(reg));
David Srbecky1109fb32015-04-07 20:21:06 +0100918 cfi_.Restore(DwarfCoreReg(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700919 }
920 }
Goran Jakovljevic10957932015-03-24 18:42:56 +0100921 OpRegImm(kOpAdd, rs_sp, frame_size_);
David Srbecky1109fb32015-04-07 20:21:06 +0100922 cfi_.AdjustCFAOffset(-frame_size_);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700923}
924
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700925bool MipsMir2Lir::IsUnconditionalBranch(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700926 return (lir->opcode == kMipsB);
927}
928
Vladimir Marko674744e2014-04-24 15:18:26 +0100929RegisterClass MipsMir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) {
Douglas Leung2db3e262014-06-25 16:02:55 -0700930 if (UNLIKELY(is_volatile)) {
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700931 // On Mips, atomic 64-bit load/store requires a core register.
Douglas Leung2db3e262014-06-25 16:02:55 -0700932 // Smaller aligned load/store is atomic for both core and fp registers.
933 if (size == k64 || size == kDouble) {
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700934 return kCoreReg;
Douglas Leung2db3e262014-06-25 16:02:55 -0700935 }
936 }
Vladimir Marko674744e2014-04-24 15:18:26 +0100937 // TODO: Verify that both core and fp registers are suitable for smaller sizes.
938 return RegClassBySize(size);
939}
940
Brian Carlstrom7940e442013-07-12 13:46:57 -0700941MipsMir2Lir::MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
Goran Jakovljevic10957932015-03-24 18:42:56 +0100942 : Mir2Lir(cu, mir_graph, arena), in_to_reg_storage_mips64_mapper_(this),
943 in_to_reg_storage_mips_mapper_(this),
944 isaIsR6_(cu_->target64 ? true : cu->compiler_driver->GetInstructionSetFeatures()
945 ->AsMipsInstructionSetFeatures()->IsR6()),
946 fpuIs32Bit_(cu_->target64 ? false : cu->compiler_driver->GetInstructionSetFeatures()
947 ->AsMipsInstructionSetFeatures()->Is32BitFloatingPoint()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700948 for (int i = 0; i < kMipsLast; i++) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700949 DCHECK_EQ(MipsMir2Lir::EncodingMap[i].opcode, i)
950 << "Encoding order for " << MipsMir2Lir::EncodingMap[i].name
951 << " is wrong: expecting " << i << ", seeing "
952 << static_cast<int>(MipsMir2Lir::EncodingMap[i].opcode);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700953 }
954}
955
956Mir2Lir* MipsCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
957 ArenaAllocator* const arena) {
958 return new MipsMir2Lir(cu, mir_graph, arena);
959}
960
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700961uint64_t MipsMir2Lir::GetTargetInstFlags(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700962 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700963 return MipsMir2Lir::EncodingMap[opcode].flags;
964}
965
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700966const char* MipsMir2Lir::GetTargetInstName(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700967 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700968 return MipsMir2Lir::EncodingMap[opcode].name;
969}
970
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700971const char* MipsMir2Lir::GetTargetInstFmt(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700972 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700973 return MipsMir2Lir::EncodingMap[opcode].fmt;
974}
975
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700976} // namespace art