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