blob: 8682c1a39b890fd4b9bf4c703455b2535f9f0bda [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 */
28static char * decodeRegList(int vector, char *buf)
29{
30 int i;
31 bool printed = false;
32 buf[0] = 0;
33 for (i = 0; i < 8; i++, vector >>= 1) {
34 if (vector & 0x1) {
35 if (printed) {
36 sprintf(buf + strlen(buf), ", r%d", i);
37 } else {
38 printed = true;
39 sprintf(buf, "r%d", i);
40 }
41 }
42 }
43 return buf;
44}
45
Bill Buzbee7ea0f642009-08-10 17:06:51 -070046static int expandImmediate(int value)
47{
48 int mode = (value & 0xf00) >> 8;
49 u4 bits = value & 0xff;
50 switch(mode) {
51 case 0:
52 return bits;
53 case 1:
54 return (bits << 16) | bits;
55 case 2:
56 return (bits << 24) | (bits << 8);
57 case 3:
58 return (bits << 24) | (bits << 16) | (bits << 8) | bits;
59 default:
60 break;
61 }
62 bits = (bits | 0x80) << 24;
63 return bits >> (((value & 0xf80) >> 7) - 8);
64}
65
Ben Chengba4fc8b2009-06-01 13:00:29 -070066/*
67 * Interpret a format string and build a string no longer than size
68 * See format key in Assemble.c.
69 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -070070static void buildInsnString(char *fmt, ArmLIR *lir, char* buf,
Ben Chengba4fc8b2009-06-01 13:00:29 -070071 unsigned char *baseAddr, int size)
72{
73 int i;
74 char *bufEnd = &buf[size-1];
75 char *fmtEnd = &fmt[strlen(fmt)];
76 char tbuf[256];
buzbeeecf8f6e2010-07-20 14:53:42 -070077 char *name;
Ben Chengba4fc8b2009-06-01 13:00:29 -070078 char nc;
79 while (fmt < fmtEnd) {
80 int operand;
81 if (*fmt == '!') {
82 fmt++;
83 assert(fmt < fmtEnd);
84 nc = *fmt++;
85 if (nc=='!') {
86 strcpy(tbuf, "!");
87 } else {
88 assert(fmt < fmtEnd);
Bill Buzbee270c1d62009-08-13 16:58:07 -070089 assert((unsigned)(nc-'0') < 4);
Ben Chengba4fc8b2009-06-01 13:00:29 -070090 operand = lir->operands[nc-'0'];
91 switch(*fmt++) {
buzbee14f711b2010-08-05 11:01:12 -070092 case 'H':
93 if (operand != 0) {
94 sprintf(tbuf, ", %s %d",shiftNames[operand & 0x3],
95 operand >> 2);
96 } else {
97 strcpy(tbuf,"");
98 }
99 break;
buzbeeecf8f6e2010-07-20 14:53:42 -0700100 case 'B':
101 switch (operand) {
102 case kSY:
103 name = "sy";
104 break;
105 case kST:
106 name = "st";
107 break;
108 case kISH:
109 name = "ish";
110 break;
111 case kISHST:
112 name = "ishst";
113 break;
114 case kNSH:
115 name = "nsh";
116 break;
117 case kNSHST:
118 name = "shst";
119 break;
120 default:
121 name = "DecodeError";
122 break;
123 }
124 strcpy(tbuf, name);
125 break;
Bill Buzbeea4a7f072009-08-27 13:58:09 -0700126 case 'b':
127 strcpy(tbuf,"0000");
128 for (i=3; i>= 0; i--) {
129 tbuf[i] += operand & 1;
130 operand >>= 1;
131 }
132 break;
Bill Buzbee270c1d62009-08-13 16:58:07 -0700133 case 'n':
134 operand = ~expandImmediate(operand);
135 sprintf(tbuf,"%d [0x%x]", operand, operand);
136 break;
Bill Buzbee7ea0f642009-08-10 17:06:51 -0700137 case 'm':
138 operand = expandImmediate(operand);
139 sprintf(tbuf,"%d [0x%x]", operand, operand);
140 break;
Bill Buzbee9727c3d2009-08-01 11:32:36 -0700141 case 's':
142 sprintf(tbuf,"s%d",operand & FP_REG_MASK);
143 break;
144 case 'S':
145 sprintf(tbuf,"d%d",(operand & FP_REG_MASK) >> 1);
146 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700147 case 'h':
148 sprintf(tbuf,"%04x", operand);
149 break;
Bill Buzbee7ea0f642009-08-10 17:06:51 -0700150 case 'M':
Ben Chengba4fc8b2009-06-01 13:00:29 -0700151 case 'd':
152 sprintf(tbuf,"%d", operand);
153 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700154 case 'E':
155 sprintf(tbuf,"%d", operand*4);
156 break;
157 case 'F':
158 sprintf(tbuf,"%d", operand*2);
159 break;
160 case 'c':
161 switch (operand) {
Bill Buzbee1465db52009-09-23 17:17:35 -0700162 case kArmCondEq:
Bill Buzbeea4a7f072009-08-27 13:58:09 -0700163 strcpy(tbuf, "eq");
Ben Chengba4fc8b2009-06-01 13:00:29 -0700164 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700165 case kArmCondNe:
Bill Buzbeea4a7f072009-08-27 13:58:09 -0700166 strcpy(tbuf, "ne");
Ben Chengba4fc8b2009-06-01 13:00:29 -0700167 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700168 case kArmCondLt:
Bill Buzbeea4a7f072009-08-27 13:58:09 -0700169 strcpy(tbuf, "lt");
Ben Chengba4fc8b2009-06-01 13:00:29 -0700170 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700171 case kArmCondGe:
Bill Buzbeea4a7f072009-08-27 13:58:09 -0700172 strcpy(tbuf, "ge");
Ben Chengba4fc8b2009-06-01 13:00:29 -0700173 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700174 case kArmCondGt:
Bill Buzbeea4a7f072009-08-27 13:58:09 -0700175 strcpy(tbuf, "gt");
Ben Chengba4fc8b2009-06-01 13:00:29 -0700176 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700177 case kArmCondLe:
Bill Buzbeea4a7f072009-08-27 13:58:09 -0700178 strcpy(tbuf, "le");
Ben Chengba4fc8b2009-06-01 13:00:29 -0700179 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700180 case kArmCondCs:
Bill Buzbeea4a7f072009-08-27 13:58:09 -0700181 strcpy(tbuf, "cs");
Ben Chengba4fc8b2009-06-01 13:00:29 -0700182 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700183 case kArmCondMi:
Bill Buzbeea4a7f072009-08-27 13:58:09 -0700184 strcpy(tbuf, "mi");
Bill Buzbee7ea0f642009-08-10 17:06:51 -0700185 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700186 default:
187 strcpy(tbuf, "");
188 break;
189 }
190 break;
191 case 't':
192 sprintf(tbuf,"0x%08x",
193 (int) baseAddr + lir->generic.offset + 4 +
194 (operand << 1));
195 break;
196 case 'u': {
197 int offset_1 = lir->operands[0];
198 int offset_2 = NEXT_LIR(lir)->operands[0];
199 intptr_t target =
200 ((((intptr_t) baseAddr + lir->generic.offset + 4) &
201 ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
202 0xfffffffc;
203 sprintf(tbuf, "%p", (void *) target);
204 break;
205 }
206
207 /* Nothing to print for BLX_2 */
208 case 'v':
209 strcpy(tbuf, "see above");
210 break;
211 case 'R':
212 decodeRegList(operand, tbuf);
213 break;
214 default:
215 strcpy(tbuf,"DecodeError");
216 break;
217 }
218 if (buf+strlen(tbuf) <= bufEnd) {
219 strcpy(buf, tbuf);
220 buf += strlen(tbuf);
221 } else {
222 break;
223 }
224 }
225 } else {
226 *buf++ = *fmt++;
227 }
228 if (buf == bufEnd)
229 break;
230 }
231 *buf = 0;
232}
233
Ben Chengd7d426a2009-09-22 11:23:36 -0700234void dvmDumpResourceMask(LIR *lir, u8 mask, const char *prefix)
235{
236 char buf[256];
237 buf[0] = 0;
238 ArmLIR *armLIR = (ArmLIR *) lir;
239
240 if (mask == ENCODE_ALL) {
241 strcpy(buf, "all");
242 } else {
243 char num[8];
244 int i;
245
246 for (i = 0; i < kRegEnd; i++) {
247 if (mask & (1ULL << i)) {
248 sprintf(num, "%d ", i);
249 strcat(buf, num);
250 }
251 }
252
253 if (mask & ENCODE_CCODE) {
254 strcat(buf, "cc ");
255 }
256 if (mask & ENCODE_FP_STATUS) {
257 strcat(buf, "fpcc ");
258 }
259 if (armLIR && (mask & ENCODE_DALVIK_REG)) {
260 sprintf(buf + strlen(buf), "dr%d%s", armLIR->aliasInfo & 0xffff,
261 (armLIR->aliasInfo & 0x80000000) ? "(+1)" : "");
262 }
263 }
264 if (buf[0]) {
265 LOGD("%s: %s", prefix, buf);
266 }
267}
268
269/*
270 * Debugging macros
271 */
272#define DUMP_RESOURCE_MASK(X)
273#define DUMP_SSA_REP(X)
274
Ben Chengba4fc8b2009-06-01 13:00:29 -0700275/* Pretty-print a LIR instruction */
Ben Chengd7d426a2009-09-22 11:23:36 -0700276void dvmDumpLIRInsn(LIR *arg, unsigned char *baseAddr)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700277{
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700278 ArmLIR *lir = (ArmLIR *) arg;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700279 char buf[256];
280 char opName[256];
281 int offset = lir->generic.offset;
282 int dest = lir->operands[0];
Ben Chengd7d426a2009-09-22 11:23:36 -0700283 const bool dumpNop = false;
284
Ben Chengba4fc8b2009-06-01 13:00:29 -0700285 /* Handle pseudo-ops individually, and all regular insns as a group */
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800286 switch(lir->opcode) {
Ben Chengcec26f62010-01-15 15:29:33 -0800287 case kArmChainingCellBottom:
288 LOGD("-------- end of chaining cells (0x%04x)\n", offset);
289 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700290 case kArmPseudoBarrier:
Ben Chengd7d426a2009-09-22 11:23:36 -0700291 LOGD("-------- BARRIER");
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700292 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700293 case kArmPseudoExtended:
Ben Cheng7a2697d2010-06-07 13:44:23 -0700294 LOGD("-------- %s\n", (char *) dest);
295 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700296 case kArmPseudoSSARep:
Ben Chengd7d426a2009-09-22 11:23:36 -0700297 DUMP_SSA_REP(LOGD("-------- %s\n", (char *) dest));
Ben Cheng4238ec22009-08-24 16:32:22 -0700298 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700299 case kArmPseudoTargetLabel:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700300 break;
Ben Chenga4973592010-03-31 11:59:18 -0700301 case kArmPseudoChainingCellBackwardBranch:
Ben Cheng4238ec22009-08-24 16:32:22 -0700302 LOGD("-------- chaining cell (backward branch): 0x%04x\n", dest);
303 break;
Ben Chenga4973592010-03-31 11:59:18 -0700304 case kArmPseudoChainingCellNormal:
Ben Cheng1efc9c52009-06-08 18:25:27 -0700305 LOGD("-------- chaining cell (normal): 0x%04x\n", dest);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700306 break;
Ben Chenga4973592010-03-31 11:59:18 -0700307 case kArmPseudoChainingCellHot:
Ben Cheng1efc9c52009-06-08 18:25:27 -0700308 LOGD("-------- chaining cell (hot): 0x%04x\n", dest);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700309 break;
Ben Chenga4973592010-03-31 11:59:18 -0700310 case kArmPseudoChainingCellInvokePredicted:
Ben Cheng38329f52009-07-07 14:19:20 -0700311 LOGD("-------- chaining cell (predicted)\n");
312 break;
Ben Chenga4973592010-03-31 11:59:18 -0700313 case kArmPseudoChainingCellInvokeSingleton:
Ben Cheng38329f52009-07-07 14:19:20 -0700314 LOGD("-------- chaining cell (invoke singleton): %s/%p\n",
Ben Chengba4fc8b2009-06-01 13:00:29 -0700315 ((Method *)dest)->name,
316 ((Method *)dest)->insns);
317 break;
Ben Chenga4973592010-03-31 11:59:18 -0700318 case kArmPseudoEntryBlock:
Ben Cheng4238ec22009-08-24 16:32:22 -0700319 LOGD("-------- entry offset: 0x%04x\n", dest);
Jeff Hao97319a82009-08-12 16:57:15 -0700320 break;
Ben Chenga4973592010-03-31 11:59:18 -0700321 case kArmPseudoDalvikByteCodeBoundary:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700322 LOGD("-------- dalvik offset: 0x%04x @ %s\n", dest,
Ben Chengccd6c012009-10-15 14:52:45 -0700323 (char *) lir->operands[1]);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700324 break;
Ben Chenga4973592010-03-31 11:59:18 -0700325 case kArmPseudoExitBlock:
Ben Cheng4238ec22009-08-24 16:32:22 -0700326 LOGD("-------- exit offset: 0x%04x\n", dest);
327 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700328 case kArmPseudoPseudoAlign4:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700329 LOGD("%p (%04x): .align4\n", baseAddr + offset, offset);
330 break;
Ben Chenga4973592010-03-31 11:59:18 -0700331 case kArmPseudoPCReconstructionCell:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700332 LOGD("-------- reconstruct dalvik PC : 0x%04x @ +0x%04x\n", dest,
333 lir->operands[1]);
334 break;
Ben Chenga4973592010-03-31 11:59:18 -0700335 case kArmPseudoPCReconstructionBlockLabel:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700336 /* Do nothing */
337 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700338 case kArmPseudoEHBlockLabel:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700339 LOGD("Exception_Handling:\n");
340 break;
Bill Buzbee1465db52009-09-23 17:17:35 -0700341 case kArmPseudoNormalBlockLabel:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700342 LOGD("L%#06x:\n", dest);
343 break;
344 default:
Ben Chengd7d426a2009-09-22 11:23:36 -0700345 if (lir->isNop && !dumpNop) {
Ben Chenge9695e52009-06-16 16:11:47 -0700346 break;
347 }
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800348 buildInsnString(EncodingMap[lir->opcode].name, lir, opName,
Ben Chengba4fc8b2009-06-01 13:00:29 -0700349 baseAddr, 256);
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800350 buildInsnString(EncodingMap[lir->opcode].fmt, lir, buf, baseAddr,
Ben Chengba4fc8b2009-06-01 13:00:29 -0700351 256);
Ben Chengd7d426a2009-09-22 11:23:36 -0700352 LOGD("%p (%04x): %-8s%s%s\n",
353 baseAddr + offset, offset, opName, buf,
354 lir->isNop ? "(nop)" : "");
Ben Chengba4fc8b2009-06-01 13:00:29 -0700355 break;
356 }
Ben Chengd7d426a2009-09-22 11:23:36 -0700357
358 if (lir->useMask && (!lir->isNop || dumpNop)) {
359 DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir,
360 lir->useMask, "use"));
361 }
362 if (lir->defMask && (!lir->isNop || dumpNop)) {
363 DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir,
364 lir->defMask, "def"));
365 }
Ben Chengba4fc8b2009-06-01 13:00:29 -0700366}
367
368/* Dump instructions and constant pool contents */
369void dvmCompilerCodegenDump(CompilationUnit *cUnit)
370{
371 LOGD("Dumping LIR insns\n");
372 LIR *lirInsn;
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700373 ArmLIR *armLIR;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700374
375 LOGD("installed code is at %p\n", cUnit->baseAddr);
376 LOGD("total size is %d bytes\n", cUnit->totalSize);
377 for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800378 dvmDumpLIRInsn(lirInsn, (unsigned char *) cUnit->baseAddr);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700379 }
380 for (lirInsn = cUnit->wordList; lirInsn; lirInsn = lirInsn->next) {
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700381 armLIR = (ArmLIR *) lirInsn;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700382 LOGD("%p (%04x): .word (0x%x)\n",
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700383 (char*)cUnit->baseAddr + armLIR->generic.offset,
384 armLIR->generic.offset,
Ben Chengba4fc8b2009-06-01 13:00:29 -0700385 armLIR->operands[0]);
386 }
387}