| /* |
| * 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]); |
| } |