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