• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "MipsLIR.h"
20 
21 /* For dumping instructions */
22 #define MIPS_REG_COUNT 32
23 static 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  */
buildInsnString(const char * fmt,MipsLIR * lir,char * buf,unsigned char * baseAddr,int size)34 static 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];
41     char nc;
42     while (fmt < fmtEnd) {
43         int operand;
44         if (*fmt == '!') {
45             fmt++;
46             assert(fmt < fmtEnd);
47             nc = *fmt++;
48             if (nc=='!') {
49                 strcpy(tbuf, "!");
50             } else {
51                assert(fmt < fmtEnd);
52                assert((unsigned)(nc-'0') < 4);
53                operand = lir->operands[nc-'0'];
54                switch(*fmt++) {
55                    case 'b':
56                        strcpy(tbuf,"0000");
57                        for (i=3; i>= 0; i--) {
58                            tbuf[i] += operand & 1;
59                            operand >>= 1;
60                        }
61                        break;
62                    case 's':
63                        sprintf(tbuf,"$f%d",operand & FP_REG_MASK);
64                        break;
65                    case 'S':
66 		       assert(((operand & FP_REG_MASK) & 1) == 0);
67                        sprintf(tbuf,"$f%d",operand & FP_REG_MASK);
68                        break;
69                    case 'h':
70                        sprintf(tbuf,"%04x", operand);
71                        break;
72                    case 'M':
73                    case 'd':
74                        sprintf(tbuf,"%d", operand);
75                        break;
76                    case 'D':
77                        sprintf(tbuf,"%d", operand+1);
78                        break;
79                    case 'E':
80                        sprintf(tbuf,"%d", operand*4);
81                        break;
82                    case 'F':
83                        sprintf(tbuf,"%d", operand*2);
84                        break;
85                    case 'c':
86                        switch (operand) {
87                            case kMipsCondEq:
88                                strcpy(tbuf, "eq");
89                                break;
90                            case kMipsCondNe:
91                                strcpy(tbuf, "ne");
92                                break;
93                            case kMipsCondLt:
94                                strcpy(tbuf, "lt");
95                                break;
96                            case kMipsCondGe:
97                                strcpy(tbuf, "ge");
98                                break;
99                            case kMipsCondGt:
100                                strcpy(tbuf, "gt");
101                                break;
102                            case kMipsCondLe:
103                                strcpy(tbuf, "le");
104                                break;
105                            case kMipsCondCs:
106                                strcpy(tbuf, "cs");
107                                break;
108                            case kMipsCondMi:
109                                strcpy(tbuf, "mi");
110                                break;
111                            default:
112                                strcpy(tbuf, "");
113                                break;
114                        }
115                        break;
116                    case 't':
117                        sprintf(tbuf,"0x%08x (L%p)",
118                                (int) baseAddr + lir->generic.offset + 4 +
119                                (operand << 2),
120                                lir->generic.target);
121                        break;
122                    case 'T':
123                        sprintf(tbuf,"0x%08x",
124                                (int) (operand << 2));
125                        break;
126                    case 'u': {
127                        int offset_1 = lir->operands[0];
128                        int offset_2 = NEXT_LIR(lir)->operands[0];
129                        intptr_t target =
130                            ((((intptr_t) baseAddr + lir->generic.offset + 4) &
131                             ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
132                            0xfffffffc;
133                        sprintf(tbuf, "%p", (void *) target);
134                        break;
135                     }
136 
137                    /* Nothing to print for BLX_2 */
138                    case 'v':
139                        strcpy(tbuf, "see above");
140                        break;
141                    case 'r':
142                        assert(operand >= 0 && operand < MIPS_REG_COUNT);
143                        strcpy(tbuf, mipsRegName[operand]);
144                        break;
145                    default:
146                        strcpy(tbuf,"DecodeError");
147                        break;
148                }
149                if (buf+strlen(tbuf) <= bufEnd) {
150                    strcpy(buf, tbuf);
151                    buf += strlen(tbuf);
152                } else {
153                    break;
154                }
155             }
156         } else {
157            *buf++ = *fmt++;
158         }
159         if (buf == bufEnd)
160             break;
161     }
162     *buf = 0;
163 }
164 
dvmDumpResourceMask(LIR * lir,u8 mask,const char * prefix)165 void dvmDumpResourceMask(LIR *lir, u8 mask, const char *prefix)
166 {
167     char buf[256];
168     buf[0] = 0;
169     MipsLIR *mipsLIR = (MipsLIR *) lir;
170 
171     if (mask == ENCODE_ALL) {
172         strcpy(buf, "all");
173     } else {
174         char num[8];
175         int i;
176 
177         for (i = 0; i < kRegEnd; i++) {
178             if (mask & (1ULL << i)) {
179                 sprintf(num, "%d ", i);
180                 strcat(buf, num);
181             }
182         }
183 
184         if (mask & ENCODE_CCODE) {
185             strcat(buf, "cc ");
186         }
187         if (mask & ENCODE_FP_STATUS) {
188             strcat(buf, "fpcc ");
189         }
190         /* Memory bits */
191         if (mipsLIR && (mask & ENCODE_DALVIK_REG)) {
192             sprintf(buf + strlen(buf), "dr%d%s", mipsLIR->aliasInfo & 0xffff,
193                     (mipsLIR->aliasInfo & 0x80000000) ? "(+1)" : "");
194         }
195         if (mask & ENCODE_LITERAL) {
196             strcat(buf, "lit ");
197         }
198 
199         if (mask & ENCODE_HEAP_REF) {
200             strcat(buf, "heap ");
201         }
202         if (mask & ENCODE_MUST_NOT_ALIAS) {
203             strcat(buf, "noalias ");
204         }
205     }
206     if (buf[0]) {
207         ALOGD("%s: %s", prefix, buf);
208     }
209 }
210 
211 /*
212  * Debugging macros
213  */
214 #define DUMP_RESOURCE_MASK(X)
215 #define DUMP_SSA_REP(X)
216 
217 /* Pretty-print a LIR instruction */
dvmDumpLIRInsn(LIR * arg,unsigned char * baseAddr)218 void dvmDumpLIRInsn(LIR *arg, unsigned char *baseAddr)
219 {
220     MipsLIR *lir = (MipsLIR *) arg;
221     char buf[256];
222     char opName[256];
223     int offset = lir->generic.offset;
224     int dest = lir->operands[0];
225     const bool dumpNop = false;
226 
227     /* Handle pseudo-ops individually, and all regular insns as a group */
228     switch(lir->opcode) {
229         case kMipsChainingCellBottom:
230             ALOGD("-------- end of chaining cells (0x%04x)", offset);
231             break;
232         case kMipsPseudoBarrier:
233             ALOGD("-------- BARRIER");
234             break;
235         case kMipsPseudoExtended:
236             /* intentional fallthrough */
237         case kMipsPseudoSSARep:
238             DUMP_SSA_REP(ALOGD("-------- %s", (char *) dest));
239             break;
240         case kMipsPseudoChainingCellBackwardBranch:
241             ALOGD("L%p:", lir);
242             ALOGD("-------- chaining cell (backward branch): 0x%04x", dest);
243             break;
244         case kMipsPseudoChainingCellNormal:
245             ALOGD("L%p:", lir);
246             ALOGD("-------- chaining cell (normal): 0x%04x", dest);
247             break;
248         case kMipsPseudoChainingCellHot:
249             ALOGD("L%p:", lir);
250             ALOGD("-------- chaining cell (hot): 0x%04x", dest);
251             break;
252         case kMipsPseudoChainingCellInvokePredicted:
253             ALOGD("L%p:", lir);
254             ALOGD("-------- chaining cell (predicted): %s%s",
255                  dest ? ((Method *) dest)->clazz->descriptor : "",
256                  dest ? ((Method *) dest)->name : "N/A");
257             break;
258         case kMipsPseudoChainingCellInvokeSingleton:
259             ALOGD("L%p:", lir);
260             ALOGD("-------- chaining cell (invoke singleton): %s%s/%p",
261                  ((Method *)dest)->clazz->descriptor,
262                  ((Method *)dest)->name,
263                  ((Method *)dest)->insns);
264             break;
265         case kMipsPseudoEntryBlock:
266             ALOGD("-------- entry offset: 0x%04x", dest);
267             break;
268         case kMipsPseudoDalvikByteCodeBoundary:
269             ALOGD("-------- dalvik offset: 0x%04x @ %s", dest,
270                  (char *) lir->operands[1]);
271             break;
272         case kMipsPseudoExitBlock:
273             ALOGD("-------- exit offset: 0x%04x", dest);
274             break;
275         case kMipsPseudoPseudoAlign4:
276             ALOGD("%p (%04x): .align4", baseAddr + offset, offset);
277             break;
278         case kMipsPseudoPCReconstructionCell:
279             ALOGD("L%p:", lir);
280             ALOGD("-------- reconstruct dalvik PC : 0x%04x @ +0x%04x", dest,
281                  lir->operands[1]);
282             break;
283         case kMipsPseudoPCReconstructionBlockLabel:
284             /* Do nothing */
285             break;
286         case kMipsPseudoEHBlockLabel:
287             ALOGD("Exception_Handling:");
288             break;
289         case kMipsPseudoTargetLabel:
290         case kMipsPseudoNormalBlockLabel:
291             ALOGD("L%p:", lir);
292             break;
293         default:
294             if (lir->flags.isNop && !dumpNop) {
295                 break;
296             }
297             buildInsnString(EncodingMap[lir->opcode].name, lir, opName,
298                             baseAddr, 256);
299             buildInsnString(EncodingMap[lir->opcode].fmt, lir, buf, baseAddr,
300                             256);
301             ALOGD("%p (%04x): %08x %-9s%s%s",
302                  baseAddr + offset, offset, *(u4 *)(baseAddr + offset), opName, buf,
303                  lir->flags.isNop ? "(nop)" : "");
304             break;
305     }
306 
307     if (lir->useMask && (!lir->flags.isNop || dumpNop)) {
308         DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir,
309                                                lir->useMask, "use"));
310     }
311     if (lir->defMask && (!lir->flags.isNop || dumpNop)) {
312         DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir,
313                                                lir->defMask, "def"));
314     }
315 }
316 
317 /* Dump instructions and constant pool contents */
dvmCompilerCodegenDump(CompilationUnit * cUnit)318 void dvmCompilerCodegenDump(CompilationUnit *cUnit)
319 {
320     ALOGD("Dumping LIR insns");
321     LIR *lirInsn;
322     MipsLIR *mipsLIR;
323 
324     ALOGD("installed code is at %p", cUnit->baseAddr);
325     ALOGD("total size is %d bytes", cUnit->totalSize);
326     for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
327         dvmDumpLIRInsn(lirInsn, (unsigned char *) cUnit->baseAddr);
328     }
329     for (lirInsn = cUnit->classPointerList; lirInsn; lirInsn = lirInsn->next) {
330         mipsLIR = (MipsLIR *) lirInsn;
331         ALOGD("%p (%04x): .class (%s)",
332              (char*)cUnit->baseAddr + mipsLIR->generic.offset,
333              mipsLIR->generic.offset,
334              ((CallsiteInfo *) mipsLIR->operands[0])->classDescriptor);
335     }
336     for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
337         mipsLIR = (MipsLIR *) lirInsn;
338         ALOGD("%p (%04x): .word (%#x)",
339              (char*)cUnit->baseAddr + mipsLIR->generic.offset,
340              mipsLIR->generic.offset,
341              mipsLIR->operands[0]);
342     }
343 }
344 
345 /* Target-specific cache flushing */
dvmCompilerCacheFlush(long start,long end,long flags)346 void dvmCompilerCacheFlush(long start, long end, long flags)
347 {
348     cacheflush(start, end, flags);
349 }
350 
351 /* Target-specific cache clearing */
dvmCompilerCacheClear(char * start,size_t size)352 void dvmCompilerCacheClear(char *start, size_t size)
353 {
354     /* 0x66 is an invalid opcode for mips. */
355     memset(start, 0x66, size);
356 }
357