blob: 4f31563ea8a8ff4ec2d42cb2c198cec44a228ee1 [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
buzbee13fbc2e2010-12-14 11:06:25 -080038#if 0 // Avoid compiler warnings when x86 disabled during development
buzbee7520ee72010-09-17 16:01:49 -070039/*
buzbeedfd1bbf2010-09-22 16:19:28 -070040 * Bail to the interpreter. Will not return to this trace.
41 * On entry, rPC must be set correctly.
42 */
43static 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(InterpState, jitToInterpEntries.dvmJitToInterpPunt),
50 rEAX);
51 opReg(cUnit, kOpUncondBr, rEAX);
52}
53
54static 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(InterpState,
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}
buzbee13fbc2e2010-12-14 11:06:25 -080083#endif
buzbeedfd1bbf2010-09-22 16:19:28 -070084
85/*
buzbee7520ee72010-09-17 16:01:49 -070086 * 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
92static 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
99static bool handleFmt10x(CompilationUnit *cUnit, MIR *mir)
100{
101 return true;
102}
103
104static bool handleFmt11n_Fmt31i(CompilationUnit *cUnit, MIR *mir)
105{
106 return true;
107}
108
109static bool handleFmt21h(CompilationUnit *cUnit, MIR *mir)
110{
111 return true;
112}
113
114static bool handleFmt20bc(CompilationUnit *cUnit, MIR *mir)
115{
116 return true;
117}
118
119static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
120{
121 return true;
122}
123
124static bool handleFmt11x(CompilationUnit *cUnit, MIR *mir)
125{
126 return true;
127}
128
129static bool handleFmt12x(CompilationUnit *cUnit, MIR *mir)
130{
131 return true;
132}
133
134static bool handleFmt21s(CompilationUnit *cUnit, MIR *mir)
135{
136 return true;
137}
138
139static bool handleFmt21t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
140 X86LIR *labelList)
141{
142 return true;
143}
144
145static bool handleFmt22b_Fmt22s(CompilationUnit *cUnit, MIR *mir)
146{
147 return true;
148}
149
150static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir)
151{
152 return true;
153}
154
155static bool handleFmt22cs(CompilationUnit *cUnit, MIR *mir)
156{
157 return true;
158}
159
160static bool handleFmt22t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
161 X86LIR *labelList)
162{
163 return true;
164}
165
166static bool handleFmt22x_Fmt32x(CompilationUnit *cUnit, MIR *mir)
167{
168 return true;
169}
170
171static bool handleFmt23x(CompilationUnit *cUnit, MIR *mir)
172{
173 return true;
174}
175
176static bool handleFmt31t(CompilationUnit *cUnit, MIR *mir)
177{
178 return true;
179}
180
181static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
182 X86LIR *labelList)
183{
184 return true;
185}
186
187static 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 */
197static bool handleExecuteInline(CompilationUnit *cUnit, MIR *mir)
198{
199 return true;
200}
201
202static bool handleFmt51l(CompilationUnit *cUnit, MIR *mir)
203{
204 return true;
205}
206#endif
207
208
209void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
210{
211}
212
213/* Accept the work and start compiling */
214bool dvmCompilerDoWork(CompilerWorkOrder *work)
215{
buzbee13fbc2e2010-12-14 11:06:25 -0800216 JitTraceDescription *desc;
buzbee7520ee72010-09-17 16:01:49 -0700217 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 */
buzbee13fbc2e2010-12-14 11:06:25 -0800226 desc = (JitTraceDescription *)work->info;
227 res = dvmCompileTrace(desc, JIT_MAX_TRACE_LEN, &work->result,
buzbee7520ee72010-09-17 16:01:49 -0700228 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 */
buzbee13fbc2e2010-12-14 11:06:25 -0800234 desc = (JitTraceDescription *)work->info;
235 res = dvmCompileTrace(desc, JIT_MAX_TRACE_LEN, &work->result,
buzbee7520ee72010-09-17 16:01:49 -0700236 work->bailPtr, 0 /* no hints */);
237 gDvmJit.printMe = oldPrintMe;
238 break;
239 }
240 default:
241 res = false;
242 LOGE("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 */
249void 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;
Dan Bornsteinccaab182010-12-03 15:32:40 -0800257 while (opcodeCoverage[i] == 0 && i < kNumPackedOpcodes) {
buzbee7520ee72010-09-17 16:01:49 -0700258 i++;
259 }
Dan Bornsteinccaab182010-12-03 15:32:40 -0800260 if (i == kNumPackedOpcodes) {
buzbee7520ee72010-09-17 16:01:49 -0700261 return;
262 }
Dan Bornsteinccaab182010-12-03 15:32:40 -0800263 for (start = i++, streak = 1; i < kNumPackedOpcodes; i++) {
buzbee7520ee72010-09-17 16:01:49 -0700264 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;
Dan Bornsteinccaab182010-12-03 15:32:40 -0800273 while (opcodeCoverage[i] == 0 && i < kNumPackedOpcodes) {
buzbee7520ee72010-09-17 16:01:49 -0700274 i++;
275 }
Dan Bornsteinccaab182010-12-03 15:32:40 -0800276 if (i < kNumPackedOpcodes) {
buzbee7520ee72010-09-17 16:01:49 -0700277 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 LOGD("dalvik.vm.jit.op = %s", buf);
291 }
292}
293
294/* Common initialization routine for an architecture family */
295bool dvmCompilerArchInit()
296{
297 return dvmCompilerArchVariantInit();
298}
299
300void *dvmCompilerGetInterpretTemplate()
301{
302 return (void*) ((int)gDvmJit.codeCache +
303 templateEntryOffsets[TEMPLATE_INTERPRET]);
304}
305
306void dvmCompilerInitializeRegAlloc(CompilationUnit *cUnit)
307{
308}