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