Home | History | Annotate | Download | only in x86
      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