blob: aef98faff5cc6c9fbfa7783986a54597e3b28afe [file] [log] [blame]
buzbee67bf8852011-08-17 17:51:35 -07001/*
2 * Copyright (C) 2011 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"
18#include "ArmLIR.h"
19
20static const char* coreRegNames[16] = {
21 "r0",
22 "r1",
23 "r2",
24 "r3",
25 "r4",
26 "r5",
27 "r6",
28 "r7",
29 "r8",
30 "rSELF",
31 "r10",
32 "r11",
33 "r12",
34 "sp",
35 "lr",
36 "pc",
37};
38
39
40static const char* shiftNames[4] = {
41 "lsl",
42 "lsr",
43 "asr",
44 "ror"};
45
46/* Decode and print a ARM register name */
buzbeeed3e9302011-09-23 17:34:19 -070047STATIC char* decodeRegList(ArmOpcode opcode, int vector, char* buf)
buzbee67bf8852011-08-17 17:51:35 -070048{
49 int i;
50 bool printed = false;
51 buf[0] = 0;
52 for (i = 0; i < 16; i++, vector >>= 1) {
53 if (vector & 0x1) {
54 int regId = i;
55 if (opcode == kThumbPush && i == 8) {
56 regId = r14lr;
57 } else if (opcode == kThumbPop && i == 8) {
58 regId = r15pc;
59 }
60 if (printed) {
61 sprintf(buf + strlen(buf), ", r%d", regId);
62 } else {
63 printed = true;
64 sprintf(buf, "r%d", regId);
65 }
66 }
67 }
68 return buf;
69}
70
buzbeeed3e9302011-09-23 17:34:19 -070071STATIC char* decodeFPCSRegList(int count, int base, char* buf)
buzbee67bf8852011-08-17 17:51:35 -070072{
73 sprintf(buf, "s%d", base);
74 for (int i = 1; i < count; i++) {
75 sprintf(buf + strlen(buf), ", s%d",base + i);
76 }
77 return buf;
78}
79
buzbeeed3e9302011-09-23 17:34:19 -070080STATIC int expandImmediate(int value)
buzbee67bf8852011-08-17 17:51:35 -070081{
82 int mode = (value & 0xf00) >> 8;
83 u4 bits = value & 0xff;
84 switch(mode) {
85 case 0:
86 return bits;
87 case 1:
88 return (bits << 16) | bits;
89 case 2:
90 return (bits << 24) | (bits << 8);
91 case 3:
92 return (bits << 24) | (bits << 16) | (bits << 8) | bits;
93 default:
94 break;
95 }
96 bits = (bits | 0x80) << 24;
97 return bits >> (((value & 0xf80) >> 7) - 8);
98}
99
100const char* ccNames[] = {"eq","ne","cs","cc","mi","pl","vs","vc",
101 "hi","ls","ge","lt","gt","le","al","nv"};
102/*
103 * Interpret a format string and build a string no longer than size
104 * See format key in Assemble.c.
105 */
buzbeeed3e9302011-09-23 17:34:19 -0700106STATIC void buildInsnString(const char* fmt, ArmLIR* lir, char* buf,
buzbee67bf8852011-08-17 17:51:35 -0700107 unsigned char* baseAddr, int size)
108{
109 int i;
110 char* bufEnd = &buf[size-1];
111 const char* fmtEnd = &fmt[strlen(fmt)];
112 char tbuf[256];
113 const char* name;
114 char nc;
115 while (fmt < fmtEnd) {
116 int operand;
117 if (*fmt == '!') {
118 fmt++;
buzbeeed3e9302011-09-23 17:34:19 -0700119 DCHECK_LT(fmt, fmtEnd);
buzbee67bf8852011-08-17 17:51:35 -0700120 nc = *fmt++;
121 if (nc=='!') {
122 strcpy(tbuf, "!");
123 } else {
buzbeeed3e9302011-09-23 17:34:19 -0700124 DCHECK_LT(fmt, fmtEnd);
Elliott Hughesf5a7a472011-10-07 14:31:02 -0700125 DCHECK_LT((unsigned)(nc-'0'), 4U);
buzbee67bf8852011-08-17 17:51:35 -0700126 operand = lir->operands[nc-'0'];
127 switch(*fmt++) {
128 case 'H':
129 if (operand != 0) {
130 sprintf(tbuf, ", %s %d",shiftNames[operand & 0x3],
131 operand >> 2);
132 } else {
133 strcpy(tbuf,"");
134 }
135 break;
136 case 'B':
137 switch (operand) {
138 case kSY:
139 name = "sy";
140 break;
141 case kST:
142 name = "st";
143 break;
144 case kISH:
145 name = "ish";
146 break;
147 case kISHST:
148 name = "ishst";
149 break;
150 case kNSH:
151 name = "nsh";
152 break;
153 case kNSHST:
154 name = "shst";
155 break;
156 default:
157 name = "DecodeError2";
158 break;
159 }
160 strcpy(tbuf, name);
161 break;
162 case 'b':
163 strcpy(tbuf,"0000");
164 for (i=3; i>= 0; i--) {
165 tbuf[i] += operand & 1;
166 operand >>= 1;
167 }
168 break;
169 case 'n':
170 operand = ~expandImmediate(operand);
171 sprintf(tbuf,"%d [%#x]", operand, operand);
172 break;
173 case 'm':
174 operand = expandImmediate(operand);
175 sprintf(tbuf,"%d [%#x]", operand, operand);
176 break;
177 case 's':
178 sprintf(tbuf,"s%d",operand & FP_REG_MASK);
179 break;
180 case 'S':
181 sprintf(tbuf,"d%d",(operand & FP_REG_MASK) >> 1);
182 break;
183 case 'h':
184 sprintf(tbuf,"%04x", operand);
185 break;
186 case 'M':
187 case 'd':
188 sprintf(tbuf,"%d", operand);
189 break;
190 case 'C':
191 sprintf(tbuf,"%s",coreRegNames[operand]);
192 break;
193 case 'E':
194 sprintf(tbuf,"%d", operand*4);
195 break;
196 case 'F':
197 sprintf(tbuf,"%d", operand*2);
198 break;
199 case 'c':
200 strcpy(tbuf, ccNames[operand]);
201 break;
202 case 't':
203 sprintf(tbuf,"0x%08x (L%p)",
204 (int) baseAddr + lir->generic.offset + 4 +
205 (operand << 1),
206 lir->generic.target);
207 break;
208 case 'u': {
209 int offset_1 = lir->operands[0];
210 int offset_2 = NEXT_LIR(lir)->operands[0];
211 intptr_t target =
212 ((((intptr_t) baseAddr + lir->generic.offset + 4) &
213 ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
214 0xfffffffc;
215 sprintf(tbuf, "%p", (void *) target);
216 break;
217 }
218
219 /* Nothing to print for BLX_2 */
220 case 'v':
221 strcpy(tbuf, "see above");
222 break;
223 case 'R':
224 decodeRegList(lir->opcode, operand, tbuf);
225 break;
226 case 'P':
227 decodeFPCSRegList(operand, 16, tbuf);
228 break;
229 case 'Q':
230 decodeFPCSRegList(operand, 0, tbuf);
231 break;
232 default:
233 strcpy(tbuf,"DecodeError1");
234 break;
235 }
236 if (buf+strlen(tbuf) <= bufEnd) {
237 strcpy(buf, tbuf);
238 buf += strlen(tbuf);
239 } else {
240 break;
241 }
242 }
243 } else {
244 *buf++ = *fmt++;
245 }
246 if (buf == bufEnd)
247 break;
248 }
249 *buf = 0;
250}
251
252void oatDumpResourceMask(LIR* lir, u8 mask, const char* prefix)
253{
254 char buf[256];
255 buf[0] = 0;
256 ArmLIR* armLIR = (ArmLIR*) lir;
257
258 if (mask == ENCODE_ALL) {
259 strcpy(buf, "all");
260 } else {
261 char num[8];
262 int i;
263
264 for (i = 0; i < kRegEnd; i++) {
265 if (mask & (1ULL << i)) {
266 sprintf(num, "%d ", i);
267 strcat(buf, num);
268 }
269 }
270
271 if (mask & ENCODE_CCODE) {
272 strcat(buf, "cc ");
273 }
274 if (mask & ENCODE_FP_STATUS) {
275 strcat(buf, "fpcc ");
276 }
277
278 /* Memory bits */
279 if (armLIR && (mask & ENCODE_DALVIK_REG)) {
280 sprintf(buf + strlen(buf), "dr%d%s", armLIR->aliasInfo & 0xffff,
281 (armLIR->aliasInfo & 0x80000000) ? "(+1)" : "");
282 }
283 if (mask & ENCODE_LITERAL) {
284 strcat(buf, "lit ");
285 }
286
287 if (mask & ENCODE_HEAP_REF) {
288 strcat(buf, "heap ");
289 }
290 if (mask & ENCODE_MUST_NOT_ALIAS) {
291 strcat(buf, "noalias ");
292 }
293 }
294 if (buf[0]) {
295 LOG(INFO) << prefix << ": " << buf;
296 }
297}
298
299/*
300 * Debugging macros
301 */
302#define DUMP_RESOURCE_MASK(X)
303#define DUMP_SSA_REP(X)
304
305/* Pretty-print a LIR instruction */
306void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr)
307{
308 ArmLIR* lir = (ArmLIR*) arg;
buzbee67bf8852011-08-17 17:51:35 -0700309 int offset = lir->generic.offset;
310 int dest = lir->operands[0];
311 const bool dumpNop = false;
312
313 /* Handle pseudo-ops individually, and all regular insns as a group */
314 switch(lir->opcode) {
315 case kArmPseudoMethodEntry:
316 LOG(INFO) << "-------- method entry " <<
buzbeedfd3d702011-08-28 12:56:51 -0700317 art::PrettyMethod(cUnit->method);
buzbee67bf8852011-08-17 17:51:35 -0700318 break;
319 case kArmPseudoMethodExit:
320 LOG(INFO) << "-------- Method_Exit";
321 break;
322 case kArmPseudoBarrier:
323 LOG(INFO) << "-------- BARRIER";
324 break;
325 case kArmPseudoExtended:
326 LOG(INFO) << "-------- " << (char* ) dest;
327 break;
328 case kArmPseudoSSARep:
329 DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " << (char* ) dest);
330 break;
331 case kArmPseudoEntryBlock:
332 LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
333 break;
334 case kArmPseudoDalvikByteCodeBoundary:
335 LOG(INFO) << "-------- dalvik offset: 0x" << std::hex <<
336 lir->generic.dalvikOffset << " @ " << (char* )lir->operands[0];
337 break;
338 case kArmPseudoExitBlock:
339 LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
340 break;
341 case kArmPseudoPseudoAlign4:
342 LOG(INFO) << (intptr_t)baseAddr + offset << " (0x" << std::hex <<
343 offset << "): .align4";
344 break;
345 case kArmPseudoEHBlockLabel:
346 LOG(INFO) << "Exception_Handling:";
347 break;
348 case kArmPseudoTargetLabel:
349 case kArmPseudoNormalBlockLabel:
350 LOG(INFO) << "L" << (intptr_t)lir << ":";
351 break;
buzbee5ade1d22011-09-09 14:44:52 -0700352 case kArmPseudoThrowTarget:
353 LOG(INFO) << "LT" << (intptr_t)lir << ":";
354 break;
buzbeec1f45042011-09-21 16:03:19 -0700355 case kArmPseudoSuspendTarget:
356 LOG(INFO) << "LS" << (intptr_t)lir << ":";
357 break;
buzbee67bf8852011-08-17 17:51:35 -0700358 case kArmPseudoCaseLabel:
359 LOG(INFO) << "LC" << (intptr_t)lir << ": Case target 0x" <<
360 std::hex << lir->operands[0] << "|" << std::dec <<
361 lir->operands[0];
362 break;
363 default:
364 if (lir->flags.isNop && !dumpNop) {
365 break;
buzbee3ea4ec52011-08-22 17:37:19 -0700366 } else {
367 // TODO: rewrite using string
368 char opOperands[256];
369 char opName[256];
370 buildInsnString(EncodingMap[lir->opcode].name, lir, opName,
371 baseAddr, 256);
372 buildInsnString(EncodingMap[lir->opcode].fmt, lir, opOperands,
373 baseAddr, 256);
374 char tBuf[256];
buzbee6181f792011-09-29 11:14:04 -0700375 snprintf(tBuf, 256, "%p (%04x): %-9s%s%s%s",
376 baseAddr + offset, offset,
377 opName, opOperands, lir->flags.isNop ? "(nop)" : "",
378 lir->flags.squashed ? "(squashed)" : "");
buzbee3ea4ec52011-08-22 17:37:19 -0700379 LOG(INFO) << tBuf;
buzbee67bf8852011-08-17 17:51:35 -0700380 }
buzbee67bf8852011-08-17 17:51:35 -0700381 break;
382 }
383
384 if (lir->useMask && (!lir->flags.isNop || dumpNop)) {
385 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir,
386 lir->useMask, "use"));
387 }
388 if (lir->defMask && (!lir->flags.isNop || dumpNop)) {
389 DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir,
390 lir->defMask, "def"));
391 }
392}
393
394/* Dump instructions and constant pool contents */
395void oatCodegenDump(CompilationUnit* cUnit)
396{
397 const Method *method = cUnit->method;
398 LOG(INFO) << "/*";
buzbeedfd3d702011-08-28 12:56:51 -0700399 LOG(INFO) << "Dumping LIR insns for " << art::PrettyMethod(cUnit->method);
buzbee67bf8852011-08-17 17:51:35 -0700400 LIR* lirInsn;
401 ArmLIR* armLIR;
402 int insnsSize = cUnit->insnsSize;
403
404 LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs;
405 LOG(INFO) << "Ins : " << cUnit->numIns;
406 LOG(INFO) << "Outs : " << cUnit->numOuts;
buzbeebbaf8942011-10-02 13:08:29 -0700407 LOG(INFO) << "CoreSpills : " << cUnit->numCoreSpills;
408 LOG(INFO) << "FPSpills : " << cUnit->numFPSpills;
buzbee67bf8852011-08-17 17:51:35 -0700409 LOG(INFO) << "Padding : " << cUnit->numPadding;
410 LOG(INFO) << "Frame size : " << cUnit->frameSize;
411 LOG(INFO) << "Start of ins : " << cUnit->insOffset;
412 LOG(INFO) << "Start of regs : " << cUnit->regsOffset;
413 LOG(INFO) << "code size is " << cUnit->totalSize <<
414 " bytes, Dalvik size is " << insnsSize * 2;
415 LOG(INFO) << "expansion factor: " <<
416 (float)cUnit->totalSize / (float)(insnsSize * 2);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700417 for (int i = 0; i < method->NumRegisters(); i++) {
buzbee67bf8852011-08-17 17:51:35 -0700418 RegLocation loc = cUnit->regLocation[i];
419 char buf[100];
420 if (loc.fpLocation == kLocPhysReg) {
421 snprintf(buf, 100, " : s%d", loc.fpLowReg & FP_REG_MASK);
422 } else {
423 buf[0] = 0;
424 }
425 char buf2[100];
426 snprintf(buf2, 100, "V[%02d] -> %s%d%s", i,
427 loc.location == kLocPhysReg ?
428 "r" : "SP+", loc.location == kLocPhysReg ?
429 loc.lowReg : loc.spOffset, buf);
430 LOG(INFO) << buf2;
431
432 }
433 for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
buzbeec143c552011-08-20 17:38:58 -0700434 oatDumpLIRInsn(cUnit, lirInsn, 0);
buzbee67bf8852011-08-17 17:51:35 -0700435 }
436 for (lirInsn = cUnit->classPointerList; lirInsn; lirInsn = lirInsn->next) {
437 armLIR = (ArmLIR*) lirInsn;
438 char buf[100];
buzbeec143c552011-08-20 17:38:58 -0700439 snprintf(buf, 100, "%x (%04x): .class (%s)",
440 armLIR->generic.offset, armLIR->generic.offset,
buzbee67bf8852011-08-17 17:51:35 -0700441 ((CallsiteInfo *) armLIR->operands[0])->classDescriptor);
442 LOG(INFO) << buf;
443 }
444 for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
445 armLIR = (ArmLIR*) lirInsn;
446 char buf[100];
buzbeec143c552011-08-20 17:38:58 -0700447 snprintf(buf, 100, "%x (%04x): .word (%#x)",
448 armLIR->generic.offset, armLIR->generic.offset,
buzbee67bf8852011-08-17 17:51:35 -0700449 armLIR->operands[0]);
450 LOG(INFO) << buf;
451
452 }
453
buzbeec143c552011-08-20 17:38:58 -0700454 std::string signature = method->GetSignature()->ToModifiedUtf8();
455 std::string name = method->GetName()->ToModifiedUtf8();
456 std::string descriptor = method->GetDeclaringClass()->GetDescriptor()->
457 ToModifiedUtf8();
458
buzbee3ea4ec52011-08-22 17:37:19 -0700459 char buf[256];
buzbee67bf8852011-08-17 17:51:35 -0700460
461 // Dump mapping table
buzbee4ef76522011-09-08 10:00:32 -0700462 if (cUnit->mappingTable.size() > 0) {
buzbee67bf8852011-08-17 17:51:35 -0700463 sprintf(buf,"\n MappingTable %s%s_%s_mappingTable[%d] = {",
buzbeec143c552011-08-20 17:38:58 -0700464 descriptor.c_str(), name.c_str(), signature.c_str(),
buzbee4ef76522011-09-08 10:00:32 -0700465 cUnit->mappingTable.size());
buzbee67bf8852011-08-17 17:51:35 -0700466 for (unsigned int i = 0; i < strlen(buf); i++)
467 if (buf[i] == ';') buf[i] = '_';
468 LOG(INFO) << buf;
469 strcpy(buf," ");
buzbee4ef76522011-09-08 10:00:32 -0700470 for (uint32_t i = 0; i < cUnit->mappingTable.size(); i+=2) {
buzbee67bf8852011-08-17 17:51:35 -0700471 sprintf(buf+strlen(buf)," {0x%08x, 0x%04x},",
buzbee4ef76522011-09-08 10:00:32 -0700472 cUnit->mappingTable[i], cUnit->mappingTable[i+1]);
buzbee67bf8852011-08-17 17:51:35 -0700473 LOG(INFO) << buf;
474 strcpy(buf," ");
475 }
476 LOG(INFO) <<" };\n\n";
477 }
buzbee67bf8852011-08-17 17:51:35 -0700478}