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 "dexdump/OpCodeNames.h" 19#include "ArmLIR.h" 20 21/* Decode and print a ARM register name */ 22static char * decodeRegList(int vector, char *buf) 23{ 24 int i; 25 bool printed = false; 26 buf[0] = 0; 27 for (i = 0; i < 8; i++, vector >>= 1) { 28 if (vector & 0x1) { 29 if (printed) { 30 sprintf(buf + strlen(buf), ", r%d", i); 31 } else { 32 printed = true; 33 sprintf(buf, "r%d", i); 34 } 35 } 36 } 37 return buf; 38} 39 40static int expandImmediate(int value) 41{ 42 int mode = (value & 0xf00) >> 8; 43 u4 bits = value & 0xff; 44 switch(mode) { 45 case 0: 46 return bits; 47 case 1: 48 return (bits << 16) | bits; 49 case 2: 50 return (bits << 24) | (bits << 8); 51 case 3: 52 return (bits << 24) | (bits << 16) | (bits << 8) | bits; 53 default: 54 break; 55 } 56 bits = (bits | 0x80) << 24; 57 return bits >> (((value & 0xf80) >> 7) - 8); 58} 59 60/* 61 * Interpret a format string and build a string no longer than size 62 * See format key in Assemble.c. 63 */ 64static void buildInsnString(char *fmt, ArmLIR *lir, char* buf, 65 unsigned char *baseAddr, int size) 66{ 67 int i; 68 char *bufEnd = &buf[size-1]; 69 char *fmtEnd = &fmt[strlen(fmt)]; 70 char tbuf[256]; 71 char nc; 72 while (fmt < fmtEnd) { 73 int operand; 74 if (*fmt == '!') { 75 fmt++; 76 assert(fmt < fmtEnd); 77 nc = *fmt++; 78 if (nc=='!') { 79 strcpy(tbuf, "!"); 80 } else { 81 assert(fmt < fmtEnd); 82 assert((unsigned)(nc-'0') < 4); 83 operand = lir->operands[nc-'0']; 84 switch(*fmt++) { 85 case 'b': 86 strcpy(tbuf,"0000"); 87 for (i=3; i>= 0; i--) { 88 tbuf[i] += operand & 1; 89 operand >>= 1; 90 } 91 break; 92 case 'n': 93 operand = ~expandImmediate(operand); 94 sprintf(tbuf,"%d [0x%x]", operand, operand); 95 break; 96 case 'm': 97 operand = expandImmediate(operand); 98 sprintf(tbuf,"%d [0x%x]", operand, operand); 99 break; 100 case 's': 101 sprintf(tbuf,"s%d",operand & FP_REG_MASK); 102 break; 103 case 'S': 104 sprintf(tbuf,"d%d",(operand & FP_REG_MASK) >> 1); 105 break; 106 case 'h': 107 sprintf(tbuf,"%04x", operand); 108 break; 109 case 'M': 110 case 'd': 111 sprintf(tbuf,"%d", operand); 112 break; 113 case 'E': 114 sprintf(tbuf,"%d", operand*4); 115 break; 116 case 'F': 117 sprintf(tbuf,"%d", operand*2); 118 break; 119 case 'c': 120 switch (operand) { 121 case kArmCondEq: 122 strcpy(tbuf, "eq"); 123 break; 124 case kArmCondNe: 125 strcpy(tbuf, "ne"); 126 break; 127 case kArmCondLt: 128 strcpy(tbuf, "lt"); 129 break; 130 case kArmCondGe: 131 strcpy(tbuf, "ge"); 132 break; 133 case kArmCondGt: 134 strcpy(tbuf, "gt"); 135 break; 136 case kArmCondLe: 137 strcpy(tbuf, "le"); 138 break; 139 case kArmCondCs: 140 strcpy(tbuf, "cs"); 141 break; 142 case kArmCondMi: 143 strcpy(tbuf, "mi"); 144 break; 145 default: 146 strcpy(tbuf, ""); 147 break; 148 } 149 break; 150 case 't': 151 sprintf(tbuf,"0x%08x", 152 (int) baseAddr + lir->generic.offset + 4 + 153 (operand << 1)); 154 break; 155 case 'u': { 156 int offset_1 = lir->operands[0]; 157 int offset_2 = NEXT_LIR(lir)->operands[0]; 158 intptr_t target = 159 ((((intptr_t) baseAddr + lir->generic.offset + 4) & 160 ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) & 161 0xfffffffc; 162 sprintf(tbuf, "%p", (void *) target); 163 break; 164 } 165 166 /* Nothing to print for BLX_2 */ 167 case 'v': 168 strcpy(tbuf, "see above"); 169 break; 170 case 'R': 171 decodeRegList(operand, tbuf); 172 break; 173 default: 174 strcpy(tbuf,"DecodeError"); 175 break; 176 } 177 if (buf+strlen(tbuf) <= bufEnd) { 178 strcpy(buf, tbuf); 179 buf += strlen(tbuf); 180 } else { 181 break; 182 } 183 } 184 } else { 185 *buf++ = *fmt++; 186 } 187 if (buf == bufEnd) 188 break; 189 } 190 *buf = 0; 191} 192 193void dvmDumpResourceMask(LIR *lir, u8 mask, const char *prefix) 194{ 195 char buf[256]; 196 buf[0] = 0; 197 ArmLIR *armLIR = (ArmLIR *) lir; 198 199 if (mask == ENCODE_ALL) { 200 strcpy(buf, "all"); 201 } else { 202 char num[8]; 203 int i; 204 205 for (i = 0; i < kRegEnd; i++) { 206 if (mask & (1ULL << i)) { 207 sprintf(num, "%d ", i); 208 strcat(buf, num); 209 } 210 } 211 212 if (mask & ENCODE_CCODE) { 213 strcat(buf, "cc "); 214 } 215 if (mask & ENCODE_FP_STATUS) { 216 strcat(buf, "fpcc "); 217 } 218 if (armLIR && (mask & ENCODE_DALVIK_REG)) { 219 sprintf(buf + strlen(buf), "dr%d%s", armLIR->aliasInfo & 0xffff, 220 (armLIR->aliasInfo & 0x80000000) ? "(+1)" : ""); 221 } 222 } 223 if (buf[0]) { 224 LOGD("%s: %s", prefix, buf); 225 } 226} 227 228/* 229 * Debugging macros 230 */ 231#define DUMP_RESOURCE_MASK(X) 232#define DUMP_SSA_REP(X) 233 234/* Pretty-print a LIR instruction */ 235void dvmDumpLIRInsn(LIR *arg, unsigned char *baseAddr) 236{ 237 ArmLIR *lir = (ArmLIR *) arg; 238 char buf[256]; 239 char opName[256]; 240 int offset = lir->generic.offset; 241 int dest = lir->operands[0]; 242 u2 *cPtr = (u2*)baseAddr; 243 const bool dumpNop = false; 244 245 /* Handle pseudo-ops individually, and all regular insns as a group */ 246 switch(lir->opCode) { 247 case kArmChainingCellBottom: 248 LOGD("-------- end of chaining cells (0x%04x)\n", offset); 249 break; 250 case kArmPseudoBarrier: 251 LOGD("-------- BARRIER"); 252 break; 253 case kArmPseudoExtended: 254 /* intentional fallthrough */ 255 case kArmPseudoSSARep: 256 DUMP_SSA_REP(LOGD("-------- %s\n", (char *) dest)); 257 break; 258 case kArmPseudoTargetLabel: 259 break; 260 case kArmPseudoChainingCellBackwardBranch: 261 LOGD("-------- chaining cell (backward branch): 0x%04x\n", dest); 262 break; 263 case kArmPseudoChainingCellNormal: 264 LOGD("-------- chaining cell (normal): 0x%04x\n", dest); 265 break; 266 case kArmPseudoChainingCellHot: 267 LOGD("-------- chaining cell (hot): 0x%04x\n", dest); 268 break; 269 case kArmPseudoChainingCellInvokePredicted: 270 LOGD("-------- chaining cell (predicted)\n"); 271 break; 272 case kArmPseudoChainingCellInvokeSingleton: 273 LOGD("-------- chaining cell (invoke singleton): %s/%p\n", 274 ((Method *)dest)->name, 275 ((Method *)dest)->insns); 276 break; 277 case kArmPseudoEntryBlock: 278 LOGD("-------- entry offset: 0x%04x\n", dest); 279 break; 280 case kArmPseudoDalvikByteCodeBoundary: 281 LOGD("-------- dalvik offset: 0x%04x @ %s\n", dest, 282 (char *) lir->operands[1]); 283 break; 284 case kArmPseudoExitBlock: 285 LOGD("-------- exit offset: 0x%04x\n", dest); 286 break; 287 case kArmPseudoPseudoAlign4: 288 LOGD("%p (%04x): .align4\n", baseAddr + offset, offset); 289 break; 290 case kArmPseudoPCReconstructionCell: 291 LOGD("-------- reconstruct dalvik PC : 0x%04x @ +0x%04x\n", dest, 292 lir->operands[1]); 293 break; 294 case kArmPseudoPCReconstructionBlockLabel: 295 /* Do nothing */ 296 break; 297 case kArmPseudoEHBlockLabel: 298 LOGD("Exception_Handling:\n"); 299 break; 300 case kArmPseudoNormalBlockLabel: 301 LOGD("L%#06x:\n", dest); 302 break; 303 default: 304 if (lir->isNop && !dumpNop) { 305 break; 306 } 307 buildInsnString(EncodingMap[lir->opCode].name, lir, opName, 308 baseAddr, 256); 309 buildInsnString(EncodingMap[lir->opCode].fmt, lir, buf, baseAddr, 310 256); 311 LOGD("%p (%04x): %-8s%s%s\n", 312 baseAddr + offset, offset, opName, buf, 313 lir->isNop ? "(nop)" : ""); 314 break; 315 } 316 317 if (lir->useMask && (!lir->isNop || dumpNop)) { 318 DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir, 319 lir->useMask, "use")); 320 } 321 if (lir->defMask && (!lir->isNop || dumpNop)) { 322 DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir, 323 lir->defMask, "def")); 324 } 325} 326 327/* Dump instructions and constant pool contents */ 328void dvmCompilerCodegenDump(CompilationUnit *cUnit) 329{ 330 LOGD("Dumping LIR insns\n"); 331 LIR *lirInsn; 332 ArmLIR *armLIR; 333 334 LOGD("installed code is at %p\n", cUnit->baseAddr); 335 LOGD("total size is %d bytes\n", cUnit->totalSize); 336 for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) { 337 dvmDumpLIRInsn(lirInsn, cUnit->baseAddr); 338 } 339 for (lirInsn = cUnit->wordList; lirInsn; lirInsn = lirInsn->next) { 340 armLIR = (ArmLIR *) lirInsn; 341 LOGD("%p (%04x): .word (0x%x)\n", 342 (char*)cUnit->baseAddr + armLIR->generic.offset, 343 armLIR->generic.offset, 344 armLIR->operands[0]); 345 } 346} 347