1 /* 2 * Copyright (C) 2010 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 /* 18 * This file contains codegen and support common to all supported 19 * X86 variants. It is included by: 20 * 21 * Codegen-$(TARGET_ARCH_VARIANT).c 22 * 23 * which combines this common code with specific support found in the 24 * applicable directory below this one. 25 */ 26 27 extern X86LIR *loadConstant(CompilationUnit *cUnit, int rDest, int value); 28 extern X86LIR *loadWordDisp(CompilationUnit *cUnit, int rBase, 29 int displacement, int rDest); 30 extern void dvmCompilerFlushAllRegs(CompilationUnit *cUnit); 31 extern void storeWordDisp(CompilationUnit *cUnit, int rBase, 32 int displacement, int rSrc); 33 extern X86LIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc); 34 35 static int opcodeCoverage[kNumPackedOpcodes]; 36 static intptr_t templateEntryOffsets[TEMPLATE_LAST_MARK]; 37 38 #if 0 // Avoid compiler warnings when x86 disabled during development 39 /* 40 * Bail to the interpreter. Will not return to this trace. 41 * On entry, rPC must be set correctly. 42 */ 43 static void genPuntToInterp(CompilationUnit *cUnit, unsigned int offset) 44 { 45 dvmCompilerFlushAllRegs(cUnit); 46 loadConstant(cUnit, rPC, (int)(cUnit->method->insns + offset)); 47 loadWordDisp(cUnit, rEBP, 0, rECX); // Get glue 48 loadWordDisp(cUnit, rECX, 49 offsetof(Thread, jitToInterpEntries.dvmJitToInterpPunt), 50 rEAX); 51 opReg(cUnit, kOpUncondBr, rEAX); 52 } 53 54 static void genInterpSingleStep(CompilationUnit *cUnit, MIR *mir) 55 { 56 int flags = dexGetFlagsFromOpcode(mir->dalvikInsn.opcode); 57 int flagsToCheck = kInstrCanBranch | kInstrCanSwitch | kInstrCanReturn | 58 kInstrCanThrow; 59 60 //If already optimized out, just ignore 61 if (mir->dalvikInsn.opcode == OP_NOP) 62 return; 63 64 //Ugly, but necessary. Flush all Dalvik regs so Interp can find them 65 dvmCompilerFlushAllRegs(cUnit); 66 67 if ((mir->next == NULL) || (flags & flagsToCheck)) { 68 genPuntToInterp(cUnit, mir->offset); 69 return; 70 } 71 int entryAddr = offsetof(Thread, 72 jitToInterpEntries.dvmJitToInterpSingleStep); 73 loadWordDisp(cUnit, rEBP, 0, rECX); // Get glue 74 loadWordDisp(cUnit, rECX, entryAddr, rEAX); // rEAX<- entry address 75 /* rPC = dalvik pc */ 76 loadConstant(cUnit, rPC, (int) (cUnit->method->insns + mir->offset)); 77 /* rECX = dalvik pc of following instruction */ 78 loadConstant(cUnit, rECX, (int) (cUnit->method->insns + mir->next->offset)); 79 /* Pass on the stack */ 80 storeWordDisp(cUnit, rESP, OUT_ARG0, rECX); 81 opReg(cUnit, kOpCall, rEAX); 82 } 83 #endif 84 85 /* 86 * The following are the first-level codegen routines that analyze the format 87 * of each bytecode then either dispatch special purpose codegen routines 88 * or produce corresponding Thumb instructions directly. 89 */ 90 91 #if 0 92 static bool handleFmt10t_Fmt20t_Fmt30t(CompilationUnit *cUnit, MIR *mir, 93 BasicBlock *bb, X86LIR *labelList) 94 { 95 /* For OP_GOTO, OP_GOTO_16, and OP_GOTO_32 */ 96 return true; 97 } 98 99 static bool handleFmt10x(CompilationUnit *cUnit, MIR *mir) 100 { 101 return true; 102 } 103 104 static bool handleFmt11n_Fmt31i(CompilationUnit *cUnit, MIR *mir) 105 { 106 return true; 107 } 108 109 static bool handleFmt21h(CompilationUnit *cUnit, MIR *mir) 110 { 111 return true; 112 } 113 114 static bool handleFmt20bc(CompilationUnit *cUnit, MIR *mir) 115 { 116 return true; 117 } 118 119 static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir) 120 { 121 return true; 122 } 123 124 static bool handleFmt11x(CompilationUnit *cUnit, MIR *mir) 125 { 126 return true; 127 } 128 129 static bool handleFmt12x(CompilationUnit *cUnit, MIR *mir) 130 { 131 return true; 132 } 133 134 static bool handleFmt21s(CompilationUnit *cUnit, MIR *mir) 135 { 136 return true; 137 } 138 139 static bool handleFmt21t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb, 140 X86LIR *labelList) 141 { 142 return true; 143 } 144 145 static bool handleFmt22b_Fmt22s(CompilationUnit *cUnit, MIR *mir) 146 { 147 return true; 148 } 149 150 static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir) 151 { 152 return true; 153 } 154 155 static bool handleFmt22cs(CompilationUnit *cUnit, MIR *mir) 156 { 157 return true; 158 } 159 160 static bool handleFmt22t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb, 161 X86LIR *labelList) 162 { 163 return true; 164 } 165 166 static bool handleFmt22x_Fmt32x(CompilationUnit *cUnit, MIR *mir) 167 { 168 return true; 169 } 170 171 static bool handleFmt23x(CompilationUnit *cUnit, MIR *mir) 172 { 173 return true; 174 } 175 176 static bool handleFmt31t(CompilationUnit *cUnit, MIR *mir) 177 { 178 return true; 179 } 180 181 static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb, 182 X86LIR *labelList) 183 { 184 return true; 185 } 186 187 static bool handleFmt35ms_3rms(CompilationUnit *cUnit, MIR *mir, 188 BasicBlock *bb, X86LIR *labelList) 189 { 190 return true; 191 } 192 193 /* 194 * NOTE: Handles both range and non-range versions (arguments 195 * have already been normalized by this point). 196 */ 197 static bool handleExecuteInline(CompilationUnit *cUnit, MIR *mir) 198 { 199 return true; 200 } 201 202 static bool handleFmt51l(CompilationUnit *cUnit, MIR *mir) 203 { 204 return true; 205 } 206 #endif 207 208 209 void dvmCompilerMIR2LIR(CompilationUnit *cUnit) 210 { 211 } 212 213 /* Accept the work and start compiling */ 214 bool dvmCompilerDoWork(CompilerWorkOrder *work) 215 { 216 JitTraceDescription *desc; 217 bool res; 218 219 if (gDvmJit.codeCacheFull) { 220 return false; 221 } 222 223 switch (work->kind) { 224 case kWorkOrderTrace: 225 /* Start compilation with maximally allowed trace length */ 226 desc = (JitTraceDescription *)work->info; 227 res = dvmCompileTrace(desc, JIT_MAX_TRACE_LEN, &work->result, 228 work->bailPtr, 0 /* no hints */); 229 break; 230 case kWorkOrderTraceDebug: { 231 bool oldPrintMe = gDvmJit.printMe; 232 gDvmJit.printMe = true; 233 /* Start compilation with maximally allowed trace length */ 234 desc = (JitTraceDescription *)work->info; 235 res = dvmCompileTrace(desc, JIT_MAX_TRACE_LEN, &work->result, 236 work->bailPtr, 0 /* no hints */); 237 gDvmJit.printMe = oldPrintMe; 238 break; 239 } 240 default: 241 res = false; 242 LOGE("Jit: unknown work order type"); 243 assert(0); // Bail if debug build, discard otherwise 244 } 245 return res; 246 } 247 248 /* Architectural-specific debugging helpers go here */ 249 void dvmCompilerArchDump(void) 250 { 251 /* Print compiled opcode in this VM instance */ 252 int i, start, streak; 253 char buf[1024]; 254 255 streak = i = 0; 256 buf[0] = 0; 257 while (opcodeCoverage[i] == 0 && i < kNumPackedOpcodes) { 258 i++; 259 } 260 if (i == kNumPackedOpcodes) { 261 return; 262 } 263 for (start = i++, streak = 1; i < kNumPackedOpcodes; i++) { 264 if (opcodeCoverage[i]) { 265 streak++; 266 } else { 267 if (streak == 1) { 268 sprintf(buf+strlen(buf), "%x,", start); 269 } else { 270 sprintf(buf+strlen(buf), "%x-%x,", start, start + streak - 1); 271 } 272 streak = 0; 273 while (opcodeCoverage[i] == 0 && i < kNumPackedOpcodes) { 274 i++; 275 } 276 if (i < kNumPackedOpcodes) { 277 streak = 1; 278 start = i; 279 } 280 } 281 } 282 if (streak) { 283 if (streak == 1) { 284 sprintf(buf+strlen(buf), "%x", start); 285 } else { 286 sprintf(buf+strlen(buf), "%x-%x", start, start + streak - 1); 287 } 288 } 289 if (strlen(buf)) { 290 LOGD("dalvik.vm.jit.op = %s", buf); 291 } 292 } 293 294 /* Common initialization routine for an architecture family */ 295 bool dvmCompilerArchInit() 296 { 297 return dvmCompilerArchVariantInit(); 298 } 299 300 void *dvmCompilerGetInterpretTemplate() 301 { 302 return (void*) ((int)gDvmJit.codeCache + 303 templateEntryOffsets[TEMPLATE_INTERPRET]); 304 } 305 306 JitInstructionSetType dvmCompilerGetInterpretTemplateSet() 307 { 308 return DALVIK_JIT_X86; 309 } 310 311 void dvmCompilerInitializeRegAlloc(CompilationUnit *cUnit) 312 { 313 } 314