blob: 713264e0d9eba56c44bf8660c1e2e55818f70c8e [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;
82 LIR* LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest, OpSize size,
83 VolatileKind is_volatile) OVERRIDE;
84 LIR* LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest, int scale,
85 OpSize size) OVERRIDE;
86 LIR* LoadConstantNoClobber(RegStorage r_dest, int value);
87 LIR* LoadConstantWideNoClobber(RegStorage r_dest, int64_t value);
88 LIR* LoadConstantWide(RegStorage r_dest, int64_t value);
89 LIR* StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src, OpSize size,
90 VolatileKind is_volatile) OVERRIDE;
91 LIR* StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src, int scale,
92 OpSize size) OVERRIDE;
93 LIR* GenAtomic64Load(RegStorage r_base, int displacement, RegStorage r_dest);
94 LIR* GenAtomic64Store(RegStorage r_base, int displacement, RegStorage r_src);
Vladimir Markobf535be2014-11-19 18:52:35 +000095
Goran Jakovljevic10957932015-03-24 18:42:56 +010096 /// @copydoc Mir2Lir::UnconditionallyMarkGCCard(RegStorage)
97 void UnconditionallyMarkGCCard(RegStorage tgt_addr_reg) OVERRIDE;
Brian Carlstrom7940e442013-07-12 13:46:57 -070098
Goran Jakovljevic10957932015-03-24 18:42:56 +010099 // Required for target - register utilities.
100 RegStorage Solo64ToPair64(RegStorage reg);
101 RegStorage Fp64ToSolo32(RegStorage reg);
102 RegStorage TargetReg(SpecialTargetRegister reg);
103 RegStorage TargetReg(SpecialTargetRegister reg, WideKind wide_kind) OVERRIDE;
104 RegStorage TargetPtrReg(SpecialTargetRegister reg) OVERRIDE {
105 return TargetReg(reg, cu_->target64 ? kWide : kNotWide);
106 }
107 RegLocation GetReturnAlt();
108 RegLocation GetReturnWideAlt();
109 RegLocation LocCReturn();
110 RegLocation LocCReturnRef();
111 RegLocation LocCReturnDouble();
112 RegLocation LocCReturnFloat();
113 RegLocation LocCReturnWide();
114 ResourceMask GetRegMaskCommon(const RegStorage& reg) const OVERRIDE;
115 void AdjustSpillMask();
116 void ClobberCallerSave();
117 void FreeCallTemps();
118 void LockCallTemps();
119 void CompilerInitializeRegAlloc();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700120
Goran Jakovljevic10957932015-03-24 18:42:56 +0100121 // Required for target - miscellaneous.
122 void AssembleLIR();
123 int AssignInsnOffsets();
124 void AssignOffsets();
125 AssemblerStatus AssembleInstructions(CodeOffset start_addr);
126 void DumpResourceMask(LIR* lir, const ResourceMask& mask, const char* prefix) OVERRIDE;
127 void SetupTargetResourceMasks(LIR* lir, uint64_t flags, ResourceMask* use_mask,
128 ResourceMask* def_mask) OVERRIDE;
129 const char* GetTargetInstFmt(int opcode);
130 const char* GetTargetInstName(int opcode);
131 std::string BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr);
132 ResourceMask GetPCUseDefEncoding() const OVERRIDE;
133 uint64_t GetTargetInstFlags(int opcode);
134 size_t GetInsnSize(LIR* lir) OVERRIDE;
135 bool IsUnconditionalBranch(LIR* lir);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700136
Goran Jakovljevic10957932015-03-24 18:42:56 +0100137 // Get the register class for load/store of a field.
138 RegisterClass RegClassForFieldLoadStore(OpSize size, bool is_volatile) OVERRIDE;
Vladimir Marko674744e2014-04-24 15:18:26 +0100139
Goran Jakovljevic10957932015-03-24 18:42:56 +0100140 // Required for target - Dalvik-level generators.
141 void GenShiftOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
142 RegLocation lr_shift);
143 void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
144 RegLocation rl_src2, int flags);
145 void GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index,
146 RegLocation rl_dest, int scale);
147 void GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index,
148 RegLocation rl_src, int scale, bool card_mark);
149 void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
150 RegLocation rl_shift, int flags);
151 void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
152 RegLocation rl_src2);
153 void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
154 RegLocation rl_src2);
155 void GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
156 RegLocation rl_src2);
157 void GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src);
158 bool GenInlinedAbsFloat(CallInfo* info) OVERRIDE;
159 bool GenInlinedAbsDouble(CallInfo* info) OVERRIDE;
160 bool GenInlinedCas(CallInfo* info, bool is_long, bool is_object);
161 bool GenInlinedMinMax(CallInfo* info, bool is_min, bool is_long);
162 bool GenInlinedSqrt(CallInfo* info);
163 bool GenInlinedPeek(CallInfo* info, OpSize size);
164 bool GenInlinedPoke(CallInfo* info, OpSize size);
165 void GenIntToLong(RegLocation rl_dest, RegLocation rl_src) OVERRIDE;
166 void GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
167 RegLocation rl_src2, int flags) OVERRIDE;
168 RegLocation GenDivRem(RegLocation rl_dest, RegStorage reg_lo, RegStorage reg_hi, bool is_div);
169 RegLocation GenDivRemLit(RegLocation rl_dest, RegStorage reg_lo, int lit, bool is_div);
170 void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
171 void GenDivZeroCheckWide(RegStorage reg);
172 void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method);
173 void GenExitSequence();
174 void GenSpecialExitSequence() OVERRIDE;
175 void GenSpecialEntryForSuspend() OVERRIDE;
176 void GenSpecialExitForSuspend() OVERRIDE;
177 void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double);
178 void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir);
179 void GenSelect(BasicBlock* bb, MIR* mir);
180 void GenSelectConst32(RegStorage left_op, RegStorage right_op, ConditionCode code,
181 int32_t true_val, int32_t false_val, RegStorage rs_dest,
182 RegisterClass dest_reg_class) OVERRIDE;
183 bool GenMemBarrier(MemBarrierKind barrier_kind);
184 void GenMoveException(RegLocation rl_dest);
185 void GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result, int lit,
186 int first_bit, int second_bit);
187 void GenNegDouble(RegLocation rl_dest, RegLocation rl_src);
188 void GenNegFloat(RegLocation rl_dest, RegLocation rl_src);
189 void GenLargePackedSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src);
190 void GenLargeSparseSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src);
191 bool GenSpecialCase(BasicBlock* bb, MIR* mir, const InlineMethod& special);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700192
Goran Jakovljevic10957932015-03-24 18:42:56 +0100193 // Required for target - single operation generators.
194 LIR* OpUnconditionalBranch(LIR* target);
195 LIR* OpCmpBranch(ConditionCode cond, RegStorage src1, RegStorage src2, LIR* target);
196 LIR* OpCmpImmBranch(ConditionCode cond, RegStorage reg, int check_value, LIR* target);
197 LIR* OpCondBranch(ConditionCode cc, LIR* target);
198 LIR* OpDecAndBranch(ConditionCode c_code, RegStorage reg, LIR* target);
199 LIR* OpFpRegCopy(RegStorage r_dest, RegStorage r_src);
200 LIR* OpIT(ConditionCode cond, const char* guide);
201 void OpEndIT(LIR* it);
202 LIR* OpMem(OpKind op, RegStorage r_base, int disp);
203 void OpPcRelLoad(RegStorage reg, LIR* target);
204 LIR* OpReg(OpKind op, RegStorage r_dest_src);
205 void OpRegCopy(RegStorage r_dest, RegStorage r_src);
206 LIR* OpRegCopyNoInsert(RegStorage r_dest, RegStorage r_src);
207 LIR* OpRegImm(OpKind op, RegStorage r_dest_src1, int value);
208 LIR* OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2);
209 LIR* OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset, MoveType move_type);
210 LIR* OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type);
211 LIR* OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src);
212 LIR* OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value);
213 LIR* OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2);
214 LIR* OpTestSuspend(LIR* target);
215 LIR* OpVldm(RegStorage r_base, int count);
216 LIR* OpVstm(RegStorage r_base, int count);
217 void OpRegCopyWide(RegStorage dest, RegStorage src);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700218
Goran Jakovljevic10957932015-03-24 18:42:56 +0100219 // TODO: collapse r_dest.
220 LIR* LoadBaseDispBody(RegStorage r_base, int displacement, RegStorage r_dest, OpSize size);
221 // TODO: collapse r_src.
222 LIR* StoreBaseDispBody(RegStorage r_base, int displacement, RegStorage r_src, OpSize size);
223 void SpillCoreRegs();
224 void UnSpillCoreRegs();
225 static const MipsEncodingMap EncodingMap[kMipsLast];
226 bool InexpensiveConstantInt(int32_t value);
227 bool InexpensiveConstantFloat(int32_t value);
228 bool InexpensiveConstantLong(int64_t value);
229 bool InexpensiveConstantDouble(int64_t value);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700230
Goran Jakovljevic10957932015-03-24 18:42:56 +0100231 bool WideGPRsAreAliases() const OVERRIDE {
232 return cu_->target64; // Wide GPRs are formed by pairing on mips32.
233 }
234 bool WideFPRsAreAliases() const OVERRIDE {
235 return cu_->target64; // Wide FPRs are formed by pairing on mips32.
236 }
237
238 LIR* InvokeTrampoline(OpKind op, RegStorage r_tgt, QuickEntrypointEnum trampoline) OVERRIDE;
239
240 RegLocation GenDivRem(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2, bool is_div,
241 int flags) OVERRIDE;
242 RegLocation GenDivRemLit(RegLocation rl_dest, RegLocation rl_src1, int lit, bool is_div) OVERRIDE;
243 NextCallInsn GetNextSDCallInsn() OVERRIDE;
244 LIR* GenCallInsn(const MirMethodLoweringInfo& method_info) OVERRIDE;
245
246 // Unimplemented intrinsics.
247 bool GenInlinedCharAt(CallInfo* info ATTRIBUTE_UNUSED) OVERRIDE {
248 return false;
249 }
250 bool GenInlinedAbsInt(CallInfo* info ATTRIBUTE_UNUSED) OVERRIDE {
251 return false;
252 }
253 bool GenInlinedAbsLong(CallInfo* info ATTRIBUTE_UNUSED) OVERRIDE {
254 return false;
255 }
256 bool GenInlinedIndexOf(CallInfo* info ATTRIBUTE_UNUSED, bool zero_based ATTRIBUTE_UNUSED)
257 OVERRIDE {
258 return false;
259 }
260
261 // True if isa is rev R6.
262 const bool isaIsR6_;
263
264 // True if floating point unit is 32bits.
265 const bool fpuIs32Bit_;
266
267 private:
268 void GenNegLong(RegLocation rl_dest, RegLocation rl_src);
269 void GenAddLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
270 void GenSubLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
271
272 void ConvertShortToLongBranch(LIR* lir);
273
274 // Mips64 specific long gen methods:
275 void GenLongOp(OpKind op, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
276 void GenNotLong(RegLocation rl_dest, RegLocation rl_src);
277 void GenMulLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
278 void GenDivRemLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
279 RegLocation rl_src2, bool is_div, int flags);
280 void GenConversionCall(QuickEntrypointEnum trampoline, RegLocation rl_dest, RegLocation rl_src,
281 RegisterClass reg_class);
282 RegStorage AllocPtrSizeTemp(bool required = true);
283
284 /**
285 * @param reg #RegStorage containing a Solo64 input register (e.g. @c a1 or @c d0).
286 * @return A Solo32 with the same register number as the @p reg (e.g. @c a1 or @c f0).
287 * @see As64BitReg
288 */
289 RegStorage As32BitReg(RegStorage reg) {
290 DCHECK(!reg.IsPair());
291 if ((kFailOnSizeError || kReportSizeError) && !reg.Is64Bit()) {
292 if (kFailOnSizeError) {
293 LOG(FATAL) << "Expected 64b register";
294 } else {
295 LOG(WARNING) << "Expected 64b register";
296 return reg;
297 }
Serguei Katkov59a42af2014-07-05 00:55:46 +0700298 }
Goran Jakovljevic10957932015-03-24 18:42:56 +0100299 RegStorage ret_val = RegStorage(RegStorage::k32BitSolo,
300 reg.GetRawBits() & RegStorage::kRegTypeMask);
301 DCHECK_EQ(GetRegInfo(reg)->FindMatchingView(RegisterInfo::k32SoloStorageMask)
302 ->GetReg().GetReg(),
303 ret_val.GetReg());
304 return ret_val;
305 }
306
307 /**
308 * @param reg #RegStorage containing a Solo32 input register (e.g. @c a1 or @c f0).
309 * @return A Solo64 with the same register number as the @p reg (e.g. @c a1 or @c d0).
310 */
311 RegStorage As64BitReg(RegStorage reg) {
312 DCHECK(!reg.IsPair());
313 if ((kFailOnSizeError || kReportSizeError) && !reg.Is32Bit()) {
314 if (kFailOnSizeError) {
315 LOG(FATAL) << "Expected 32b register";
316 } else {
317 LOG(WARNING) << "Expected 32b register";
318 return reg;
319 }
Serguei Katkov59a42af2014-07-05 00:55:46 +0700320 }
Goran Jakovljevic10957932015-03-24 18:42:56 +0100321 RegStorage ret_val = RegStorage(RegStorage::k64BitSolo,
322 reg.GetRawBits() & RegStorage::kRegTypeMask);
323 DCHECK_EQ(GetRegInfo(reg)->FindMatchingView(RegisterInfo::k64SoloStorageMask)
324 ->GetReg().GetReg(),
325 ret_val.GetReg());
326 return ret_val;
327 }
Serguei Katkov59a42af2014-07-05 00:55:46 +0700328
Goran Jakovljevic10957932015-03-24 18:42:56 +0100329 RegStorage Check64BitReg(RegStorage reg) {
330 if ((kFailOnSizeError || kReportSizeError) && !reg.Is64Bit()) {
331 if (kFailOnSizeError) {
332 LOG(FATAL) << "Checked for 64b register";
333 } else {
334 LOG(WARNING) << "Checked for 64b register";
335 return As64BitReg(reg);
336 }
Andreas Gamped500b532015-01-16 22:09:55 -0800337 }
Goran Jakovljevic10957932015-03-24 18:42:56 +0100338 return reg;
339 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700340};
341
342} // namespace art
343
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700344#endif // ART_COMPILER_DEX_QUICK_MIPS_CODEGEN_MIPS_H_