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 LOGE("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