blob: d94b1a7e1619b0f5956b24519139c3b86670f1a3 [file] [log] [blame]
Ben Chengba4fc8b2009-06-01 13:00:29 -07001/*
2 * Copyright (C) 2009 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#include "../../CompilerInternals.h"
Dan Bornsteindf4daaf2010-12-01 14:23:44 -080018#include "libdex/DexOpcodes.h"
Bill Buzbee89efc3d2009-07-28 11:22:22 -070019#include "ArmLIR.h"
Ben Chengba4fc8b2009-06-01 13:00:29 -070020
buzbee14f711b2010-08-05 11:01:12 -070021static char *shiftNames[4] = {
22 "lsl",
23 "lsr",
24 "asr",
25 "ror"};
26
Ben Chengba4fc8b2009-06-01 13:00:29 -070027/* Decode and print a ARM register name */
Ben Cheng18c990e2011-01-24 10:14:29 -080028static char * decodeRegList(ArmOpcode opcode, int vector, char *buf)
Ben Chengba4fc8b2009-06-01 13:00:29 -070029{
30 int i;
31 bool printed = false;
32 buf[0] = 0;
Ben Cheng18c990e2011-01-24 10:14:29 -080033 for (i = 0; i < 16; i++, vector >>= 1) {
Ben Chengba4fc8b2009-06-01 13:00:29 -070034 if (vector & 0x1) {
Ben Cheng18c990e2011-01-24 10:14:29 -080035 int regId = i;
36 if (opcode == kThumbPush && i == 8) {
Ben Cheng20d7e6c2011-02-18 17:12:42 -080037 regId = r14lr;
Ben Cheng18c990e2011-01-24 10:14:29 -080038 } else if (opcode == kThumbPop && i == 8) {
Ben Cheng20d7e6c2011-02-18 17:12:42 -080039 regId = r15pc;
Ben Cheng18c990e2011-01-24 10:14:29 -080040 }
Ben Chengba4fc8b2009-06-01 13:00:29 -070041 if (printed) {
Ben Cheng18c990e2011-01-24 10:14:29 -080042 sprintf(buf + strlen(buf), ", r%d", regId);
Ben Chengba4fc8b2009-06-01 13:00:29 -070043 } else {
44 printed = true;
Ben Cheng18c990e2011-01-24 10:14:29 -080045 sprintf(buf, "r%d", regId);
Ben Chengba4fc8b2009-06-01 13:00:29 -070046 }
47 }
48 }
49 return buf;
50}
51
Bill Buzbee7ea0f642009-08-10 17:06:51 -070052static int expandImmediate(int value)
53{
54 int mode = (value & 0xf00) >> 8;
55 u4 bits = value & 0xff;
56 switch(mode) {
57 case 0:
58 return bits;
59 case 1:
60 return (bits << 16) | bits;
61 case 2:
62 return (bits << 24) | (bits << 8);
63 case 3:
64 return (bits << 24) | (bits << 16) | (bits << 8) | bits;
65 default:
66 break;
67 }
68 bits = (bits | 0x80) << 24;
69 return bits >> (((value & 0xf80) >> 7) - 8);
70}
71
Ben Chengba4fc8b2009-06-01 13:00:29 -070072/*
73 * Interpret a format string and build a string no longer than size
74 * See format key in Assemble.c.
75 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -070076static void buildInsnString(char *fmt, ArmLIR *lir, char* buf,
Ben Chengba4fc8b2009-06-01 13:00:29 -070077 unsigned char *baseAddr, int size)
78{
79 int i;
80 char *bufEnd = &buf[size-1];
81 char *fmtEnd = &fmt[strlen(fmt)];
82 char tbuf[256];
buzbeeecf8f6e2010-07-20 14:53:42 -070083 char *name;
Ben Chengba4fc8b2009-06-01 13:00:29 -070084 char nc;
85 while (fmt < fmtEnd) {
86 int operand;
87 if (*fmt == '!') {
88 fmt++;
89 assert(fmt < fmtEnd);
90 nc = *fmt++;
91 if (nc=='!') {
92 strcpy(tbuf, "!");
93 } else {
94 assert(fmt < fmtEnd);
Bill Buzbee270c1d62009-08-13 16:58:07 -070095 assert((unsigned)(nc-'0') < 4);
Ben Chengba4fc8b2009-06-01 13:00:29 -070096 operand = lir->operands[nc-'0'];
97 switch(*fmt++) {
buzbee14f711b2010-08-05 11:01:12 -070098 case 'H':
99 if (operand != 0) {
100 sprintf(tbuf, ", %s %d",shiftNames[operand & 0x3],
101 operand >> 2);
102 } else {
103 strcpy(tbuf,"");
104 }
105 break;
buzbeeecf8f6e2010-07-20 14:53:42 -0700106 case 'B':
107 switch (operand) {
108 case kSY:
109 name = "sy";
110 break;
111 case kST:
112 name = "st";
113 break;
114 case kISH:
115 name = "ish";
116 break;
117 case kISHST:
118 name = "ishst";
119 break;
120 case kNSH:
121 name = "nsh";
122 break;
123 case kNSHST:
124 name = "shst";
125 break;
126 default:
127 name = "DecodeError";
128 break;
129 }
130 strcpy(tbuf, name);
131 break;
Bill Buzbeea4a7f072009-08-27 13:58:09 -0700132 case 'b':
133 strcpy(tbuf,"0000");
134 for (i=3; i>= 0; i--) {
135 tbuf[i] += operand & 1;
136 operand >>= 1;
137 }
138 break;
Bill Buzbee270c1d62009-08-13 16:58:07 -0700139 case 'n':
140 operand = ~expandImmediate(operand);
141 sprintf(tbuf,"%d [0x%x]", operand, operand);
142 break;
Bill Buzbee7ea0f642009-08-10 17:06:51 -0700143 case 'm':
144 operand = expandImmediate(operand);
145 sprintf(tbuf,"%d [0x%x]", operand, operand);
146 break;
Bill Buzbee9727c3d2009-08-01 11:32:36 -0700147 case 's':
148 sprintf(tbuf,"s%d",operand & FP_REG_MASK);
149 break;
150 case 'S':
151 sprintf(tbuf,"d%d",(operand & FP_REG_MASK) >> 1);
152 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700153 case 'h':
154 sprintf(tbuf,"%04x", operand);
155 break;
Bill Buzbee7ea0f642009-08-10 17:06:51 -0700156 case 'M':
Ben Chengba4fc8b2009-06-01 13:00:29 -0700157 case 'd':
158 sprintf(tbuf,"%d", operand);
159 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700160 case 'E':
161 sprintf(tbuf,"%d", operand*4);
162 break;
163 case 'F':
164 sprintf(tbuf,"%d", operand*2);
165 break;
166 case 'c':
167 switch (operand) {
Bill Buzbee1465db52009-09-23 17:17:35 -0700168 case kArmCondEq:
Bill Buzbeea4a7f072009-08-27 13:58:09 -0700169 strcpy(tbuf, "eq");
Ben Chengba4fc8b2009-06-01 13:00:29 -0700170 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700171 case kArmCondNe:
Bill Buzbeea4a7f072009-08-27 13:58:09 -0700172 strcpy(tbuf, "ne");
Ben Chengba4fc8b2009-06-01 13:00:29 -0700173 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700174 case kArmCondLt:
Bill Buzbeea4a7f072009-08-27 13:58:09 -0700175 strcpy(tbuf, "lt");
Ben Chengba4fc8b2009-06-01 13:00:29 -0700176 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700177 case kArmCondGe:
Bill Buzbeea4a7f072009-08-27 13:58:09 -0700178 strcpy(tbuf, "ge");
Ben Chengba4fc8b2009-06-01 13:00:29 -0700179 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700180 case kArmCondGt:
Bill Buzbeea4a7f072009-08-27 13:58:09 -0700181 strcpy(tbuf, "gt");
Ben Chengba4fc8b2009-06-01 13:00:29 -0700182 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700183 case kArmCondLe:
Bill Buzbeea4a7f072009-08-27 13:58:09 -0700184 strcpy(tbuf, "le");
Ben Chengba4fc8b2009-06-01 13:00:29 -0700185 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700186 case kArmCondCs:
Bill Buzbeea4a7f072009-08-27 13:58:09 -0700187 strcpy(tbuf, "cs");
Ben Chengba4fc8b2009-06-01 13:00:29 -0700188 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700189 case kArmCondMi:
Bill Buzbeea4a7f072009-08-27 13:58:09 -0700190 strcpy(tbuf, "mi");
Bill Buzbee7ea0f642009-08-10 17:06:51 -0700191 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700192 default:
193 strcpy(tbuf, "");
194 break;
195 }
196 break;
197 case 't':
Ben Chengcfdeca32011-01-14 11:36:46 -0800198 sprintf(tbuf,"0x%08x (L%p)",
Ben Chengba4fc8b2009-06-01 13:00:29 -0700199 (int) baseAddr + lir->generic.offset + 4 +
Ben Chengcfdeca32011-01-14 11:36:46 -0800200 (operand << 1),
201 lir->generic.target);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700202 break;
203 case 'u': {
204 int offset_1 = lir->operands[0];
205 int offset_2 = NEXT_LIR(lir)->operands[0];
206 intptr_t target =
207 ((((intptr_t) baseAddr + lir->generic.offset + 4) &
208 ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
209 0xfffffffc;
210 sprintf(tbuf, "%p", (void *) target);
211 break;
212 }
213
214 /* Nothing to print for BLX_2 */
215 case 'v':
216 strcpy(tbuf, "see above");
217 break;
218 case 'R':
Ben Cheng18c990e2011-01-24 10:14:29 -0800219 decodeRegList(lir->opcode, operand, tbuf);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700220 break;
221 default:
222 strcpy(tbuf,"DecodeError");
223 break;
224 }
225 if (buf+strlen(tbuf) <= bufEnd) {
226 strcpy(buf, tbuf);
227 buf += strlen(tbuf);
228 } else {
229 break;
230 }
231 }
232 } else {
233 *buf++ = *fmt++;
234 }
235 if (buf == bufEnd)
236 break;
237 }
238 *buf = 0;
239}
240
Ben Chengd7d426a2009-09-22 11:23:36 -0700241void dvmDumpResourceMask(LIR *lir, u8 mask, const char *prefix)
242{
243 char buf[256];
244 buf[0] = 0;
245 ArmLIR *armLIR = (ArmLIR *) lir;
246
247 if (mask == ENCODE_ALL) {
248 strcpy(buf, "all");
249 } else {
250 char num[8];
251 int i;
252
253 for (i = 0; i < kRegEnd; i++) {
254 if (mask & (1ULL << i)) {
255 sprintf(num, "%d ", i);
256 strcat(buf, num);
257 }
258 }
259
260 if (mask & ENCODE_CCODE) {
261 strcat(buf, "cc ");
262 }
263 if (mask & ENCODE_FP_STATUS) {
264 strcat(buf, "fpcc ");
265 }
Ben Cheng7ab74e12011-02-03 14:02:06 -0800266
267 /* Memory bits */
Ben Chengd7d426a2009-09-22 11:23:36 -0700268 if (armLIR && (mask & ENCODE_DALVIK_REG)) {
269 sprintf(buf + strlen(buf), "dr%d%s", armLIR->aliasInfo & 0xffff,
270 (armLIR->aliasInfo & 0x80000000) ? "(+1)" : "");
271 }
Ben Cheng7ab74e12011-02-03 14:02:06 -0800272 if (mask & ENCODE_LITERAL) {
273 strcat(buf, "lit ");
274 }
275
276 if (mask & ENCODE_HEAP_REF) {
277 strcat(buf, "heap ");
278 }
279 if (mask & ENCODE_MUST_NOT_ALIAS) {
280 strcat(buf, "noalias ");
281 }
Ben Chengd7d426a2009-09-22 11:23:36 -0700282 }
283 if (buf[0]) {
284 LOGD("%s: %s", prefix, buf);
285 }
286}
287
288/*
289 * Debugging macros
290 */
291#define DUMP_RESOURCE_MASK(X)
292#define DUMP_SSA_REP(X)
293
Ben Chengba4fc8b2009-06-01 13:00:29 -0700294/* Pretty-print a LIR instruction */
Ben Chengd7d426a2009-09-22 11:23:36 -0700295void dvmDumpLIRInsn(LIR *arg, unsigned char *baseAddr)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700296{
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700297 ArmLIR *lir = (ArmLIR *) arg;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700298 char buf[256];
299 char opName[256];
300 int offset = lir->generic.offset;
301 int dest = lir->operands[0];
Ben Chengd7d426a2009-09-22 11:23:36 -0700302 const bool dumpNop = false;
303
Ben Chengba4fc8b2009-06-01 13:00:29 -0700304 /* Handle pseudo-ops individually, and all regular insns as a group */
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800305 switch(lir->opcode) {
Ben Chengcec26f62010-01-15 15:29:33 -0800306 case kArmChainingCellBottom:
307 LOGD("-------- end of chaining cells (0x%04x)\n", offset);
308 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700309 case kArmPseudoBarrier:
Ben Chengd7d426a2009-09-22 11:23:36 -0700310 LOGD("-------- BARRIER");
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700311 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700312 case kArmPseudoExtended:
Ben Cheng7a2697d2010-06-07 13:44:23 -0700313 LOGD("-------- %s\n", (char *) dest);
314 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700315 case kArmPseudoSSARep:
Ben Chengd7d426a2009-09-22 11:23:36 -0700316 DUMP_SSA_REP(LOGD("-------- %s\n", (char *) dest));
Ben Cheng4238ec22009-08-24 16:32:22 -0700317 break;
Ben Chenga4973592010-03-31 11:59:18 -0700318 case kArmPseudoChainingCellBackwardBranch:
Ben Cheng4238ec22009-08-24 16:32:22 -0700319 LOGD("-------- chaining cell (backward branch): 0x%04x\n", dest);
320 break;
Ben Chenga4973592010-03-31 11:59:18 -0700321 case kArmPseudoChainingCellNormal:
Ben Cheng1efc9c52009-06-08 18:25:27 -0700322 LOGD("-------- chaining cell (normal): 0x%04x\n", dest);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700323 break;
Ben Chenga4973592010-03-31 11:59:18 -0700324 case kArmPseudoChainingCellHot:
Ben Cheng1efc9c52009-06-08 18:25:27 -0700325 LOGD("-------- chaining cell (hot): 0x%04x\n", dest);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700326 break;
Ben Chenga4973592010-03-31 11:59:18 -0700327 case kArmPseudoChainingCellInvokePredicted:
Ben Cheng38329f52009-07-07 14:19:20 -0700328 LOGD("-------- chaining cell (predicted)\n");
329 break;
Ben Chenga4973592010-03-31 11:59:18 -0700330 case kArmPseudoChainingCellInvokeSingleton:
Ben Cheng38329f52009-07-07 14:19:20 -0700331 LOGD("-------- chaining cell (invoke singleton): %s/%p\n",
Ben Chengba4fc8b2009-06-01 13:00:29 -0700332 ((Method *)dest)->name,
333 ((Method *)dest)->insns);
334 break;
Ben Chenga4973592010-03-31 11:59:18 -0700335 case kArmPseudoEntryBlock:
Ben Cheng4238ec22009-08-24 16:32:22 -0700336 LOGD("-------- entry offset: 0x%04x\n", dest);
Jeff Hao97319a82009-08-12 16:57:15 -0700337 break;
Ben Chenga4973592010-03-31 11:59:18 -0700338 case kArmPseudoDalvikByteCodeBoundary:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700339 LOGD("-------- dalvik offset: 0x%04x @ %s\n", dest,
Ben Chengccd6c012009-10-15 14:52:45 -0700340 (char *) lir->operands[1]);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700341 break;
Ben Chenga4973592010-03-31 11:59:18 -0700342 case kArmPseudoExitBlock:
Ben Cheng4238ec22009-08-24 16:32:22 -0700343 LOGD("-------- exit offset: 0x%04x\n", dest);
344 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700345 case kArmPseudoPseudoAlign4:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700346 LOGD("%p (%04x): .align4\n", baseAddr + offset, offset);
347 break;
Ben Chenga4973592010-03-31 11:59:18 -0700348 case kArmPseudoPCReconstructionCell:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700349 LOGD("-------- reconstruct dalvik PC : 0x%04x @ +0x%04x\n", dest,
350 lir->operands[1]);
351 break;
Ben Chenga4973592010-03-31 11:59:18 -0700352 case kArmPseudoPCReconstructionBlockLabel:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700353 /* Do nothing */
354 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700355 case kArmPseudoEHBlockLabel:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700356 LOGD("Exception_Handling:\n");
357 break;
Ben Chengcfdeca32011-01-14 11:36:46 -0800358 case kArmPseudoTargetLabel:
Bill Buzbee1465db52009-09-23 17:17:35 -0700359 case kArmPseudoNormalBlockLabel:
Ben Chengcfdeca32011-01-14 11:36:46 -0800360 LOGD("L%p:\n", lir);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700361 break;
362 default:
Ben Chengd72564c2011-02-08 17:09:25 -0800363 if (lir->flags.isNop && !dumpNop) {
Ben Chenge9695e52009-06-16 16:11:47 -0700364 break;
365 }
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800366 buildInsnString(EncodingMap[lir->opcode].name, lir, opName,
Ben Chengba4fc8b2009-06-01 13:00:29 -0700367 baseAddr, 256);
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800368 buildInsnString(EncodingMap[lir->opcode].fmt, lir, buf, baseAddr,
Ben Chengba4fc8b2009-06-01 13:00:29 -0700369 256);
Ben Chengd7d426a2009-09-22 11:23:36 -0700370 LOGD("%p (%04x): %-8s%s%s\n",
371 baseAddr + offset, offset, opName, buf,
Ben Chengd72564c2011-02-08 17:09:25 -0800372 lir->flags.isNop ? "(nop)" : "");
Ben Chengba4fc8b2009-06-01 13:00:29 -0700373 break;
374 }
Ben Chengd7d426a2009-09-22 11:23:36 -0700375
Ben Chengd72564c2011-02-08 17:09:25 -0800376 if (lir->useMask && (!lir->flags.isNop || dumpNop)) {
Ben Chengd7d426a2009-09-22 11:23:36 -0700377 DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir,
378 lir->useMask, "use"));
379 }
Ben Chengd72564c2011-02-08 17:09:25 -0800380 if (lir->defMask && (!lir->flags.isNop || dumpNop)) {
Ben Chengd7d426a2009-09-22 11:23:36 -0700381 DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir,
382 lir->defMask, "def"));
383 }
Ben Chengba4fc8b2009-06-01 13:00:29 -0700384}
385
386/* Dump instructions and constant pool contents */
387void dvmCompilerCodegenDump(CompilationUnit *cUnit)
388{
389 LOGD("Dumping LIR insns\n");
390 LIR *lirInsn;
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700391 ArmLIR *armLIR;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700392
393 LOGD("installed code is at %p\n", cUnit->baseAddr);
394 LOGD("total size is %d bytes\n", cUnit->totalSize);
395 for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800396 dvmDumpLIRInsn(lirInsn, (unsigned char *) cUnit->baseAddr);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700397 }
Ben Cheng385828e2011-03-04 16:48:33 -0800398 for (lirInsn = cUnit->classPointerList; lirInsn; lirInsn = lirInsn->next) {
399 armLIR = (ArmLIR *) lirInsn;
400 LOGD("%p (%04x): .class (%s)\n",
401 (char*)cUnit->baseAddr + armLIR->generic.offset,
402 armLIR->generic.offset,
403 ((CallsiteInfo *) armLIR->operands[0])->classDescriptor);
404 }
405 for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700406 armLIR = (ArmLIR *) lirInsn;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700407 LOGD("%p (%04x): .word (0x%x)\n",
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700408 (char*)cUnit->baseAddr + armLIR->generic.offset,
409 armLIR->generic.offset,
Ben Chengba4fc8b2009-06-01 13:00:29 -0700410 armLIR->operands[0]);
411 }
412}
buzbee13fbc2e2010-12-14 11:06:25 -0800413
414/* Target-specific cache flushing */
415int dvmCompilerCacheFlush(long start, long end, long flags)
416{
417 return cacheflush(start, end, flags);
418}