| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 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 |  | 
| Brian Carlstrom | fc0e321 | 2013-07-17 14:40:12 -0700 | [diff] [blame] | 17 | #ifndef ART_COMPILER_DEX_QUICK_X86_CODEGEN_X86_H_ | 
|  | 18 | #define ART_COMPILER_DEX_QUICK_X86_CODEGEN_X86_H_ | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 19 |  | 
|  | 20 | #include "dex/compiler_internals.h" | 
|  | 21 | #include "x86_lir.h" | 
|  | 22 |  | 
|  | 23 | namespace art { | 
|  | 24 |  | 
|  | 25 | class X86Mir2Lir : public Mir2Lir { | 
|  | 26 | public: | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 27 | X86Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena); | 
|  | 28 |  | 
|  | 29 | // Required for target - codegen helpers. | 
| buzbee | 11b63d1 | 2013-08-27 07:34:17 -0700 | [diff] [blame] | 30 | bool SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div, RegLocation rl_src, | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 31 | RegLocation rl_dest, int lit); | 
| Ian Rogers | 468532e | 2013-08-05 10:56:33 -0700 | [diff] [blame] | 32 | int LoadHelper(ThreadOffset offset); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 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); | 
| buzbee | 2c1ed45 | 2014-02-20 11:48:04 -0800 | [diff] [blame^] | 51 | // TODO: for consistency, make this return a RegStorage as well? | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 52 | int AllocTypedTemp(bool fp_hint, int reg_class); | 
| buzbee | 2c1ed45 | 2014-02-20 11:48:04 -0800 | [diff] [blame^] | 53 | RegStorage AllocTypedTempWide(bool fp_hint, int reg_class); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 54 | int S2d(int low_reg, int high_reg); | 
|  | 55 | int TargetReg(SpecialTargetRegister reg); | 
| Razvan A Lupusoru | 3bc0174 | 2014-02-06 13:18:43 -0800 | [diff] [blame] | 56 | int GetArgMappingToPhysicalReg(int arg_num); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 57 | RegLocation GetReturnAlt(); | 
|  | 58 | RegLocation GetReturnWideAlt(); | 
|  | 59 | RegLocation LocCReturn(); | 
|  | 60 | RegLocation LocCReturnDouble(); | 
|  | 61 | RegLocation LocCReturnFloat(); | 
|  | 62 | RegLocation LocCReturnWide(); | 
|  | 63 | uint32_t FpRegMask(); | 
|  | 64 | uint64_t GetRegMaskCommon(int reg); | 
|  | 65 | void AdjustSpillMask(); | 
| Vladimir Marko | 31c2aac | 2013-12-09 16:31:19 +0000 | [diff] [blame] | 66 | void ClobberCallerSave(); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 67 | void FlushReg(int reg); | 
|  | 68 | void FlushRegWide(int reg1, int reg2); | 
|  | 69 | void FreeCallTemps(); | 
|  | 70 | void FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free); | 
|  | 71 | void LockCallTemps(); | 
|  | 72 | void MarkPreservedSingle(int v_reg, int reg); | 
|  | 73 | void CompilerInitializeRegAlloc(); | 
|  | 74 |  | 
|  | 75 | // Required for target - miscellaneous. | 
| buzbee | b48819d | 2013-09-14 16:15:25 -0700 | [diff] [blame] | 76 | void AssembleLIR(); | 
|  | 77 | int AssignInsnOffsets(); | 
|  | 78 | void AssignOffsets(); | 
| buzbee | 0d82948 | 2013-10-11 15:24:55 -0700 | [diff] [blame] | 79 | AssemblerStatus AssembleInstructions(CodeOffset start_addr); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 80 | void DumpResourceMask(LIR* lir, uint64_t mask, const char* prefix); | 
| buzbee | b48819d | 2013-09-14 16:15:25 -0700 | [diff] [blame] | 81 | void SetupTargetResourceMasks(LIR* lir, uint64_t flags); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 82 | const char* GetTargetInstFmt(int opcode); | 
|  | 83 | const char* GetTargetInstName(int opcode); | 
|  | 84 | std::string BuildInsnString(const char* fmt, LIR* lir, unsigned char* base_addr); | 
|  | 85 | uint64_t GetPCUseDefEncoding(); | 
|  | 86 | uint64_t GetTargetInstFlags(int opcode); | 
|  | 87 | int GetInsnSize(LIR* lir); | 
|  | 88 | bool IsUnconditionalBranch(LIR* lir); | 
|  | 89 |  | 
|  | 90 | // Required for target - Dalvik-level generators. | 
|  | 91 | void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest, | 
|  | 92 | RegLocation rl_src1, RegLocation rl_src2); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 93 | void GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, | 
|  | 94 | RegLocation rl_index, RegLocation rl_dest, int scale); | 
|  | 95 | void GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, | 
| Ian Rogers | a9a8254 | 2013-10-04 11:17:26 -0700 | [diff] [blame] | 96 | RegLocation rl_index, RegLocation rl_src, int scale, bool card_mark); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 97 | void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, | 
| Ian Rogers | a9a8254 | 2013-10-04 11:17:26 -0700 | [diff] [blame] | 98 | RegLocation rl_src1, RegLocation rl_shift); | 
| Mark Mendell | e02d48f | 2014-01-15 11:19:23 -0800 | [diff] [blame] | 99 | void GenMulLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); | 
|  | 100 | void GenAddLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); | 
|  | 101 | void GenAndLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 102 | void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest, | 
|  | 103 | RegLocation rl_src1, RegLocation rl_src2); | 
|  | 104 | void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, | 
|  | 105 | RegLocation rl_src1, RegLocation rl_src2); | 
|  | 106 | void GenCmpFP(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, | 
|  | 107 | RegLocation rl_src2); | 
|  | 108 | void GenConversion(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src); | 
| Vladimir Marko | 1c282e2 | 2013-11-21 14:49:47 +0000 | [diff] [blame] | 109 | bool GenInlinedCas(CallInfo* info, bool is_long, bool is_object); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 110 | bool GenInlinedMinMaxInt(CallInfo* info, bool is_min); | 
|  | 111 | bool GenInlinedSqrt(CallInfo* info); | 
| Vladimir Marko | e508a20 | 2013-11-04 15:24:22 +0000 | [diff] [blame] | 112 | bool GenInlinedPeek(CallInfo* info, OpSize size); | 
|  | 113 | bool GenInlinedPoke(CallInfo* info, OpSize size); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 114 | void GenNegLong(RegLocation rl_dest, RegLocation rl_src); | 
| Mark Mendell | e02d48f | 2014-01-15 11:19:23 -0800 | [diff] [blame] | 115 | void GenOrLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); | 
|  | 116 | void GenSubLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); | 
|  | 117 | void GenXorLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 118 | LIR* GenRegMemCheck(ConditionCode c_code, int reg1, int base, int offset, | 
|  | 119 | ThrowKind kind); | 
| Mark Mendell | 343adb5 | 2013-12-18 06:02:17 -0800 | [diff] [blame] | 120 | LIR* GenMemImmedCheck(ConditionCode c_code, int base, int offset, int check_value, | 
|  | 121 | ThrowKind kind); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 122 | RegLocation GenDivRem(RegLocation rl_dest, int reg_lo, int reg_hi, bool is_div); | 
|  | 123 | RegLocation GenDivRemLit(RegLocation rl_dest, int reg_lo, int lit, bool is_div); | 
|  | 124 | void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); | 
|  | 125 | void GenDivZeroCheck(int reg_lo, int reg_hi); | 
|  | 126 | void GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method); | 
|  | 127 | void GenExitSequence(); | 
| Razvan A Lupusoru | 3bc0174 | 2014-02-06 13:18:43 -0800 | [diff] [blame] | 128 | void GenSpecialExitSequence(); | 
| buzbee | 0d82948 | 2013-10-11 15:24:55 -0700 | [diff] [blame] | 129 | void GenFillArrayData(DexOffset table_offset, RegLocation rl_src); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 130 | void GenFusedFPCmpBranch(BasicBlock* bb, MIR* mir, bool gt_bias, bool is_double); | 
|  | 131 | void GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir); | 
|  | 132 | void GenSelect(BasicBlock* bb, MIR* mir); | 
|  | 133 | void GenMemBarrier(MemBarrierKind barrier_kind); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 134 | void GenMoveException(RegLocation rl_dest); | 
|  | 135 | void GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result, | 
|  | 136 | int lit, int first_bit, int second_bit); | 
|  | 137 | void GenNegDouble(RegLocation rl_dest, RegLocation rl_src); | 
|  | 138 | void GenNegFloat(RegLocation rl_dest, RegLocation rl_src); | 
| buzbee | 0d82948 | 2013-10-11 15:24:55 -0700 | [diff] [blame] | 139 | void GenPackedSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src); | 
|  | 140 | void GenSparseSwitch(MIR* mir, DexOffset table_offset, RegLocation rl_src); | 
| Razvan A Lupusoru | 3bc0174 | 2014-02-06 13:18:43 -0800 | [diff] [blame] | 141 |  | 
| Mark Mendell | e02d48f | 2014-01-15 11:19:23 -0800 | [diff] [blame] | 142 | /* | 
|  | 143 | * @brief Generate a two address long operation with a constant value | 
|  | 144 | * @param rl_dest location of result | 
|  | 145 | * @param rl_src constant source operand | 
|  | 146 | * @param op Opcode to be generated | 
|  | 147 | */ | 
|  | 148 | void GenLongImm(RegLocation rl_dest, RegLocation rl_src, Instruction::Code op); | 
|  | 149 | /* | 
|  | 150 | * @brief Generate a three address long operation with a constant value | 
|  | 151 | * @param rl_dest location of result | 
|  | 152 | * @param rl_src1 source operand | 
|  | 153 | * @param rl_src2 constant source operand | 
|  | 154 | * @param op Opcode to be generated | 
|  | 155 | */ | 
|  | 156 | void GenLongLongImm(RegLocation rl_dest, RegLocation rl_src1, | 
|  | 157 | RegLocation rl_src2, Instruction::Code op); | 
|  | 158 |  | 
|  | 159 | /** | 
|  | 160 | * @brief Generate a long arithmetic operation. | 
|  | 161 | * @param rl_dest The destination. | 
|  | 162 | * @param rl_src1 First operand. | 
|  | 163 | * @param rl_src2 Second operand. | 
|  | 164 | * @param op The DEX opcode for the operation. | 
|  | 165 | * @param is_commutative The sources can be swapped if needed. | 
|  | 166 | */ | 
|  | 167 | void GenLongArith(RegLocation rl_dest, RegLocation rl_src1, | 
|  | 168 | RegLocation rl_src2, Instruction::Code op, bool is_commutative); | 
|  | 169 |  | 
|  | 170 | /** | 
|  | 171 | * @brief Generate a two operand long arithmetic operation. | 
|  | 172 | * @param rl_dest The destination. | 
|  | 173 | * @param rl_src Second operand. | 
|  | 174 | * @param op The DEX opcode for the operation. | 
|  | 175 | */ | 
|  | 176 | void GenLongArith(RegLocation rl_dest, RegLocation rl_src, Instruction::Code op); | 
|  | 177 |  | 
|  | 178 | /** | 
|  | 179 | * @brief Generate a long operation. | 
|  | 180 | * @param rl_dest The destination.  Must be in a register | 
|  | 181 | * @param rl_src The other operand.  May be in a register or in memory. | 
|  | 182 | * @param op The DEX opcode for the operation. | 
|  | 183 | */ | 
|  | 184 | void GenLongRegOrMemOp(RegLocation rl_dest, RegLocation rl_src, Instruction::Code op); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 185 |  | 
| Mark Mendell | df8ee2e | 2014-01-27 16:37:47 -0800 | [diff] [blame] | 186 | /** | 
|  | 187 | * @brief Implement instanceof a final class with x86 specific code. | 
|  | 188 | * @param use_declaring_class 'true' if we can use the class itself. | 
|  | 189 | * @param type_idx Type index to use if use_declaring_class is 'false'. | 
|  | 190 | * @param rl_dest Result to be set to 0 or 1. | 
|  | 191 | * @param rl_src Object to be tested. | 
|  | 192 | */ | 
|  | 193 | void GenInstanceofFinal(bool use_declaring_class, uint32_t type_idx, | 
|  | 194 | RegLocation rl_dest, RegLocation rl_src); | 
| Mark Mendell | 6607d97 | 2014-02-10 06:54:18 -0800 | [diff] [blame] | 195 | /* | 
|  | 196 | * | 
|  | 197 | * @brief Implement Set up instanceof a class with x86 specific code. | 
|  | 198 | * @param needs_access_check 'true' if we must check the access. | 
|  | 199 | * @param type_known_final 'true' if the type is known to be a final class. | 
|  | 200 | * @param type_known_abstract 'true' if the type is known to be an abstract class. | 
|  | 201 | * @param use_declaring_class 'true' if the type can be loaded off the current Method*. | 
|  | 202 | * @param can_assume_type_is_in_dex_cache 'true' if the type is known to be in the cache. | 
|  | 203 | * @param type_idx Type index to use if use_declaring_class is 'false'. | 
|  | 204 | * @param rl_dest Result to be set to 0 or 1. | 
|  | 205 | * @param rl_src Object to be tested. | 
|  | 206 | */ | 
|  | 207 | void GenInstanceofCallingHelper(bool needs_access_check, bool type_known_final, | 
|  | 208 | bool type_known_abstract, bool use_declaring_class, | 
|  | 209 | bool can_assume_type_is_in_dex_cache, | 
|  | 210 | uint32_t type_idx, RegLocation rl_dest, | 
|  | 211 | RegLocation rl_src); | 
|  | 212 |  | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 213 | // Single operation generators. | 
|  | 214 | LIR* OpUnconditionalBranch(LIR* target); | 
|  | 215 | LIR* OpCmpBranch(ConditionCode cond, int src1, int src2, LIR* target); | 
|  | 216 | LIR* OpCmpImmBranch(ConditionCode cond, int reg, int check_value, LIR* target); | 
|  | 217 | LIR* OpCondBranch(ConditionCode cc, LIR* target); | 
|  | 218 | LIR* OpDecAndBranch(ConditionCode c_code, int reg, LIR* target); | 
|  | 219 | LIR* OpFpRegCopy(int r_dest, int r_src); | 
|  | 220 | LIR* OpIT(ConditionCode cond, const char* guide); | 
|  | 221 | LIR* OpMem(OpKind op, int rBase, int disp); | 
|  | 222 | LIR* OpPcRelLoad(int reg, LIR* target); | 
|  | 223 | LIR* OpReg(OpKind op, int r_dest_src); | 
|  | 224 | LIR* OpRegCopy(int r_dest, int r_src); | 
|  | 225 | LIR* OpRegCopyNoInsert(int r_dest, int r_src); | 
|  | 226 | LIR* OpRegImm(OpKind op, int r_dest_src1, int value); | 
|  | 227 | LIR* OpRegMem(OpKind op, int r_dest, int rBase, int offset); | 
| Mark Mendell | feb2b4e | 2014-01-28 12:59:49 -0800 | [diff] [blame] | 228 | LIR* OpMemReg(OpKind op, RegLocation rl_dest, int value); | 
|  | 229 | LIR* OpRegMem(OpKind op, int r_dest, RegLocation value); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 230 | LIR* OpRegReg(OpKind op, int r_dest_src1, int r_src2); | 
| Razvan A Lupusoru | 2c498d1 | 2014-01-29 16:02:57 -0800 | [diff] [blame] | 231 | LIR* OpMovRegMem(int r_dest, int r_base, int offset, MoveType move_type); | 
|  | 232 | LIR* OpMovMemReg(int r_base, int offset, int r_src, MoveType move_type); | 
| Razvan A Lupusoru | bd288c2 | 2013-12-20 17:27:23 -0800 | [diff] [blame] | 233 | LIR* OpCondRegReg(OpKind op, ConditionCode cc, int r_dest, int r_src); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 234 | LIR* OpRegRegImm(OpKind op, int r_dest, int r_src1, int value); | 
|  | 235 | LIR* OpRegRegReg(OpKind op, int r_dest, int r_src1, int r_src2); | 
|  | 236 | LIR* OpTestSuspend(LIR* target); | 
| Ian Rogers | 468532e | 2013-08-05 10:56:33 -0700 | [diff] [blame] | 237 | LIR* OpThreadMem(OpKind op, ThreadOffset thread_offset); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 238 | LIR* OpVldm(int rBase, int count); | 
|  | 239 | LIR* OpVstm(int rBase, int count); | 
|  | 240 | void OpLea(int rBase, int reg1, int reg2, int scale, int offset); | 
|  | 241 | void OpRegCopyWide(int dest_lo, int dest_hi, int src_lo, int src_hi); | 
| Ian Rogers | 468532e | 2013-08-05 10:56:33 -0700 | [diff] [blame] | 242 | void OpTlsCmp(ThreadOffset offset, int val); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 243 |  | 
| Ian Rogers | 468532e | 2013-08-05 10:56:33 -0700 | [diff] [blame] | 244 | void OpRegThreadMem(OpKind op, int r_dest, ThreadOffset thread_offset); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 245 | void SpillCoreRegs(); | 
|  | 246 | void UnSpillCoreRegs(); | 
|  | 247 | static const X86EncodingMap EncodingMap[kX86Last]; | 
|  | 248 | bool InexpensiveConstantInt(int32_t value); | 
|  | 249 | bool InexpensiveConstantFloat(int32_t value); | 
|  | 250 | bool InexpensiveConstantLong(int64_t value); | 
|  | 251 | bool InexpensiveConstantDouble(int64_t value); | 
|  | 252 |  | 
| Bill Buzbee | d61ba4b | 2014-01-13 21:44:01 +0000 | [diff] [blame] | 253 | RegLocation UpdateLocWide(RegLocation loc); | 
|  | 254 | RegLocation EvalLocWide(RegLocation loc, int reg_class, bool update); | 
|  | 255 | RegLocation EvalLoc(RegLocation loc, int reg_class, bool update); | 
|  | 256 | int AllocTempDouble(); | 
|  | 257 | void ResetDefLocWide(RegLocation rl); | 
|  | 258 |  | 
| Mark Mendell | feb2b4e | 2014-01-28 12:59:49 -0800 | [diff] [blame] | 259 | /* | 
|  | 260 | * @brief x86 specific codegen for int operations. | 
|  | 261 | * @param opcode Operation to perform. | 
|  | 262 | * @param rl_dest Destination for the result. | 
|  | 263 | * @param rl_lhs Left hand operand. | 
|  | 264 | * @param rl_rhs Right hand operand. | 
|  | 265 | */ | 
|  | 266 | void GenArithOpInt(Instruction::Code opcode, RegLocation rl_dest, | 
|  | 267 | RegLocation rl_lhs, RegLocation rl_rhs); | 
|  | 268 |  | 
| Mark Mendell | 55d0eac | 2014-02-06 11:02:52 -0800 | [diff] [blame] | 269 | /* | 
|  | 270 | * @brief Dump a RegLocation using printf | 
|  | 271 | * @param loc Register location to dump | 
|  | 272 | */ | 
|  | 273 | static void DumpRegLocation(RegLocation loc); | 
|  | 274 |  | 
|  | 275 | /* | 
|  | 276 | * @brief Load the Method* of a dex method into the register. | 
|  | 277 | * @param dex_method_index The index of the method to be invoked. | 
|  | 278 | * @param type How the method will be invoked. | 
|  | 279 | * @param register that will contain the code address. | 
|  | 280 | * @note register will be passed to TargetReg to get physical register. | 
|  | 281 | */ | 
|  | 282 | void LoadMethodAddress(int dex_method_index, InvokeType type, | 
|  | 283 | SpecialTargetRegister symbolic_reg); | 
|  | 284 |  | 
|  | 285 | /* | 
|  | 286 | * @brief Load the Class* of a Dex Class type into the register. | 
|  | 287 | * @param type How the method will be invoked. | 
|  | 288 | * @param register that will contain the code address. | 
|  | 289 | * @note register will be passed to TargetReg to get physical register. | 
|  | 290 | */ | 
|  | 291 | void LoadClassType(uint32_t type_idx, SpecialTargetRegister symbolic_reg); | 
|  | 292 |  | 
|  | 293 | /* | 
|  | 294 | * @brief Generate a relative call to the method that will be patched at link time. | 
|  | 295 | * @param dex_method_index The index of the method to be invoked. | 
|  | 296 | * @param type How the method will be invoked. | 
|  | 297 | * @returns Call instruction | 
|  | 298 | */ | 
|  | 299 | LIR * CallWithLinkerFixup(int dex_method_index, InvokeType type); | 
|  | 300 |  | 
|  | 301 | /* | 
|  | 302 | * @brief Handle x86 specific literals | 
|  | 303 | */ | 
|  | 304 | void InstallLiteralPools(); | 
|  | 305 |  | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 306 | private: | 
| Vladimir Marko | 057c74a | 2013-12-03 15:20:45 +0000 | [diff] [blame] | 307 | void EmitPrefix(const X86EncodingMap* entry); | 
|  | 308 | void EmitOpcode(const X86EncodingMap* entry); | 
|  | 309 | void EmitPrefixAndOpcode(const X86EncodingMap* entry); | 
|  | 310 | void EmitDisp(uint8_t base, int disp); | 
|  | 311 | void EmitModrmDisp(uint8_t reg_or_opcode, uint8_t base, int disp); | 
|  | 312 | void EmitModrmSibDisp(uint8_t reg_or_opcode, uint8_t base, uint8_t index, int scale, int disp); | 
|  | 313 | void EmitImm(const X86EncodingMap* entry, int imm); | 
| Vladimir Marko | a8b4caf | 2013-10-24 15:08:57 +0100 | [diff] [blame] | 314 | void EmitOpRegOpcode(const X86EncodingMap* entry, uint8_t reg); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 315 | void EmitOpReg(const X86EncodingMap* entry, uint8_t reg); | 
|  | 316 | void EmitOpMem(const X86EncodingMap* entry, uint8_t base, int disp); | 
| Vladimir Marko | 057c74a | 2013-12-03 15:20:45 +0000 | [diff] [blame] | 317 | void EmitOpArray(const X86EncodingMap* entry, uint8_t base, uint8_t index, | 
|  | 318 | int scale, int disp); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 319 | void EmitMemReg(const X86EncodingMap* entry, uint8_t base, int disp, uint8_t reg); | 
| Mark Mendell | 343adb5 | 2013-12-18 06:02:17 -0800 | [diff] [blame] | 320 | void EmitMemImm(const X86EncodingMap* entry, uint8_t base, int disp, int32_t imm); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 321 | void EmitRegMem(const X86EncodingMap* entry, uint8_t reg, uint8_t base, int disp); | 
|  | 322 | void EmitRegArray(const X86EncodingMap* entry, uint8_t reg, uint8_t base, uint8_t index, | 
|  | 323 | int scale, int disp); | 
|  | 324 | void EmitArrayReg(const X86EncodingMap* entry, uint8_t base, uint8_t index, int scale, int disp, | 
|  | 325 | uint8_t reg); | 
|  | 326 | void EmitRegThread(const X86EncodingMap* entry, uint8_t reg, int disp); | 
|  | 327 | void EmitRegReg(const X86EncodingMap* entry, uint8_t reg1, uint8_t reg2); | 
|  | 328 | void EmitRegRegImm(const X86EncodingMap* entry, uint8_t reg1, uint8_t reg2, int32_t imm); | 
| Mark Mendell | 4708dcd | 2014-01-22 09:05:18 -0800 | [diff] [blame] | 329 | void EmitRegRegImmRev(const X86EncodingMap* entry, uint8_t reg1, uint8_t reg2, int32_t imm); | 
|  | 330 | void EmitRegMemImm(const X86EncodingMap* entry, uint8_t reg1, uint8_t base, int disp, int32_t imm); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 331 | void EmitRegImm(const X86EncodingMap* entry, uint8_t reg, int imm); | 
|  | 332 | void EmitThreadImm(const X86EncodingMap* entry, int disp, int imm); | 
|  | 333 | void EmitMovRegImm(const X86EncodingMap* entry, uint8_t reg, int imm); | 
|  | 334 | void EmitShiftRegImm(const X86EncodingMap* entry, uint8_t reg, int imm); | 
| Mark Mendell | feb2b4e | 2014-01-28 12:59:49 -0800 | [diff] [blame] | 335 | void EmitShiftMemCl(const X86EncodingMap* entry, uint8_t base, int displacement, uint8_t cl); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 336 | void EmitShiftRegCl(const X86EncodingMap* entry, uint8_t reg, uint8_t cl); | 
|  | 337 | void EmitRegCond(const X86EncodingMap* entry, uint8_t reg, uint8_t condition); | 
| Razvan A Lupusoru | bd288c2 | 2013-12-20 17:27:23 -0800 | [diff] [blame] | 338 |  | 
|  | 339 | /** | 
|  | 340 | * @brief Used for encoding conditional register to register operation. | 
|  | 341 | * @param entry The entry in the encoding map for the opcode. | 
|  | 342 | * @param reg1 The first physical register. | 
|  | 343 | * @param reg2 The second physical register. | 
|  | 344 | * @param condition The condition code for operation. | 
|  | 345 | */ | 
|  | 346 | void EmitRegRegCond(const X86EncodingMap* entry, uint8_t reg1, uint8_t reg2, uint8_t condition); | 
|  | 347 |  | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 348 | void EmitJmp(const X86EncodingMap* entry, int rel); | 
|  | 349 | void EmitJcc(const X86EncodingMap* entry, int rel, uint8_t cc); | 
|  | 350 | void EmitCallMem(const X86EncodingMap* entry, uint8_t base, int disp); | 
| Mark Mendell | 55d0eac | 2014-02-06 11:02:52 -0800 | [diff] [blame] | 351 | void EmitCallImmediate(const X86EncodingMap* entry, int disp); | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 352 | void EmitCallThread(const X86EncodingMap* entry, int disp); | 
|  | 353 | void EmitPcRel(const X86EncodingMap* entry, uint8_t reg, int base_or_table, uint8_t index, | 
|  | 354 | int scale, int table_or_disp); | 
|  | 355 | void EmitMacro(const X86EncodingMap* entry, uint8_t reg, int offset); | 
|  | 356 | void EmitUnimplemented(const X86EncodingMap* entry, LIR* lir); | 
| Mark Mendell | 412d4f8 | 2013-12-18 13:32:36 -0800 | [diff] [blame] | 357 | void GenFusedLongCmpImmBranch(BasicBlock* bb, RegLocation rl_src1, | 
|  | 358 | int64_t val, ConditionCode ccode); | 
| Bill Buzbee | d61ba4b | 2014-01-13 21:44:01 +0000 | [diff] [blame] | 359 | void OpVectorRegCopyWide(uint8_t fp_reg, uint8_t low_reg, uint8_t high_reg); | 
|  | 360 | void GenConstWide(RegLocation rl_dest, int64_t value); | 
| Mark Mendell | e02d48f | 2014-01-15 11:19:23 -0800 | [diff] [blame] | 361 |  | 
|  | 362 | /* | 
| Mark Mendell | 4028a6c | 2014-02-19 20:06:20 -0800 | [diff] [blame] | 363 | * @brief generate inline code for fast case of Strng.indexOf. | 
|  | 364 | * @param info Call parameters | 
|  | 365 | * @param zero_based 'true' if the index into the string is 0. | 
|  | 366 | * @returns 'true' if the call was inlined, 'false' if a regular call needs to be | 
|  | 367 | * generated. | 
|  | 368 | */ | 
|  | 369 | bool GenInlinedIndexOf(CallInfo* info, bool zero_based); | 
|  | 370 |  | 
|  | 371 | /* | 
| Mark Mendell | e02d48f | 2014-01-15 11:19:23 -0800 | [diff] [blame] | 372 | * @brief Return the correct x86 opcode for the Dex operation | 
|  | 373 | * @param op Dex opcode for the operation | 
|  | 374 | * @param loc Register location of the operand | 
|  | 375 | * @param is_high_op 'true' if this is an operation on the high word | 
|  | 376 | * @param value Immediate value for the operation.  Used for byte variants | 
|  | 377 | * @returns the correct x86 opcode to perform the operation | 
|  | 378 | */ | 
|  | 379 | X86OpCode GetOpcode(Instruction::Code op, RegLocation loc, bool is_high_op, int32_t value); | 
|  | 380 |  | 
|  | 381 | /* | 
|  | 382 | * @brief Return the correct x86 opcode for the Dex operation | 
|  | 383 | * @param op Dex opcode for the operation | 
|  | 384 | * @param dest location of the destination.  May be register or memory. | 
|  | 385 | * @param rhs Location for the rhs of the operation.  May be in register or memory. | 
|  | 386 | * @param is_high_op 'true' if this is an operation on the high word | 
|  | 387 | * @returns the correct x86 opcode to perform the operation | 
|  | 388 | * @note at most one location may refer to memory | 
|  | 389 | */ | 
|  | 390 | X86OpCode GetOpcode(Instruction::Code op, RegLocation dest, RegLocation rhs, | 
|  | 391 | bool is_high_op); | 
|  | 392 |  | 
|  | 393 | /* | 
|  | 394 | * @brief Is this operation a no-op for this opcode and value | 
|  | 395 | * @param op Dex opcode for the operation | 
|  | 396 | * @param value Immediate value for the operation. | 
|  | 397 | * @returns 'true' if the operation will have no effect | 
|  | 398 | */ | 
|  | 399 | bool IsNoOp(Instruction::Code op, int32_t value); | 
|  | 400 |  | 
| Mark Mendell | 2bf31e6 | 2014-01-23 12:13:40 -0800 | [diff] [blame] | 401 | /** | 
|  | 402 | * @brief Calculate magic number and shift for a given divisor | 
|  | 403 | * @param divisor divisor number for calculation | 
|  | 404 | * @param magic hold calculated magic number | 
|  | 405 | * @param shift hold calculated shift | 
|  | 406 | */ | 
|  | 407 | void CalculateMagicAndShift(int divisor, int& magic, int& shift); | 
|  | 408 |  | 
|  | 409 | /* | 
|  | 410 | * @brief Generate an integer div or rem operation. | 
|  | 411 | * @param rl_dest Destination Location. | 
|  | 412 | * @param rl_src1 Numerator Location. | 
|  | 413 | * @param rl_src2 Divisor Location. | 
|  | 414 | * @param is_div 'true' if this is a division, 'false' for a remainder. | 
|  | 415 | * @param check_zero 'true' if an exception should be generated if the divisor is 0. | 
|  | 416 | */ | 
|  | 417 | RegLocation GenDivRem(RegLocation rl_dest, RegLocation rl_src1, | 
|  | 418 | RegLocation rl_src2, bool is_div, bool check_zero); | 
|  | 419 |  | 
|  | 420 | /* | 
|  | 421 | * @brief Generate an integer div or rem operation by a literal. | 
|  | 422 | * @param rl_dest Destination Location. | 
|  | 423 | * @param rl_src Numerator Location. | 
|  | 424 | * @param lit Divisor. | 
|  | 425 | * @param is_div 'true' if this is a division, 'false' for a remainder. | 
|  | 426 | */ | 
|  | 427 | RegLocation GenDivRemLit(RegLocation rl_dest, RegLocation rl_src, int lit, bool is_div); | 
| Mark Mendell | 4708dcd | 2014-01-22 09:05:18 -0800 | [diff] [blame] | 428 |  | 
|  | 429 | /* | 
|  | 430 | * Generate code to implement long shift operations. | 
|  | 431 | * @param opcode The DEX opcode to specify the shift type. | 
|  | 432 | * @param rl_dest The destination. | 
|  | 433 | * @param rl_src The value to be shifted. | 
|  | 434 | * @param shift_amount How much to shift. | 
|  | 435 | * @returns the RegLocation of the result. | 
|  | 436 | */ | 
|  | 437 | RegLocation GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, | 
|  | 438 | RegLocation rl_src, int shift_amount); | 
|  | 439 | /* | 
|  | 440 | * Generate an imul of a register by a constant or a better sequence. | 
|  | 441 | * @param dest Destination Register. | 
|  | 442 | * @param src Source Register. | 
|  | 443 | * @param val Constant multiplier. | 
|  | 444 | */ | 
|  | 445 | void GenImulRegImm(int dest, int src, int val); | 
| Mark Mendell | feb2b4e | 2014-01-28 12:59:49 -0800 | [diff] [blame] | 446 |  | 
| Mark Mendell | 4708dcd | 2014-01-22 09:05:18 -0800 | [diff] [blame] | 447 | /* | 
|  | 448 | * Generate an imul of a memory location by a constant or a better sequence. | 
|  | 449 | * @param dest Destination Register. | 
|  | 450 | * @param sreg Symbolic register. | 
|  | 451 | * @param displacement Displacement on stack of Symbolic Register. | 
|  | 452 | * @param val Constant multiplier. | 
|  | 453 | */ | 
|  | 454 | void GenImulMemImm(int dest, int sreg, int displacement, int val); | 
| Mark Mendell | 766e929 | 2014-01-27 07:55:47 -0800 | [diff] [blame] | 455 |  | 
|  | 456 | /* | 
|  | 457 | * @brief Compare memory to immediate, and branch if condition true. | 
|  | 458 | * @param cond The condition code that when true will branch to the target. | 
|  | 459 | * @param temp_reg A temporary register that can be used if compare memory is not | 
|  | 460 | * supported by the architecture. | 
|  | 461 | * @param base_reg The register holding the base address. | 
|  | 462 | * @param offset The offset from the base. | 
|  | 463 | * @param check_value The immediate to compare to. | 
|  | 464 | */ | 
|  | 465 | LIR* OpCmpMemImmBranch(ConditionCode cond, int temp_reg, int base_reg, | 
|  | 466 | int offset, int check_value, LIR* target); | 
| Razvan A Lupusoru | 614c2b4 | 2014-01-28 17:05:21 -0800 | [diff] [blame] | 467 |  | 
| Mark Mendell | feb2b4e | 2014-01-28 12:59:49 -0800 | [diff] [blame] | 468 | /* | 
|  | 469 | * Can this operation be using core registers without temporaries? | 
|  | 470 | * @param rl_lhs Left hand operand. | 
|  | 471 | * @param rl_rhs Right hand operand. | 
|  | 472 | * @returns 'true' if the operation can proceed without needing temporary regs. | 
|  | 473 | */ | 
|  | 474 | bool IsOperationSafeWithoutTemps(RegLocation rl_lhs, RegLocation rl_rhs); | 
| Mark Mendell | 67c39c4 | 2014-01-31 17:28:00 -0800 | [diff] [blame] | 475 |  | 
| Razvan A Lupusoru | 614c2b4 | 2014-01-28 17:05:21 -0800 | [diff] [blame] | 476 | /** | 
|  | 477 | * @brief Generates inline code for conversion of long to FP by using x87/ | 
|  | 478 | * @param rl_dest The destination of the FP. | 
|  | 479 | * @param rl_src The source of the long. | 
|  | 480 | * @param is_double 'true' if dealing with double, 'false' for float. | 
|  | 481 | */ | 
|  | 482 | void GenLongToFP(RegLocation rl_dest, RegLocation rl_src, bool is_double); | 
|  | 483 |  | 
| Mark Mendell | 67c39c4 | 2014-01-31 17:28:00 -0800 | [diff] [blame] | 484 | /* | 
|  | 485 | * @brief Perform MIR analysis before compiling method. | 
|  | 486 | * @note Invokes Mir2LiR::Materialize after analysis. | 
|  | 487 | */ | 
|  | 488 | void Materialize(); | 
|  | 489 |  | 
|  | 490 | /* | 
|  | 491 | * @brief Analyze MIR before generating code, to prepare for the code generation. | 
|  | 492 | */ | 
|  | 493 | void AnalyzeMIR(); | 
|  | 494 |  | 
|  | 495 | /* | 
|  | 496 | * @brief Analyze one basic block. | 
|  | 497 | * @param bb Basic block to analyze. | 
|  | 498 | */ | 
|  | 499 | void AnalyzeBB(BasicBlock * bb); | 
|  | 500 |  | 
|  | 501 | /* | 
|  | 502 | * @brief Analyze one extended MIR instruction | 
|  | 503 | * @param opcode MIR instruction opcode. | 
|  | 504 | * @param bb Basic block containing instruction. | 
|  | 505 | * @param mir Extended instruction to analyze. | 
|  | 506 | */ | 
|  | 507 | void AnalyzeExtendedMIR(int opcode, BasicBlock * bb, MIR *mir); | 
|  | 508 |  | 
|  | 509 | /* | 
|  | 510 | * @brief Analyze one MIR instruction | 
|  | 511 | * @param opcode MIR instruction opcode. | 
|  | 512 | * @param bb Basic block containing instruction. | 
|  | 513 | * @param mir Instruction to analyze. | 
|  | 514 | */ | 
|  | 515 | void AnalyzeMIR(int opcode, BasicBlock * bb, MIR *mir); | 
|  | 516 |  | 
|  | 517 | /* | 
|  | 518 | * @brief Analyze one MIR float/double instruction | 
|  | 519 | * @param opcode MIR instruction opcode. | 
|  | 520 | * @param bb Basic block containing instruction. | 
|  | 521 | * @param mir Instruction to analyze. | 
|  | 522 | */ | 
|  | 523 | void AnalyzeFPInstruction(int opcode, BasicBlock * bb, MIR *mir); | 
|  | 524 |  | 
|  | 525 | /* | 
|  | 526 | * @brief Analyze one use of a double operand. | 
|  | 527 | * @param rl_use Double RegLocation for the operand. | 
|  | 528 | */ | 
|  | 529 | void AnalyzeDoubleUse(RegLocation rl_use); | 
|  | 530 |  | 
|  | 531 | // Information derived from analysis of MIR | 
|  | 532 |  | 
| Mark Mendell | 55d0eac | 2014-02-06 11:02:52 -0800 | [diff] [blame] | 533 | // The compiler temporary for the code address of the method. | 
|  | 534 | CompilerTemp *base_of_code_; | 
|  | 535 |  | 
| Mark Mendell | 67c39c4 | 2014-01-31 17:28:00 -0800 | [diff] [blame] | 536 | // Have we decided to compute a ptr to code and store in temporary VR? | 
|  | 537 | bool store_method_addr_; | 
|  | 538 |  | 
| Mark Mendell | 55d0eac | 2014-02-06 11:02:52 -0800 | [diff] [blame] | 539 | // Have we used the stored method address? | 
|  | 540 | bool store_method_addr_used_; | 
|  | 541 |  | 
|  | 542 | // Instructions to remove if we didn't use the stored method address. | 
|  | 543 | LIR* setup_method_address_[2]; | 
|  | 544 |  | 
|  | 545 | // Instructions needing patching with Method* values. | 
|  | 546 | GrowableArray<LIR*> method_address_insns_; | 
|  | 547 |  | 
|  | 548 | // Instructions needing patching with Class Type* values. | 
|  | 549 | GrowableArray<LIR*> class_type_address_insns_; | 
|  | 550 |  | 
|  | 551 | // Instructions needing patching with PC relative code addresses. | 
|  | 552 | GrowableArray<LIR*> call_method_insns_; | 
| Brian Carlstrom | 7940e44 | 2013-07-12 13:46:57 -0700 | [diff] [blame] | 553 | }; | 
|  | 554 |  | 
|  | 555 | }  // namespace art | 
|  | 556 |  | 
| Brian Carlstrom | fc0e321 | 2013-07-17 14:40:12 -0700 | [diff] [blame] | 557 | #endif  // ART_COMPILER_DEX_QUICK_X86_CODEGEN_X86_H_ |