1 /*
2 * Copyright (C) 2010 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 * This file contains codegen and support common to all supported
19 * X86 variants. It is included by:
20 *
21 * Codegen-$(TARGET_ARCH_VARIANT).c
22 *
23 * which combines this common code with specific support found in the
24 * applicable directory below this one.
25 */
26
27 extern X86LIR *loadConstant(CompilationUnit *cUnit, int rDest, int value);
28 extern X86LIR *loadWordDisp(CompilationUnit *cUnit, int rBase,
29 int displacement, int rDest);
30 extern void dvmCompilerFlushAllRegs(CompilationUnit *cUnit);
31 extern void storeWordDisp(CompilationUnit *cUnit, int rBase,
32 int displacement, int rSrc);
33 extern X86LIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc);
34
35 static int opcodeCoverage[kNumPackedOpcodes];
36 static intptr_t templateEntryOffsets[TEMPLATE_LAST_MARK];
37
38 #if 0 // Avoid compiler warnings when x86 disabled during development
39 /*
40 * Bail to the interpreter. Will not return to this trace.
41 * On entry, rPC must be set correctly.
42 */
43 static void genPuntToInterp(CompilationUnit *cUnit, unsigned int offset)
44 {
45 dvmCompilerFlushAllRegs(cUnit);
46 loadConstant(cUnit, rPC, (int)(cUnit->method->insns + offset));
47 loadWordDisp(cUnit, rEBP, 0, rECX); // Get glue
48 loadWordDisp(cUnit, rECX,
49 offsetof(Thread, jitToInterpEntries.dvmJitToInterpPunt),
50 rEAX);
51 opReg(cUnit, kOpUncondBr, rEAX);
52 }
53
54 static void genInterpSingleStep(CompilationUnit *cUnit, MIR *mir)
55 {
56 int flags = dexGetFlagsFromOpcode(mir->dalvikInsn.opcode);
57 int flagsToCheck = kInstrCanBranch | kInstrCanSwitch | kInstrCanReturn |
58 kInstrCanThrow;
59
60 //If already optimized out, just ignore
61 if (mir->dalvikInsn.opcode == OP_NOP)
62 return;
63
64 //Ugly, but necessary. Flush all Dalvik regs so Interp can find them
65 dvmCompilerFlushAllRegs(cUnit);
66
67 if ((mir->next == NULL) || (flags & flagsToCheck)) {
68 genPuntToInterp(cUnit, mir->offset);
69 return;
70 }
71 int entryAddr = offsetof(Thread,
72 jitToInterpEntries.dvmJitToInterpSingleStep);
73 loadWordDisp(cUnit, rEBP, 0, rECX); // Get glue
74 loadWordDisp(cUnit, rECX, entryAddr, rEAX); // rEAX<- entry address
75 /* rPC = dalvik pc */
76 loadConstant(cUnit, rPC, (int) (cUnit->method->insns + mir->offset));
77 /* rECX = dalvik pc of following instruction */
78 loadConstant(cUnit, rECX, (int) (cUnit->method->insns + mir->next->offset));
79 /* Pass on the stack */
80 storeWordDisp(cUnit, rESP, OUT_ARG0, rECX);
81 opReg(cUnit, kOpCall, rEAX);
82 }
83 #endif
84
85 /*
86 * The following are the first-level codegen routines that analyze the format
87 * of each bytecode then either dispatch special purpose codegen routines
88 * or produce corresponding Thumb instructions directly.
89 */
90
91 #if 0
92 static bool handleFmt10t_Fmt20t_Fmt30t(CompilationUnit *cUnit, MIR *mir,
93 BasicBlock *bb, X86LIR *labelList)
94 {
95 /* For OP_GOTO, OP_GOTO_16, and OP_GOTO_32 */
96 return true;
97 }
98
99 static bool handleFmt10x(CompilationUnit *cUnit, MIR *mir)
100 {
101 return true;
102 }
103
104 static bool handleFmt11n_Fmt31i(CompilationUnit *cUnit, MIR *mir)
105 {
106 return true;
107 }
108
109 static bool handleFmt21h(CompilationUnit *cUnit, MIR *mir)
110 {
111 return true;
112 }
113
114 static bool handleFmt20bc(CompilationUnit *cUnit, MIR *mir)
115 {
116 return true;
117 }
118
119 static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
120 {
121 return true;
122 }
123
124 static bool handleFmt11x(CompilationUnit *cUnit, MIR *mir)
125 {
126 return true;
127 }
128
129 static bool handleFmt12x(CompilationUnit *cUnit, MIR *mir)
130 {
131 return true;
132 }
133
134 static bool handleFmt21s(CompilationUnit *cUnit, MIR *mir)
135 {
136 return true;
137 }
138
139 static bool handleFmt21t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
140 X86LIR *labelList)
141 {
142 return true;
143 }
144
145 static bool handleFmt22b_Fmt22s(CompilationUnit *cUnit, MIR *mir)
146 {
147 return true;
148 }
149
150 static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir)
151 {
152 return true;
153 }
154
155 static bool handleFmt22cs(CompilationUnit *cUnit, MIR *mir)
156 {
157 return true;
158 }
159
160 static bool handleFmt22t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
161 X86LIR *labelList)
162 {
163 return true;
164 }
165
166 static bool handleFmt22x_Fmt32x(CompilationUnit *cUnit, MIR *mir)
167 {
168 return true;
169 }
170
171 static bool handleFmt23x(CompilationUnit *cUnit, MIR *mir)
172 {
173 return true;
174 }
175
176 static bool handleFmt31t(CompilationUnit *cUnit, MIR *mir)
177 {
178 return true;
179 }
180
181 static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
182 X86LIR *labelList)
183 {
184 return true;
185 }
186
187 static bool handleFmt35ms_3rms(CompilationUnit *cUnit, MIR *mir,
188 BasicBlock *bb, X86LIR *labelList)
189 {
190 return true;
191 }
192
193 /*
194 * NOTE: Handles both range and non-range versions (arguments
195 * have already been normalized by this point).
196 */
197 static bool handleExecuteInline(CompilationUnit *cUnit, MIR *mir)
198 {
199 return true;
200 }
201
202 static bool handleFmt51l(CompilationUnit *cUnit, MIR *mir)
203 {
204 return true;
205 }
206 #endif
207
208
dvmCompilerMIR2LIR(CompilationUnit * cUnit)209 void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
210 {
211 }
212
213 /* Accept the work and start compiling */
dvmCompilerDoWork(CompilerWorkOrder * work)214 bool dvmCompilerDoWork(CompilerWorkOrder *work)
215 {
216 JitTraceDescription *desc;
217 bool res;
218
219 if (gDvmJit.codeCacheFull) {
220 return false;
221 }
222
223 switch (work->kind) {
224 case kWorkOrderTrace:
225 /* Start compilation with maximally allowed trace length */
226 desc = (JitTraceDescription *)work->info;
227 res = dvmCompileTrace(desc, JIT_MAX_TRACE_LEN, &work->result,
228 work->bailPtr, 0 /* no hints */);
229 break;
230 case kWorkOrderTraceDebug: {
231 bool oldPrintMe = gDvmJit.printMe;
232 gDvmJit.printMe = true;
233 /* Start compilation with maximally allowed trace length */
234 desc = (JitTraceDescription *)work->info;
235 res = dvmCompileTrace(desc, JIT_MAX_TRACE_LEN, &work->result,
236 work->bailPtr, 0 /* no hints */);
237 gDvmJit.printMe = oldPrintMe;
238 break;
239 }
240 default:
241 res = false;
242 ALOGE("Jit: unknown work order type");
243 assert(0); // Bail if debug build, discard otherwise
244 }
245 return res;
246 }
247
248 /* Architectural-specific debugging helpers go here */
dvmCompilerArchDump(void)249 void dvmCompilerArchDump(void)
250 {
251 /* Print compiled opcode in this VM instance */
252 int i, start, streak;
253 char buf[1024];
254
255 streak = i = 0;
256 buf[0] = 0;
257 while (opcodeCoverage[i] == 0 && i < kNumPackedOpcodes) {
258 i++;
259 }
260 if (i == kNumPackedOpcodes) {
261 return;
262 }
263 for (start = i++, streak = 1; i < kNumPackedOpcodes; i++) {
264 if (opcodeCoverage[i]) {
265 streak++;
266 } else {
267 if (streak == 1) {
268 sprintf(buf+strlen(buf), "%x,", start);
269 } else {
270 sprintf(buf+strlen(buf), "%x-%x,", start, start + streak - 1);
271 }
272 streak = 0;
273 while (opcodeCoverage[i] == 0 && i < kNumPackedOpcodes) {
274 i++;
275 }
276 if (i < kNumPackedOpcodes) {
277 streak = 1;
278 start = i;
279 }
280 }
281 }
282 if (streak) {
283 if (streak == 1) {
284 sprintf(buf+strlen(buf), "%x", start);
285 } else {
286 sprintf(buf+strlen(buf), "%x-%x", start, start + streak - 1);
287 }
288 }
289 if (strlen(buf)) {
290 ALOGD("dalvik.vm.jit.op = %s", buf);
291 }
292 }
293
294 /* Common initialization routine for an architecture family */
dvmCompilerArchInit()295 bool dvmCompilerArchInit()
296 {
297 return dvmCompilerArchVariantInit();
298 }
299
dvmCompilerGetInterpretTemplate()300 void *dvmCompilerGetInterpretTemplate()
301 {
302 return (void*) ((int)gDvmJit.codeCache +
303 templateEntryOffsets[TEMPLATE_INTERPRET]);
304 }
305
dvmCompilerGetInterpretTemplateSet()306 JitInstructionSetType dvmCompilerGetInterpretTemplateSet()
307 {
308 return DALVIK_JIT_X86;
309 }
310
dvmCompilerInitializeRegAlloc(CompilationUnit * cUnit)311 void dvmCompilerInitializeRegAlloc(CompilationUnit *cUnit)
312 {
313 }
314