/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "Lower.h" #include "NcgAot.h" #include "NcgHelper.h" //returns # of ops generated by this function //entries relocatable: eip + relativePC int get_eip_API() { call("ncgGetEIP");//%edx //will push eip to stack return 1; } #define NEW_EXPORT_PC //!update current PC in the stack frame with %eip //! int export_pc() { /* for trace-based JIT, pc points to bytecode for NCG, pc points to native code */ move_imm_to_mem(OpndSize_32, (int)rPC, -sizeofStackSaveArea+offStackSaveArea_localRefTop, PhysicalReg_FP, true); return 1; //return number of ops } /* jump from JIT'ed code to interpreter without chaining */ int jumpToInterpNoChain() { typedef void (*vmHelper)(int); vmHelper funcPtr = dvmJitToInterpNoChain; move_imm_to_reg(OpndSize_32, (int)funcPtr, C_SCRATCH_1, isScratchPhysical); unconditional_jump_reg(C_SCRATCH_1, isScratchPhysical); if(gDvm.executionMode == kExecutionModeNcgO1) touchEax(); return 0; } /* jump from JIT'ed code to interpreter becaues of exception */ int jumpToInterpPunt() { typedef void (*vmHelper)(int); vmHelper funcPtr = dvmJitToInterpPunt; move_imm_to_reg(OpndSize_32, (int)funcPtr, C_SCRATCH_1, isScratchPhysical); unconditional_jump_reg(C_SCRATCH_1, isScratchPhysical); //if(gDvm.executionMode == kExecutionModeNcgO1) touchEax(); return 0; } /* jump to common_exceptionThrown from JIT'ed code */ int jumpToExceptionThrown(int exceptionNum) { if(gDvm.executionMode == kExecutionModeNcgO1) { rememberState(exceptionNum); export_pc(); constVREndOfBB(); beforeCall("exception"); //dump GG, GL VRs } typedef void (*vmHelper)(int); vmHelper funcPtr = dvmJitToExceptionThrown; move_imm_to_reg(OpndSize_32, (int)funcPtr, C_SCRATCH_1, isScratchPhysical); unconditional_jump_reg(C_SCRATCH_1, isScratchPhysical); if(gDvm.executionMode == kExecutionModeNcgO1) { goToState(exceptionNum); } return 0; } //! generate native code to call dvmNcgInvokeInterpreter //!the interpreter will start execution from %eax int invokeInterpreter(bool fromApp) { typedef void (*vmHelper)(int); vmHelper funcPtr = dvmNcgInvokeInterpreter; move_imm_to_reg(OpndSize_32, (int)funcPtr, C_SCRATCH_1, isScratchPhysical); unconditional_jump_reg(C_SCRATCH_1, isScratchPhysical); if(gDvm.executionMode == kExecutionModeNcgO1) touchEax(); return 0; } //!work to do before calling a function pointer with code cache enabled //! void callFuncPtr(int funcPtr, const char* funcName) { move_imm_to_reg(OpndSize_32, (int)funcPtr, C_SCRATCH_1, isScratchPhysical); call_reg(C_SCRATCH_1, isScratchPhysical); } //.const_string_resolve: input in %eax, output in %eax //.const_string_helper: //.class_resolve: input in %eax, output in %eax int call_helper_API(const char* helperName) { call(helperName); return 1; } /* check whether we are throwing an exception */ bool jumpToException(const char* target) { bool isException = false; if(!strncmp(target, "common_err", 10)) isException = true; if(!strncmp(target, "common_throw", 12)) isException = true; if(!strncmp(target, "common_exception", 16)) isException = true; return isException; } int conditional_jump_global_API( ConditionCode cc, const char* target, bool isShortTerm) { if(jumpToException(target) && currentExceptionBlockIdx >= 0) { //jump to the exceptionThrow block condJumpToBasicBlock(stream, cc, currentExceptionBlockIdx); return 1; //return number of ops } conditional_jump(cc, target, isShortTerm); return 1; } int unconditional_jump_global_API( const char* target, bool isShortTerm) { if(jumpToException(target) && currentExceptionBlockIdx >= 0) { //jump to the exceptionThrow block jumpToBasicBlock(stream, currentExceptionBlockIdx); return 1; //return number of ops } unconditional_jump(target, isShortTerm); return 1; } int getGlobalDataAddr(const char* dataName) { int dataAddr = -1; if(!strcmp(dataName, "doubNeg")) dataAddr = LdoubNeg; else if(!strcmp(dataName, "intMax")) dataAddr = LintMax; else if(!strcmp(dataName, "intMin")) dataAddr = LintMin; else if(!strcmp(dataName, "valueNanLong")) dataAddr = LvalueNanLong; else if(!strcmp(dataName, "valuePosInfLong")) dataAddr = LvaluePosInfLong; else if(!strcmp(dataName, "valueNegInfLong")) dataAddr = LvalueNegInfLong; else if(!strcmp(dataName, "shiftMask")) dataAddr = LshiftMask; else if(!strcmp(dataName, "value64")) dataAddr = Lvalue64; else if(!strcmp(dataName, "64bits")) dataAddr = L64bits; else if(!strcmp(dataName, "strClassCastExceptionPtr")) dataAddr = LstrClassCastExceptionPtr; else if(!strcmp(dataName, "strInstantiationError")) dataAddr = LstrInstantiationErrorPtr; else if(!strcmp(dataName, "gDvmInlineOpsTable")) dataAddr = (int)gDvmInlineOpsTable; else ALOGE("global data %s not supported", dataName); return dataAddr; } //for shared code cache, we use scratchRegs[0] & [1] int load_imm_global_data_API(const char* dataName, OpndSize size, int reg, bool isPhysical) { //find the address from name int dataAddr = getGlobalDataAddr(dataName); move_imm_to_reg(size, dataAddr, reg, isPhysical); return 0; } //for shared code cache, we use scratchRegs[0] & [1] & [2] //FIXME: [2] is assumed to be hard-coded register int load_global_data_API(const char* dataName, OpndSize size, int reg, bool isPhysical) { //find the address from name int dataAddr = getGlobalDataAddr(dataName); move_mem_to_reg(size, dataAddr, PhysicalReg_Null, true, reg, isPhysical); return 0; } int load_sd_global_data_API(const char* dataName, int reg, bool isPhysical) { //find the address from name int dataAddr = getGlobalDataAddr(dataName); move_sd_mem_to_reg(dataAddr, PhysicalReg_Null, true, reg, isPhysical); return 0; } int load_fp_stack_global_data_API(const char* dataName, OpndSize size) { int dataAddr = getGlobalDataAddr(dataName); load_int_fp_stack_imm(size, dataAddr); //fildl return 0; }