• 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 "ArmLIR.h"
20 
21 static const char *shiftNames[4] = {
22     "lsl",
23     "lsr",
24     "asr",
25     "ror"};
26 
27 /* Decode and print a ARM register name */
decodeRegList(ArmOpcode opcode,int vector,char * buf)28 static char * decodeRegList(ArmOpcode opcode, int vector, char *buf)
29 {
30     int i;
31     bool printed = false;
32     buf[0] = 0;
33     for (i = 0; i < 16; i++, vector >>= 1) {
34         if (vector & 0x1) {
35             int regId = i;
36             if (opcode == kThumbPush && i == 8) {
37                 regId = r14lr;
38             } else if (opcode == kThumbPop && i == 8) {
39                 regId = r15pc;
40             }
41             if (printed) {
42                 sprintf(buf + strlen(buf), ", r%d", regId);
43             } else {
44                 printed = true;
45                 sprintf(buf, "r%d", regId);
46             }
47         }
48     }
49     return buf;
50 }
51 
expandImmediate(int value)52 static int expandImmediate(int value)
53 {
54     int mode = (value & 0xf00) >> 8;
55     u4 bits = value & 0xff;
56     switch(mode) {
57         case 0:
58             return bits;
59        case 1:
60             return (bits << 16) | bits;
61        case 2:
62             return (bits << 24) | (bits << 8);
63        case 3:
64             return (bits << 24) | (bits << 16) | (bits << 8) | bits;
65       default:
66             break;
67     }
68     bits = (bits | 0x80) << 24;
69     return bits >> (((value & 0xf80) >> 7) - 8);
70 }
71 
72 /*
73  * Interpret a format string and build a string no longer than size
74  * See format key in Assemble.c.
75  */
buildInsnString(const char * fmt,ArmLIR * lir,char * buf,unsigned char * baseAddr,int size)76 static void buildInsnString(const char *fmt, ArmLIR *lir, char* buf,
77                             unsigned char *baseAddr, int size)
78 {
79     int i;
80     char *bufEnd = &buf[size-1];
81     const char *fmtEnd = &fmt[strlen(fmt)];
82     char tbuf[256];
83     const char *name;
84     char nc;
85     while (fmt < fmtEnd) {
86         int operand;
87         if (*fmt == '!') {
88             fmt++;
89             assert(fmt < fmtEnd);
90             nc = *fmt++;
91             if (nc=='!') {
92                 strcpy(tbuf, "!");
93             } else {
94                assert(fmt < fmtEnd);
95                assert((unsigned)(nc-'0') < 4);
96                operand = lir->operands[nc-'0'];
97                switch(*fmt++) {
98                    case 'H':
99                        if (operand != 0) {
100                            sprintf(tbuf, ", %s %d",shiftNames[operand & 0x3],
101                                    operand >> 2);
102                        } else {
103                            strcpy(tbuf,"");
104                        }
105                        break;
106                    case 'B':
107                        switch (operand) {
108                            case kSY:
109                                name = "sy";
110                                break;
111                            case kST:
112                                name = "st";
113                                break;
114                            case kISH:
115                                name = "ish";
116                                break;
117                            case kISHST:
118                                name = "ishst";
119                                break;
120                            case kNSH:
121                                name = "nsh";
122                                break;
123                            case kNSHST:
124                                name = "shst";
125                                break;
126                            default:
127                                name = "DecodeError";
128                                break;
129                        }
130                        strcpy(tbuf, name);
131                        break;
132                    case 'b':
133                        strcpy(tbuf,"0000");
134                        for (i=3; i>= 0; i--) {
135                            tbuf[i] += operand & 1;
136                            operand >>= 1;
137                        }
138                        break;
139                    case 'n':
140                        operand = ~expandImmediate(operand);
141                        sprintf(tbuf,"%d [%#x]", operand, operand);
142                        break;
143                    case 'm':
144                        operand = expandImmediate(operand);
145                        sprintf(tbuf,"%d [%#x]", operand, operand);
146                        break;
147                    case 's':
148                        sprintf(tbuf,"s%d",operand & FP_REG_MASK);
149                        break;
150                    case 'S':
151                        sprintf(tbuf,"d%d",(operand & FP_REG_MASK) >> 1);
152                        break;
153                    case 'h':
154                        sprintf(tbuf,"%04x", operand);
155                        break;
156                    case 'M':
157                    case 'd':
158                        sprintf(tbuf,"%d", operand);
159                        break;
160                    case 'E':
161                        sprintf(tbuf,"%d", operand*4);
162                        break;
163                    case 'F':
164                        sprintf(tbuf,"%d", operand*2);
165                        break;
166                    case 'c':
167                        switch (operand) {
168                            case kArmCondEq:
169                                strcpy(tbuf, "eq");
170                                break;
171                            case kArmCondNe:
172                                strcpy(tbuf, "ne");
173                                break;
174                            case kArmCondLt:
175                                strcpy(tbuf, "lt");
176                                break;
177                            case kArmCondGe:
178                                strcpy(tbuf, "ge");
179                                break;
180                            case kArmCondGt:
181                                strcpy(tbuf, "gt");
182                                break;
183                            case kArmCondLe:
184                                strcpy(tbuf, "le");
185                                break;
186                            case kArmCondCs:
187                                strcpy(tbuf, "cs");
188                                break;
189                            case kArmCondMi:
190                                strcpy(tbuf, "mi");
191                                break;
192                            default:
193                                strcpy(tbuf, "");
194                                break;
195                        }
196                        break;
197                    case 't':
198                        sprintf(tbuf,"0x%08x (L%p)",
199                                (int) baseAddr + lir->generic.offset + 4 +
200                                (operand << 1),
201                                lir->generic.target);
202                        break;
203                    case 'u': {
204                        int offset_1 = lir->operands[0];
205                        int offset_2 = NEXT_LIR(lir)->operands[0];
206                        intptr_t target =
207                            ((((intptr_t) baseAddr + lir->generic.offset + 4) &
208                             ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
209                            0xfffffffc;
210                        sprintf(tbuf, "%p", (void *) target);
211                        break;
212                     }
213 
214                    /* Nothing to print for BLX_2 */
215                    case 'v':
216                        strcpy(tbuf, "see above");
217                        break;
218                    case 'R':
219                        decodeRegList(lir->opcode, operand, tbuf);
220                        break;
221                    default:
222                        strcpy(tbuf,"DecodeError");
223                        break;
224                }
225                if (buf+strlen(tbuf) <= bufEnd) {
226                    strcpy(buf, tbuf);
227                    buf += strlen(tbuf);
228                } else {
229                    break;
230                }
231             }
232         } else {
233            *buf++ = *fmt++;
234         }
235         if (buf == bufEnd)
236             break;
237     }
238     *buf = 0;
239 }
240 
dvmDumpResourceMask(LIR * lir,u8 mask,const char * prefix)241 void dvmDumpResourceMask(LIR *lir, u8 mask, const char *prefix)
242 {
243     char buf[256];
244     buf[0] = 0;
245     ArmLIR *armLIR = (ArmLIR *) lir;
246 
247     if (mask == ENCODE_ALL) {
248         strcpy(buf, "all");
249     } else {
250         char num[8];
251         int i;
252 
253         for (i = 0; i < kRegEnd; i++) {
254             if (mask & (1ULL << i)) {
255                 sprintf(num, "%d ", i);
256                 strcat(buf, num);
257             }
258         }
259 
260         if (mask & ENCODE_CCODE) {
261             strcat(buf, "cc ");
262         }
263         if (mask & ENCODE_FP_STATUS) {
264             strcat(buf, "fpcc ");
265         }
266 
267         /* Memory bits */
268         if (armLIR && (mask & ENCODE_DALVIK_REG)) {
269             sprintf(buf + strlen(buf), "dr%d%s", armLIR->aliasInfo & 0xffff,
270                     (armLIR->aliasInfo & 0x80000000) ? "(+1)" : "");
271         }
272         if (mask & ENCODE_LITERAL) {
273             strcat(buf, "lit ");
274         }
275 
276         if (mask & ENCODE_HEAP_REF) {
277             strcat(buf, "heap ");
278         }
279         if (mask & ENCODE_MUST_NOT_ALIAS) {
280             strcat(buf, "noalias ");
281         }
282     }
283     if (buf[0]) {
284         ALOGD("%s: %s", prefix, buf);
285     }
286 }
287 
288 /*
289  * Debugging macros
290  */
291 #define DUMP_RESOURCE_MASK(X)
292 #define DUMP_SSA_REP(X)
293 
294 /* Pretty-print a LIR instruction */
dvmDumpLIRInsn(LIR * arg,unsigned char * baseAddr)295 void dvmDumpLIRInsn(LIR *arg, unsigned char *baseAddr)
296 {
297     ArmLIR *lir = (ArmLIR *) arg;
298     char buf[256];
299     char opName[256];
300     int offset = lir->generic.offset;
301     int dest = lir->operands[0];
302     const bool dumpNop = false;
303 
304     /* Handle pseudo-ops individually, and all regular insns as a group */
305     switch(lir->opcode) {
306         case kArmChainingCellBottom:
307             ALOGD("-------- end of chaining cells (0x%04x)", offset);
308             break;
309         case kArmPseudoBarrier:
310             ALOGD("-------- BARRIER");
311             break;
312         case kArmPseudoExtended:
313             ALOGD("-------- %s", (char *) dest);
314             break;
315         case kArmPseudoSSARep:
316             DUMP_SSA_REP(LOGD("-------- %s", (char *) dest));
317             break;
318         case kArmPseudoChainingCellBackwardBranch:
319             ALOGD("L%p:", lir);
320             ALOGD("-------- chaining cell (backward branch): 0x%04x", dest);
321             break;
322         case kArmPseudoChainingCellNormal:
323             ALOGD("L%p:", lir);
324             ALOGD("-------- chaining cell (normal): 0x%04x", dest);
325             break;
326         case kArmPseudoChainingCellHot:
327             ALOGD("L%p:", lir);
328             ALOGD("-------- chaining cell (hot): 0x%04x", dest);
329             break;
330         case kArmPseudoChainingCellInvokePredicted:
331             ALOGD("L%p:", lir);
332             ALOGD("-------- chaining cell (predicted): %s%s",
333                  dest ? ((Method *) dest)->clazz->descriptor : "",
334                  dest ? ((Method *) dest)->name : "N/A");
335             break;
336         case kArmPseudoChainingCellInvokeSingleton:
337             ALOGD("L%p:", lir);
338             ALOGD("-------- chaining cell (invoke singleton): %s%s/%p",
339                  ((Method *)dest)->clazz->descriptor,
340                  ((Method *)dest)->name,
341                  ((Method *)dest)->insns);
342             break;
343         case kArmPseudoEntryBlock:
344             ALOGD("-------- entry offset: 0x%04x", dest);
345             break;
346         case kArmPseudoDalvikByteCodeBoundary:
347             ALOGD("-------- dalvik offset: 0x%04x @ %s", dest,
348                  (char *) lir->operands[1]);
349             break;
350         case kArmPseudoExitBlock:
351             ALOGD("-------- exit offset: 0x%04x", dest);
352             break;
353         case kArmPseudoPseudoAlign4:
354             ALOGD("%p (%04x): .align4", baseAddr + offset, offset);
355             break;
356         case kArmPseudoPCReconstructionCell:
357             ALOGD("L%p:", lir);
358             ALOGD("-------- reconstruct dalvik PC : 0x%04x @ +0x%04x", dest,
359                  lir->operands[1]);
360             break;
361         case kArmPseudoPCReconstructionBlockLabel:
362             /* Do nothing */
363             break;
364         case kArmPseudoEHBlockLabel:
365             ALOGD("Exception_Handling:");
366             break;
367         case kArmPseudoTargetLabel:
368         case kArmPseudoNormalBlockLabel:
369             ALOGD("L%p:", lir);
370             break;
371         default:
372             if (lir->flags.isNop && !dumpNop) {
373                 break;
374             }
375             buildInsnString(EncodingMap[lir->opcode].name, lir, opName,
376                             baseAddr, 256);
377             buildInsnString(EncodingMap[lir->opcode].fmt, lir, buf, baseAddr,
378                             256);
379             ALOGD("%p (%04x): %-8s%s%s",
380                  baseAddr + offset, offset, opName, buf,
381                  lir->flags.isNop ? "(nop)" : "");
382             break;
383     }
384 
385     if (lir->useMask && (!lir->flags.isNop || dumpNop)) {
386         DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir,
387                                                lir->useMask, "use"));
388     }
389     if (lir->defMask && (!lir->flags.isNop || dumpNop)) {
390         DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir,
391                                                lir->defMask, "def"));
392     }
393 }
394 
395 /* Dump instructions and constant pool contents */
dvmCompilerCodegenDump(CompilationUnit * cUnit)396 void dvmCompilerCodegenDump(CompilationUnit *cUnit)
397 {
398     ALOGD("Dumping LIR insns");
399     LIR *lirInsn;
400     ArmLIR *armLIR;
401 
402     ALOGD("installed code is at %p", cUnit->baseAddr);
403     ALOGD("total size is %d bytes", cUnit->totalSize);
404     for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
405         dvmDumpLIRInsn(lirInsn, (unsigned char *) cUnit->baseAddr);
406     }
407     for (lirInsn = cUnit->classPointerList; lirInsn; lirInsn = lirInsn->next) {
408         armLIR = (ArmLIR *) lirInsn;
409         ALOGD("%p (%04x): .class (%s)",
410              (char*)cUnit->baseAddr + armLIR->generic.offset,
411              armLIR->generic.offset,
412              ((CallsiteInfo *) armLIR->operands[0])->classDescriptor);
413     }
414     for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
415         armLIR = (ArmLIR *) lirInsn;
416         ALOGD("%p (%04x): .word (%#x)",
417              (char*)cUnit->baseAddr + armLIR->generic.offset,
418              armLIR->generic.offset,
419              armLIR->operands[0]);
420     }
421 }
422 
423 /* Target-specific cache flushing */
dvmCompilerCacheFlush(long start,long end,long flags)424 void dvmCompilerCacheFlush(long start, long end, long flags)
425 {
426     cacheflush(start, end, flags);
427 }
428 
429 /* Target-specific cache clearing */
dvmCompilerCacheClear(char * start,size_t size)430 void dvmCompilerCacheClear(char *start, size_t size)
431 {
432     /*
433      * de is an invalid opcode for arm.
434      * From gdb disassembly:  <UNDEFINED> instruction: 0xdede
435      */
436 
437     memset(start, 0xde, size);
438 }
439