/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * This file contains arm-specific codegen factory support. * It is included by * * Codegen-$(TARGET_ARCH_VARIANT).c * */ /* * Perform a "reg cmp imm" operation and jump to the PCR region if condition * satisfies. */ static TGT_LIR *genRegImmCheck(CompilationUnit *cUnit, ArmConditionCode cond, int reg, int checkValue, int dOffset, TGT_LIR *pcrLabel) { TGT_LIR *branch = genCmpImmBranch(cUnit, cond, reg, checkValue); if (cUnit->jitMode == kJitMethod) { BasicBlock *bb = cUnit->curBlock; if (bb->taken) { ArmLIR *exceptionLabel = (ArmLIR *) cUnit->blockLabelList; exceptionLabel += bb->taken->id; branch->generic.target = (LIR *) exceptionLabel; return exceptionLabel; } else { ALOGE("Catch blocks not handled yet"); dvmAbort(); return NULL; } } else { return genCheckCommon(cUnit, dOffset, branch, pcrLabel); } } /* * Perform null-check on a register. sReg is the ssa register being checked, * and mReg is the machine register holding the actual value. If internal state * indicates that sReg has been checked before the check request is ignored. */ static TGT_LIR *genNullCheck(CompilationUnit *cUnit, int sReg, int mReg, int dOffset, TGT_LIR *pcrLabel) { /* This particular Dalvik register has been null-checked */ if (dvmIsBitSet(cUnit->regPool->nullCheckedRegs, sReg)) { return pcrLabel; } dvmSetBit(cUnit->regPool->nullCheckedRegs, sReg); return genRegImmCheck(cUnit, kArmCondEq, mReg, 0, dOffset, pcrLabel); } /* * Perform a "reg cmp reg" operation and jump to the PCR region if condition * satisfies. */ static TGT_LIR *genRegRegCheck(CompilationUnit *cUnit, ArmConditionCode cond, int reg1, int reg2, int dOffset, TGT_LIR *pcrLabel) { TGT_LIR *res; res = opRegReg(cUnit, kOpCmp, reg1, reg2); TGT_LIR *branch = opCondBranch(cUnit, cond); genCheckCommon(cUnit, dOffset, branch, pcrLabel); return res; } /* * Perform zero-check on a register. Similar to genNullCheck but the value being * checked does not have a corresponding Dalvik register. */ static TGT_LIR *genZeroCheck(CompilationUnit *cUnit, int mReg, int dOffset, TGT_LIR *pcrLabel) { return genRegImmCheck(cUnit, kArmCondEq, mReg, 0, dOffset, pcrLabel); } /* Perform bound check on two registers */ static TGT_LIR *genBoundsCheck(CompilationUnit *cUnit, int rIndex, int rBound, int dOffset, TGT_LIR *pcrLabel) { return genRegRegCheck(cUnit, kArmCondCs, rIndex, rBound, dOffset, pcrLabel); } /* * Jump to the out-of-line handler in ARM mode to finish executing the * remaining of more complex instructions. */ static void genDispatchToHandler(CompilationUnit *cUnit, TemplateOpcode opcode) { /* * NOTE - In practice BLX only needs one operand, but since the assembler * may abort itself and retry due to other out-of-range conditions we * cannot really use operand[0] to store the absolute target address since * it may get clobbered by the final relative offset. Therefore, * we fake BLX_1 is a two operand instruction and the absolute target * address is stored in operand[1]. */ dvmCompilerClobberHandlerRegs(cUnit); newLIR2(cUnit, kThumbBlx1, (int) gDvmJit.codeCache + templateEntryOffsets[opcode], (int) gDvmJit.codeCache + templateEntryOffsets[opcode]); newLIR2(cUnit, kThumbBlx2, (int) gDvmJit.codeCache + templateEntryOffsets[opcode], (int) gDvmJit.codeCache + templateEntryOffsets[opcode]); }