• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
get_eip_API()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 //!
export_pc()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 */
jumpToInterpNoChain()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 */
jumpToInterpPunt()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 */
jumpToExceptionThrown(int exceptionNum)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
invokeInterpreter(bool fromApp)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 //!
callFuncPtr(int funcPtr,const char * funcName)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
call_helper_API(const char * helperName)108 int call_helper_API(const char* helperName) {
109     call(helperName);
110     return 1;
111 }
112 
113 /* check whether we are throwing an exception */
jumpToException(const char * target)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 
conditional_jump_global_API(ConditionCode cc,const char * target,bool isShortTerm)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 }
unconditional_jump_global_API(const char * target,bool isShortTerm)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 }
getGlobalDataAddr(const char * dataName)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]
load_imm_global_data_API(const char * dataName,OpndSize size,int reg,bool isPhysical)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
load_global_data_API(const char * dataName,OpndSize size,int reg,bool isPhysical)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 }
load_sd_global_data_API(const char * dataName,int reg,bool isPhysical)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 
load_fp_stack_global_data_API(const char * dataName,OpndSize size)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