summaryrefslogtreecommitdiffstats
path: root/compiler/dex/quick/arm/codegen_arm.h
blob: a9199dfa7ca879e408cf8ac40d96b5308fda3f81 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_SRC_COMPILER_DEX_QUICK_ARM_CODEGENARM_H_
#define ART_SRC_COMPILER_DEX_QUICK_ARM_CODEGENARM_H_

#include "dex/compiler_internals.h"

namespace art {

class ArmMir2Lir : public Mir2Lir {
  public:
    ArmMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena);

    // Required for target - codegen helpers.
    bool SmallLiteralDivide(Instruction::Code dalvik_opcode, RegLocation rl_src,
                                    RegLocation rl_dest, int lit);
    int LoadHelper(int offset);
    LIR* LoadBaseDisp(int rBase, int displacement, int r_dest, OpSize size, int s_reg);
    LIR* LoadBaseDispWide(int rBase, int displacement, int r_dest_lo, int r_dest_hi,
                          int s_reg);
    LIR* LoadBaseIndexed(int rBase, int r_index, int r_dest, int scale, OpSize size);
    LIR* LoadBaseIndexedDisp(int rBase, int r_index, int scale, int displacement,
                             int r_dest, int r_dest_hi, OpSize size, int s_reg);
    LIR* LoadConstantNoClobber(int r_dest, int value);
    LIR* LoadConstantWide(int r_dest_lo, int r_dest_hi, int64_t value);
    LIR* StoreBaseDisp(int rBase, int displacement, int r_src, OpSize size);
    LIR* StoreBaseDispWide(int rBase, int displacement, int r_src_lo, int r_src_hi);
    LIR* StoreBaseIndexed(int rBase, int r_index, int r_src, int scale, OpSize size);
    LIR* StoreBaseIndexedDisp(int rBase, int r_index, int scale, int displacement,
                              int r_src, int r_src_hi, OpSize size, int s_reg);
    void MarkGCCard(int val_reg, int tgt_addr_reg);

