ArchUtility.c revision 4238ec2ad1ace5103b2206a483f5f03d2e96c476
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 'D': 114 sprintf(tbuf,"%d", operand+8); 115 break; 116 case 'E': 117 sprintf(tbuf,"%d", operand*4); 118 break; 119 case 'F': 120 sprintf(tbuf,"%d", operand*2); 121 break; 122 case 'c': 123 switch (operand) { 124 case ARM_COND_EQ: 125 strcpy(tbuf, "eq"); 126 break; 127 case ARM_COND_NE: 128 strcpy(tbuf, "ne"); 129 break; 130 case ARM_COND_LT: 131 strcpy(tbuf, "lt"); 132 break; 133 case ARM_COND_GE: 134 strcpy(tbuf, "ge"); 135 break; 136 case ARM_COND_GT: 137 strcpy(tbuf, "gt"); 138 break; 139 case ARM_COND_LE: 140 strcpy(tbuf, "le"); 141 break; 142 case ARM_COND_CS: 143 strcpy(tbuf, "cs"); 144 break; 145 case ARM_COND_MI: 146 strcpy(tbuf, "mi"); 147 break; 148 default: 149 strcpy(tbuf, ""); 150 break; 151 } 152 break; 153 case 't': 154 sprintf(tbuf,"0x%08x", 155 (int) baseAddr + lir->generic.offset + 4 + 156 (operand << 1)); 157 break; 158 case 'u': { 159 int offset_1 = lir->operands[0]; 160 int offset_2 = NEXT_LIR(lir)->operands[0]; 161 intptr_t target = 162 ((((intptr_t) baseAddr + lir->generic.offset + 4) & 163 ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) & 164 0xfffffffc; 165 sprintf(tbuf, "%p", (void *) target); 166 break; 167 } 168 169 /* Nothing to print for BLX_2 */ 170 case 'v': 171 strcpy(tbuf, "see above"); 172 break; 173 case 'R': 174 decodeRegList(operand, tbuf); 175 break; 176 default: 177 strcpy(tbuf,"DecodeError"); 178 break; 179 } 180 if (buf+strlen(tbuf) <= bufEnd) { 181 strcpy(buf, tbuf); 182 buf += strlen(tbuf); 183 } else { 184 break; 185 } 186 } 187 } else { 188 *buf++ = *fmt++; 189 } 190 if (buf == bufEnd) 191 break; 192 } 193 *buf = 0; 194} 195 196/* Pretty-print a LIR instruction */ 197static void dumpLIRInsn(LIR *arg, unsigned char *baseAddr) 198{ 199 ArmLIR *lir = (ArmLIR *) arg; 200 char buf[256]; 201 char opName[256]; 202 int offset = lir->generic.offset; 203 int dest = lir->operands[0]; 204 u2 *cPtr = (u2*)baseAddr; 205 /* Handle pseudo-ops individually, and all regular insns as a group */ 206 switch(lir->opCode) { 207 case ARM_PSEUDO_EXTENDED_MIR: 208 /* intentional fallthrough */ 209 case ARM_PSEUDO_SSA_REP: 210 LOGD("-------- %s\n", (char *) dest); 211 break; 212 case ARM_PSEUDO_TARGET_LABEL: 213 break; 214 case ARM_PSEUDO_CHAINING_CELL_BACKWARD_BRANCH: 215 LOGD("-------- chaining cell (backward branch): 0x%04x\n", dest); 216 break; 217 case ARM_PSEUDO_CHAINING_CELL_NORMAL: 218 LOGD("-------- chaining cell (normal): 0x%04x\n", dest); 219 break; 220 case ARM_PSEUDO_CHAINING_CELL_HOT: 221 LOGD("-------- chaining cell (hot): 0x%04x\n", dest); 222 break; 223 case ARM_PSEUDO_CHAINING_CELL_INVOKE_PREDICTED: 224 LOGD("-------- chaining cell (predicted)\n"); 225 break; 226 case ARM_PSEUDO_CHAINING_CELL_INVOKE_SINGLETON: 227 LOGD("-------- chaining cell (invoke singleton): %s/%p\n", 228 ((Method *)dest)->name, 229 ((Method *)dest)->insns); 230 break; 231 case ARM_PSEUDO_ENTRY_BLOCK: 232 LOGD("-------- entry offset: 0x%04x\n", dest); 233 break; 234 case ARM_PSEUDO_DALVIK_BYTECODE_BOUNDARY: 235 LOGD("-------- dalvik offset: 0x%04x @ %s\n", dest, 236 getOpcodeName(lir->operands[1])); 237 break; 238 case ARM_PSEUDO_EXIT_BLOCK: 239 LOGD("-------- exit offset: 0x%04x\n", dest); 240 break; 241 case ARM_PSEUDO_ALIGN4: 242 LOGD("%p (%04x): .align4\n", baseAddr + offset, offset); 243 break; 244 case ARM_PSEUDO_PC_RECONSTRUCTION_CELL: 245 LOGD("-------- reconstruct dalvik PC : 0x%04x @ +0x%04x\n", dest, 246 lir->operands[1]); 247 break; 248 case ARM_PSEUDO_PC_RECONSTRUCTION_BLOCK_LABEL: 249 /* Do nothing */ 250 break; 251 case ARM_PSEUDO_EH_BLOCK_LABEL: 252 LOGD("Exception_Handling:\n"); 253 break; 254 case ARM_PSEUDO_NORMAL_BLOCK_LABEL: 255 LOGD("L%#06x:\n", dest); 256 break; 257 default: 258 if (lir->isNop) { 259 break; 260 } 261 buildInsnString(EncodingMap[lir->opCode].name, lir, opName, 262 baseAddr, 256); 263 buildInsnString(EncodingMap[lir->opCode].fmt, lir, buf, baseAddr, 264 256); 265 LOGD("%p (%04x): %-8s%s\n", 266 baseAddr + offset, offset, opName, buf); 267 break; 268 } 269} 270 271/* Dump instructions and constant pool contents */ 272void dvmCompilerCodegenDump(CompilationUnit *cUnit) 273{ 274 LOGD("Dumping LIR insns\n"); 275 LIR *lirInsn; 276 ArmLIR *armLIR; 277 278 LOGD("installed code is at %p\n", cUnit->baseAddr); 279 LOGD("total size is %d bytes\n", cUnit->totalSize); 280 for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) { 281 dumpLIRInsn(lirInsn, cUnit->baseAddr); 282 } 283 for (lirInsn = cUnit->wordList; lirInsn; lirInsn = lirInsn->next) { 284 armLIR = (ArmLIR *) lirInsn; 285 LOGD("%p (%04x): .word (0x%x)\n", 286 (char*)cUnit->baseAddr + armLIR->generic.offset, armLIR->generic.offset, 287 armLIR->operands[0]); 288 } 289} 290