blob: ec4bad778cbb2296e1c8fa2958db54bbe28c3088 [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) {
198 DCHECK((kArg0 <= reg && reg < kArg7) || (kFArg0 <= reg && reg < kFArg15) || (kRet0 == reg));
199 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);
253
254 RegStorage result = RegStorage::InvalidReg();
255 if (cur_core_reg_ < coreArgMappingToPhysicalRegSize) {
256 result = m2l_->TargetReg(coreArgMappingToPhysicalReg[cur_core_reg_++],
257 arg.IsRef() ? kRef : kNotWide);
258 if (arg.IsWide() && cur_core_reg_ < coreArgMappingToPhysicalRegSize) {
259 result = RegStorage::MakeRegPair(
260 result, m2l_->TargetReg(coreArgMappingToPhysicalReg[cur_core_reg_++], kNotWide));
261 }
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800262 }
Serguei Katkov717a3e42014-11-13 17:19:42 +0600263 return result;
Razvan A Lupusoru3bc01742014-02-06 13:18:43 -0800264}
265
Goran Jakovljevic10957932015-03-24 18:42:56 +0100266RegStorage MipsMir2Lir::InToRegStorageMips64Mapper::GetNextReg(ShortyArg arg) {
267 const SpecialTargetRegister coreArgMappingToPhysicalReg[] =
268 {kArg1, kArg2, kArg3, kArg4, kArg5, kArg6, kArg7};
269 const size_t coreArgMappingToPhysicalRegSize = arraysize(coreArgMappingToPhysicalReg);
270 const SpecialTargetRegister fpArgMappingToPhysicalReg[] =
271 {kFArg1, kFArg2, kFArg3, kFArg4, kFArg5, kFArg6, kFArg7};
272 const size_t fpArgMappingToPhysicalRegSize = arraysize(fpArgMappingToPhysicalReg);
273
274 RegStorage result = RegStorage::InvalidReg();
275 if (arg.IsFP()) {
276 if (cur_arg_reg_ < fpArgMappingToPhysicalRegSize) {
277 DCHECK(!arg.IsRef());
278 result = m2l_->TargetReg(fpArgMappingToPhysicalReg[cur_arg_reg_++],
279 arg.IsWide() ? kWide : kNotWide);
280 }
281 } else {
282 if (cur_arg_reg_ < coreArgMappingToPhysicalRegSize) {
283 DCHECK(!(arg.IsWide() && arg.IsRef()));
284 result = m2l_->TargetReg(coreArgMappingToPhysicalReg[cur_arg_reg_++],
285 arg.IsRef() ? kRef : (arg.IsWide() ? kWide : kNotWide));
286 }
287 }
288 return result;
289}
290
Brian Carlstrom7940e442013-07-12 13:46:57 -0700291/*
292 * Decode the register id.
293 */
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100294ResourceMask MipsMir2Lir::GetRegMaskCommon(const RegStorage& reg) const {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100295 if (cu_->target64) {
296 return ResourceMask::Bit((reg.IsFloat() ? kMipsFPReg0 : 0) + reg.GetRegNum());
Ian Rogersd582fa42014-11-05 23:46:43 -0800297 } else {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100298 if (reg.IsDouble()) {
299 return ResourceMask::TwoBits((reg.GetRegNum() & ~1) + kMipsFPReg0);
300 } else if (reg.IsSingle()) {
301 return ResourceMask::Bit(reg.GetRegNum() + kMipsFPReg0);
302 } else {
303 return ResourceMask::Bit(reg.GetRegNum());
304 }
Ian Rogersd582fa42014-11-05 23:46:43 -0800305 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700306}
307
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100308ResourceMask MipsMir2Lir::GetPCUseDefEncoding() const {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100309 return cu_->target64 ? ResourceMask::Bit(kMips64RegPC) : ResourceMask::Bit(kMipsRegPC);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700310}
311
Goran Jakovljevic10957932015-03-24 18:42:56 +0100312void MipsMir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags, ResourceMask* use_mask,
313 ResourceMask* def_mask) {
buzbeeb48819d2013-09-14 16:15:25 -0700314 DCHECK(!lir->flags.use_def_invalid);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700315
316 // Mips-specific resource map setup here.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700317 if (flags & REG_DEF_SP) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100318 def_mask->SetBit(kMipsRegSP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700319 }
320
321 if (flags & REG_USE_SP) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100322 use_mask->SetBit(kMipsRegSP);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700323 }
324
325 if (flags & REG_DEF_LR) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100326 def_mask->SetBit(kMipsRegLR);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700327 }
buzbee9da5c102014-03-28 12:59:18 -0700328
Goran Jakovljevic10957932015-03-24 18:42:56 +0100329 if (!cu_->target64) {
330 if (flags & REG_DEF_HI) {
331 def_mask->SetBit(kMipsRegHI);
332 }
buzbee9da5c102014-03-28 12:59:18 -0700333
Goran Jakovljevic10957932015-03-24 18:42:56 +0100334 if (flags & REG_DEF_LO) {
335 def_mask->SetBit(kMipsRegLO);
336 }
buzbee9da5c102014-03-28 12:59:18 -0700337
Goran Jakovljevic10957932015-03-24 18:42:56 +0100338 if (flags & REG_USE_HI) {
339 use_mask->SetBit(kMipsRegHI);
340 }
buzbee9da5c102014-03-28 12:59:18 -0700341
Goran Jakovljevic10957932015-03-24 18:42:56 +0100342 if (flags & REG_USE_LO) {
343 use_mask->SetBit(kMipsRegLO);
344 }
buzbee9da5c102014-03-28 12:59:18 -0700345 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700346}
347
348/* For dumping instructions */
349#define MIPS_REG_COUNT 32
350static const char *mips_reg_name[MIPS_REG_COUNT] = {
351 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
352 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
353 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
354 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
355};
356
Goran Jakovljevic10957932015-03-24 18:42:56 +0100357static const char *mips64_reg_name[MIPS_REG_COUNT] = {
358 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
359 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
360 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
361 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
362};
363
Brian Carlstrom7940e442013-07-12 13:46:57 -0700364/*
365 * Interpret a format string and build a string no longer than size
Goran Jakovljevic10957932015-03-24 18:42:56 +0100366 * See format key in assemble_mips.cc.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700367 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700368std::string MipsMir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700369 std::string buf;
370 int i;
371 const char *fmt_end = &fmt[strlen(fmt)];
372 char tbuf[256];
373 char nc;
374 while (fmt < fmt_end) {
375 int operand;
376 if (*fmt == '!') {
377 fmt++;
378 DCHECK_LT(fmt, fmt_end);
379 nc = *fmt++;
Brian Carlstrom38f85e42013-07-18 14:45:22 -0700380 if (nc == '!') {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700381 strcpy(tbuf, "!");
382 } else {
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800383 DCHECK_LT(fmt, fmt_end);
384 DCHECK_LT(static_cast<unsigned>(nc-'0'), 4u);
385 operand = lir->operands[nc-'0'];
386 switch (*fmt++) {
387 case 'b':
388 strcpy(tbuf, "0000");
389 for (i = 3; i >= 0; i--) {
390 tbuf[i] += operand & 1;
391 operand >>= 1;
392 }
393 break;
394 case 's':
395 snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
396 break;
397 case 'S':
398 DCHECK_EQ(RegStorage::RegNum(operand) & 1, 0);
399 snprintf(tbuf, arraysize(tbuf), "$f%d", RegStorage::RegNum(operand));
400 break;
401 case 'h':
402 snprintf(tbuf, arraysize(tbuf), "%04x", operand);
403 break;
404 case 'M':
405 case 'd':
406 snprintf(tbuf, arraysize(tbuf), "%d", operand);
407 break;
408 case 'D':
409 snprintf(tbuf, arraysize(tbuf), "%d", operand+1);
410 break;
411 case 'E':
412 snprintf(tbuf, arraysize(tbuf), "%d", operand*4);
413 break;
414 case 'F':
415 snprintf(tbuf, arraysize(tbuf), "%d", operand*2);
416 break;
417 case 't':
418 snprintf(tbuf, arraysize(tbuf), "0x%08" PRIxPTR " (L%p)",
419 reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4 + (operand << 1),
420 lir->target);
421 break;
422 case 'T':
423 snprintf(tbuf, arraysize(tbuf), "0x%08x", operand << 2);
424 break;
425 case 'u': {
426 int offset_1 = lir->operands[0];
427 int offset_2 = NEXT_LIR(lir)->operands[0];
428 uintptr_t target =
429 (((reinterpret_cast<uintptr_t>(base_addr) + lir->offset + 4) & ~3) +
430 (offset_1 << 21 >> 9) + (offset_2 << 1)) & 0xfffffffc;
431 snprintf(tbuf, arraysize(tbuf), "%p", reinterpret_cast<void*>(target));
432 break;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700433 }
434
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800435 /* Nothing to print for BLX_2 */
436 case 'v':
437 strcpy(tbuf, "see above");
438 break;
439 case 'r':
440 DCHECK(operand >= 0 && operand < MIPS_REG_COUNT);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100441 if (cu_->target64) {
442 strcpy(tbuf, mips64_reg_name[operand]);
443 } else {
444 strcpy(tbuf, mips_reg_name[operand]);
445 }
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800446 break;
447 case 'N':
448 // Placeholder for delay slot handling
449 strcpy(tbuf, "; nop");
450 break;
451 default:
452 strcpy(tbuf, "DecodeError");
453 break;
454 }
455 buf += tbuf;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700456 }
457 } else {
Andreas Gampe8ebdc2b2015-01-14 12:09:25 -0800458 buf += *fmt++;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700459 }
460 }
461 return buf;
462}
463
Goran Jakovljevic10957932015-03-24 18:42:56 +0100464// FIXME: need to redo resource maps for MIPS - fix this at that time.
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100465void MipsMir2Lir::DumpResourceMask(LIR *mips_lir, const ResourceMask& mask, const char *prefix) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700466 char buf[256];
467 buf[0] = 0;
468
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100469 if (mask.Equals(kEncodeAll)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700470 strcpy(buf, "all");
471 } else {
472 char num[8];
473 int i;
474
Goran Jakovljevic10957932015-03-24 18:42:56 +0100475 for (i = 0; i < (cu_->target64 ? kMips64RegEnd : kMipsRegEnd); i++) {
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100476 if (mask.HasBit(i)) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800477 snprintf(num, arraysize(num), "%d ", i);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700478 strcat(buf, num);
479 }
480 }
481
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100482 if (mask.HasBit(ResourceMask::kCCode)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700483 strcat(buf, "cc ");
484 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100485 if (mask.HasBit(ResourceMask::kFPStatus)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700486 strcat(buf, "fpcc ");
487 }
Goran Jakovljevic10957932015-03-24 18:42:56 +0100488 // Memory bits.
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100489 if (mips_lir && (mask.HasBit(ResourceMask::kDalvikReg))) {
Ian Rogers988e6ea2014-01-08 11:30:50 -0800490 snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s",
491 DECODE_ALIAS_INFO_REG(mips_lir->flags.alias_info),
492 DECODE_ALIAS_INFO_WIDE(mips_lir->flags.alias_info) ? "(+1)" : "");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700493 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100494 if (mask.HasBit(ResourceMask::kLiteral)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700495 strcat(buf, "lit ");
496 }
497
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100498 if (mask.HasBit(ResourceMask::kHeapRef)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700499 strcat(buf, "heap ");
500 }
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100501 if (mask.HasBit(ResourceMask::kMustNotAlias)) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700502 strcat(buf, "noalias ");
503 }
504 }
505 if (buf[0]) {
506 LOG(INFO) << prefix << ": " << buf;
507 }
508}
509
510/*
511 * TUNING: is true leaf? Can't just use METHOD_IS_LEAF to determine as some
512 * instructions might call out to C/assembly helper functions. Until
513 * machinery is in place, always spill lr.
514 */
515
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700516void MipsMir2Lir::AdjustSpillMask() {
buzbee091cc402014-03-31 10:14:40 -0700517 core_spill_mask_ |= (1 << rs_rRA.GetRegNum());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700518 num_core_spills_++;
519}
520
Brian Carlstrom7940e442013-07-12 13:46:57 -0700521/* Clobber all regs that might be used by an external C call */
Vladimir Marko31c2aac2013-12-09 16:31:19 +0000522void MipsMir2Lir::ClobberCallerSave() {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100523 if (cu_->target64) {
524 Clobber(rs_rZEROd);
525 Clobber(rs_rATd);
526 Clobber(rs_rV0d);
527 Clobber(rs_rV1d);
528 Clobber(rs_rA0d);
529 Clobber(rs_rA1d);
530 Clobber(rs_rA2d);
531 Clobber(rs_rA3d);
532 Clobber(rs_rA4d);
533 Clobber(rs_rA5d);
534 Clobber(rs_rA6d);
535 Clobber(rs_rA7d);
536 Clobber(rs_rT0d);
537 Clobber(rs_rT1d);
538 Clobber(rs_rT2d);
539 Clobber(rs_rT3d);
540 Clobber(rs_rT8d);
541 Clobber(rs_rT9d);
542 Clobber(rs_rK0d);
543 Clobber(rs_rK1d);
544 Clobber(rs_rGPd);
545 Clobber(rs_rFPd);
546 Clobber(rs_rRAd);
547
548 Clobber(rs_rF0);
549 Clobber(rs_rF1);
550 Clobber(rs_rF2);
551 Clobber(rs_rF3);
552 Clobber(rs_rF4);
553 Clobber(rs_rF5);
554 Clobber(rs_rF6);
555 Clobber(rs_rF7);
556 Clobber(rs_rF8);
557 Clobber(rs_rF9);
558 Clobber(rs_rF10);
559 Clobber(rs_rF11);
560 Clobber(rs_rF12);
561 Clobber(rs_rF13);
562 Clobber(rs_rF14);
563 Clobber(rs_rF15);
564 Clobber(rs_rD0);
565 Clobber(rs_rD1);
566 Clobber(rs_rD2);
567 Clobber(rs_rD3);
568 Clobber(rs_rD4);
569 Clobber(rs_rD5);
570 Clobber(rs_rD6);
571 Clobber(rs_rD7);
Ian Rogersd582fa42014-11-05 23:46:43 -0800572 } else {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100573 Clobber(rs_rZERO);
574 Clobber(rs_rAT);
575 Clobber(rs_rV0);
576 Clobber(rs_rV1);
577 Clobber(rs_rA0);
578 Clobber(rs_rA1);
579 Clobber(rs_rA2);
580 Clobber(rs_rA3);
581 Clobber(rs_rT0_32);
582 Clobber(rs_rT1_32);
583 Clobber(rs_rT2_32);
584 Clobber(rs_rT3_32);
585 Clobber(rs_rT4_32);
586 Clobber(rs_rT5_32);
587 Clobber(rs_rT6_32);
588 Clobber(rs_rT7_32);
589 Clobber(rs_rT8);
590 Clobber(rs_rT9);
591 Clobber(rs_rK0);
592 Clobber(rs_rK1);
593 Clobber(rs_rGP);
594 Clobber(rs_rFP);
595 Clobber(rs_rRA);
596 Clobber(rs_rF0);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100597 Clobber(rs_rF2);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100598 Clobber(rs_rF4);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100599 Clobber(rs_rF6);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100600 Clobber(rs_rF8);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100601 Clobber(rs_rF10);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100602 Clobber(rs_rF12);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100603 Clobber(rs_rF14);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100604 if (fpuIs32Bit_) {
Goran Jakovljevicfc8156a2015-07-28 14:26:12 +0200605 Clobber(rs_rF1);
606 Clobber(rs_rF3);
607 Clobber(rs_rF5);
608 Clobber(rs_rF7);
609 Clobber(rs_rF9);
610 Clobber(rs_rF11);
611 Clobber(rs_rF13);
612 Clobber(rs_rF15);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100613 Clobber(rs_rD0_fr0);
614 Clobber(rs_rD1_fr0);
615 Clobber(rs_rD2_fr0);
616 Clobber(rs_rD3_fr0);
617 Clobber(rs_rD4_fr0);
618 Clobber(rs_rD5_fr0);
619 Clobber(rs_rD6_fr0);
620 Clobber(rs_rD7_fr0);
621 } else {
622 Clobber(rs_rD0_fr1);
623 Clobber(rs_rD1_fr1);
624 Clobber(rs_rD2_fr1);
625 Clobber(rs_rD3_fr1);
626 Clobber(rs_rD4_fr1);
627 Clobber(rs_rD5_fr1);
628 Clobber(rs_rD6_fr1);
629 Clobber(rs_rD7_fr1);
630 }
Ian Rogersd582fa42014-11-05 23:46:43 -0800631 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700632}
633
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700634RegLocation MipsMir2Lir::GetReturnWideAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700635 UNIMPLEMENTED(FATAL) << "No GetReturnWideAlt for MIPS";
636 RegLocation res = LocCReturnWide();
637 return res;
638}
639
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700640RegLocation MipsMir2Lir::GetReturnAlt() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700641 UNIMPLEMENTED(FATAL) << "No GetReturnAlt for MIPS";
642 RegLocation res = LocCReturn();
643 return res;
644}
645
Brian Carlstrom7940e442013-07-12 13:46:57 -0700646/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700647void MipsMir2Lir::LockCallTemps() {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100648 LockTemp(TargetReg(kArg0));
649 LockTemp(TargetReg(kArg1));
650 LockTemp(TargetReg(kArg2));
651 LockTemp(TargetReg(kArg3));
652 if (cu_->target64) {
653 LockTemp(TargetReg(kArg4));
654 LockTemp(TargetReg(kArg5));
655 LockTemp(TargetReg(kArg6));
656 LockTemp(TargetReg(kArg7));
657 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700658}
659
660/* To be used when explicitly managing register use */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700661void MipsMir2Lir::FreeCallTemps() {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100662 FreeTemp(TargetReg(kArg0));
663 FreeTemp(TargetReg(kArg1));
664 FreeTemp(TargetReg(kArg2));
665 FreeTemp(TargetReg(kArg3));
666 if (cu_->target64) {
667 FreeTemp(TargetReg(kArg4));
668 FreeTemp(TargetReg(kArg5));
669 FreeTemp(TargetReg(kArg6));
670 FreeTemp(TargetReg(kArg7));
671 }
Vladimir Markobfe400b2014-12-19 19:27:26 +0000672 FreeTemp(TargetReg(kHiddenArg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700673}
674
Ian Rogersd582fa42014-11-05 23:46:43 -0800675bool MipsMir2Lir::GenMemBarrier(MemBarrierKind barrier_kind ATTRIBUTE_UNUSED) {
Andreas Gampe0b9203e2015-01-22 20:39:27 -0800676 if (cu_->compiler_driver->GetInstructionSetFeatures()->IsSmp()) {
Ian Rogersd582fa42014-11-05 23:46:43 -0800677 NewLIR1(kMipsSync, 0 /* Only stype currently supported */);
678 return true;
679 } else {
680 return false;
681 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700682}
683
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700684void MipsMir2Lir::CompilerInitializeRegAlloc() {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100685 if (cu_->target64) {
686 reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs_64, core_regs_64d, sp_regs_64,
687 dp_regs_64, reserved_regs_64, reserved_regs_64d,
688 core_temps_64, core_temps_64d, sp_temps_64,
689 dp_temps_64));
buzbee091cc402014-03-31 10:14:40 -0700690
Goran Jakovljevic10957932015-03-24 18:42:56 +0100691 // Alias single precision floats to appropriate half of overlapping double.
692 for (RegisterInfo* info : reg_pool_->sp_regs_) {
693 int sp_reg_num = info->GetReg().GetRegNum();
694 int dp_reg_num = sp_reg_num;
695 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
696 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
697 // Double precision register's master storage should refer to itself.
698 DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
699 // Redirect single precision's master storage to master.
700 info->SetMaster(dp_reg_info);
701 // Singles should show a single 32-bit mask bit, at first referring to the low half.
702 DCHECK_EQ(info->StorageMask(), 0x1U);
703 }
buzbee091cc402014-03-31 10:14:40 -0700704
Goran Jakovljevic10957932015-03-24 18:42:56 +0100705 // Alias 32bit W registers to corresponding 64bit X registers.
706 for (RegisterInfo* info : reg_pool_->core_regs_) {
707 int d_reg_num = info->GetReg().GetRegNum();
708 RegStorage d_reg = RegStorage::Solo64(d_reg_num);
709 RegisterInfo* d_reg_info = GetRegInfo(d_reg);
710 // 64bit D register's master storage should refer to itself.
711 DCHECK_EQ(d_reg_info, d_reg_info->Master());
712 // Redirect 32bit master storage to 64bit D.
713 info->SetMaster(d_reg_info);
714 // 32bit should show a single 32-bit mask bit, at first referring to the low half.
715 DCHECK_EQ(info->StorageMask(), 0x1U);
716 }
717 } else {
718 reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs_32, empty_pool, // core64
719 sp_regs_32,
720 fpuIs32Bit_ ? dp_fr0_regs_32 : dp_fr1_regs_32,
721 reserved_regs_32, empty_pool, // reserved64
722 core_temps_32, empty_pool, // core64_temps
Goran Jakovljevicfc8156a2015-07-28 14:26:12 +0200723 fpuIs32Bit_ ? sp_fr0_temps_32 : sp_fr1_temps_32,
Goran Jakovljevic10957932015-03-24 18:42:56 +0100724 fpuIs32Bit_ ? dp_fr0_temps_32 : dp_fr1_temps_32));
725
726 // Alias single precision floats to appropriate half of overlapping double.
727 for (RegisterInfo* info : reg_pool_->sp_regs_) {
728 int sp_reg_num = info->GetReg().GetRegNum();
729 int dp_reg_num = sp_reg_num & ~1;
Goran Jakovljevicfc8156a2015-07-28 14:26:12 +0200730 if (fpuIs32Bit_ || (sp_reg_num == dp_reg_num)) {
731 RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | dp_reg_num);
732 RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
733 // Double precision register's master storage should refer to itself.
734 DCHECK_EQ(dp_reg_info, dp_reg_info->Master());
735 // Redirect single precision's master storage to master.
736 info->SetMaster(dp_reg_info);
737 // Singles should show a single 32-bit mask bit, at first referring to the low half.
738 DCHECK_EQ(info->StorageMask(), 0x1U);
739 if (sp_reg_num & 1) {
740 // For odd singles, change to user the high word of the backing double.
741 info->SetStorageMask(0x2);
742 }
Goran Jakovljevic10957932015-03-24 18:42:56 +0100743 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700744 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700745 }
buzbee091cc402014-03-31 10:14:40 -0700746
747 // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
748 // TODO: adjust when we roll to hard float calling convention.
749 reg_pool_->next_core_reg_ = 2;
750 reg_pool_->next_sp_reg_ = 2;
Goran Jakovljevic10957932015-03-24 18:42:56 +0100751 if (cu_->target64) {
752 reg_pool_->next_dp_reg_ = 1;
753 } else {
754 reg_pool_->next_dp_reg_ = 2;
755 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700756}
757
Brian Carlstrom7940e442013-07-12 13:46:57 -0700758/*
759 * In the Arm code a it is typical to use the link register
760 * to hold the target address. However, for Mips we must
761 * ensure that all branch instructions can be restarted if
762 * there is a trap in the shadow. Allocate a temp register.
763 */
Andreas Gampe98430592014-07-27 19:44:50 -0700764RegStorage MipsMir2Lir::LoadHelper(QuickEntrypointEnum trampoline) {
buzbee695d13a2014-04-19 13:32:20 -0700765 // NOTE: native pointer.
Goran Jakovljevic10957932015-03-24 18:42:56 +0100766 if (cu_->target64) {
767 LoadWordDisp(TargetPtrReg(kSelf), GetThreadOffset<8>(trampoline).Int32Value(),
768 TargetPtrReg(kInvokeTgt));
769 } else {
770 LoadWordDisp(TargetPtrReg(kSelf), GetThreadOffset<4>(trampoline).Int32Value(),
771 TargetPtrReg(kInvokeTgt));
772 }
773 return TargetPtrReg(kInvokeTgt);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700774}
775
Dave Allisonb373e092014-02-20 16:06:36 -0800776LIR* MipsMir2Lir::CheckSuspendUsingLoad() {
buzbee2700f7e2014-03-07 09:46:20 -0800777 RegStorage tmp = AllocTemp();
buzbee695d13a2014-04-19 13:32:20 -0700778 // NOTE: native pointer.
Goran Jakovljevic10957932015-03-24 18:42:56 +0100779 if (cu_->target64) {
780 LoadWordDisp(TargetPtrReg(kSelf), Thread::ThreadSuspendTriggerOffset<8>().Int32Value(), tmp);
781 } else {
782 LoadWordDisp(TargetPtrReg(kSelf), Thread::ThreadSuspendTriggerOffset<4>().Int32Value(), tmp);
783 }
Dave Allisonb373e092014-02-20 16:06:36 -0800784 LIR *inst = LoadWordDisp(tmp, 0, tmp);
785 FreeTemp(tmp);
786 return inst;
787}
788
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700789LIR* MipsMir2Lir::GenAtomic64Load(RegStorage r_base, int displacement, RegStorage r_dest) {
790 DCHECK(!r_dest.IsFloat()); // See RegClassForFieldLoadStore().
Goran Jakovljevic10957932015-03-24 18:42:56 +0100791 if (!cu_->target64) {
792 DCHECK(r_dest.IsPair());
793 }
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700794 ClobberCallerSave();
Goran Jakovljevic10957932015-03-24 18:42:56 +0100795 LockCallTemps(); // Using fixed registers.
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700796 RegStorage reg_ptr = TargetReg(kArg0);
797 OpRegRegImm(kOpAdd, reg_ptr, r_base, displacement);
Andreas Gampe98430592014-07-27 19:44:50 -0700798 RegStorage r_tgt = LoadHelper(kQuickA64Load);
Douglas Leung22bb5a22015-07-02 16:42:08 -0700799 ForceImplicitNullCheck(reg_ptr, 0, true); // is_wide = true
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700800 LIR *ret = OpReg(kOpBlx, r_tgt);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100801 RegStorage reg_ret;
802 if (cu_->target64) {
803 OpRegCopy(r_dest, TargetReg(kRet0));
804 } else {
805 reg_ret = RegStorage::MakeRegPair(TargetReg(kRet0), TargetReg(kRet1));
806 OpRegCopyWide(r_dest, reg_ret);
807 }
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700808 return ret;
809}
810
811LIR* MipsMir2Lir::GenAtomic64Store(RegStorage r_base, int displacement, RegStorage r_src) {
812 DCHECK(!r_src.IsFloat()); // See RegClassForFieldLoadStore().
Goran Jakovljevic10957932015-03-24 18:42:56 +0100813 if (cu_->target64) {
814 DCHECK(!r_src.IsPair());
815 } else {
816 DCHECK(r_src.IsPair());
817 }
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700818 ClobberCallerSave();
Goran Jakovljevic10957932015-03-24 18:42:56 +0100819 LockCallTemps(); // Using fixed registers.
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700820 RegStorage temp_ptr = AllocTemp();
821 OpRegRegImm(kOpAdd, temp_ptr, r_base, displacement);
Douglas Leung22bb5a22015-07-02 16:42:08 -0700822 ForceImplicitNullCheck(temp_ptr, 0, true); // is_wide = true
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700823 RegStorage temp_value = AllocTempWide();
824 OpRegCopyWide(temp_value, r_src);
Goran Jakovljevic10957932015-03-24 18:42:56 +0100825 if (cu_->target64) {
826 OpRegCopyWide(TargetReg(kArg0, kWide), temp_ptr);
827 OpRegCopyWide(TargetReg(kArg1, kWide), temp_value);
828 } else {
829 RegStorage reg_ptr = TargetReg(kArg0);
830 OpRegCopy(reg_ptr, temp_ptr);
831 RegStorage reg_value = RegStorage::MakeRegPair(TargetReg(kArg2), TargetReg(kArg3));
832 OpRegCopyWide(reg_value, temp_value);
833 }
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700834 FreeTemp(temp_ptr);
835 FreeTemp(temp_value);
Andreas Gampe98430592014-07-27 19:44:50 -0700836 RegStorage r_tgt = LoadHelper(kQuickA64Store);
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700837 return OpReg(kOpBlx, r_tgt);
838}
839
David Srbecky1109fb32015-04-07 20:21:06 +0100840static dwarf::Reg DwarfCoreReg(int num) {
841 return dwarf::Reg::MipsCore(num);
842}
843
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700844void MipsMir2Lir::SpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700845 if (num_core_spills_ == 0) {
846 return;
847 }
848 uint32_t mask = core_spill_mask_;
Goran Jakovljevic10957932015-03-24 18:42:56 +0100849 int ptr_size = cu_->target64 ? 8 : 4;
850 int offset = num_core_spills_ * ptr_size;
851 const RegStorage rs_sp = TargetPtrReg(kSp);
852 OpRegImm(kOpSub, rs_sp, offset);
David Srbecky1109fb32015-04-07 20:21:06 +0100853 cfi_.AdjustCFAOffset(offset);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700854 for (int reg = 0; mask; mask >>= 1, reg++) {
855 if (mask & 0x1) {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100856 offset -= ptr_size;
857 StoreWordDisp(rs_sp, offset,
858 cu_->target64 ? RegStorage::Solo64(reg) : RegStorage::Solo32(reg));
David Srbecky1109fb32015-04-07 20:21:06 +0100859 cfi_.RelOffset(DwarfCoreReg(reg), offset);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700860 }
861 }
862}
863
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700864void MipsMir2Lir::UnSpillCoreRegs() {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700865 if (num_core_spills_ == 0) {
866 return;
867 }
868 uint32_t mask = core_spill_mask_;
Goran Jakovljevic10957932015-03-24 18:42:56 +0100869 int offset = frame_size_;
870 int ptr_size = cu_->target64 ? 8 : 4;
871 const RegStorage rs_sp = TargetPtrReg(kSp);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700872 for (int reg = 0; mask; mask >>= 1, reg++) {
873 if (mask & 0x1) {
Goran Jakovljevic10957932015-03-24 18:42:56 +0100874 offset -= ptr_size;
875 LoadWordDisp(rs_sp, offset,
876 cu_->target64 ? RegStorage::Solo64(reg) : RegStorage::Solo32(reg));
David Srbecky1109fb32015-04-07 20:21:06 +0100877 cfi_.Restore(DwarfCoreReg(reg));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700878 }
879 }
Goran Jakovljevic10957932015-03-24 18:42:56 +0100880 OpRegImm(kOpAdd, rs_sp, frame_size_);
David Srbecky1109fb32015-04-07 20:21:06 +0100881 cfi_.AdjustCFAOffset(-frame_size_);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700882}
883
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700884bool MipsMir2Lir::IsUnconditionalBranch(LIR* lir) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700885 return (lir->opcode == kMipsB);
886}
887
Vladimir Marko674744e2014-04-24 15:18:26 +0100888RegisterClass MipsMir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) {
Douglas Leung2db3e262014-06-25 16:02:55 -0700889 if (UNLIKELY(is_volatile)) {
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700890 // On Mips, atomic 64-bit load/store requires a core register.
Douglas Leung2db3e262014-06-25 16:02:55 -0700891 // Smaller aligned load/store is atomic for both core and fp registers.
892 if (size == k64 || size == kDouble) {
Douglas Leungd9cb8ae2014-07-09 14:28:35 -0700893 return kCoreReg;
Douglas Leung2db3e262014-06-25 16:02:55 -0700894 }
895 }
Vladimir Marko674744e2014-04-24 15:18:26 +0100896 // TODO: Verify that both core and fp registers are suitable for smaller sizes.
897 return RegClassBySize(size);
898}
899
Brian Carlstrom7940e442013-07-12 13:46:57 -0700900MipsMir2Lir::MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
Goran Jakovljevic10957932015-03-24 18:42:56 +0100901 : Mir2Lir(cu, mir_graph, arena), in_to_reg_storage_mips64_mapper_(this),
902 in_to_reg_storage_mips_mapper_(this),
903 isaIsR6_(cu_->target64 ? true : cu->compiler_driver->GetInstructionSetFeatures()
904 ->AsMipsInstructionSetFeatures()->IsR6()),
905 fpuIs32Bit_(cu_->target64 ? false : cu->compiler_driver->GetInstructionSetFeatures()
906 ->AsMipsInstructionSetFeatures()->Is32BitFloatingPoint()) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700907 for (int i = 0; i < kMipsLast; i++) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700908 DCHECK_EQ(MipsMir2Lir::EncodingMap[i].opcode, i)
909 << "Encoding order for " << MipsMir2Lir::EncodingMap[i].name
910 << " is wrong: expecting " << i << ", seeing "
911 << static_cast<int>(MipsMir2Lir::EncodingMap[i].opcode);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700912 }
913}
914
915Mir2Lir* MipsCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
916 ArenaAllocator* const arena) {
917 return new MipsMir2Lir(cu, mir_graph, arena);
918}
919
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700920uint64_t MipsMir2Lir::GetTargetInstFlags(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700921 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700922 return MipsMir2Lir::EncodingMap[opcode].flags;
923}
924
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700925const char* MipsMir2Lir::GetTargetInstName(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700926 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700927 return MipsMir2Lir::EncodingMap[opcode].name;
928}
929
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700930const char* MipsMir2Lir::GetTargetInstFmt(int opcode) {
buzbee409fe942013-10-11 10:49:56 -0700931 DCHECK(!IsPseudoLirOp(opcode));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700932 return MipsMir2Lir::EncodingMap[opcode].fmt;
933}
934
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700935} // namespace art