blob: eeee00b4dafbd1de64febd283cb7067d0e94dedf [file] [log] [blame]
Ben Chengba4fc8b2009-06-01 13:00:29 -07001/*
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"
Bill Buzbee89efc3d2009-07-28 11:22:22 -070019#include "ArmLIR.h"
Ben Chengba4fc8b2009-06-01 13:00:29 -070020
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
Bill Buzbee7ea0f642009-08-10 17:06:51 -070040static 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
Ben Chengba4fc8b2009-06-01 13:00:29 -070060/*
61 * Interpret a format string and build a string no longer than size
62 * See format key in Assemble.c.
63 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -070064static void buildInsnString(char *fmt, ArmLIR *lir, char* buf,
Ben Chengba4fc8b2009-06-01 13:00:29 -070065 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);
Bill Buzbee270c1d62009-08-13 16:58:07 -070082 assert((unsigned)(nc-'0') < 4);
Ben Chengba4fc8b2009-06-01 13:00:29 -070083 operand = lir->operands[nc-'0'];
84 switch(*fmt++) {
Bill Buzbee270c1d62009-08-13 16:58:07 -070085 case 'n':
86 operand = ~expandImmediate(operand);
87 sprintf(tbuf,"%d [0x%x]", operand, operand);
88 break;
Bill Buzbee7ea0f642009-08-10 17:06:51 -070089 case 'm':
90 operand = expandImmediate(operand);
91 sprintf(tbuf,"%d [0x%x]", operand, operand);
92 break;
Bill Buzbee9727c3d2009-08-01 11:32:36 -070093 case 's':
94 sprintf(tbuf,"s%d",operand & FP_REG_MASK);
95 break;
96 case 'S':
97 sprintf(tbuf,"d%d",(operand & FP_REG_MASK) >> 1);
98 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -070099 case 'h':
100 sprintf(tbuf,"%04x", operand);
101 break;
Bill Buzbee7ea0f642009-08-10 17:06:51 -0700102 case 'M':
Ben Chengba4fc8b2009-06-01 13:00:29 -0700103 case 'd':
104 sprintf(tbuf,"%d", operand);
105 break;
106 case 'D':
107 sprintf(tbuf,"%d", operand+8);
108 break;
109 case 'E':
110 sprintf(tbuf,"%d", operand*4);
111 break;
112 case 'F':
113 sprintf(tbuf,"%d", operand*2);
114 break;
115 case 'c':
116 switch (operand) {
117 case ARM_COND_EQ:
118 strcpy(tbuf, "beq");
119 break;
120 case ARM_COND_NE:
121 strcpy(tbuf, "bne");
122 break;
123 case ARM_COND_LT:
124 strcpy(tbuf, "blt");
125 break;
126 case ARM_COND_GE:
127 strcpy(tbuf, "bge");
128 break;
129 case ARM_COND_GT:
130 strcpy(tbuf, "bgt");
131 break;
132 case ARM_COND_LE:
133 strcpy(tbuf, "ble");
134 break;
135 case ARM_COND_CS:
136 strcpy(tbuf, "bcs");
137 break;
Bill Buzbee7ea0f642009-08-10 17:06:51 -0700138 case ARM_COND_MI:
139 strcpy(tbuf, "bmi");
140 break;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700141 default:
142 strcpy(tbuf, "");
143 break;
144 }
145 break;
146 case 't':
147 sprintf(tbuf,"0x%08x",
148 (int) baseAddr + lir->generic.offset + 4 +
149 (operand << 1));
150 break;
151 case 'u': {
152 int offset_1 = lir->operands[0];
153 int offset_2 = NEXT_LIR(lir)->operands[0];
154 intptr_t target =
155 ((((intptr_t) baseAddr + lir->generic.offset + 4) &
156 ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
157 0xfffffffc;
158 sprintf(tbuf, "%p", (void *) target);
159 break;
160 }
161
162 /* Nothing to print for BLX_2 */
163 case 'v':
164 strcpy(tbuf, "see above");
165 break;
166 case 'R':
167 decodeRegList(operand, tbuf);
168 break;
169 default:
170 strcpy(tbuf,"DecodeError");
171 break;
172 }
173 if (buf+strlen(tbuf) <= bufEnd) {
174 strcpy(buf, tbuf);
175 buf += strlen(tbuf);
176 } else {
177 break;
178 }
179 }
180 } else {
181 *buf++ = *fmt++;
182 }
183 if (buf == bufEnd)
184 break;
185 }
186 *buf = 0;
187}
188
189/* Pretty-print a LIR instruction */
190static void dumpLIRInsn(LIR *arg, unsigned char *baseAddr)
191{
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700192 ArmLIR *lir = (ArmLIR *) arg;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700193 char buf[256];
194 char opName[256];
195 int offset = lir->generic.offset;
196 int dest = lir->operands[0];
197 u2 *cPtr = (u2*)baseAddr;
198 /* Handle pseudo-ops individually, and all regular insns as a group */
199 switch(lir->opCode) {
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700200 case ARM_PSEUDO_TARGET_LABEL:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700201 break;
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700202 case ARM_PSEUDO_CHAINING_CELL_NORMAL:
Ben Cheng1efc9c52009-06-08 18:25:27 -0700203 LOGD("-------- chaining cell (normal): 0x%04x\n", dest);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700204 break;
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700205 case ARM_PSEUDO_CHAINING_CELL_HOT:
Ben Cheng1efc9c52009-06-08 18:25:27 -0700206 LOGD("-------- chaining cell (hot): 0x%04x\n", dest);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700207 break;
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700208 case ARM_PSEUDO_CHAINING_CELL_INVOKE_PREDICTED:
Ben Cheng38329f52009-07-07 14:19:20 -0700209 LOGD("-------- chaining cell (predicted)\n");
210 break;
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700211 case ARM_PSEUDO_CHAINING_CELL_INVOKE_SINGLETON:
Ben Cheng38329f52009-07-07 14:19:20 -0700212 LOGD("-------- chaining cell (invoke singleton): %s/%p\n",
Ben Chengba4fc8b2009-06-01 13:00:29 -0700213 ((Method *)dest)->name,
214 ((Method *)dest)->insns);
215 break;
Jeff Hao97319a82009-08-12 16:57:15 -0700216 case ARM_PSEUDO_CHAINING_CELL_BACKWARD_BRANCH:
217 LOGD("-------- chaining cell (backward branch): 0x%04x\n", dest);
218 break;
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700219 case ARM_PSEUDO_DALVIK_BYTECODE_BOUNDARY:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700220 LOGD("-------- dalvik offset: 0x%04x @ %s\n", dest,
221 getOpcodeName(lir->operands[1]));
222 break;
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700223 case ARM_PSEUDO_ALIGN4:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700224 LOGD("%p (%04x): .align4\n", baseAddr + offset, offset);
225 break;
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700226 case ARM_PSEUDO_PC_RECONSTRUCTION_CELL:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700227 LOGD("-------- reconstruct dalvik PC : 0x%04x @ +0x%04x\n", dest,
228 lir->operands[1]);
229 break;
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700230 case ARM_PSEUDO_PC_RECONSTRUCTION_BLOCK_LABEL:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700231 /* Do nothing */
232 break;
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700233 case ARM_PSEUDO_EH_BLOCK_LABEL:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700234 LOGD("Exception_Handling:\n");
235 break;
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700236 case ARM_PSEUDO_NORMAL_BLOCK_LABEL:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700237 LOGD("L%#06x:\n", dest);
238 break;
239 default:
Ben Chenge9695e52009-06-16 16:11:47 -0700240 if (lir->isNop) {
241 break;
242 }
Ben Chengba4fc8b2009-06-01 13:00:29 -0700243 buildInsnString(EncodingMap[lir->opCode].name, lir, opName,
244 baseAddr, 256);
245 buildInsnString(EncodingMap[lir->opCode].fmt, lir, buf, baseAddr,
246 256);
Ben Chenge9695e52009-06-16 16:11:47 -0700247 LOGD("%p (%04x): %-8s%s\n",
248 baseAddr + offset, offset, opName, buf);
Ben Chengba4fc8b2009-06-01 13:00:29 -0700249 break;
250 }
251}
252
253/* Dump instructions and constant pool contents */
254void dvmCompilerCodegenDump(CompilationUnit *cUnit)
255{
256 LOGD("Dumping LIR insns\n");
257 LIR *lirInsn;
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700258 ArmLIR *armLIR;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700259
260 LOGD("installed code is at %p\n", cUnit->baseAddr);
261 LOGD("total size is %d bytes\n", cUnit->totalSize);
262 for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
263 dumpLIRInsn(lirInsn, cUnit->baseAddr);
264 }
265 for (lirInsn = cUnit->wordList; lirInsn; lirInsn = lirInsn->next) {
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700266 armLIR = (ArmLIR *) lirInsn;
Ben Chengba4fc8b2009-06-01 13:00:29 -0700267 LOGD("%p (%04x): .word (0x%x)\n",
Bill Buzbee716f1202009-07-23 13:22:09 -0700268 (char*)cUnit->baseAddr + armLIR->generic.offset, armLIR->generic.offset,
Ben Chengba4fc8b2009-06-01 13:00:29 -0700269 armLIR->operands[0]);
270 }
271}