codegen_x86.h revision 766e9295d2c34cd1846d81610c9045b5d5093ddd
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_X86_CODEGEN_X86_H_
18#define ART_COMPILER_DEX_QUICK_X86_CODEGEN_X86_H_
19
20#include "dex/compiler_internals.h"
21#include "x86_lir.h"
22
23namespace art {
24
25class X86Mir2Lir : public Mir2Lir {
26  public:
27    X86Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena);
28
29    // Required for target - codegen helpers.
30    bool SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div, RegLocation rl_src,
31                                    RegLocation rl_dest, int lit);
32    int LoadHelper(ThreadOffset offset);
33    LIR* LoadBaseDisp(int rBase, int displacement, int r_dest, OpSize size, int s_reg);
34    LIR* LoadBaseDispWide(int rBase, int displacement, int r_dest_lo, int r_dest_hi,
35                                  int s_reg);
36    LIR* LoadBaseIndexed(int rBase, int r_index, int r_dest, int scale, OpSize size);
37    LIR* LoadBaseIndexedDisp(int rBase, int r_index, int scale, int displacement,
38                                     int r_dest, int r_dest_hi, OpSize size, int s_reg);
39    LIR* LoadConstantNoClobber(int r_dest, int value);
40    LIR* LoadConstantWide(int r_dest_lo, int r_dest_hi, int64_t value);
41    LIR* StoreBaseDisp(int rBase, int displacement, int r_src, OpSize size);
42    LIR* StoreBaseDispWide(int rBase, int displacement, int r_src_lo, int r_src_hi);
43    LIR* StoreBaseIndexed(int rBase, int r_index, int r_src, int scale, OpSize size);
44    LIR* StoreBaseIndexedDisp(int rBase, int r_index, int scale, int displacement,
45                                      int r_src, int r_src_hi, OpSize size, int s_reg);
46    void MarkGCCard(int val_reg, int tgt_addr_reg);
47
48    // Required for target - register utilities.
49    bool IsFpReg(int reg);
50    bool SameRegType(int reg1, int reg2);
51    int AllocTypedTemp(bool fp_hint, int reg_class);
52    int AllocTypedTempPair(bool fp_hint, int reg_class);
53    int S2d(int low_reg, int high_reg);
54    int TargetReg(SpecialTargetRegister reg);
55    RegLocation GetReturnAlt();
56    RegLocation GetReturnWideAlt();
57    RegLocation LocCReturn();
58    RegLocation LocCReturnDouble();
59    RegLocation LocCReturnFloat();
60    RegLocation LocCReturnWide();
61    uint32_t FpRegMask();
62    uint64_t GetRegMaskCommon(int reg);
63    void AdjustSpillMask();
64    void ClobberCallerSave();
65    void FlushReg(int reg);
66    void FlushRegWide(int reg1, int reg2);
67    void FreeCallTemps();
68    void FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free);
69    void LockCallTemps();
70    void MarkPreservedSingle(int v_reg, int reg);
71    void CompilerInitializeRegAlloc();
72
73    // Required for target - miscellaneous.
74    void AssembleLIR();
75    int AssignInsnOffsets();
76    void AssignOffsets();
77    AssemblerStatus AssembleInstructions(CodeOffset start_addr);
78    void DumpResourceMask(LIR* lir, uint64_t mask, const char* prefix);
79    void SetupTargetResourceMasks(LIR* lir, uint64_t flags);
80    const char* GetTargetInstFmt(int opcode);
81    const char* GetTargetInstName(int opcode);
82    std::string BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr);
83    uint64_t GetPCUseDefEncoding();
84    uint64_t GetTargetInstFlags(int opcode);
85    int GetInsnSize(LIR* lir);
86    bool IsUnconditionalBranch(LIR* lir);
87
88    // Required for target - Dalvik-level generators.
89    void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest,
90                                   RegLocation rl_src1, RegLocation rl_src2);
91    void GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array,
92                             RegLocation rl_index, RegLocation rl_dest, int scale);
93    void GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array,
94                     RegLocation rl_index, RegLocation rl_src, int scale, bool card_mark);
95    void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest,
96                           RegLocation rl_src1, RegLocation rl_shift);
97    void GenMulLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
98    void GenAddLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
99    void GenAndLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
100    void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest,
101                                  RegLocation rl_src1, RegLocation rl_src2);
102    void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest,
103                                 RegLocation rl_src1, RegLocation rl_src2);
104    void GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
105                          RegLocation rl_src2);
106    void GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src);
107    bool GenInlinedCas(CallInfo* info, bool is_long, bool is_object);
108    bool GenInlinedMinMaxInt(CallInfo* info, bool is_min);
109    bool GenInlinedSqrt(CallInfo* info);
110    bool GenInlinedPeek(CallInfo* info, OpSize size);
111    bool GenInlinedPoke(CallInfo* info, OpSize size);
112    void GenNegLong(RegLocation rl_dest, RegLocation rl_src);
113    void GenOrLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
114    void GenSubLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
115    void GenXorLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
116    LIR* GenRegMemCheck(ConditionCode c_code, int reg1, int base, int offset,
117                                ThrowKind kind);
118    LIR* GenMemImmedCheck(ConditionCode c_code, int base, int offset, int check_value,
119                          ThrowKind kind);
120    RegLocation GenDivRem(RegLocation rl_dest, int reg_lo, int reg_hi, bool is_div);
121    RegLocation GenDivRemLit(RegLocation rl_dest, int reg_lo, int lit, bool is_div);
122    void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
123    void GenDivZeroCheck(int reg_lo, int reg_hi);
124    void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method);
125    void GenExitSequence();
126    void GenFillArrayData(DexOffset table_offset, RegLocation rl_src);
127    void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double);
128    void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir);
129    void GenSelect(BasicBlock* bb, MIR* mir);
130    void GenMemBarrier(MemBarrierKind barrier_kind);
131    void GenMoveException(RegLocation rl_dest);
132    void GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result,
133                                               int lit, int first_bit, int second_bit);
134    void GenNegDouble(RegLocation rl_dest, RegLocation rl_src);
135    void GenNegFloat(RegLocation rl_dest, RegLocation rl_src);
136    void GenPackedSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src);
137    void GenSparseSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src);
138    void GenSpecialCase(BasicBlock* bb, MIR* mir, const InlineMethod& special);
139    /*
140     * @brief Generate a two address long operation with a constant value
141     * @param rl_dest location of result
142     * @param rl_src constant source operand
143     * @param op Opcode to be generated
144     */
145    void GenLongImm(RegLocation rl_dest, RegLocation rl_src, Instruction::Code op);
146    /*
147     * @brief Generate a three address long operation with a constant value
148     * @param rl_dest location of result
149     * @param rl_src1 source operand
150     * @param rl_src2 constant source operand
151     * @param op Opcode to be generated
152     */
153    void GenLongLongImm(RegLocation rl_dest, RegLocation rl_src1,
154                        RegLocation rl_src2, Instruction::Code op);
155
156    /**
157      * @brief Generate a long arithmetic operation.
158      * @param rl_dest The destination.
159      * @param rl_src1 First operand.
160      * @param rl_src2 Second operand.
161      * @param op The DEX opcode for the operation.
162      * @param is_commutative The sources can be swapped if needed.
163      */
164    void GenLongArith(RegLocation rl_dest, RegLocation rl_src1,
165                      RegLocation rl_src2, Instruction::Code op, bool is_commutative);
166
167    /**
168      * @brief Generate a two operand long arithmetic operation.
169      * @param rl_dest The destination.
170      * @param rl_src Second operand.
171      * @param op The DEX opcode for the operation.
172      */
173    void GenLongArith(RegLocation rl_dest, RegLocation rl_src, Instruction::Code op);
174
175    /**
176      * @brief Generate a long operation.
177      * @param rl_dest The destination.  Must be in a register
178      * @param rl_src The other operand.  May be in a register or in memory.
179      * @param op The DEX opcode for the operation.
180      */
181    void GenLongRegOrMemOp(RegLocation rl_dest, RegLocation rl_src, Instruction::Code op);
182
183    // Single operation generators.
184    LIR* OpUnconditionalBranch(LIR* target);
185    LIR* OpCmpBranch(ConditionCode cond, int src1, int src2, LIR* target);
186    LIR* OpCmpImmBranch(ConditionCode cond, int reg, int check_value, LIR* target);
187    LIR* OpCondBranch(ConditionCode cc, LIR* target);
188    LIR* OpDecAndBranch(ConditionCode c_code, int reg, LIR* target);
189    LIR* OpFpRegCopy(int r_dest, int r_src);
190    LIR* OpIT(ConditionCode cond, const char* guide);
191    LIR* OpMem(OpKind op, int rBase, int disp);
192    LIR* OpPcRelLoad(int reg, LIR* target);
193    LIR* OpReg(OpKind op, int r_dest_src);
194    LIR* OpRegCopy(int r_dest, int r_src);
195    LIR* OpRegCopyNoInsert(int r_dest, int r_src);
196    LIR* OpRegImm(OpKind op, int r_dest_src1, int value);
197    LIR* OpRegMem(OpKind op, int r_dest, int rBase, int offset);
198    LIR* OpRegReg(OpKind op, int r_dest_src1, int r_src2);
199    LIR* OpCondRegReg(OpKind op, ConditionCode cc, int r_dest, int r_src);
200    LIR* OpRegRegImm(OpKind op, int r_dest, int r_src1, int value);
201    LIR* OpRegRegReg(OpKind op, int r_dest, int r_src1, int r_src2);
202    LIR* OpTestSuspend(LIR* target);
203    LIR* OpThreadMem(OpKind op, ThreadOffset thread_offset);
204    LIR* OpVldm(int rBase, int count);
205    LIR* OpVstm(int rBase, int count);
206    void OpLea(int rBase, int reg1, int reg2, int scale, int offset);
207    void OpRegCopyWide(int dest_lo, int dest_hi, int src_lo, int src_hi);
208    void OpTlsCmp(ThreadOffset offset, int val);
209
210    void OpRegThreadMem(OpKind op, int r_dest, ThreadOffset thread_offset);
211    void SpillCoreRegs();
212    void UnSpillCoreRegs();
213    static const X86EncodingMap EncodingMap[kX86Last];
214    bool InexpensiveConstantInt(int32_t value);
215    bool InexpensiveConstantFloat(int32_t value);
216    bool InexpensiveConstantLong(int64_t value);
217    bool InexpensiveConstantDouble(int64_t value);
218
219    RegLocation UpdateLocWide(RegLocation loc);
220    RegLocation EvalLocWide(RegLocation loc, int reg_class, bool update);
221    RegLocation EvalLoc(RegLocation loc, int reg_class, bool update);
222    int AllocTempDouble();
223    void ResetDefLocWide(RegLocation rl);
224
225  private:
226    void EmitPrefix(const X86EncodingMap* entry);
227    void EmitOpcode(const X86EncodingMap* entry);
228    void EmitPrefixAndOpcode(const X86EncodingMap* entry);
229    void EmitDisp(uint8_t base, int disp);
230    void EmitModrmDisp(uint8_t reg_or_opcode, uint8_t base, int disp);
231    void EmitModrmSibDisp(uint8_t reg_or_opcode, uint8_t base, uint8_t index, int scale, int disp);
232    void EmitImm(const X86EncodingMap* entry, int imm);
233    void EmitOpRegOpcode(const X86EncodingMap* entry, uint8_t reg);
234    void EmitOpReg(const X86EncodingMap* entry, uint8_t reg);
235    void EmitOpMem(const X86EncodingMap* entry, uint8_t base, int disp);
236    void EmitOpArray(const X86EncodingMap* entry, uint8_t base, uint8_t index,
237                     int scale, int disp);
238    void EmitMemReg(const X86EncodingMap* entry, uint8_t base, int disp, uint8_t reg);
239    void EmitMemImm(const X86EncodingMap* entry, uint8_t base, int disp, int32_t imm);
240    void EmitRegMem(const X86EncodingMap* entry, uint8_t reg, uint8_t base, int disp);
241    void EmitRegArray(const X86EncodingMap* entry, uint8_t reg, uint8_t base, uint8_t index,
242                      int scale, int disp);
243    void EmitArrayReg(const X86EncodingMap* entry, uint8_t base, uint8_t index, int scale, int disp,
244                      uint8_t reg);
245    void EmitRegThread(const X86EncodingMap* entry, uint8_t reg, int disp);
246    void EmitRegReg(const X86EncodingMap* entry, uint8_t reg1, uint8_t reg2);
247    void EmitRegRegImm(const X86EncodingMap* entry, uint8_t reg1, uint8_t reg2, int32_t imm);
248    void EmitRegRegImmRev(const X86EncodingMap* entry, uint8_t reg1, uint8_t reg2, int32_t imm);
249    void EmitRegMemImm(const X86EncodingMap* entry, uint8_t reg1, uint8_t base, int disp, int32_t imm);
250    void EmitRegImm(const X86EncodingMap* entry, uint8_t reg, int imm);
251    void EmitThreadImm(const X86EncodingMap* entry, int disp, int imm);
252    void EmitMovRegImm(const X86EncodingMap* entry, uint8_t reg, int imm);
253    void EmitShiftRegImm(const X86EncodingMap* entry, uint8_t reg, int imm);
254    void EmitShiftRegCl(const X86EncodingMap* entry, uint8_t reg, uint8_t cl);
255    void EmitRegCond(const X86EncodingMap* entry, uint8_t reg, uint8_t condition);
256
257    /**
258     * @brief Used for encoding conditional register to register operation.
259     * @param entry The entry in the encoding map for the opcode.
260     * @param reg1 The first physical register.
261     * @param reg2 The second physical register.
262     * @param condition The condition code for operation.
263     */
264    void EmitRegRegCond(const X86EncodingMap* entry, uint8_t reg1, uint8_t reg2, uint8_t condition);
265
266    void EmitJmp(const X86EncodingMap* entry, int rel);
267    void EmitJcc(const X86EncodingMap* entry, int rel, uint8_t cc);
268    void EmitCallMem(const X86EncodingMap* entry, uint8_t base, int disp);
269    void EmitCallThread(const X86EncodingMap* entry, int disp);
270    void EmitPcRel(const X86EncodingMap* entry, uint8_t reg, int base_or_table, uint8_t index,
271                   int scale, int table_or_disp);
272    void EmitMacro(const X86EncodingMap* entry, uint8_t reg, int offset);
273    void EmitUnimplemented(const X86EncodingMap* entry, LIR* lir);
274    void GenFusedLongCmpImmBranch(BasicBlock* bb, RegLocation rl_src1,
275                                  int64_t val, ConditionCode ccode);
276    void OpVectorRegCopyWide(uint8_t fp_reg, uint8_t low_reg, uint8_t high_reg);
277    void GenConstWide(RegLocation rl_dest, int64_t value);
278
279    /*
280     * @brief Return the correct x86 opcode for the Dex operation
281     * @param op Dex opcode for the operation
282     * @param loc Register location of the operand
283     * @param is_high_op 'true' if this is an operation on the high word
284     * @param value Immediate value for the operation.  Used for byte variants
285     * @returns the correct x86 opcode to perform the operation
286     */
287    X86OpCode GetOpcode(Instruction::Code op, RegLocation loc, bool is_high_op, int32_t value);
288
289    /*
290     * @brief Return the correct x86 opcode for the Dex operation
291     * @param op Dex opcode for the operation
292     * @param dest location of the destination.  May be register or memory.
293     * @param rhs Location for the rhs of the operation.  May be in register or memory.
294     * @param is_high_op 'true' if this is an operation on the high word
295     * @returns the correct x86 opcode to perform the operation
296     * @note at most one location may refer to memory
297     */
298    X86OpCode GetOpcode(Instruction::Code op, RegLocation dest, RegLocation rhs,
299                        bool is_high_op);
300
301    /*
302     * @brief Is this operation a no-op for this opcode and value
303     * @param op Dex opcode for the operation
304     * @param value Immediate value for the operation.
305     * @returns 'true' if the operation will have no effect
306     */
307    bool IsNoOp(Instruction::Code op, int32_t value);
308
309    /*
310     * @brief Dump a RegLocation using printf
311     * @param loc Register location to dump
312     */
313    static void DumpRegLocation(RegLocation loc);
314
315    /**
316     * @brief Calculate magic number and shift for a given divisor
317     * @param divisor divisor number for calculation
318     * @param magic hold calculated magic number
319     * @param shift hold calculated shift
320     */
321    void CalculateMagicAndShift(int divisor, int& magic, int& shift);
322
323    /*
324     * @brief Generate an integer div or rem operation.
325     * @param rl_dest Destination Location.
326     * @param rl_src1 Numerator Location.
327     * @param rl_src2 Divisor Location.
328     * @param is_div 'true' if this is a division, 'false' for a remainder.
329     * @param check_zero 'true' if an exception should be generated if the divisor is 0.
330     */
331    RegLocation GenDivRem(RegLocation rl_dest, RegLocation rl_src1,
332                                  RegLocation rl_src2, bool is_div, bool check_zero);
333
334    /*
335     * @brief Generate an integer div or rem operation by a literal.
336     * @param rl_dest Destination Location.
337     * @param rl_src Numerator Location.
338     * @param lit Divisor.
339     * @param is_div 'true' if this is a division, 'false' for a remainder.
340     */
341    RegLocation GenDivRemLit(RegLocation rl_dest, RegLocation rl_src, int lit, bool is_div);
342
343    /*
344     * Generate code to implement long shift operations.
345     * @param opcode The DEX opcode to specify the shift type.
346     * @param rl_dest The destination.
347     * @param rl_src The value to be shifted.
348     * @param shift_amount How much to shift.
349     * @returns the RegLocation of the result.
350     */
351    RegLocation GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest,
352                                  RegLocation rl_src, int shift_amount);
353    /*
354     * Generate an imul of a register by a constant or a better sequence.
355     * @param dest Destination Register.
356     * @param src Source Register.
357     * @param val Constant multiplier.
358     */
359    void GenImulRegImm(int dest, int src, int val);
360    /*
361     * Generate an imul of a memory location by a constant or a better sequence.
362     * @param dest Destination Register.
363     * @param sreg Symbolic register.
364     * @param displacement Displacement on stack of Symbolic Register.
365     * @param val Constant multiplier.
366     */
367    void GenImulMemImm(int dest, int sreg, int displacement, int val);
368
369    /*
370     * @brief Compare memory to immediate, and branch if condition true.
371     * @param cond The condition code that when true will branch to the target.
372     * @param temp_reg A temporary register that can be used if compare memory is not
373     * supported by the architecture.
374     * @param base_reg The register holding the base address.
375     * @param offset The offset from the base.
376     * @param check_value The immediate to compare to.
377     */
378    LIR* OpCmpMemImmBranch(ConditionCode cond, int temp_reg, int base_reg,
379                           int offset, int check_value, LIR* target);
380};
381
382}  // namespace art
383
384#endif  // ART_COMPILER_DEX_QUICK_X86_CODEGEN_X86_H_
385