• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
genRegImmCheck(CompilationUnit * cUnit,ArmConditionCode cond,int reg,int checkValue,int dOffset,TGT_LIR * pcrLabel)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  */
genNullCheck(CompilationUnit * cUnit,int sReg,int mReg,int dOffset,TGT_LIR * pcrLabel)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  */
genRegRegCheck(CompilationUnit * cUnit,ArmConditionCode cond,int reg1,int reg2,int dOffset,TGT_LIR * pcrLabel)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  */
genZeroCheck(CompilationUnit * cUnit,int mReg,int dOffset,TGT_LIR * pcrLabel)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 */
genBoundsCheck(CompilationUnit * cUnit,int rIndex,int rBound,int dOffset,TGT_LIR * pcrLabel)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  */
genDispatchToHandler(CompilationUnit * cUnit,TemplateOpcode opcode)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