diff options
Diffstat (limited to 'compiler/dex/quick/arm/codegen_arm.h')
-rw-r--r-- | compiler/dex/quick/arm/codegen_arm.h | 138 |
1 files changed, 127 insertions, 11 deletions
diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h index 6fd29f2..442c4fc 100644 --- a/compiler/dex/quick/arm/codegen_arm.h +++ b/compiler/dex/quick/arm/codegen_arm.h @@ -25,6 +25,64 @@ namespace art { class ArmMir2Lir FINAL : public Mir2Lir { + protected: + // TODO: Consolidate hard float target support. + // InToRegStorageMapper and InToRegStorageMapping can be shared with all backends. + // Base class used to get RegStorage for next argument. + class InToRegStorageMapper { + public: + virtual RegStorage GetNextReg(bool is_double_or_float, bool is_wide) = 0; + virtual ~InToRegStorageMapper() { + } + }; + + // Inherited class for ARM backend. + class InToRegStorageArmMapper FINAL : public InToRegStorageMapper { + public: + InToRegStorageArmMapper() + : cur_core_reg_(0), cur_fp_reg_(0), cur_fp_double_reg_(0) { + } + + virtual ~InToRegStorageArmMapper() { + } + + RegStorage GetNextReg(bool is_double_or_float, bool is_wide) OVERRIDE; + + private: + uint32_t cur_core_reg_; + uint32_t cur_fp_reg_; + uint32_t cur_fp_double_reg_; + }; + + // Class to map argument to RegStorage. The mapping object is initialized by a mapper. + class InToRegStorageMapping FINAL { + public: + InToRegStorageMapping() + : max_mapped_in_(0), is_there_stack_mapped_(false), initialized_(false) { + } + + int GetMaxMappedIn() const { + return max_mapped_in_; + } + + bool IsThereStackMapped() const { + return is_there_stack_mapped_; + } + + bool IsInitialized() const { + return initialized_; + } + + void Initialize(RegLocation* arg_locs, int count, InToRegStorageMapper* mapper); + RegStorage Get(int in_position) const; + + private: + std::map<int, RegStorage> mapping_; + int max_mapped_in_; + bool is_there_stack_mapped_; + bool initialized_; + }; + public: ArmMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena); @@ -47,15 +105,30 @@ class ArmMir2Lir FINAL : public Mir2Lir { void MarkGCCard(RegStorage val_reg, RegStorage tgt_addr_reg); // Required for target - register utilities. - RegStorage TargetReg(SpecialTargetRegister reg); - RegStorage GetArgMappingToPhysicalReg(int arg_num); - RegLocation GetReturnAlt(); - RegLocation GetReturnWideAlt(); - RegLocation LocCReturn(); - RegLocation LocCReturnRef(); - RegLocation LocCReturnDouble(); - RegLocation LocCReturnFloat(); - RegLocation LocCReturnWide(); + RegStorage TargetReg(SpecialTargetRegister reg) OVERRIDE; + RegStorage TargetReg(SpecialTargetRegister reg, WideKind wide_kind) OVERRIDE { + if (wide_kind == kWide) { + DCHECK((kArg0 <= reg && reg < kArg3) || (kFArg0 <= reg && reg < kFArg15) || (kRet0 == reg)); + RegStorage ret_reg = RegStorage::MakeRegPair(TargetReg(reg), + TargetReg(static_cast<SpecialTargetRegister>(reg + 1))); + if (ret_reg.IsFloat()) { + // Regard double as double, be consistent with register allocation. + ret_reg = As64BitFloatReg(ret_reg); + } + return ret_reg; + } else { + return TargetReg(reg); + } + } + + RegStorage GetArgMappingToPhysicalReg(int arg_num) OVERRIDE; + RegLocation GetReturnAlt() OVERRIDE; + RegLocation GetReturnWideAlt() OVERRIDE; + RegLocation LocCReturn() OVERRIDE; + RegLocation LocCReturnRef() OVERRIDE; + RegLocation LocCReturnDouble() OVERRIDE; + RegLocation LocCReturnFloat() OVERRIDE; + RegLocation LocCReturnWide() OVERRIDE; ResourceMask GetRegMaskCommon(const RegStorage& reg) const OVERRIDE; void AdjustSpillMask(); void ClobberCallerSave(); @@ -210,6 +283,19 @@ class ArmMir2Lir FINAL : public Mir2Lir { LIR* InvokeTrampoline(OpKind op, RegStorage r_tgt, QuickEntrypointEnum trampoline) OVERRIDE; size_t GetInstructionOffset(LIR* lir); + int GenDalvikArgsNoRange(CallInfo* info, int call_state, LIR** pcrLabel, + NextCallInsn next_call_insn, + const MethodReference& target_method, + uint32_t vtable_idx, + uintptr_t direct_code, uintptr_t direct_method, InvokeType type, + bool skip_this) OVERRIDE; + int GenDalvikArgsRange(CallInfo* info, int call_state, LIR** pcrLabel, + NextCallInsn next_call_insn, + const MethodReference& target_method, + uint32_t vtable_idx, + uintptr_t direct_code, uintptr_t direct_method, InvokeType type, + bool skip_this) OVERRIDE; + private: void GenNegLong(RegLocation rl_dest, RegLocation rl_src); void GenMulLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, @@ -226,10 +312,10 @@ class ArmMir2Lir FINAL : public Mir2Lir { RegLocation GenDivRem(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2, bool is_div, int flags) OVERRIDE; RegLocation GenDivRemLit(RegLocation rl_dest, RegLocation rl_src1, int lit, bool is_div) OVERRIDE; - typedef struct { + struct EasyMultiplyOp { OpKind op; uint32_t shift; - } EasyMultiplyOp; + }; bool GetEasyMultiplyOp(int lit, EasyMultiplyOp* op); bool GetEasyMultiplyTwoOps(int lit, EasyMultiplyOp* ops); void GenEasyMultiplyTwoOps(RegStorage r_dest, RegStorage r_src, EasyMultiplyOp* ops); @@ -239,6 +325,36 @@ class ArmMir2Lir FINAL : public Mir2Lir { static constexpr ResourceMask EncodeArmRegFpcsList(int reg_list); ArenaVector<LIR*> call_method_insns_; + + /** + * @brief Given float register pair, returns Solo64 float register. + * @param reg #RegStorage containing a float register pair (e.g. @c s2 and @c s3). + * @return A Solo64 float mapping to the register pair (e.g. @c d1). + */ + static RegStorage As64BitFloatReg(RegStorage reg) { + DCHECK(reg.IsFloat()); + + RegStorage low = reg.GetLow(); + RegStorage high = reg.GetHigh(); + DCHECK((low.GetRegNum() % 2 == 0) && (low.GetRegNum() + 1 == high.GetRegNum())); + + return RegStorage::FloatSolo64(low.GetRegNum() / 2); + } + + /** + * @brief Given Solo64 float register, returns float register pair. + * @param reg #RegStorage containing a Solo64 float register (e.g. @c d1). + * @return A float register pair mapping to the Solo64 float pair (e.g. @c s2 and s3). + */ + static RegStorage As64BitFloatRegPair(RegStorage reg) { + DCHECK(reg.IsDouble() && reg.Is64BitSolo()); + + int reg_num = reg.GetRegNum(); + return RegStorage::MakeRegPair(RegStorage::FloatSolo32(reg_num * 2), + RegStorage::FloatSolo32(reg_num * 2 + 1)); + } + + InToRegStorageMapping in_to_reg_storage_mapping_; }; } // namespace art |