1 /* 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" 18 #include "libdex/DexOpcodes.h" 19 #include "ArmLIR.h" 20 21 static const char *shiftNames[4] = { 22 "lsl", 23 "lsr", 24 "asr", 25 "ror"}; 26 27 /* Decode and print a ARM register name */ 28 static char * decodeRegList(ArmOpcode opcode, int vector, char *buf) 29 { 30 int i; 31 bool printed = false; 32 buf[0] = 0; 33 for (i = 0; i < 16; i++, vector >>= 1) { 34 if (vector & 0x1) { 35 int regId = i; 36 if (opcode == kThumbPush && i == 8) { 37 regId = r14lr; 38 } else if (opcode == kThumbPop && i == 8) { 39 regId = r15pc; 40 } 41 if (printed) { 42 sprintf(buf + strlen(buf), ", r%d", regId); 43 } else { 44 printed = true; 45 sprintf(buf, "r%d", regId); 46 } 47 } 48 } 49 return buf; 50 } 51 52 static 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 72 /* 73 * Interpret a format string and build a string no longer than size 74 * See format key in Assemble.c. 75 */ 76 static void buildInsnString(const char *fmt, ArmLIR *lir, char* buf, 77 unsigned char *baseAddr, int size) 78 { 79 int i; 80 char *bufEnd = &buf[size-1]; 81 const char *fmtEnd = &fmt[strlen(fmt)]; 82 char tbuf[256]; 83 const char *name; 84 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); 95 assert((unsigned)(nc-'0') < 4); 96 operand = lir->operands[nc-'0']; 97 switch(*fmt++) { 98 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; 106 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; 132 case 'b': 133 strcpy(tbuf,"0000"); 134 for (i=3; i>= 0; i--) { 135 tbuf[i] += operand & 1; 136 operand >>= 1; 137 } 138 break; 139 case 'n': 140 operand = ~expandImmediate(operand); 141 sprintf(tbuf,"%d [%#x]", operand, operand); 142 break; 143 case 'm': 144 operand = expandImmediate(operand); 145 sprintf(tbuf,"%d [%#x]", operand, operand); 146 break; 147 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; 153 case 'h': 154 sprintf(tbuf,"%04x", operand); 155 break; 156 case 'M': 157 case 'd': 158 sprintf(tbuf,"%d", operand); 159 break; 160 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) { 168 case kArmCondEq: 169 strcpy(tbuf, "eq"); 170 break; 171 case kArmCondNe: 172 strcpy(tbuf, "ne"); 173 break; 174 case kArmCondLt: 175 strcpy(tbuf, "lt"); 176 break; 177 case kArmCondGe: 178 strcpy(tbuf, "ge"); 179 break; 180 case kArmCondGt: 181 strcpy(tbuf, "gt"); 182 break; 183 case kArmCondLe: 184 strcpy(tbuf, "le"); 185 break; 186 case kArmCondCs: 187 strcpy(tbuf, "cs"); 188 break; 189 case kArmCondMi: 190 strcpy(tbuf, "mi"); 191 break; 192 default: 193 strcpy(tbuf, ""); 194 break; 195 } 196 break; 197 case 't': 198 sprintf(tbuf,"0x%08x (L%p)", 199 (int) baseAddr + lir->generic.offset + 4 + 200 (operand << 1), 201 lir->generic.target); 202 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': 219 decodeRegList(lir->opcode, operand, tbuf); 220 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 241 void 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 } 266 267 /* Memory bits */ 268 if (armLIR && (mask & ENCODE_DALVIK_REG)) { 269 sprintf(buf + strlen(buf), "dr%d%s", armLIR->aliasInfo & 0xffff, 270 (armLIR->aliasInfo & 0x80000000) ? "(+1)" : ""); 271 } 272 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 } 282 } 283 if (buf[0]) { 284 ALOGD("%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 294 /* Pretty-print a LIR instruction */ 295 void dvmDumpLIRInsn(LIR *arg, unsigned char *baseAddr) 296 { 297 ArmLIR *lir = (ArmLIR *) arg; 298 char buf[256]; 299 char opName[256]; 300 int offset = lir->generic.offset; 301 int dest = lir->operands[0]; 302 const bool dumpNop = false; 303 304 /* Handle pseudo-ops individually, and all regular insns as a group */ 305 switch(lir->opcode) { 306 case kArmChainingCellBottom: 307 ALOGD("-------- end of chaining cells (0x%04x)", offset); 308 break; 309 case kArmPseudoBarrier: 310 ALOGD("-------- BARRIER"); 311 break; 312 case kArmPseudoExtended: 313 ALOGD("-------- %s", (char *) dest); 314 break; 315 case kArmPseudoSSARep: 316 DUMP_SSA_REP(LOGD("-------- %s", (char *) dest)); 317 break; 318 case kArmPseudoChainingCellBackwardBranch: 319 ALOGD("L%p:", lir); 320 ALOGD("-------- chaining cell (backward branch): 0x%04x", dest); 321 break; 322 case kArmPseudoChainingCellNormal: 323 ALOGD("L%p:", lir); 324 ALOGD("-------- chaining cell (normal): 0x%04x", dest); 325 break; 326 case kArmPseudoChainingCellHot: 327 ALOGD("L%p:", lir); 328 ALOGD("-------- chaining cell (hot): 0x%04x", dest); 329 break; 330 case kArmPseudoChainingCellInvokePredicted: 331 ALOGD("L%p:", lir); 332 ALOGD("-------- chaining cell (predicted): %s%s", 333 dest ? ((Method *) dest)->clazz->descriptor : "", 334 dest ? ((Method *) dest)->name : "N/A"); 335 break; 336 case kArmPseudoChainingCellInvokeSingleton: 337 ALOGD("L%p:", lir); 338 ALOGD("-------- chaining cell (invoke singleton): %s%s/%p", 339 ((Method *)dest)->clazz->descriptor, 340 ((Method *)dest)->name, 341 ((Method *)dest)->insns); 342 break; 343 case kArmPseudoEntryBlock: 344 ALOGD("-------- entry offset: 0x%04x", dest); 345 break; 346 case kArmPseudoDalvikByteCodeBoundary: 347 ALOGD("-------- dalvik offset: 0x%04x @ %s", dest, 348 (char *) lir->operands[1]); 349 break; 350 case kArmPseudoExitBlock: 351 ALOGD("-------- exit offset: 0x%04x", dest); 352 break; 353 case kArmPseudoPseudoAlign4: 354 ALOGD("%p (%04x): .align4", baseAddr + offset, offset); 355 break; 356 case kArmPseudoPCReconstructionCell: 357 ALOGD("L%p:", lir); 358 ALOGD("-------- reconstruct dalvik PC : 0x%04x @ +0x%04x", dest, 359 lir->operands[1]); 360 break; 361 case kArmPseudoPCReconstructionBlockLabel: 362 /* Do nothing */ 363 break; 364 case kArmPseudoEHBlockLabel: 365 ALOGD("Exception_Handling:"); 366 break; 367 case kArmPseudoTargetLabel: 368 case kArmPseudoNormalBlockLabel: 369 ALOGD("L%p:", lir); 370 break; 371 default: 372 if (lir->flags.isNop && !dumpNop) { 373 break; 374 } 375 buildInsnString(EncodingMap[lir->opcode].name, lir, opName, 376 baseAddr, 256); 377 buildInsnString(EncodingMap[lir->opcode].fmt, lir, buf, baseAddr, 378 256); 379 ALOGD("%p (%04x): %-8s%s%s", 380 baseAddr + offset, offset, opName, buf, 381 lir->flags.isNop ? "(nop)" : ""); 382 break; 383 } 384 385 if (lir->useMask && (!lir->flags.isNop || dumpNop)) { 386 DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir, 387 lir->useMask, "use")); 388 } 389 if (lir->defMask && (!lir->flags.isNop || dumpNop)) { 390 DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir, 391 lir->defMask, "def")); 392 } 393 } 394 395 /* Dump instructions and constant pool contents */ 396 void dvmCompilerCodegenDump(CompilationUnit *cUnit) 397 { 398 ALOGD("Dumping LIR insns"); 399 LIR *lirInsn; 400 ArmLIR *armLIR; 401 402 ALOGD("installed code is at %p", cUnit->baseAddr); 403 ALOGD("total size is %d bytes", cUnit->totalSize); 404 for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) { 405 dvmDumpLIRInsn(lirInsn, (unsigned char *) cUnit->baseAddr); 406 } 407 for (lirInsn = cUnit->classPointerList; lirInsn; lirInsn = lirInsn->next) { 408 armLIR = (ArmLIR *) lirInsn; 409 ALOGD("%p (%04x): .class (%s)", 410 (char*)cUnit->baseAddr + armLIR->generic.offset, 411 armLIR->generic.offset, 412 ((CallsiteInfo *) armLIR->operands[0])->classDescriptor); 413 } 414 for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) { 415 armLIR = (ArmLIR *) lirInsn; 416 ALOGD("%p (%04x): .word (%#x)", 417 (char*)cUnit->baseAddr + armLIR->generic.offset, 418 armLIR->generic.offset, 419 armLIR->operands[0]); 420 } 421 } 422 423 /* Target-specific cache flushing */ 424 int dvmCompilerCacheFlush(long start, long end, long flags) 425 { 426 return cacheflush(start, end, flags); 427 } 428