blob: 57c30d8b4bdda6abe78b2fe93888d63f070e51e8 [file] [log] [blame]
Maja Gagic6ea651f2015-02-24 16:55:04 +01001/*
2 * Copyright (C) 2015 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#ifndef ART_COMPILER_DEX_QUICK_MIPS64_CODEGEN_MIPS64_H_
18#define ART_COMPILER_DEX_QUICK_MIPS64_CODEGEN_MIPS64_H_
19
20#include "dex/quick/mir_to_lir.h"
21#include "mips64_lir.h"
22
23namespace art {
24
25struct CompilationUnit;
26
27class Mips64Mir2Lir FINAL : public Mir2Lir {
28 protected:
29 class InToRegStorageMips64Mapper : public InToRegStorageMapper {
30 public:
31 explicit InToRegStorageMips64Mapper(Mir2Lir* m2l) : m2l_(m2l), cur_arg_reg_(0) {}
32 virtual RegStorage GetNextReg(ShortyArg arg);
33 virtual void Reset() OVERRIDE {
34 cur_arg_reg_ = 0;
35 }
36 protected:
37 Mir2Lir* m2l_;
38 private:
39 size_t cur_arg_reg_;
40 };
41
42 InToRegStorageMips64Mapper in_to_reg_storage_mips64_mapper_;
43 InToRegStorageMapper* GetResetedInToRegStorageMapper() OVERRIDE {
44 in_to_reg_storage_mips64_mapper_.Reset();
45 return &in_to_reg_storage_mips64_mapper_;
46 }
47
48 public:
49 Mips64Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena);
50
51 // Required for target - codegen utilities.
52 bool SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div, RegLocation rl_src,
53 RegLocation rl_dest, int lit);
54 bool EasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit) OVERRIDE;
55 void GenMultiplyByConstantFloat(RegLocation rl_dest, RegLocation rl_src1, int32_t constant)
56 OVERRIDE;
57 void GenMultiplyByConstantDouble(RegLocation rl_dest, RegLocation rl_src1, int64_t constant)
58 OVERRIDE;
59 LIR* CheckSuspendUsingLoad() OVERRIDE;
60 RegStorage LoadHelper(QuickEntrypointEnum trampoline) OVERRIDE;
61 LIR* LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest, OpSize size,
62 VolatileKind is_volatile) OVERRIDE;
63 LIR* LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest, int scale,
64 OpSize size) OVERRIDE;
65 LIR* LoadConstantNoClobber(RegStorage r_dest, int value);
66 LIR* LoadConstantWide(RegStorage r_dest, int64_t value);
67 LIR* StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src, OpSize size,
68 VolatileKind is_volatile) OVERRIDE;
69 LIR* StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src, int scale,
70 OpSize size) OVERRIDE;
71 LIR* GenAtomic64Load(RegStorage r_base, int displacement, RegStorage r_dest);
72 LIR* GenAtomic64Store(RegStorage r_base, int displacement, RegStorage r_src);
73
74 /// @copydoc Mir2Lir::UnconditionallyMarkGCCard(RegStorage)
75 void UnconditionallyMarkGCCard(RegStorage tgt_addr_reg) OVERRIDE;
76
77 // Required for target - register utilities.
78 RegStorage TargetReg(SpecialTargetRegister reg) OVERRIDE;
79 RegStorage TargetReg(SpecialTargetRegister reg, WideKind wide_kind) OVERRIDE {
80 if (wide_kind == kWide || wide_kind == kRef) {
81 return As64BitReg(TargetReg(reg));
82 } else {
83 return Check32BitReg(TargetReg(reg));
84 }
85 }
86 RegStorage TargetPtrReg(SpecialTargetRegister reg) OVERRIDE {
87 return As64BitReg(TargetReg(reg));
88 }
89 RegLocation GetReturnAlt();
90 RegLocation GetReturnWideAlt();
91 RegLocation LocCReturn();
92 RegLocation LocCReturnRef();
93 RegLocation LocCReturnDouble();
94 RegLocation LocCReturnFloat();
95 RegLocation LocCReturnWide();
96 ResourceMask GetRegMaskCommon(const RegStorage& reg) const OVERRIDE;
97 void AdjustSpillMask();
98 void ClobberCallerSave();
99 void FreeCallTemps();
100 void LockCallTemps();
101 void CompilerInitializeRegAlloc();
102
103 // Required for target - miscellaneous.
104 void AssembleLIR();
105 int AssignInsnOffsets();
106 void AssignOffsets();
107 AssemblerStatus AssembleInstructions(CodeOffset start_addr);
108 void DumpResourceMask(LIR* lir, const ResourceMask& mask, const char* prefix) OVERRIDE;
109 void SetupTargetResourceMasks(LIR* lir, uint64_t flags, ResourceMask* use_mask,
110 ResourceMask* def_mask) OVERRIDE;
111 const char* GetTargetInstFmt(int opcode);
112 const char* GetTargetInstName(int opcode);
113 std::string BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr);
114 ResourceMask GetPCUseDefEncoding() const OVERRIDE;
115 uint64_t GetTargetInstFlags(int opcode);
116 size_t GetInsnSize(LIR* lir) OVERRIDE;
117 bool IsUnconditionalBranch(LIR* lir);
118
119 // Get the register class for load/store of a field.
120 RegisterClass RegClassForFieldLoadStore(OpSize size, bool is_volatile) OVERRIDE;
121
122 // Required for target - Dalvik-level generators.
123 void GenShiftOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
124 RegLocation lr_shift);
125 void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
126 RegLocation rl_src2, int flags);
127 void GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index,
128 RegLocation rl_dest, int scale);
129 void GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index,
130 RegLocation rl_src, int scale, bool card_mark);
131 void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
132 RegLocation rl_shift, int flags);
133 void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
134 RegLocation rl_src2);
135 void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
136 RegLocation rl_src2);
137 void GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
138 RegLocation rl_src2);
139 void GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src);
140 bool GenInlinedAbsFloat(CallInfo* info) OVERRIDE;
141 bool GenInlinedAbsDouble(CallInfo* info) OVERRIDE;
142 bool GenInlinedCas(CallInfo* info, bool is_long, bool is_object);
143 bool GenInlinedMinMax(CallInfo* info, bool is_min, bool is_long);
144 bool GenInlinedSqrt(CallInfo* info);
145 bool GenInlinedPeek(CallInfo* info, OpSize size);
146 bool GenInlinedPoke(CallInfo* info, OpSize size);
147 void GenIntToLong(RegLocation rl_dest, RegLocation rl_src) OVERRIDE;
148 void GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
149 RegLocation rl_src2, int flags) OVERRIDE;
150 RegLocation GenDivRem(RegLocation rl_dest, RegStorage reg_lo, RegStorage reg_hi, bool is_div);
151 RegLocation GenDivRemLit(RegLocation rl_dest, RegStorage reg_lo, int lit, bool is_div);
152 void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
153 void GenDivZeroCheckWide(RegStorage reg);
154 void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method);
155 void GenExitSequence();
156 void GenSpecialExitSequence() OVERRIDE;
157 void GenSpecialEntryForSuspend() OVERRIDE;
158 void GenSpecialExitForSuspend() OVERRIDE;
159 void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double);
160 void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir);
161 void GenSelect(BasicBlock* bb, MIR* mir);
162 void GenSelectConst32(RegStorage left_op, RegStorage right_op, ConditionCode code,
163 int32_t true_val, int32_t false_val, RegStorage rs_dest,
164 RegisterClass dest_reg_class) OVERRIDE;
165 bool GenMemBarrier(MemBarrierKind barrier_kind);
166 void GenMoveException(RegLocation rl_dest);
167 void GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result, int lit,
168 int first_bit, int second_bit);
169 void GenNegDouble(RegLocation rl_dest, RegLocation rl_src);
170 void GenNegFloat(RegLocation rl_dest, RegLocation rl_src);
171 void GenLargePackedSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src);
172 void GenLargeSparseSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src);
173 bool GenSpecialCase(BasicBlock* bb, MIR* mir, const InlineMethod& special);
174
175 // Required for target - single operation generators.
176 LIR* OpUnconditionalBranch(LIR* target);
177 LIR* OpCmpBranch(ConditionCode cond, RegStorage src1, RegStorage src2, LIR* target);
178 LIR* OpCmpImmBranch(ConditionCode cond, RegStorage reg, int check_value, LIR* target);
179 LIR* OpCondBranch(ConditionCode cc, LIR* target);
180 LIR* OpDecAndBranch(ConditionCode c_code, RegStorage reg, LIR* target);
181 LIR* OpFpRegCopy(RegStorage r_dest, RegStorage r_src);
182 LIR* OpIT(ConditionCode cond, const char* guide);
183 void OpEndIT(LIR* it);
184 LIR* OpMem(OpKind op, RegStorage r_base, int disp);
185 LIR* OpPcRelLoad(RegStorage reg, LIR* target);
186 LIR* OpReg(OpKind op, RegStorage r_dest_src);
187 void OpRegCopy(RegStorage r_dest, RegStorage r_src);
188 LIR* OpRegCopyNoInsert(RegStorage r_dest, RegStorage r_src);
189 LIR* OpRegImm(OpKind op, RegStorage r_dest_src1, int value);
190 LIR* OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2);
191 LIR* OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset, MoveType move_type);
192 LIR* OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type);
193 LIR* OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src);
194 LIR* OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value);
195 LIR* OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2);
196 LIR* OpTestSuspend(LIR* target);
197 LIR* OpVldm(RegStorage r_base, int count);
198 LIR* OpVstm(RegStorage r_base, int count);
199 void OpRegCopyWide(RegStorage dest, RegStorage src);
200
201 // TODO: collapse r_dest.
202 LIR* LoadBaseDispBody(RegStorage r_base, int displacement, RegStorage r_dest, OpSize size);
203 // TODO: collapse r_src.
204 LIR* StoreBaseDispBody(RegStorage r_base, int displacement, RegStorage r_src, OpSize size);
205 void SpillCoreRegs();
206 void UnSpillCoreRegs();
207 static const Mips64EncodingMap EncodingMap[kMips64Last];
208 bool InexpensiveConstantInt(int32_t value);
209 bool InexpensiveConstantFloat(int32_t value);
210 bool InexpensiveConstantLong(int64_t value);
211 bool InexpensiveConstantDouble(int64_t value);
212
213 bool WideGPRsAreAliases() const OVERRIDE {
214 return true; // 64b architecture.
215 }
216 bool WideFPRsAreAliases() const OVERRIDE {
217 return true; // 64b architecture.
218 }
219
220 LIR* InvokeTrampoline(OpKind op, RegStorage r_tgt, QuickEntrypointEnum trampoline) OVERRIDE;
221 RegLocation GenDivRem(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2,
222 bool is_div, int flags) OVERRIDE;
223 RegLocation GenDivRemLit(RegLocation rl_dest, RegLocation rl_src1, int lit, bool is_div)
224 OVERRIDE;
225 NextCallInsn GetNextSDCallInsn() OVERRIDE;
226 LIR* GenCallInsn(const MirMethodLoweringInfo& method_info) OVERRIDE;
227 // Unimplemented intrinsics.
228 bool GenInlinedCharAt(CallInfo* info ATTRIBUTE_UNUSED) OVERRIDE {
229 return false;
230 }
231 bool GenInlinedAbsInt(CallInfo* info ATTRIBUTE_UNUSED) OVERRIDE {
232 return false;
233 }
234 bool GenInlinedAbsLong(CallInfo* info ATTRIBUTE_UNUSED) OVERRIDE {
235 return false;
236 }
237 bool GenInlinedIndexOf(CallInfo* info ATTRIBUTE_UNUSED, bool zero_based ATTRIBUTE_UNUSED)
238 OVERRIDE {
239 return false;
240 }
241
242 private:
243 void GenLongOp(OpKind op, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
244 void GenNotLong(RegLocation rl_dest, RegLocation rl_src);
245 void GenNegLong(RegLocation rl_dest, RegLocation rl_src);
246 void GenMulLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
247 void GenDivRemLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
248 RegLocation rl_src2, bool is_div, int flags);
249 void GenConversionCall(QuickEntrypointEnum trampoline, RegLocation rl_dest, RegLocation rl_src,
250 RegisterClass reg_class);
251
252 void ConvertShortToLongBranch(LIR* lir);
253
254 /**
255 * @param reg #RegStorage containing a Solo64 input register (e.g. @c a1 or @c d0).
256 * @return A Solo32 with the same register number as the @p reg (e.g. @c a1 or @c f0).
257 * @see As64BitReg
258 */
259 RegStorage As32BitReg(RegStorage reg) {
260 DCHECK(!reg.IsPair());
261 if ((kFailOnSizeError || kReportSizeError) && !reg.Is64Bit()) {
262 if (kFailOnSizeError) {
263 LOG(FATAL) << "Expected 64b register";
264 } else {
265 LOG(WARNING) << "Expected 64b register";
266 return reg;
267 }
268 }
269 RegStorage ret_val = RegStorage(RegStorage::k32BitSolo,
270 reg.GetRawBits() & RegStorage::kRegTypeMask);
271 DCHECK_EQ(GetRegInfo(reg)->FindMatchingView(RegisterInfo::k32SoloStorageMask)
272 ->GetReg().GetReg(),
273 ret_val.GetReg());
274 return ret_val;
275 }
276
277 RegStorage Check32BitReg(RegStorage reg) {
278 if ((kFailOnSizeError || kReportSizeError) && !reg.Is32Bit()) {
279 if (kFailOnSizeError) {
280 LOG(FATAL) << "Checked for 32b register";
281 } else {
282 LOG(WARNING) << "Checked for 32b register";
283 return As32BitReg(reg);
284 }
285 }
286 return reg;
287 }
288
289 /**
290 * @param reg #RegStorage containing a Solo32 input register (e.g. @c a1 or @c f0).
291 * @return A Solo64 with the same register number as the @p reg (e.g. @c a1 or @c d0).
292 */
293 RegStorage As64BitReg(RegStorage reg) {
294 DCHECK(!reg.IsPair());
295 if ((kFailOnSizeError || kReportSizeError) && !reg.Is32Bit()) {
296 if (kFailOnSizeError) {
297 LOG(FATAL) << "Expected 32b register";
298 } else {
299 LOG(WARNING) << "Expected 32b register";
300 return reg;
301 }
302 }
303 RegStorage ret_val = RegStorage(RegStorage::k64BitSolo,
304 reg.GetRawBits() & RegStorage::kRegTypeMask);
305 DCHECK_EQ(GetRegInfo(reg)->FindMatchingView(RegisterInfo::k64SoloStorageMask)
306 ->GetReg().GetReg(),
307 ret_val.GetReg());
308 return ret_val;
309 }
310
311 RegStorage Check64BitReg(RegStorage reg) {
312 if ((kFailOnSizeError || kReportSizeError) && !reg.Is64Bit()) {
313 if (kFailOnSizeError) {
314 LOG(FATAL) << "Checked for 64b register";
315 } else {
316 LOG(WARNING) << "Checked for 64b register";
317 return As64BitReg(reg);
318 }
319 }
320 return reg;
321 }
322
323 void GenBreakpoint(int code);
324};
325
326} // namespace art
327
328#endif // ART_COMPILER_DEX_QUICK_MIPS64_CODEGEN_MIPS64_H_