Home | History | Annotate | Download | only in arm
      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 */
     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 
     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  */
     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 
    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         LOGD("%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 */
    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             LOGD("-------- end of chaining cells (0x%04x)", offset);
    308             break;
    309         case kArmPseudoBarrier:
    310             LOGD("-------- BARRIER");
    311             break;
    312         case kArmPseudoExtended:
    313             LOGD("-------- %s", (char *) dest);
    314             break;
    315         case kArmPseudoSSARep:
    316             DUMP_SSA_REP(LOGD("-------- %s", (char *) dest));
    317             break;
    318         case kArmPseudoChainingCellBackwardBranch:
    319             LOGD("L%p:", lir);
    320             LOGD("-------- chaining cell (backward branch): 0x%04x", dest);
    321             break;
    322         case kArmPseudoChainingCellNormal:
    323             LOGD("L%p:", lir);
    324             LOGD("-------- chaining cell (normal): 0x%04x", dest);
    325             break;
    326         case kArmPseudoChainingCellHot:
    327             LOGD("L%p:", lir);
    328             LOGD("-------- chaining cell (hot): 0x%04x", dest);
    329             break;
    330         case kArmPseudoChainingCellInvokePredicted:
    331             LOGD("L%p:", lir);
    332             LOGD("-------- chaining cell (predicted): %s%s",
    333                  dest ? ((Method *) dest)->clazz->descriptor : "",
    334                  dest ? ((Method *) dest)->name : "N/A");
    335             break;
    336         case kArmPseudoChainingCellInvokeSingleton:
    337             LOGD("L%p:", lir);
    338             LOGD("-------- 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             LOGD("-------- entry offset: 0x%04x", dest);
    345             break;
    346         case kArmPseudoDalvikByteCodeBoundary:
    347             LOGD("-------- dalvik offset: 0x%04x @ %s", dest,
    348                  (char *) lir->operands[1]);
    349             break;
    350         case kArmPseudoExitBlock:
    351             LOGD("-------- exit offset: 0x%04x", dest);
    352             break;
    353         case kArmPseudoPseudoAlign4:
    354             LOGD("%p (%04x): .align4", baseAddr + offset, offset);
    355             break;
    356         case kArmPseudoPCReconstructionCell:
    357             LOGD("L%p:", lir);
    358             LOGD("-------- 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             LOGD("Exception_Handling:");
    366             break;
    367         case kArmPseudoTargetLabel:
    368         case kArmPseudoNormalBlockLabel:
    369             LOGD("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             LOGD("%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 */
    396 void dvmCompilerCodegenDump(CompilationUnit *cUnit)
    397 {
    398     LOGD("Dumping LIR insns");
    399     LIR *lirInsn;
    400     ArmLIR *armLIR;
    401 
    402     LOGD("installed code is at %p", cUnit->baseAddr);
    403     LOGD("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         LOGD("%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         LOGD("%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 */
    424 int dvmCompilerCacheFlush(long start, long end, long flags)
    425 {
    426     return cacheflush(start, end, flags);
    427 }
    428