codegen_x86.h revision 96992e8f2eddba05dc38a15cc7d4e705e8db4022
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, bool gen64bit);
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    bool EasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit) OVERRIDE;
33    LIR* CheckSuspendUsingLoad() OVERRIDE;
34    RegStorage LoadHelper(ThreadOffset<4> offset) OVERRIDE;
35    RegStorage LoadHelper(ThreadOffset<8> offset) OVERRIDE;
36    LIR* LoadBaseDispVolatile(RegStorage r_base, int displacement, RegStorage r_dest,
37                              OpSize size) OVERRIDE;
38    LIR* LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest,
39                      OpSize size) OVERRIDE;
40    LIR* LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest, int scale,
41                         OpSize size) OVERRIDE;
42    LIR* LoadBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale, int displacement,
43                             RegStorage r_dest, OpSize size) OVERRIDE;
44    LIR* LoadConstantNoClobber(RegStorage r_dest, int value);
45    LIR* LoadConstantWide(RegStorage r_dest, int64_t value);
46    LIR* StoreBaseDispVolatile(RegStorage r_base, int displacement, RegStorage r_src,
47                               OpSize size) OVERRIDE;
48    LIR* StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src,
49                       OpSize size) OVERRIDE;
50    LIR* StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src, int scale,
51                          OpSize size) OVERRIDE;
52    LIR* StoreBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale, int displacement,
53                              RegStorage r_src, OpSize size) OVERRIDE;
54    void MarkGCCard(RegStorage val_reg, RegStorage tgt_addr_reg);
55
56    // Required for target - register utilities.
57    RegStorage TargetReg(SpecialTargetRegister reg);
58    RegStorage GetArgMappingToPhysicalReg(int arg_num);
59    RegLocation GetReturnAlt();
60    RegLocation GetReturnWideAlt();
61    RegLocation LocCReturn();
62    RegLocation LocCReturnDouble();
63    RegLocation LocCReturnFloat();
64    RegLocation LocCReturnWide();
65    uint64_t GetRegMaskCommon(RegStorage reg);
66    void AdjustSpillMask();
67    void ClobberCallerSave();
68    void FreeCallTemps();
69    void LockCallTemps();
70    void MarkPreservedSingle(int v_reg, RegStorage reg);
71    void MarkPreservedDouble(int v_reg, RegStorage reg);
72    void CompilerInitializeRegAlloc();
73
74    // Required for target - miscellaneous.
75    void AssembleLIR();
76    int AssignInsnOffsets();
77    void AssignOffsets();
78    AssemblerStatus AssembleInstructions(CodeOffset start_addr);
79    void DumpResourceMask(LIR* lir, uint64_t mask, const char* prefix);
80    void SetupTargetResourceMasks(LIR* lir, uint64_t flags);
81    const char* GetTargetInstFmt(int opcode);
82    const char* GetTargetInstName(int opcode);
83    std::string BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr);
84    uint64_t GetPCUseDefEncoding();
85    uint64_t GetTargetInstFlags(int opcode);
86    int GetInsnSize(LIR* lir);
87    bool IsUnconditionalBranch(LIR* lir);
88
89    // Check support for volatile load/store of a given size.
90    bool SupportsVolatileLoadStore(OpSize size) OVERRIDE;
91    // Get the register class for load/store of a field.
92    RegisterClass RegClassForFieldLoadStore(OpSize size, bool is_volatile) OVERRIDE;
93
94    // Required for target - Dalvik-level generators.
95    void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
96                           RegLocation rl_src2);
97    void GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index,
98                     RegLocation rl_dest, int scale);
99    void GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array,
100                     RegLocation rl_index, RegLocation rl_src, int scale, bool card_mark);
101    void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest,
102                           RegLocation rl_src1, RegLocation rl_shift);
103    void GenMulLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
104                    RegLocation rl_src2);
105    void GenAddLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
106                    RegLocation rl_src2);
107    void GenAndLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
108                    RegLocation rl_src2);
109    void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
110                          RegLocation rl_src2);
111    void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
112                         RegLocation rl_src2);
113    void GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
114                  RegLocation rl_src2);
115    void GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src);
116    bool GenInlinedCas(CallInfo* info, bool is_long, bool is_object);
117    bool GenInlinedMinMaxInt(CallInfo* info, bool is_min);
118    bool GenInlinedSqrt(CallInfo* info);
119    bool GenInlinedPeek(CallInfo* info, OpSize size);
120    bool GenInlinedPoke(CallInfo* info, OpSize size);
121    void GenNotLong(RegLocation rl_dest, RegLocation rl_src);
122    void GenNegLong(RegLocation rl_dest, RegLocation rl_src);
123    void GenOrLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
124                   RegLocation rl_src2);
125    void GenSubLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
126                    RegLocation rl_src2);
127    void GenXorLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1,
128                    RegLocation rl_src2);
129    void GenDivRemLong(Instruction::Code, RegLocation rl_dest, RegLocation rl_src1,
130                       RegLocation rl_src2, bool is_div);
131    // TODO: collapse reg_lo, reg_hi
132    RegLocation GenDivRem(RegLocation rl_dest, RegStorage reg_lo, RegStorage reg_hi, bool is_div);
133    RegLocation GenDivRemLit(RegLocation rl_dest, RegStorage reg_lo, int lit, bool is_div);
134    void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
135    void GenDivZeroCheckWide(RegStorage reg);
136    void GenArrayBoundsCheck(RegStorage index, RegStorage array_base, int32_t len_offset);
137    void GenArrayBoundsCheck(int32_t index, RegStorage array_base, int32_t len_offset);
138    void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method);
139    void GenExitSequence();
140    void GenSpecialExitSequence();
141    void GenFillArrayData(DexOffset table_offset, RegLocation rl_src);
142    void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double);
143    void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir);
144    void GenSelect(BasicBlock* bb, MIR* mir);
145    bool GenMemBarrier(MemBarrierKind barrier_kind);
146    void GenMoveException(RegLocation rl_dest);
147    void GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result, int lit,
148                                       int first_bit, int second_bit);
149    void GenNegDouble(RegLocation rl_dest, RegLocation rl_src);
150    void GenNegFloat(RegLocation rl_dest, RegLocation rl_src);
151    void GenPackedSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src);
152    void GenSparseSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src);
153
154    /*
155     * @brief Generate a two address long operation with a constant value
156     * @param rl_dest location of result
157     * @param rl_src constant source operand
158     * @param op Opcode to be generated
159     */
160    void GenLongImm(RegLocation rl_dest, RegLocation rl_src, Instruction::Code op);
161    /*
162     * @brief Generate a three address long operation with a constant value
163     * @param rl_dest location of result
164     * @param rl_src1 source operand
165     * @param rl_src2 constant source operand
166     * @param op Opcode to be generated
167     */
168    void GenLongLongImm(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2,
169                        Instruction::Code op);
170
171    /**
172      * @brief Generate a long arithmetic operation.
173      * @param rl_dest The destination.
174      * @param rl_src1 First operand.
175      * @param rl_src2 Second operand.
176      * @param op The DEX opcode for the operation.
177      * @param is_commutative The sources can be swapped if needed.
178      */
179    virtual void GenLongArith(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2,
180                              Instruction::Code op, bool is_commutative);
181
182    /**
183      * @brief Generate a two operand long arithmetic operation.
184      * @param rl_dest The destination.
185      * @param rl_src Second operand.
186      * @param op The DEX opcode for the operation.
187      */
188    void GenLongArith(RegLocation rl_dest, RegLocation rl_src, Instruction::Code op);
189
190    /**
191      * @brief Generate a long operation.
192      * @param rl_dest The destination.  Must be in a register
193      * @param rl_src The other operand.  May be in a register or in memory.
194      * @param op The DEX opcode for the operation.
195      */
196    virtual void GenLongRegOrMemOp(RegLocation rl_dest, RegLocation rl_src, Instruction::Code op);
197
198    /**
199     * @brief Implement instanceof a final class with x86 specific code.
200     * @param use_declaring_class 'true' if we can use the class itself.
201     * @param type_idx Type index to use if use_declaring_class is 'false'.
202     * @param rl_dest Result to be set to 0 or 1.
203     * @param rl_src Object to be tested.
204     */
205    void GenInstanceofFinal(bool use_declaring_class, uint32_t type_idx, RegLocation rl_dest,
206                            RegLocation rl_src);
207    /*
208     *
209     * @brief Implement Set up instanceof a class with x86 specific code.
210     * @param needs_access_check 'true' if we must check the access.
211     * @param type_known_final 'true' if the type is known to be a final class.
212     * @param type_known_abstract 'true' if the type is known to be an abstract class.
213     * @param use_declaring_class 'true' if the type can be loaded off the current Method*.
214     * @param can_assume_type_is_in_dex_cache 'true' if the type is known to be in the cache.
215     * @param type_idx Type index to use if use_declaring_class is 'false'.
216     * @param rl_dest Result to be set to 0 or 1.
217     * @param rl_src Object to be tested.
218     */
219    void GenInstanceofCallingHelper(bool needs_access_check, bool type_known_final,
220                                    bool type_known_abstract, bool use_declaring_class,
221                                    bool can_assume_type_is_in_dex_cache,
222                                    uint32_t type_idx, RegLocation rl_dest, RegLocation rl_src);
223
224    // Single operation generators.
225    LIR* OpUnconditionalBranch(LIR* target);
226    LIR* OpCmpBranch(ConditionCode cond, RegStorage src1, RegStorage src2, LIR* target);
227    LIR* OpCmpImmBranch(ConditionCode cond, RegStorage reg, int check_value, LIR* target);
228    LIR* OpCondBranch(ConditionCode cc, LIR* target);
229    LIR* OpDecAndBranch(ConditionCode c_code, RegStorage reg, LIR* target);
230    LIR* OpFpRegCopy(RegStorage r_dest, RegStorage r_src);
231    LIR* OpIT(ConditionCode cond, const char* guide);
232    void OpEndIT(LIR* it);
233    LIR* OpMem(OpKind op, RegStorage r_base, int disp);
234    LIR* OpPcRelLoad(RegStorage reg, LIR* target);
235    LIR* OpReg(OpKind op, RegStorage r_dest_src);
236    void OpRegCopy(RegStorage r_dest, RegStorage r_src);
237    LIR* OpRegCopyNoInsert(RegStorage r_dest, RegStorage r_src);
238    LIR* OpRegImm(OpKind op, RegStorage r_dest_src1, int value);
239    LIR* OpRegMem(OpKind op, RegStorage r_dest, RegStorage r_base, int offset);
240    LIR* OpRegMem(OpKind op, RegStorage r_dest, RegLocation value);
241    LIR* OpMemReg(OpKind op, RegLocation rl_dest, int value);
242    LIR* OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2);
243    LIR* OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset, MoveType move_type);
244    LIR* OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type);
245    LIR* OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src);
246    LIR* OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value);
247    LIR* OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2);
248    LIR* OpTestSuspend(LIR* target);
249    LIR* OpThreadMem(OpKind op, ThreadOffset<4> thread_offset) OVERRIDE;
250    LIR* OpThreadMem(OpKind op, ThreadOffset<8> thread_offset) OVERRIDE;
251    LIR* OpVldm(RegStorage r_base, int count);
252    LIR* OpVstm(RegStorage r_base, int count);
253    void OpLea(RegStorage r_base, RegStorage reg1, RegStorage reg2, int scale, int offset);
254    void OpRegCopyWide(RegStorage dest, RegStorage src);
255    void OpTlsCmp(ThreadOffset<4> offset, int val) OVERRIDE;
256    void OpTlsCmp(ThreadOffset<8> offset, int val) OVERRIDE;
257
258    void OpRegThreadMem(OpKind op, RegStorage r_dest, ThreadOffset<4> thread_offset);
259    void OpRegThreadMem(OpKind op, RegStorage r_dest, ThreadOffset<8> thread_offset);
260    void SpillCoreRegs();
261    void UnSpillCoreRegs();
262    static const X86EncodingMap EncodingMap[kX86Last];
263    bool InexpensiveConstantInt(int32_t value);
264    bool InexpensiveConstantFloat(int32_t value);
265    bool InexpensiveConstantLong(int64_t value);
266    bool InexpensiveConstantDouble(int64_t value);
267
268    /*
269     * @brief Should try to optimize for two address instructions?
270     * @return true if we try to avoid generating three operand instructions.
271     */
272    virtual bool GenerateTwoOperandInstructions() const { return true; }
273
274    /*
275     * @brief x86 specific codegen for int operations.
276     * @param opcode Operation to perform.
277     * @param rl_dest Destination for the result.
278     * @param rl_lhs Left hand operand.
279     * @param rl_rhs Right hand operand.
280     */
281    void GenArithOpInt(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_lhs,
282                       RegLocation rl_rhs);
283
284    /*
285     * @brief Dump a RegLocation using printf
286     * @param loc Register location to dump
287     */
288    static void DumpRegLocation(RegLocation loc);
289
290    /*
291     * @brief Load the Method* of a dex method into the register.
292     * @param target_method The MethodReference of the method to be invoked.
293     * @param type How the method will be invoked.
294     * @param register that will contain the code address.
295     * @note register will be passed to TargetReg to get physical register.
296     */
297    void LoadMethodAddress(const MethodReference& target_method, InvokeType type,
298                           SpecialTargetRegister symbolic_reg);
299
300    /*
301     * @brief Load the Class* of a Dex Class type into the register.
302     * @param type How the method will be invoked.
303     * @param register that will contain the code address.
304     * @note register will be passed to TargetReg to get physical register.
305     */
306    void LoadClassType(uint32_t type_idx, SpecialTargetRegister symbolic_reg);
307
308    /*
309     * @brief Generate a relative call to the method that will be patched at link time.
310     * @param target_method The MethodReference of the method to be invoked.
311     * @param type How the method will be invoked.
312     * @returns Call instruction
313     */
314    virtual LIR * CallWithLinkerFixup(const MethodReference& target_method, InvokeType type);
315
316    /*
317     * @brief Handle x86 specific literals
318     */
319    void InstallLiteralPools();
320
321    /*
322     * @brief Generate the debug_frame CFI information.
323     * @returns pointer to vector containing CFE information
324     */
325    static std::vector<uint8_t>* ReturnCommonCallFrameInformation();
326
327    /*
328     * @brief Generate the debug_frame FDE information.
329     * @returns pointer to vector containing CFE information
330     */
331    std::vector<uint8_t>* ReturnCallFrameInformation();
332
333  protected:
334    size_t ComputeSize(const X86EncodingMap* entry, int base, int displacement, bool has_sib);
335    void EmitPrefix(const X86EncodingMap* entry);
336    void EmitOpcode(const X86EncodingMap* entry);
337    void EmitPrefixAndOpcode(const X86EncodingMap* entry);
338    void EmitDisp(uint8_t base, int disp);
339    void EmitModrmThread(uint8_t reg_or_opcode);
340    void EmitModrmDisp(uint8_t reg_or_opcode, uint8_t base, int disp);
341    void EmitModrmSibDisp(uint8_t reg_or_opcode, uint8_t base, uint8_t index, int scale, int disp);
342    void EmitImm(const X86EncodingMap* entry, int64_t imm);
343    void EmitOpRegOpcode(const X86EncodingMap* entry, uint8_t reg);
344    void EmitOpReg(const X86EncodingMap* entry, uint8_t reg);
345    void EmitOpMem(const X86EncodingMap* entry, uint8_t base, int disp);
346    void EmitOpArray(const X86EncodingMap* entry, uint8_t base, uint8_t index, int scale, int disp);
347    void EmitMemReg(const X86EncodingMap* entry, uint8_t base, int disp, uint8_t reg);
348    void EmitMemImm(const X86EncodingMap* entry, uint8_t base, int disp, int32_t imm);
349    void EmitRegMem(const X86EncodingMap* entry, uint8_t reg, uint8_t base, int disp);
350    void EmitRegArray(const X86EncodingMap* entry, uint8_t reg, uint8_t base, uint8_t index,
351                      int scale, int disp);
352    void EmitArrayReg(const X86EncodingMap* entry, uint8_t base, uint8_t index, int scale, int disp,
353                      uint8_t reg);
354    void EmitArrayImm(const X86EncodingMap* entry, uint8_t base, uint8_t index, int scale, int disp,
355                      int32_t imm);
356    void EmitRegThread(const X86EncodingMap* entry, uint8_t reg, int disp);
357    void EmitRegReg(const X86EncodingMap* entry, uint8_t reg1, uint8_t reg2);
358    void EmitRegRegImm(const X86EncodingMap* entry, uint8_t reg1, uint8_t reg2, int32_t imm);
359    void EmitRegRegImmRev(const X86EncodingMap* entry, uint8_t reg1, uint8_t reg2, int32_t imm);
360    void EmitRegMemImm(const X86EncodingMap* entry, uint8_t reg1, uint8_t base, int disp,
361                       int32_t imm);
362    void EmitMemRegImm(const X86EncodingMap* entry, uint8_t base, int disp, uint8_t reg1, int32_t imm);
363    void EmitRegImm(const X86EncodingMap* entry, uint8_t reg, int imm);
364    void EmitThreadImm(const X86EncodingMap* entry, int disp, int imm);
365    void EmitMovRegImm(const X86EncodingMap* entry, uint8_t reg, int64_t imm);
366    void EmitShiftRegImm(const X86EncodingMap* entry, uint8_t reg, int imm);
367    void EmitShiftMemImm(const X86EncodingMap* entry, uint8_t base, int disp, int imm);
368    void EmitShiftMemCl(const X86EncodingMap* entry, uint8_t base, int displacement, uint8_t cl);
369    void EmitShiftRegCl(const X86EncodingMap* entry, uint8_t reg, uint8_t cl);
370    void EmitRegCond(const X86EncodingMap* entry, uint8_t reg, uint8_t condition);
371    void EmitMemCond(const X86EncodingMap* entry, uint8_t base, int displacement, uint8_t condition);
372
373    /**
374     * @brief Used for encoding conditional register to register operation.
375     * @param entry The entry in the encoding map for the opcode.
376     * @param reg1 The first physical register.
377     * @param reg2 The second physical register.
378     * @param condition The condition code for operation.
379     */
380    void EmitRegRegCond(const X86EncodingMap* entry, uint8_t reg1, uint8_t reg2, uint8_t condition);
381
382    /**
383     * @brief Used for encoding conditional register to memory operation.
384     * @param entry The entry in the encoding map for the opcode.
385     * @param reg1 The first physical register.
386     * @param base The memory base register.
387     * @param displacement The memory displacement.
388     * @param condition The condition code for operation.
389     */
390    void EmitRegMemCond(const X86EncodingMap* entry, uint8_t reg1, uint8_t base, int displacement, uint8_t condition);
391
392    void EmitJmp(const X86EncodingMap* entry, int rel);
393    void EmitJcc(const X86EncodingMap* entry, int rel, uint8_t cc);
394    void EmitCallMem(const X86EncodingMap* entry, uint8_t base, int disp);
395    void EmitCallImmediate(const X86EncodingMap* entry, int disp);
396    void EmitCallThread(const X86EncodingMap* entry, int disp);
397    void EmitPcRel(const X86EncodingMap* entry, uint8_t reg, int base_or_table, uint8_t index,
398                   int scale, int table_or_disp);
399    void EmitMacro(const X86EncodingMap* entry, uint8_t reg, int offset);
400    void EmitUnimplemented(const X86EncodingMap* entry, LIR* lir);
401    void GenFusedLongCmpImmBranch(BasicBlock* bb, RegLocation rl_src1,
402                                  int64_t val, ConditionCode ccode);
403    void GenConstWide(RegLocation rl_dest, int64_t value);
404
405    static bool ProvidesFullMemoryBarrier(X86OpCode opcode);
406
407    /*
408     * @brief Ensure that a temporary register is byte addressable.
409     * @returns a temporary guarenteed to be byte addressable.
410     */
411    virtual RegStorage AllocateByteRegister();
412
413    /*
414     * @brief generate inline code for fast case of Strng.indexOf.
415     * @param info Call parameters
416     * @param zero_based 'true' if the index into the string is 0.
417     * @returns 'true' if the call was inlined, 'false' if a regular call needs to be
418     * generated.
419     */
420    bool GenInlinedIndexOf(CallInfo* info, bool zero_based);
421
422    /*
423     * @brief Load 128 bit constant into vector register.
424     * @param bb The basic block in which the MIR is from.
425     * @param mir The MIR whose opcode is kMirConstVector
426     * @note vA is the TypeSize for the register.
427     * @note vB is the destination XMM register. arg[0..3] are 32 bit constant values.
428     */
429    void GenConst128(BasicBlock* bb, MIR* mir);
430
431    /*
432     * @brief MIR to move a vectorized register to another.
433     * @param bb The basic block in which the MIR is from.
434     * @param mir The MIR whose opcode is kMirConstVector.
435     * @note vA: TypeSize
436     * @note vB: destination
437     * @note vC: source
438     */
439    void GenMoveVector(BasicBlock *bb, MIR *mir);
440
441    /*
442     * @brief Packed multiply of units in two vector registers: vB = vB .* @note vC using vA to know the type of the vector.
443     * @param bb The basic block in which the MIR is from.
444     * @param mir The MIR whose opcode is kMirConstVector.
445     * @note vA: TypeSize
446     * @note vB: destination and source
447     * @note vC: source
448     */
449    void GenMultiplyVector(BasicBlock *bb, MIR *mir);
450
451    /*
452     * @brief Packed addition of units in two vector registers: vB = vB .+ vC using vA to know the type of the vector.
453     * @param bb The basic block in which the MIR is from.
454     * @param mir The MIR whose opcode is kMirConstVector.
455     * @note vA: TypeSize
456     * @note vB: destination and source
457     * @note vC: source
458     */
459    void GenAddVector(BasicBlock *bb, MIR *mir);
460
461    /*
462     * @brief Packed subtraction of units in two vector registers: vB = vB .- vC using vA to know the type of the vector.
463     * @param bb The basic block in which the MIR is from.
464     * @param mir The MIR whose opcode is kMirConstVector.
465     * @note vA: TypeSize
466     * @note vB: destination and source
467     * @note vC: source
468     */
469    void GenSubtractVector(BasicBlock *bb, MIR *mir);
470
471    /*
472     * @brief Packed shift left of units in two vector registers: vB = vB .<< vC using vA to know the type of the vector.
473     * @param bb The basic block in which the MIR is from.
474     * @param mir The MIR whose opcode is kMirConstVector.
475     * @note vA: TypeSize
476     * @note vB: destination and source
477     * @note vC: immediate
478     */
479    void GenShiftLeftVector(BasicBlock *bb, MIR *mir);
480
481    /*
482     * @brief Packed signed shift right of units in two vector registers: vB = vB .>> vC using vA to know the type of the vector.
483     * @param bb The basic block in which the MIR is from.
484     * @param mir The MIR whose opcode is kMirConstVector.
485     * @note vA: TypeSize
486     * @note vB: destination and source
487     * @note vC: immediate
488     */
489    void GenSignedShiftRightVector(BasicBlock *bb, MIR *mir);
490
491    /*
492     * @brief Packed unsigned shift right of units in two vector registers: vB = vB .>>> vC using vA to know the type of the vector.
493     * @param bb The basic block in which the MIR is from..
494     * @param mir The MIR whose opcode is kMirConstVector.
495     * @note vA: TypeSize
496     * @note vB: destination and source
497     * @note vC: immediate
498     */
499    void GenUnsignedShiftRightVector(BasicBlock *bb, MIR *mir);
500
501    /*
502     * @brief Packed bitwise and of units in two vector registers: vB = vB .& vC using vA to know the type of the vector.
503     * @note vA: TypeSize
504     * @note vB: destination and source
505     * @note vC: source
506     */
507    void GenAndVector(BasicBlock *bb, MIR *mir);
508
509    /*
510     * @brief Packed bitwise or of units in two vector registers: vB = vB .| vC using vA to know the type of the vector.
511     * @param bb The basic block in which the MIR is from.
512     * @param mir The MIR whose opcode is kMirConstVector.
513     * @note vA: TypeSize
514     * @note vB: destination and source
515     * @note vC: source
516     */
517    void GenOrVector(BasicBlock *bb, MIR *mir);
518
519    /*
520     * @brief Packed bitwise xor of units in two vector registers: vB = vB .^ vC using vA to know the type of the vector.
521     * @param bb The basic block in which the MIR is from.
522     * @param mir The MIR whose opcode is kMirConstVector.
523     * @note vA: TypeSize
524     * @note vB: destination and source
525     * @note vC: source
526     */
527    void GenXorVector(BasicBlock *bb, MIR *mir);
528
529    /*
530     * @brief Reduce a 128-bit packed element into a single VR by taking lower bits
531     * @param bb The basic block in which the MIR is from.
532     * @param mir The MIR whose opcode is kMirConstVector.
533     * @details Instruction does a horizontal addition of the packed elements and then adds it to VR.
534     * @note vA: TypeSize
535     * @note vB: destination and source VR (not vector register)
536     * @note vC: source (vector register)
537     */
538    void GenAddReduceVector(BasicBlock *bb, MIR *mir);
539
540    /*
541     * @brief Extract a packed element into a single VR.
542     * @param bb The basic block in which the MIR is from.
543     * @param mir The MIR whose opcode is kMirConstVector.
544     * @note vA: TypeSize
545     * @note vB: destination VR (not vector register)
546     * @note vC: source (vector register)
547     * @note arg[0]: The index to use for extraction from vector register (which packed element).
548     */
549    void GenReduceVector(BasicBlock *bb, MIR *mir);
550
551    /*
552     * @brief Create a vector value, with all TypeSize values equal to vC
553     * @param bb The basic block in which the MIR is from.
554     * @param mir The MIR whose opcode is kMirConstVector.
555     * @note vA: TypeSize.
556     * @note vB: destination vector register.
557     * @note vC: source VR (not vector register).
558     */
559    void GenSetVector(BasicBlock *bb, MIR *mir);
560
561    /*
562     * @brief Generate code for a vector opcode.
563     * @param bb The basic block in which the MIR is from.
564     * @param mir The MIR whose opcode is a non-standard opcode.
565     */
566    void GenMachineSpecificExtendedMethodMIR(BasicBlock* bb, MIR* mir);
567
568    /*
569     * @brief Return the correct x86 opcode for the Dex operation
570     * @param op Dex opcode for the operation
571     * @param loc Register location of the operand
572     * @param is_high_op 'true' if this is an operation on the high word
573     * @param value Immediate value for the operation.  Used for byte variants
574     * @returns the correct x86 opcode to perform the operation
575     */
576    X86OpCode GetOpcode(Instruction::Code op, RegLocation loc, bool is_high_op, int32_t value);
577
578    /*
579     * @brief Return the correct x86 opcode for the Dex operation
580     * @param op Dex opcode for the operation
581     * @param dest location of the destination.  May be register or memory.
582     * @param rhs Location for the rhs of the operation.  May be in register or memory.
583     * @param is_high_op 'true' if this is an operation on the high word
584     * @returns the correct x86 opcode to perform the operation
585     * @note at most one location may refer to memory
586     */
587    X86OpCode GetOpcode(Instruction::Code op, RegLocation dest, RegLocation rhs,
588                        bool is_high_op);
589
590    /*
591     * @brief Is this operation a no-op for this opcode and value
592     * @param op Dex opcode for the operation
593     * @param value Immediate value for the operation.
594     * @returns 'true' if the operation will have no effect
595     */
596    bool IsNoOp(Instruction::Code op, int32_t value);
597
598    /**
599     * @brief Calculate magic number and shift for a given divisor
600     * @param divisor divisor number for calculation
601     * @param magic hold calculated magic number
602     * @param shift hold calculated shift
603     */
604    void CalculateMagicAndShift(int divisor, int& magic, int& shift);
605
606    /*
607     * @brief Generate an integer div or rem operation.
608     * @param rl_dest Destination Location.
609     * @param rl_src1 Numerator Location.
610     * @param rl_src2 Divisor Location.
611     * @param is_div 'true' if this is a division, 'false' for a remainder.
612     * @param check_zero 'true' if an exception should be generated if the divisor is 0.
613     */
614    RegLocation GenDivRem(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2,
615                          bool is_div, bool check_zero);
616
617    /*
618     * @brief Generate an integer div or rem operation by a literal.
619     * @param rl_dest Destination Location.
620     * @param rl_src Numerator Location.
621     * @param lit Divisor.
622     * @param is_div 'true' if this is a division, 'false' for a remainder.
623     */
624    RegLocation GenDivRemLit(RegLocation rl_dest, RegLocation rl_src, int lit, bool is_div);
625
626    /*
627     * Generate code to implement long shift operations.
628     * @param opcode The DEX opcode to specify the shift type.
629     * @param rl_dest The destination.
630     * @param rl_src The value to be shifted.
631     * @param shift_amount How much to shift.
632     * @returns the RegLocation of the result.
633     */
634    RegLocation GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest,
635                                  RegLocation rl_src, int shift_amount);
636    /*
637     * Generate an imul of a register by a constant or a better sequence.
638     * @param dest Destination Register.
639     * @param src Source Register.
640     * @param val Constant multiplier.
641     */
642    void GenImulRegImm(RegStorage dest, RegStorage src, int val);
643
644    /*
645     * Generate an imul of a memory location by a constant or a better sequence.
646     * @param dest Destination Register.
647     * @param sreg Symbolic register.
648     * @param displacement Displacement on stack of Symbolic Register.
649     * @param val Constant multiplier.
650     */
651    void GenImulMemImm(RegStorage dest, int sreg, int displacement, int val);
652
653    /*
654     * @brief Compare memory to immediate, and branch if condition true.
655     * @param cond The condition code that when true will branch to the target.
656     * @param temp_reg A temporary register that can be used if compare memory is not
657     * supported by the architecture.
658     * @param base_reg The register holding the base address.
659     * @param offset The offset from the base.
660     * @param check_value The immediate to compare to.
661     */
662    LIR* OpCmpMemImmBranch(ConditionCode cond, RegStorage temp_reg, RegStorage base_reg,
663                           int offset, int check_value, LIR* target);
664
665    /*
666     * Can this operation be using core registers without temporaries?
667     * @param rl_lhs Left hand operand.
668     * @param rl_rhs Right hand operand.
669     * @returns 'true' if the operation can proceed without needing temporary regs.
670     */
671    bool IsOperationSafeWithoutTemps(RegLocation rl_lhs, RegLocation rl_rhs);
672
673    /**
674     * @brief Generates inline code for conversion of long to FP by using x87/
675     * @param rl_dest The destination of the FP.
676     * @param rl_src The source of the long.
677     * @param is_double 'true' if dealing with double, 'false' for float.
678     */
679    virtual void GenLongToFP(RegLocation rl_dest, RegLocation rl_src, bool is_double);
680
681    /*
682     * @brief Perform MIR analysis before compiling method.
683     * @note Invokes Mir2LiR::Materialize after analysis.
684     */
685    void Materialize();
686
687    /*
688     * Mir2Lir's UpdateLoc() looks to see if the Dalvik value is currently live in any temp register
689     * without regard to data type.  In practice, this can result in UpdateLoc returning a
690     * location record for a Dalvik float value in a core register, and vis-versa.  For targets
691     * which can inexpensively move data between core and float registers, this can often be a win.
692     * However, for x86 this is generally not a win.  These variants of UpdateLoc()
693     * take a register class argument - and will return an in-register location record only if
694     * the value is live in a temp register of the correct class.  Additionally, if the value is in
695     * a temp register of the wrong register class, it will be clobbered.
696     */
697    RegLocation UpdateLocTyped(RegLocation loc, int reg_class);
698    RegLocation UpdateLocWideTyped(RegLocation loc, int reg_class);
699
700    /*
701     * @brief Analyze MIR before generating code, to prepare for the code generation.
702     */
703    void AnalyzeMIR();
704
705    /*
706     * @brief Analyze one basic block.
707     * @param bb Basic block to analyze.
708     */
709    void AnalyzeBB(BasicBlock * bb);
710
711    /*
712     * @brief Analyze one extended MIR instruction
713     * @param opcode MIR instruction opcode.
714     * @param bb Basic block containing instruction.
715     * @param mir Extended instruction to analyze.
716     */
717    void AnalyzeExtendedMIR(int opcode, BasicBlock * bb, MIR *mir);
718
719    /*
720     * @brief Analyze one MIR instruction
721     * @param opcode MIR instruction opcode.
722     * @param bb Basic block containing instruction.
723     * @param mir Instruction to analyze.
724     */
725    virtual void AnalyzeMIR(int opcode, BasicBlock * bb, MIR *mir);
726
727    /*
728     * @brief Analyze one MIR float/double instruction
729     * @param opcode MIR instruction opcode.
730     * @param bb Basic block containing instruction.
731     * @param mir Instruction to analyze.
732     */
733    void AnalyzeFPInstruction(int opcode, BasicBlock * bb, MIR *mir);
734
735    /*
736     * @brief Analyze one use of a double operand.
737     * @param rl_use Double RegLocation for the operand.
738     */
739    void AnalyzeDoubleUse(RegLocation rl_use);
740
741    bool Gen64Bit() const  { return gen64bit_; }
742
743    // Information derived from analysis of MIR
744
745    // The compiler temporary for the code address of the method.
746    CompilerTemp *base_of_code_;
747
748    // Have we decided to compute a ptr to code and store in temporary VR?
749    bool store_method_addr_;
750
751    // Have we used the stored method address?
752    bool store_method_addr_used_;
753
754    // Instructions to remove if we didn't use the stored method address.
755    LIR* setup_method_address_[2];
756
757    // Instructions needing patching with Method* values.
758    GrowableArray<LIR*> method_address_insns_;
759
760    // Instructions needing patching with Class Type* values.
761    GrowableArray<LIR*> class_type_address_insns_;
762
763    // Instructions needing patching with PC relative code addresses.
764    GrowableArray<LIR*> call_method_insns_;
765
766    // Prologue decrement of stack pointer.
767    LIR* stack_decrement_;
768
769    // Epilogue increment of stack pointer.
770    LIR* stack_increment_;
771
772    // 64-bit mode
773    bool gen64bit_;
774
775    // The list of const vector literals.
776    LIR *const_vectors_;
777
778    /*
779     * @brief Search for a matching vector literal
780     * @param mir A kMirOpConst128b MIR instruction to match.
781     * @returns pointer to matching LIR constant, or nullptr if not found.
782     */
783    LIR *ScanVectorLiteral(MIR *mir);
784
785    /*
786     * @brief Add a constant vector literal
787     * @param mir A kMirOpConst128b MIR instruction to match.
788     */
789    LIR *AddVectorLiteral(MIR *mir);
790};
791
792}  // namespace art
793
794#endif  // ART_COMPILER_DEX_QUICK_X86_CODEGEN_X86_H_
795