Home | History | Annotate | Download | only in mips
      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:
     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 
     43   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_;
     57   InToRegStorageMipsMapper in_to_reg_storage_mips_mapper_;
     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;
    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 
    232   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       }
    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    */
    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 
    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