blob: 47c4c6de118a3e4814fb016b7b6e0372cc0a7778 [file] [log] [blame]
Raghu Gandhama8b91c52012-05-02 14:27:16 -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 "libdex/DexOpcodes.h"
19#include "MipsLIR.h"
20
21/* For dumping instructions */
22#define MIPS_REG_COUNT 32
23static const char *mipsRegName[MIPS_REG_COUNT] = {
24 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
25 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
26 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
27 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
28};
29
30/*
31 * Interpret a format string and build a string no longer than size
32 * See format key in Assemble.c.
33 */
34static void buildInsnString(const char *fmt, MipsLIR *lir, char* buf,
35 unsigned char *baseAddr, int size)
36{
37 int i;
38 char *bufEnd = &buf[size-1];
39 const char *fmtEnd = &fmt[strlen(fmt)];
40 char tbuf[256];
Chris Dearman5e22c9a2013-10-25 11:40:53 -070041 const char *name;
Raghu Gandhama8b91c52012-05-02 14:27:16 -070042 char nc;
43 while (fmt < fmtEnd) {
44 int operand;
45 if (*fmt == '!') {
46 fmt++;
47 assert(fmt < fmtEnd);
48 nc = *fmt++;
49 if (nc=='!') {
50 strcpy(tbuf, "!");
51 } else {
52 assert(fmt < fmtEnd);
53 assert((unsigned)(nc-'0') < 4);
54 operand = lir->operands[nc-'0'];
55 switch(*fmt++) {
56 case 'b':
57 strcpy(tbuf,"0000");
58 for (i=3; i>= 0; i--) {
59 tbuf[i] += operand & 1;
60 operand >>= 1;
61 }
62 break;
63 case 's':
64 sprintf(tbuf,"$f%d",operand & FP_REG_MASK);
65 break;
66 case 'S':
67 assert(((operand & FP_REG_MASK) & 1) == 0);
68 sprintf(tbuf,"$f%d",operand & FP_REG_MASK);
69 break;
70 case 'h':
71 sprintf(tbuf,"%04x", operand);
72 break;
73 case 'M':
74 case 'd':
75 sprintf(tbuf,"%d", operand);
76 break;
77 case 'D':
78 sprintf(tbuf,"%d", operand+1);
79 break;
80 case 'E':
81 sprintf(tbuf,"%d", operand*4);
82 break;
83 case 'F':
84 sprintf(tbuf,"%d", operand*2);
85 break;
86 case 'c':
87 switch (operand) {
88 case kMipsCondEq:
89 strcpy(tbuf, "eq");
90 break;
91 case kMipsCondNe:
92 strcpy(tbuf, "ne");
93 break;
94 case kMipsCondLt:
95 strcpy(tbuf, "lt");
96 break;
97 case kMipsCondGe:
98 strcpy(tbuf, "ge");
99 break;
100 case kMipsCondGt:
101 strcpy(tbuf, "gt");
102 break;
103 case kMipsCondLe:
104 strcpy(tbuf, "le");
105 break;
106 case kMipsCondCs:
107 strcpy(tbuf, "cs");
108 break;
109 case kMipsCondMi:
110 strcpy(tbuf, "mi");
111 break;
112 default:
113 strcpy(tbuf, "");
114 break;
115 }
116 break;
117 case 't':
118 sprintf(tbuf,"0x%08x (L%p)",
119 (int) baseAddr + lir->generic.offset + 4 +
120 (operand << 2),
121 lir->generic.target);
122 break;
123 case 'T':
124 sprintf(tbuf,"0x%08x",
125 (int) (operand << 2));
126 break;
127 case 'u': {
128 int offset_1 = lir->operands[0];
129 int offset_2 = NEXT_LIR(lir)->operands[0];
130 intptr_t target =
131 ((((intptr_t) baseAddr + lir->generic.offset + 4) &
132 ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
133 0xfffffffc;
134 sprintf(tbuf, "%p", (void *) target);
135 break;
136 }
137
138 /* Nothing to print for BLX_2 */
139 case 'v':
140 strcpy(tbuf, "see above");
141 break;
142 case 'r':
143 assert(operand >= 0 && operand < MIPS_REG_COUNT);
144 strcpy(tbuf, mipsRegName[operand]);
145 break;
Chris Dearman5e22c9a2013-10-25 11:40:53 -0700146 case 'B':
147 switch (operand) {
148 case kSY:
149 name = "0/sy";
150 break;
151 case kWMB:
152 name = "4/wmb";
153 break;
154 case kMB:
155 name = "16/mb";
156 break;
157 case kACQUIRE:
158 name = "17/acquire";
159 break;
160 case kRELEASE:
161 name = "18/release";
162 break;
163 case kRMB:
164 name = "19/rmb";
165 break;
166 default:
167 name = "DecodeError";
168 break;
169 }
170 strcpy(tbuf, name);
171 break;
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700172 default:
173 strcpy(tbuf,"DecodeError");
174 break;
175 }
176 if (buf+strlen(tbuf) <= bufEnd) {
177 strcpy(buf, tbuf);
178 buf += strlen(tbuf);
179 } else {
180 break;
181 }
182 }
183 } else {
184 *buf++ = *fmt++;
185 }
186 if (buf == bufEnd)
187 break;
188 }
189 *buf = 0;
190}
191
192void dvmDumpResourceMask(LIR *lir, u8 mask, const char *prefix)
193{
194 char buf[256];
195 buf[0] = 0;
196 MipsLIR *mipsLIR = (MipsLIR *) lir;
197
198 if (mask == ENCODE_ALL) {
199 strcpy(buf, "all");
200 } else {
201 char num[8];
202 int i;
203
204 for (i = 0; i < kRegEnd; i++) {
205 if (mask & (1ULL << i)) {
206 sprintf(num, "%d ", i);
207 strcat(buf, num);
208 }
209 }
210
211 if (mask & ENCODE_CCODE) {
212 strcat(buf, "cc ");
213 }
214 if (mask & ENCODE_FP_STATUS) {
215 strcat(buf, "fpcc ");
216 }
217 /* Memory bits */
218 if (mipsLIR && (mask & ENCODE_DALVIK_REG)) {
219 sprintf(buf + strlen(buf), "dr%d%s", mipsLIR->aliasInfo & 0xffff,
220 (mipsLIR->aliasInfo & 0x80000000) ? "(+1)" : "");
221 }
222 if (mask & ENCODE_LITERAL) {
223 strcat(buf, "lit ");
224 }
225
226 if (mask & ENCODE_HEAP_REF) {
227 strcat(buf, "heap ");
228 }
229 if (mask & ENCODE_MUST_NOT_ALIAS) {
230 strcat(buf, "noalias ");
231 }
232 }
233 if (buf[0]) {
Raghu Gandhamfc3b0c42012-07-30 14:46:12 -0700234 ALOGD("%s: %s", prefix, buf);
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700235 }
236}
237
238/*
239 * Debugging macros
240 */
241#define DUMP_RESOURCE_MASK(X)
242#define DUMP_SSA_REP(X)
243
244/* Pretty-print a LIR instruction */
245void dvmDumpLIRInsn(LIR *arg, unsigned char *baseAddr)
246{
247 MipsLIR *lir = (MipsLIR *) arg;
248 char buf[256];
249 char opName[256];
250 int offset = lir->generic.offset;
251 int dest = lir->operands[0];
252 const bool dumpNop = false;
253
254 /* Handle pseudo-ops individually, and all regular insns as a group */
255 switch(lir->opcode) {
256 case kMipsChainingCellBottom:
Raghu Gandhamfc3b0c42012-07-30 14:46:12 -0700257 ALOGD("-------- end of chaining cells (0x%04x)", offset);
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700258 break;
259 case kMipsPseudoBarrier:
Raghu Gandhamfc3b0c42012-07-30 14:46:12 -0700260 ALOGD("-------- BARRIER");
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700261 break;
262 case kMipsPseudoExtended:
263 /* intentional fallthrough */
264 case kMipsPseudoSSARep:
Raghu Gandhamfc3b0c42012-07-30 14:46:12 -0700265 DUMP_SSA_REP(ALOGD("-------- %s", (char *) dest));
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700266 break;
267 case kMipsPseudoChainingCellBackwardBranch:
Raghu Gandhamfc3b0c42012-07-30 14:46:12 -0700268 ALOGD("L%p:", lir);
269 ALOGD("-------- chaining cell (backward branch): 0x%04x", dest);
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700270 break;
271 case kMipsPseudoChainingCellNormal:
Raghu Gandhamfc3b0c42012-07-30 14:46:12 -0700272 ALOGD("L%p:", lir);
273 ALOGD("-------- chaining cell (normal): 0x%04x", dest);
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700274 break;
275 case kMipsPseudoChainingCellHot:
Raghu Gandhamfc3b0c42012-07-30 14:46:12 -0700276 ALOGD("L%p:", lir);
277 ALOGD("-------- chaining cell (hot): 0x%04x", dest);
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700278 break;
279 case kMipsPseudoChainingCellInvokePredicted:
Raghu Gandhamfc3b0c42012-07-30 14:46:12 -0700280 ALOGD("L%p:", lir);
281 ALOGD("-------- chaining cell (predicted): %s%s",
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700282 dest ? ((Method *) dest)->clazz->descriptor : "",
283 dest ? ((Method *) dest)->name : "N/A");
284 break;
285 case kMipsPseudoChainingCellInvokeSingleton:
Raghu Gandhamfc3b0c42012-07-30 14:46:12 -0700286 ALOGD("L%p:", lir);
287 ALOGD("-------- chaining cell (invoke singleton): %s%s/%p",
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700288 ((Method *)dest)->clazz->descriptor,
289 ((Method *)dest)->name,
290 ((Method *)dest)->insns);
291 break;
292 case kMipsPseudoEntryBlock:
Raghu Gandhamfc3b0c42012-07-30 14:46:12 -0700293 ALOGD("-------- entry offset: 0x%04x", dest);
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700294 break;
295 case kMipsPseudoDalvikByteCodeBoundary:
Raghu Gandhamfc3b0c42012-07-30 14:46:12 -0700296 ALOGD("-------- dalvik offset: 0x%04x @ %s", dest,
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700297 (char *) lir->operands[1]);
298 break;
299 case kMipsPseudoExitBlock:
Raghu Gandhamfc3b0c42012-07-30 14:46:12 -0700300 ALOGD("-------- exit offset: 0x%04x", dest);
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700301 break;
302 case kMipsPseudoPseudoAlign4:
Raghu Gandhamfc3b0c42012-07-30 14:46:12 -0700303 ALOGD("%p (%04x): .align4", baseAddr + offset, offset);
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700304 break;
305 case kMipsPseudoPCReconstructionCell:
Raghu Gandhamfc3b0c42012-07-30 14:46:12 -0700306 ALOGD("L%p:", lir);
307 ALOGD("-------- reconstruct dalvik PC : 0x%04x @ +0x%04x", dest,
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700308 lir->operands[1]);
309 break;
310 case kMipsPseudoPCReconstructionBlockLabel:
311 /* Do nothing */
312 break;
313 case kMipsPseudoEHBlockLabel:
Raghu Gandhamfc3b0c42012-07-30 14:46:12 -0700314 ALOGD("Exception_Handling:");
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700315 break;
316 case kMipsPseudoTargetLabel:
317 case kMipsPseudoNormalBlockLabel:
Raghu Gandhamfc3b0c42012-07-30 14:46:12 -0700318 ALOGD("L%p:", lir);
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700319 break;
320 default:
321 if (lir->flags.isNop && !dumpNop) {
322 break;
323 }
324 buildInsnString(EncodingMap[lir->opcode].name, lir, opName,
325 baseAddr, 256);
326 buildInsnString(EncodingMap[lir->opcode].fmt, lir, buf, baseAddr,
327 256);
Raghu Gandhamfc3b0c42012-07-30 14:46:12 -0700328 ALOGD("%p (%04x): %08x %-9s%s%s",
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700329 baseAddr + offset, offset, *(u4 *)(baseAddr + offset), opName, buf,
330 lir->flags.isNop ? "(nop)" : "");
331 break;
332 }
333
334 if (lir->useMask && (!lir->flags.isNop || dumpNop)) {
335 DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir,
336 lir->useMask, "use"));
337 }
338 if (lir->defMask && (!lir->flags.isNop || dumpNop)) {
339 DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir,
340 lir->defMask, "def"));
341 }
342}
343
344/* Dump instructions and constant pool contents */
345void dvmCompilerCodegenDump(CompilationUnit *cUnit)
346{
Raghu Gandhamfc3b0c42012-07-30 14:46:12 -0700347 ALOGD("Dumping LIR insns");
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700348 LIR *lirInsn;
349 MipsLIR *mipsLIR;
350
Raghu Gandhamfc3b0c42012-07-30 14:46:12 -0700351 ALOGD("installed code is at %p", cUnit->baseAddr);
352 ALOGD("total size is %d bytes", cUnit->totalSize);
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700353 for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
354 dvmDumpLIRInsn(lirInsn, (unsigned char *) cUnit->baseAddr);
355 }
356 for (lirInsn = cUnit->classPointerList; lirInsn; lirInsn = lirInsn->next) {
357 mipsLIR = (MipsLIR *) lirInsn;
Raghu Gandhamfc3b0c42012-07-30 14:46:12 -0700358 ALOGD("%p (%04x): .class (%s)",
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700359 (char*)cUnit->baseAddr + mipsLIR->generic.offset,
360 mipsLIR->generic.offset,
361 ((CallsiteInfo *) mipsLIR->operands[0])->classDescriptor);
362 }
363 for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
364 mipsLIR = (MipsLIR *) lirInsn;
Raghu Gandhamfc3b0c42012-07-30 14:46:12 -0700365 ALOGD("%p (%04x): .word (%#x)",
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700366 (char*)cUnit->baseAddr + mipsLIR->generic.offset,
367 mipsLIR->generic.offset,
368 mipsLIR->operands[0]);
369 }
370}
371
372/* Target-specific cache flushing */
Dong-Yuan Chen0c2dc522012-07-03 13:13:07 -0700373void dvmCompilerCacheFlush(long start, long end, long flags)
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700374{
Dong-Yuan Chen0c2dc522012-07-03 13:13:07 -0700375 cacheflush(start, end, flags);
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700376}
377
378/* Target-specific cache clearing */
379void dvmCompilerCacheClear(char *start, size_t size)
380{
381 /* 0x66 is an invalid opcode for mips. */
382 memset(start, 0x66, size);
383}