    // Required for target - register utilities.
    bool IsFpReg(int reg);
    bool SameRegType(int reg1, int reg2);
    int AllocTypedTemp(bool fp_hint, int reg_class);
    int AllocTypedTempPair(bool fp_hint, int reg_class);
    int S2d(int low_reg, int high_reg);
    int TargetReg(SpecialTargetRegister reg);
    RegisterInfo* GetRegInfo(int reg);
    RegLocation GetReturnAlt();
    RegLocation GetReturnWideAlt();
    RegLocation LocCReturn();
    RegLocation LocCReturnDouble();
    RegLocation LocCReturnFloat();
    RegLocation LocCReturnWide();
    uint32_t FpRegMask();
    uint64_t GetRegMaskCommon(int reg);
    void AdjustSpillMask();
    void ClobberCalleeSave();
    void FlushReg(int reg);
    void FlushRegWide(int reg1, int reg2);
    void FreeCallTemps();
    void FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free);
    void LockCallTemps();
    void MarkPreservedSingle(int v_reg, int reg);
    void CompilerInitializeRegAlloc();

    // Required for target - miscellaneous.
    AssemblerStatus AssembleInstructions(uintptr_t start_addr);
    void DumpResourceMask(LIR* lir, uint64_t mask, const char* prefix);
    void SetupTargetResourceMasks(LIR* lir);
    const char* GetTargetInstFmt(int opcode);
    const char* GetTargetInstName(int opcode);
    std::string BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr);
    uint64_t GetPCUseDefEncoding();
    uint64_t GetTargetInstFlags(int opcode);
    int GetInsnSize(LIR* lir);
    bool IsUnconditionalBranch(LIR* lir);

    // Required for target - Dalvik-level generators.
    void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest,
                           RegLocation rl_src1, RegLocation rl_src2);
    void GenArrayObjPut(int opt_flags, RegLocation rl_array, RegLocation rl_index,
                        RegLocation rl_src, int scale);
    void GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array,
                     RegLocation rl_index, RegLocation rl_dest, int scale);
    void GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array,
                     RegLocation rl_index, RegLocation rl_src, int scale);
    void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest,
                           RegLocation rl_src1, RegLocation rl_shift);
    void GenMulLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
    void GenAddLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
    void GenAndLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
    void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest,
                          RegLocation rl_src1, RegLocation rl_src2);
    void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest,
                         RegLocation rl_src1, RegLocation rl_src2);
    void GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
                  RegLocation rl_src2);
    void GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src);
    bool GenInlinedCas32(CallInfo* info, bool need_write_barrier);
    bool GenInlinedMinMaxInt(CallInfo* info, bool is_min);
    bool GenInlinedSqrt(CallInfo* info);
    void GenNegLong(RegLocation rl_dest, RegLocation rl_src);
    void GenOrLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
    void GenSubLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
    void GenXorLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
    LIR* GenRegMemCheck(ConditionCode c_code, int reg1, int base, int offset,
                                ThrowKind kind);
    RegLocation GenDivRem(RegLocation rl_dest, int reg_lo, int reg_hi, bool is_div);
    RegLocation GenDivRemLit(RegLocation rl_dest, int reg_lo, int lit, bool is_div);
    void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
    void GenDivZeroCheck(int reg_lo, int reg_hi);
    void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method);
    void GenExitSequence();
    void GenFillArrayData(uint32_t table_offset, RegLocation rl_src);
    void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double);
    void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir);
    void GenSelect(BasicBlock* bb, MIR* mir);
    void GenMemBarrier(MemBarrierKind barrier_kind);
    void GenMonitorEnter(int opt_flags, RegLocation rl_src);
    void GenMonitorExit(int opt_flags, RegLocation rl_src);
    void GenMoveException(RegLocation rl_dest);
    void GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result, int lit,
                                               int first_bit, int second_bit);
    void GenNegDouble(RegLocation rl_dest, RegLocation rl_src);
    void GenNegFloat(RegLocation rl_dest, RegLocation rl_src);
    void GenPackedSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src);
    void GenSparseSwitch(MIR* mir, uint32_t table_offset, RegLocation rl_src);
    void GenSpecialCase(BasicBlock* bb, MIR* mir, SpecialCaseHandler special_case);

    // Required for target - single operation generators.
    LIR* OpUnconditionalBranch(LIR* target);
    LIR* OpCmpBranch(ConditionCode cond, int src1, int src2, LIR* target);
    LIR* OpCmpImmBranch(ConditionCode cond, int reg, int check_value, LIR* target);
    LIR* OpCondBranch(ConditionCode cc, LIR* target);
    LIR* OpDecAndBranch(ConditionCode c_code, int reg, LIR* target);
    LIR* OpFpRegCopy(int r_dest, int r_src);
    LIR* OpIT(ConditionCode cond, const char* guide);
    LIR* OpMem(OpKind op, int rBase, int disp);
    LIR* OpPcRelLoad(int reg, LIR* target);
    LIR* OpReg(OpKind op, int r_dest_src);
    LIR* OpRegCopy(int r_dest, int r_src);
    LIR* OpRegCopyNoInsert(int r_dest, int r_src);
    LIR* OpRegImm(OpKind op, int r_dest_src1, int value);
    LIR* OpRegMem(OpKind op, int r_dest, int rBase, int offset);
    LIR* OpRegReg(OpKind op, int r_dest_src1, int r_src2);
    LIR* OpRegRegImm(OpKind op, int r_dest, int r_src1, int value);
    LIR* OpRegRegReg(OpKind op, int r_dest, int r_src1, int r_src2);
    LIR* OpTestSuspend(LIR* target);
    LIR* OpThreadMem(OpKind op, int thread_offset);
    LIR* OpVldm(int rBase, int count);
    LIR* OpVstm(int rBase, int count);
    void OpLea(int rBase, int reg1, int reg2, int scale, int offset);
    void OpRegCopyWide(int dest_lo, int dest_hi, int src_lo, int src_hi);
    void OpTlsCmp(int offset, int val);

    RegLocation ArgLoc(RegLocation loc);
    LIR* LoadBaseDispBody(int rBase, int displacement, int r_dest, int r_dest_hi, OpSize size,
                          int s_reg);
    LIR* StoreBaseDispBody(int rBase, int displacement, int r_src, int r_src_hi, OpSize size);
    void GenPrintLabel(MIR* mir);
    LIR* OpRegRegRegShift(OpKind op, int r_dest, int r_src1, int r_src2, int shift);
    LIR* OpRegRegShift(OpKind op, int r_dest_src1, int r_src2, int shift);
    static const ArmEncodingMap EncodingMap[kArmLast];
    int EncodeShift(int code, int amount);
    int ModifiedImmediate(uint32_t value);
    ArmConditionCode ArmConditionEncoding(ConditionCode code);
    bool InexpensiveConstantInt(int32_t value);
    bool InexpensiveConstantFloat(int32_t value);
    bool InexpensiveConstantLong(int64_t value);
    bool InexpensiveConstantDouble(int64_t value);

  private:
    void GenFusedLongCmpImmBranch(BasicBlock* bb, RegLocation rl_src1, int64_t val,
                                  ConditionCode ccode);
    int InPosition(int s_reg);
    RegLocation LoadArg(RegLocation loc);
    void LockLiveArgs(MIR* mir);
    MIR* GetNextMir(BasicBlock** p_bb, MIR* mir);
    MIR* SpecialIGet(BasicBlock** bb, MIR* mir, OpSize size, bool long_or_double, bool is_object);
    MIR* SpecialIPut(BasicBlock** bb, MIR* mir, OpSize size, bool long_or_double, bool is_object);
    MIR* SpecialIdentity(MIR* mir);
    LIR* LoadFPConstantValue(int r_dest, int value);
    bool BadOverlap(RegLocation rl_src, RegLocation rl_dest);
};

}  // namespace art

#endif  // ART_SRC_COMPILER_DEX_QUICK_ARM_CODEGENARM_H_