Home | History | Annotate | Download | only in arm
      1 /*
      2  * Copyright (C) 2010 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 /*
     18  * This file contains arm-specific codegen factory support.
     19  * It is included by
     20  *
     21  *        Codegen-$(TARGET_ARCH_VARIANT).c
     22  *
     23  */
     24 
     25 /*
     26  * Perform a "reg cmp imm" operation and jump to the PCR region if condition
     27  * satisfies.
     28  */
     29 static TGT_LIR *genRegImmCheck(CompilationUnit *cUnit,
     30                                ArmConditionCode cond, int reg,
     31                                int checkValue, int dOffset,
     32                                TGT_LIR *pcrLabel)
     33 {
     34     TGT_LIR *branch = genCmpImmBranch(cUnit, cond, reg, checkValue);
     35     if (cUnit->jitMode == kJitMethod) {
     36         BasicBlock *bb = cUnit->curBlock;
     37         if (bb->taken) {
     38             ArmLIR  *exceptionLabel = (ArmLIR *) cUnit->blockLabelList;
     39             exceptionLabel += bb->taken->id;
     40             branch->generic.target = (LIR *) exceptionLabel;
     41             return exceptionLabel;
     42         } else {
     43             ALOGE("Catch blocks not handled yet");
     44             dvmAbort();
     45             return NULL;
     46         }
     47     } else {
     48         return genCheckCommon(cUnit, dOffset, branch, pcrLabel);
     49     }
     50 }
     51 
     52 /*
     53  * Perform null-check on a register. sReg is the ssa register being checked,
     54  * and mReg is the machine register holding the actual value. If internal state
     55  * indicates that sReg has been checked before the check request is ignored.
     56  */
     57 static TGT_LIR *genNullCheck(CompilationUnit *cUnit, int sReg, int mReg,
     58                              int dOffset, TGT_LIR *pcrLabel)
     59 {
     60     /* This particular Dalvik register has been null-checked */
     61     if (dvmIsBitSet(cUnit->regPool->nullCheckedRegs, sReg)) {
     62         return pcrLabel;
     63     }
     64     dvmSetBit(cUnit->regPool->nullCheckedRegs, sReg);
     65     return genRegImmCheck(cUnit, kArmCondEq, mReg, 0, dOffset, pcrLabel);
     66 }
     67 
     68 /*
     69  * Perform a "reg cmp reg" operation and jump to the PCR region if condition
     70  * satisfies.
     71  */
     72 static TGT_LIR *genRegRegCheck(CompilationUnit *cUnit,
     73                                ArmConditionCode cond,
     74                                int reg1, int reg2, int dOffset,
     75                                TGT_LIR *pcrLabel)
     76 {
     77     TGT_LIR *res;
     78     res = opRegReg(cUnit, kOpCmp, reg1, reg2);
     79     TGT_LIR *branch = opCondBranch(cUnit, cond);
     80     genCheckCommon(cUnit, dOffset, branch, pcrLabel);
     81     return res;
     82 }
     83 
     84 /*
     85  * Perform zero-check on a register. Similar to genNullCheck but the value being
     86  * checked does not have a corresponding Dalvik register.
     87  */
     88 static TGT_LIR *genZeroCheck(CompilationUnit *cUnit, int mReg,
     89                              int dOffset, TGT_LIR *pcrLabel)
     90 {
     91     return genRegImmCheck(cUnit, kArmCondEq, mReg, 0, dOffset, pcrLabel);
     92 }
     93 
     94 /* Perform bound check on two registers */
     95 static TGT_LIR *genBoundsCheck(CompilationUnit *cUnit, int rIndex,
     96                                int rBound, int dOffset, TGT_LIR *pcrLabel)
     97 {
     98     return genRegRegCheck(cUnit, kArmCondCs, rIndex, rBound, dOffset,
     99                           pcrLabel);
    100 }
    101 
    102 /*
    103  * Jump to the out-of-line handler in ARM mode to finish executing the
    104  * remaining of more complex instructions.
    105  */
    106 static void genDispatchToHandler(CompilationUnit *cUnit, TemplateOpcode opcode)
    107 {
    108     /*
    109      * NOTE - In practice BLX only needs one operand, but since the assembler
    110      * may abort itself and retry due to other out-of-range conditions we
    111      * cannot really use operand[0] to store the absolute target address since
    112      * it may get clobbered by the final relative offset. Therefore,
    113      * we fake BLX_1 is a two operand instruction and the absolute target
    114      * address is stored in operand[1].
    115      */
    116     dvmCompilerClobberHandlerRegs(cUnit);
    117     newLIR2(cUnit, kThumbBlx1,
    118             (int) gDvmJit.codeCache + templateEntryOffsets[opcode],
    119             (int) gDvmJit.codeCache + templateEntryOffsets[opcode]);
    120     newLIR2(cUnit, kThumbBlx2,
    121             (int) gDvmJit.codeCache + templateEntryOffsets[opcode],
    122             (int) gDvmJit.codeCache + templateEntryOffsets[opcode]);
    123 }
    124