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