Home | History | Annotate | Download | only in x86
      1 /*
      2  * Copyright (C) 2012 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 #include "Lower.h"
     19 #include "NcgAot.h"
     20 #include "NcgHelper.h"
     21 
     22 //returns # of ops generated by this function
     23 //entries relocatable: eip + relativePC
     24 int get_eip_API() {
     25     call("ncgGetEIP");//%edx //will push eip to stack
     26     return 1;
     27 }
     28 #define NEW_EXPORT_PC
     29 //!update current PC in the stack frame with %eip
     30 
     31 //!
     32 int export_pc() {
     33     /* for trace-based JIT, pc points to bytecode
     34        for NCG, pc points to native code */
     35     move_imm_to_mem(OpndSize_32, (int)rPC,
     36                     -sizeofStackSaveArea+offStackSaveArea_localRefTop, PhysicalReg_FP, true);
     37     return 1; //return number of ops
     38 }
     39 
     40 /* jump from JIT'ed code to interpreter without chaining */
     41 int jumpToInterpNoChain() {
     42     typedef void (*vmHelper)(int);
     43     vmHelper funcPtr = dvmJitToInterpNoChain;
     44     move_imm_to_reg(OpndSize_32, (int)funcPtr, C_SCRATCH_1, isScratchPhysical);
     45 
     46     unconditional_jump_reg(C_SCRATCH_1, isScratchPhysical);
     47     if(gDvm.executionMode == kExecutionModeNcgO1) touchEax();
     48     return 0;
     49 }
     50 
     51 /* jump from JIT'ed code to interpreter becaues of exception */
     52 int jumpToInterpPunt() {
     53     typedef void (*vmHelper)(int);
     54     vmHelper funcPtr = dvmJitToInterpPunt;
     55     move_imm_to_reg(OpndSize_32, (int)funcPtr, C_SCRATCH_1, isScratchPhysical);
     56 
     57     unconditional_jump_reg(C_SCRATCH_1, isScratchPhysical);
     58     //if(gDvm.executionMode == kExecutionModeNcgO1) touchEax();
     59     return 0;
     60 }
     61 
     62 /* jump to common_exceptionThrown from JIT'ed code */
     63 int jumpToExceptionThrown(int exceptionNum) {
     64     if(gDvm.executionMode == kExecutionModeNcgO1) {
     65         rememberState(exceptionNum);
     66         export_pc();
     67         constVREndOfBB();
     68         beforeCall("exception"); //dump GG, GL VRs
     69     }
     70 
     71     typedef void (*vmHelper)(int);
     72     vmHelper funcPtr = dvmJitToExceptionThrown;
     73     move_imm_to_reg(OpndSize_32, (int)funcPtr, C_SCRATCH_1, isScratchPhysical);
     74     unconditional_jump_reg(C_SCRATCH_1, isScratchPhysical);
     75 
     76     if(gDvm.executionMode == kExecutionModeNcgO1) {
     77         goToState(exceptionNum);
     78     }
     79     return 0;
     80 }
     81 
     82 //! generate native code to call dvmNcgInvokeInterpreter
     83 
     84 //!the interpreter will start execution from %eax
     85 int invokeInterpreter(bool fromApp)
     86 {
     87     typedef void (*vmHelper)(int);
     88     vmHelper funcPtr = dvmNcgInvokeInterpreter;
     89 
     90     move_imm_to_reg(OpndSize_32, (int)funcPtr, C_SCRATCH_1, isScratchPhysical);
     91 
     92     unconditional_jump_reg(C_SCRATCH_1, isScratchPhysical);
     93     if(gDvm.executionMode == kExecutionModeNcgO1) touchEax();
     94     return 0;
     95 }
     96 
     97 //!work to do before calling a function pointer with code cache enabled
     98 
     99 //!
    100 void callFuncPtr(int funcPtr, const char* funcName) {
    101 
    102     move_imm_to_reg(OpndSize_32, (int)funcPtr, C_SCRATCH_1, isScratchPhysical);
    103     call_reg(C_SCRATCH_1, isScratchPhysical);
    104 }
    105 //.const_string_resolve: input in %eax, output in %eax
    106 //.const_string_helper:
    107 //.class_resolve: input in %eax, output in %eax
    108 int call_helper_API(const char* helperName) {
    109     call(helperName);
    110     return 1;
    111 }
    112 
    113 /* check whether we are throwing an exception */
    114 bool jumpToException(const char* target) {
    115     bool isException = false;
    116     if(!strncmp(target, "common_err", 10)) isException = true;
    117     if(!strncmp(target, "common_throw", 12)) isException = true;
    118     if(!strncmp(target, "common_exception", 16)) isException = true;
    119     return isException;
    120 }
    121 
    122 int conditional_jump_global_API(
    123                                 ConditionCode cc, const char* target,
    124                                 bool isShortTerm) {
    125     if(jumpToException(target) && currentExceptionBlockIdx >= 0) { //jump to the exceptionThrow block
    126         condJumpToBasicBlock(stream, cc, currentExceptionBlockIdx);
    127         return 1; //return number of ops
    128     }
    129     conditional_jump(cc, target, isShortTerm);
    130     return 1;
    131 }
    132 int unconditional_jump_global_API(
    133                                   const char* target, bool isShortTerm) {
    134     if(jumpToException(target) && currentExceptionBlockIdx >= 0) { //jump to the exceptionThrow block
    135         jumpToBasicBlock(stream, currentExceptionBlockIdx);
    136         return 1; //return number of ops
    137     }
    138     unconditional_jump(target, isShortTerm);
    139     return 1;
    140 }
    141 int getGlobalDataAddr(const char* dataName) {
    142     int dataAddr = -1;
    143     if(!strcmp(dataName, "doubNeg")) dataAddr = LdoubNeg;
    144     else if(!strcmp(dataName, "intMax")) dataAddr = LintMax;
    145     else if(!strcmp(dataName, "intMin")) dataAddr = LintMin;
    146     else if(!strcmp(dataName, "valueNanLong")) dataAddr = LvalueNanLong;
    147     else if(!strcmp(dataName, "valuePosInfLong")) dataAddr = LvaluePosInfLong;
    148     else if(!strcmp(dataName, "valueNegInfLong")) dataAddr = LvalueNegInfLong;
    149     else if(!strcmp(dataName, "shiftMask")) dataAddr = LshiftMask;
    150     else if(!strcmp(dataName, "value64")) dataAddr = Lvalue64;
    151     else if(!strcmp(dataName, "64bits")) dataAddr = L64bits;
    152     else if(!strcmp(dataName, "strClassCastExceptionPtr")) dataAddr = LstrClassCastExceptionPtr;
    153     else if(!strcmp(dataName, "strInstantiationError")) dataAddr = LstrInstantiationErrorPtr;
    154     else if(!strcmp(dataName, "gDvmInlineOpsTable")) dataAddr = (int)gDvmInlineOpsTable;
    155     else ALOGE("global data %s not supported", dataName);
    156     return dataAddr;
    157 }
    158 
    159 //for shared code cache, we use scratchRegs[0] & [1]
    160 int load_imm_global_data_API(const char* dataName,
    161                          OpndSize size,
    162                          int reg, bool isPhysical) {
    163 
    164     //find the address from name
    165     int dataAddr = getGlobalDataAddr(dataName);
    166     move_imm_to_reg(size, dataAddr, reg, isPhysical);
    167     return 0;
    168 }
    169 //for shared code cache, we use scratchRegs[0] & [1] & [2]
    170 //FIXME: [2] is assumed to be hard-coded register
    171 int load_global_data_API(const char* dataName,
    172                          OpndSize size,
    173                          int reg, bool isPhysical) {
    174 
    175     //find the address from name
    176     int dataAddr = getGlobalDataAddr(dataName);
    177     move_mem_to_reg(size, dataAddr, PhysicalReg_Null, true, reg, isPhysical);
    178     return 0;
    179 }
    180 int load_sd_global_data_API(const char* dataName,
    181                             int reg, bool isPhysical) {
    182 
    183     //find the address from name
    184     int dataAddr = getGlobalDataAddr(dataName);
    185     move_sd_mem_to_reg(dataAddr, PhysicalReg_Null, true, reg, isPhysical);
    186     return 0;
    187 }
    188 
    189 int load_fp_stack_global_data_API(const char* dataName,
    190                                   OpndSize size) {
    191 
    192     int dataAddr = getGlobalDataAddr(dataName);
    193     load_int_fp_stack_imm(size, dataAddr); //fildl
    194     return 0;
    195 }
    196