blob: 43fbcbdd2bfcf48ad53b9859be5965a57c4378e9 [file] [log] [blame]
Brian Carlstrom7940e442013-07-12 13:46:57 -07001/*
2 * Copyright (C) 2011 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
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_COMPILER_DEX_QUICK_MIPS_CODEGEN_MIPS_H_
18#define ART_COMPILER_DEX_QUICK_MIPS_CODEGEN_MIPS_H_
Brian Carlstrom7940e442013-07-12 13:46:57 -070019
Goran Jakovljevic10957932015-03-24 18:42:56 +010020#include "dex/compiler_ir.h"
Andreas Gampe53c913b2014-08-12 23:19:23 -070021#include "dex/quick/mir_to_lir.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070022#include "mips_lir.h"
23
24namespace art {
25
Andreas Gampe0b9203e2015-01-22 20:39:27 -080026struct CompilationUnit;
27
Ian Rogerse2143c02014-03-28 08:47:16 -070028class MipsMir2Lir FINAL : public Mir2Lir {
Serguei Katkov717a3e42014-11-13 17:19:42 +060029 protected:
30 class InToRegStorageMipsMapper : public InToRegStorageMapper {
31 public:
32 explicit InToRegStorageMipsMapper(Mir2Lir* m2l) : m2l_(m2l), cur_core_reg_(0) {}
33 virtual RegStorage GetNextReg(ShortyArg arg);
34 virtual void Reset() OVERRIDE {
35 cur_core_reg_ = 0;
36 }
37 protected:
38 Mir2Lir* m2l_;
39 private:
40 size_t cur_core_reg_;
41 };
42
Goran Jakovljevic10957932015-03-24 18:42:56 +010043 class InToRegStorageMips64Mapper : public InToRegStorageMapper {
44 public:
45 explicit InToRegStorageMips64Mapper(Mir2Lir* m2l) : m2l_(m2l), cur_arg_reg_(0) {}
46 virtual RegStorage GetNextReg(ShortyArg arg);
47 virtual void Reset() OVERRIDE {
48 cur_arg_reg_ = 0;
49 }
50 protected:
51 Mir2Lir* m2l_;
52 private:
53 size_t cur_arg_reg_;
54 };
55
56 InToRegStorageMips64Mapper in_to_reg_storage_mips64_mapper_;
Serguei Katkov717a3e42014-11-13 17:19:42 +060057 InToRegStorageMipsMapper in_to_reg_storage_mips_mapper_;
58 InToRegStorageMapper* GetResetedInToRegStorageMapper() OVERRIDE {
Goran Jakovljevic10957932015-03-24 18:42:56 +010059 InToRegStorageMapper* res;
60 if (cu_->target64) {
61 res = &in_to_reg_storage_mips64_mapper_;
62 } else {
63 res = &in_to_reg_storage_mips_mapper_;
64 }
65 res->Reset();
66 return res;
Serguei Katkov717a3e42014-11-13 17:19:42 +060067 }
68
Goran Jakovljevic10957932015-03-24 18:42:56 +010069 public:
70 MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena);
Brian Carlstrom7940e442013-07-12 13:46:57 -070071
Goran Jakovljevic10957932015-03-24 18:42:56 +010072 // Required for target - codegen utilities.
73 bool SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div, RegLocation rl_src,
74 RegLocation rl_dest, int lit);
75 bool EasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit) OVERRIDE;
76 void GenMultiplyByConstantFloat(RegLocation rl_dest, RegLocation rl_src1, int32_t constant)
77 OVERRIDE;
78 void GenMultiplyByConstantDouble(RegLocation rl_dest, RegLocation rl_src1, int64_t constant)
79 OVERRIDE;
80 LIR* CheckSuspendUsingLoad() OVERRIDE;
81 RegStorage LoadHelper(QuickEntrypointEnum trampoline) OVERRIDE;
Douglas Leung22bb5a22015-07-02 16:42:08 -070082 void ForceImplicitNullCheck(RegStorage reg, int opt_flags, bool is_wide);
Goran Jakovljevic10957932015-03-24 18:42:56 +010083 LIR* LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest, OpSize size,
84 VolatileKind is_volatile) OVERRIDE;
85 LIR* LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest, int scale,
86 OpSize size) OVERRIDE;
87 LIR* LoadConstantNoClobber(RegStorage r_dest, int value);
88 LIR* LoadConstantWideNoClobber(RegStorage r_dest, int64_t value);
89 LIR* LoadConstantWide(RegStorage r_dest, int64_t value);
90 LIR* StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src, OpSize size,
91 VolatileKind is_volatile) OVERRIDE;
92 LIR* StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src, int scale,
93 OpSize size) OVERRIDE;
94 LIR* GenAtomic64Load(RegStorage r_base, int displacement, RegStorage r_dest);
95 LIR* GenAtomic64Store(RegStorage r_base, int displacement, RegStorage r_src);
Vladimir Markobf535be2014-11-19 18:52:35 +000096
Goran Jakovljevic10957932015-03-24 18:42:56 +010097 /// @copydoc Mir2Lir::UnconditionallyMarkGCCard(RegStorage)
98 void UnconditionallyMarkGCCard(RegStorage tgt_addr_reg) OVERRIDE;
Brian Carlstrom7940e442013-07-12 13:46:57 -070099
Goran Jakovljevic10957932015-03-24 18:42:56 +0100100 // Required for target - register utilities.
101 RegStorage Solo64ToPair64(RegStorage reg);
102 RegStorage Fp64ToSolo32(RegStorage reg);
103 RegStorage TargetReg(SpecialTargetRegister reg);
104 RegStorage TargetReg(SpecialTargetRegister reg, WideKind wide_kind) OVERRIDE;
105 RegStorage TargetPtrReg(SpecialTargetRegister reg) OVERRIDE {
106 return TargetReg(reg, cu_->target64 ? kWide : kNotWide);
107 }
108 RegLocation GetReturnAlt();
109 RegLocation GetReturnWideAlt();
110 RegLocation LocCReturn();
111 RegLocation LocCReturnRef();
112 RegLocation LocCReturnDouble();
113 RegLocation LocCReturnFloat();
114 RegLocation LocCReturnWide();
115 ResourceMask GetRegMaskCommon(const RegStorage& reg) const OVERRIDE;
116 void AdjustSpillMask();
117 void ClobberCallerSave();
118 void FreeCallTemps();
119 void LockCallTemps();
120 void CompilerInitializeRegAlloc();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700121
Goran Jakovljevic10957932015-03-24 18:42:56 +0100122 // Required for target - miscellaneous.
123 void AssembleLIR();
124 int AssignInsnOffsets();
125 void AssignOffsets();
126 AssemblerStatus AssembleInstructions(CodeOffset start_addr);
127 void DumpResourceMask(LIR* lir, const ResourceMask& mask, const char* prefix) OVERRIDE;
128 void SetupTargetResourceMasks(LIR* lir, uint64_t flags, ResourceMask* use_mask,
129 ResourceMask* def_mask) OVERRIDE;
130 const char* GetTargetInstFmt(int opcode);
131 const char* GetTargetInstName(int opcode);
132 std::string BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr);
133 ResourceMask GetPCUseDefEncoding() const OVERRIDE;
134 uint64_t GetTargetInstFlags(int opcode);
135 size_t GetInsnSize(LIR* lir) OVERRIDE;
136 bool IsUnconditionalBranch(LIR* lir);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700137
Goran Jakovljevic10957932015-03-24 18:42:56 +0100138 // Get the register class for load/store of a field.
139 RegisterClass RegClassForFieldLoadStore(OpSize size, bool is_volatile) OVERRIDE;
Vladimir Marko674744e2014-04-24 15:18:26 +0100140
Goran Jakovljevic10957932015-03-24 18:42:56 +0100141 // Required for target - Dalvik-level generators.
142 void GenShiftOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
143 RegLocation lr_shift);
144 void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
145 RegLocation rl_src2, int flags);
146 void GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index,
147 RegLocation rl_dest, int scale);
148 void GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index,
149 RegLocation rl_src, int scale, bool card_mark);
150 void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
151 RegLocation rl_shift, int flags);
152 void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
153 RegLocation rl_src2);
154 void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
155 RegLocation rl_src2);
156 void GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
157 RegLocation rl_src2);
158 void GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src);
159 bool GenInlinedAbsFloat(CallInfo* info) OVERRIDE;
160 bool GenInlinedAbsDouble(CallInfo* info) OVERRIDE;
161 bool GenInlinedCas(CallInfo* info, bool is_long, bool is_object);
162 bool GenInlinedMinMax(CallInfo* info, bool is_min, bool is_long);
163 bool GenInlinedSqrt(CallInfo* info);
164 bool GenInlinedPeek(CallInfo* info, OpSize size);
165 bool GenInlinedPoke(CallInfo* info, OpSize size);
166 void GenIntToLong(RegLocation rl_dest, RegLocation rl_src) OVERRIDE;
167 void GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
168 RegLocation rl_src2, int flags) OVERRIDE;
169 RegLocation GenDivRem(RegLocation rl_dest, RegStorage reg_lo, RegStorage reg_hi, bool is_div);
170 RegLocation GenDivRemLit(RegLocation rl_dest, RegStorage reg_lo, int lit, bool is_div);
171 void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
172 void GenDivZeroCheckWide(RegStorage reg);
173 void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method);
174 void GenExitSequence();
175 void GenSpecialExitSequence() OVERRIDE;
176 void GenSpecialEntryForSuspend() OVERRIDE;
177 void GenSpecialExitForSuspend() OVERRIDE;
178 void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double);
179 void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir);
180 void GenSelect(BasicBlock* bb, MIR* mir);
181 void GenSelectConst32(RegStorage left_op, RegStorage right_op, ConditionCode code,
182 int32_t true_val, int32_t false_val, RegStorage rs_dest,
183 RegisterClass dest_reg_class) OVERRIDE;
184 bool GenMemBarrier(MemBarrierKind barrier_kind);
185 void GenMoveException(RegLocation rl_dest);
186 void GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result, int lit,
187 int first_bit, int second_bit);
188 void GenNegDouble(RegLocation rl_dest, RegLocation rl_src);
189 void GenNegFloat(RegLocation rl_dest, RegLocation rl_src);
190 void GenLargePackedSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src);
191 void GenLargeSparseSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src);
192 bool GenSpecialCase(BasicBlock* bb, MIR* mir, const InlineMethod& special);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700193
Goran Jakovljevic10957932015-03-24 18:42:56 +0100194 // Required for target - single operation generators.
195 LIR* OpUnconditionalBranch(LIR* target);
196 LIR* OpCmpBranch(ConditionCode cond, RegStorage src1, RegStorage src2, LIR* target);
197 LIR* OpCmpImmBranch(ConditionCode cond, RegStorage reg, int check_value, LIR* target);
198 LIR* OpCondBranch(ConditionCode cc, LIR* target);
199 LIR* OpDecAndBranch(ConditionCode c_code, RegStorage reg, LIR* target);
200 LIR* OpFpRegCopy(RegStorage r_dest, RegStorage r_src);
201 LIR* OpIT(ConditionCode cond, const char* guide);
202 void OpEndIT(LIR* it);
203 LIR* OpMem(OpKind op, RegStorage r_base, int disp);
204 void OpPcRelLoad(RegStorage reg, LIR* target);
205 LIR* OpReg(OpKind op, RegStorage r_dest_src);
206 void OpRegCopy(RegStorage r_dest, RegStorage r_src);
207 LIR* OpRegCopyNoInsert(RegStorage r_dest, RegStorage r_src);
208 LIR* OpRegImm(OpKind op, RegStorage r_dest_src1, int value);
209 LIR* OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2);
210 LIR* OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset, MoveType move_type);
211 LIR* OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type);
212 LIR* OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src);
213 LIR* OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value);
214 LIR* OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2);
215 LIR* OpTestSuspend(LIR* target);
216 LIR* OpVldm(RegStorage r_base, int count);
217 LIR* OpVstm(RegStorage r_base, int count);
218 void OpRegCopyWide(RegStorage dest, RegStorage src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700219
Goran Jakovljevic10957932015-03-24 18:42:56 +0100220 // TODO: collapse r_dest.
221 LIR* LoadBaseDispBody(RegStorage r_base, int displacement, RegStorage r_dest, OpSize size);
222 // TODO: collapse r_src.
223 LIR* StoreBaseDispBody(RegStorage r_base, int displacement, RegStorage r_src, OpSize size);
224 void SpillCoreRegs();
225 void UnSpillCoreRegs();
226 static const MipsEncodingMap EncodingMap[kMipsLast];
227 bool InexpensiveConstantInt(int32_t value);
228 bool InexpensiveConstantFloat(int32_t value);
229 bool InexpensiveConstantLong(int64_t value);
230 bool InexpensiveConstantDouble(int64_t value);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700231
Goran Jakovljevic10957932015-03-24 18:42:56 +0100232 bool WideGPRsAreAliases() const OVERRIDE {
233 return cu_->target64; // Wide GPRs are formed by pairing on mips32.
234 }
235 bool WideFPRsAreAliases() const OVERRIDE {
236 return cu_->target64; // Wide FPRs are formed by pairing on mips32.
237 }
238
239 LIR* InvokeTrampoline(OpKind op, RegStorage r_tgt, QuickEntrypointEnum trampoline) OVERRIDE;
240
241 RegLocation GenDivRem(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2, bool is_div,
242 int flags) OVERRIDE;
243 RegLocation GenDivRemLit(RegLocation rl_dest, RegLocation rl_src1, int lit, bool is_div) OVERRIDE;
244 NextCallInsn GetNextSDCallInsn() OVERRIDE;
245 LIR* GenCallInsn(const MirMethodLoweringInfo& method_info) OVERRIDE;
246
247 // Unimplemented intrinsics.
248 bool GenInlinedCharAt(CallInfo* info ATTRIBUTE_UNUSED) OVERRIDE {
249 return false;
250 }
251 bool GenInlinedAbsInt(CallInfo* info ATTRIBUTE_UNUSED) OVERRIDE {
252 return false;
253 }
254 bool GenInlinedAbsLong(CallInfo* info ATTRIBUTE_UNUSED) OVERRIDE {
255 return false;
256 }
257 bool GenInlinedIndexOf(CallInfo* info ATTRIBUTE_UNUSED, bool zero_based ATTRIBUTE_UNUSED)
258 OVERRIDE {
259 return false;
260 }
261
262 // True if isa is rev R6.
263 const bool isaIsR6_;
264
265 // True if floating point unit is 32bits.
266 const bool fpuIs32Bit_;
267
268 private:
269 void GenNegLong(RegLocation rl_dest, RegLocation rl_src);
270 void GenAddLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
271 void GenSubLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
272
273 void ConvertShortToLongBranch(LIR* lir);
274
275 // Mips64 specific long gen methods:
276 void GenLongOp(OpKind op, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
277 void GenNotLong(RegLocation rl_dest, RegLocation rl_src);
278 void GenMulLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
279 void GenDivRemLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
280 RegLocation rl_src2, bool is_div, int flags);
281 void GenConversionCall(QuickEntrypointEnum trampoline, RegLocation rl_dest, RegLocation rl_src,
282 RegisterClass reg_class);
283 RegStorage AllocPtrSizeTemp(bool required = true);
284
285 /**
286 * @param reg #RegStorage containing a Solo64 input register (e.g. @c a1 or @c d0).
287 * @return A Solo32 with the same register number as the @p reg (e.g. @c a1 or @c f0).
288 * @see As64BitReg
289 */
290 RegStorage As32BitReg(RegStorage reg) {
291 DCHECK(!reg.IsPair());
292 if ((kFailOnSizeError || kReportSizeError) && !reg.Is64Bit()) {
293 if (kFailOnSizeError) {
294 LOG(FATAL) << "Expected 64b register";
295 } else {
296 LOG(WARNING) << "Expected 64b register";
297 return reg;
298 }
Serguei Katkov59a42af2014-07-05 00:55:46 +0700299 }
Goran Jakovljevic10957932015-03-24 18:42:56 +0100300 RegStorage ret_val = RegStorage(RegStorage::k32BitSolo,
301 reg.GetRawBits() & RegStorage::kRegTypeMask);
302 DCHECK_EQ(GetRegInfo(reg)->FindMatchingView(RegisterInfo::k32SoloStorageMask)
303 ->GetReg().GetReg(),
304 ret_val.GetReg());
305 return ret_val;
306 }
307
308 /**
309 * @param reg #RegStorage containing a Solo32 input register (e.g. @c a1 or @c f0).
310 * @return A Solo64 with the same register number as the @p reg (e.g. @c a1 or @c d0).
311 */
312 RegStorage As64BitReg(RegStorage reg) {
313 DCHECK(!reg.IsPair());
314 if ((kFailOnSizeError || kReportSizeError) && !reg.Is32Bit()) {
315 if (kFailOnSizeError) {
316 LOG(FATAL) << "Expected 32b register";
317 } else {
318 LOG(WARNING) << "Expected 32b register";
319 return reg;
320 }
Serguei Katkov59a42af2014-07-05 00:55:46 +0700321 }
Goran Jakovljevic10957932015-03-24 18:42:56 +0100322 RegStorage ret_val = RegStorage(RegStorage::k64BitSolo,
323 reg.GetRawBits() & RegStorage::kRegTypeMask);
324 DCHECK_EQ(GetRegInfo(reg)->FindMatchingView(RegisterInfo::k64SoloStorageMask)
325 ->GetReg().GetReg(),
326 ret_val.GetReg());
327 return ret_val;
328 }
Serguei Katkov59a42af2014-07-05 00:55:46 +0700329
Goran Jakovljevic10957932015-03-24 18:42:56 +0100330 RegStorage Check64BitReg(RegStorage reg) {
331 if ((kFailOnSizeError || kReportSizeError) && !reg.Is64Bit()) {
332 if (kFailOnSizeError) {
333 LOG(FATAL) << "Checked for 64b register";
334 } else {
335 LOG(WARNING) << "Checked for 64b register";
336 return As64BitReg(reg);
337 }
Andreas Gamped500b532015-01-16 22:09:55 -0800338 }
Goran Jakovljevic10957932015-03-24 18:42:56 +0100339 return reg;
340 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700341};
342
343} // namespace art
344
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700345#endif // ART_COMPILER_DEX_QUICK_MIPS_CODEGEN_MIPS_H_