1 /* 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 17 #ifndef ART_COMPILER_DEX_QUICK_MIPS_CODEGEN_MIPS_H_ 18 #define ART_COMPILER_DEX_QUICK_MIPS_CODEGEN_MIPS_H_ 19 20 #include "dex/compiler_ir.h" 21 #include "dex/quick/mir_to_lir.h" 22 #include "mips_lir.h" 23 24 namespace art { 25 26 struct CompilationUnit; 27 28 class MipsMir2Lir FINAL : public Mir2Lir { 29 protected: 30 class InToRegStorageMipsMapper : public InToRegStorageMapper { 31 public: InToRegStorageMipsMapper(Mir2Lir * m2l)32 explicit InToRegStorageMipsMapper(Mir2Lir* m2l) : m2l_(m2l), cur_core_reg_(0) {} 33 virtual RegStorage GetNextReg(ShortyArg arg); Reset()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 43 class InToRegStorageMips64Mapper : public InToRegStorageMapper { 44 public: InToRegStorageMips64Mapper(Mir2Lir * m2l)45 explicit InToRegStorageMips64Mapper(Mir2Lir* m2l) : m2l_(m2l), cur_arg_reg_(0) {} 46 virtual RegStorage GetNextReg(ShortyArg arg); Reset()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_; 57 InToRegStorageMipsMapper in_to_reg_storage_mips_mapper_; GetResetedInToRegStorageMapper()58 InToRegStorageMapper* GetResetedInToRegStorageMapper() OVERRIDE { 59 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; 67 } 68 69 public: 70 MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena); 71 72 // 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 void ForceImplicitNullCheck(RegStorage reg, int opt_flags, bool is_wide); 83 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); 96 97 /// @copydoc Mir2Lir::UnconditionallyMarkGCCard(RegStorage) 98 void UnconditionallyMarkGCCard(RegStorage tgt_addr_reg) OVERRIDE; 99 100 // 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; TargetPtrReg(SpecialTargetRegister reg)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(); 121 122 // 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); 137 138 // Get the register class for load/store of a field. 139 RegisterClass RegClassForFieldLoadStore(OpSize size, bool is_volatile) OVERRIDE; 140 141 // 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); 193 194 // 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); 219 220 // 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); 231 WideGPRsAreAliases()232 bool WideGPRsAreAliases() const OVERRIDE { 233 return cu_->target64; // Wide GPRs are formed by pairing on mips32. 234 } WideFPRsAreAliases()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. GenInlinedCharAt(CallInfo * info ATTRIBUTE_UNUSED)248 bool GenInlinedCharAt(CallInfo* info ATTRIBUTE_UNUSED) OVERRIDE { 249 return false; 250 } GenInlinedAbsInt(CallInfo * info ATTRIBUTE_UNUSED)251 bool GenInlinedAbsInt(CallInfo* info ATTRIBUTE_UNUSED) OVERRIDE { 252 return false; 253 } GenInlinedAbsLong(CallInfo * info ATTRIBUTE_UNUSED)254 bool GenInlinedAbsLong(CallInfo* info ATTRIBUTE_UNUSED) OVERRIDE { 255 return false; 256 } GenInlinedIndexOf(CallInfo * info ATTRIBUTE_UNUSED,bool zero_based ATTRIBUTE_UNUSED)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 */ As32BitReg(RegStorage reg)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 } 299 } 300 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 */ As64BitReg(RegStorage reg)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 } 321 } 322 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 } 329 Check64BitReg(RegStorage reg)330 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 } 338 } 339 return reg; 340 } 341 }; 342 343 } // namespace art 344 345 #endif // ART_COMPILER_DEX_QUICK_MIPS_CODEGEN_MIPS_H_ 346