aboutsummaryrefslogtreecommitdiff
path: root/vm/compiler/codegen/arm/CodegenCommon.c
diff options
context:
space:
mode:
Diffstat (limited to 'vm/compiler/codegen/arm/CodegenCommon.c')
-rw-r--r--vm/compiler/codegen/arm/CodegenCommon.c447
1 files changed, 0 insertions, 447 deletions
diff --git a/vm/compiler/codegen/arm/CodegenCommon.c b/vm/compiler/codegen/arm/CodegenCommon.c
deleted file mode 100644
index ae41fe9af..000000000
--- a/vm/compiler/codegen/arm/CodegenCommon.c
+++ /dev/null
@@ -1,447 +0,0 @@
-/*
- * Copyright (C) 2009 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 codegen and support common to all supported
- * ARM variants. It is included by:
- *
- * Codegen-$(TARGET_ARCH_VARIANT).c
- *
- * which combines this common code with specific support found in the
- * applicable directory below this one.
- */
-
-#include "compiler/Loop.h"
-
-/* Array holding the entry offset of each template relative to the first one */
-static intptr_t templateEntryOffsets[TEMPLATE_LAST_MARK];
-
-/* Track exercised opcodes */
-static int opcodeCoverage[kNumPackedOpcodes];
-
-static void setMemRefType(ArmLIR *lir, bool isLoad, int memType)
-{
- u8 *maskPtr;
- u8 mask = ENCODE_MEM;;
- assert(EncodingMap[lir->opcode].flags & (IS_LOAD | IS_STORE));
- if (isLoad) {
- maskPtr = &lir->useMask;
- } else {
- maskPtr = &lir->defMask;
- }
- /* Clear out the memref flags */
- *maskPtr &= ~mask;
- /* ..and then add back the one we need */
- switch(memType) {
- case kLiteral:
- assert(isLoad);
- *maskPtr |= ENCODE_LITERAL;
- break;
- case kDalvikReg:
- *maskPtr |= ENCODE_DALVIK_REG;
- break;
- case kHeapRef:
- *maskPtr |= ENCODE_HEAP_REF;
- break;
- case kMustNotAlias:
- /* Currently only loads can be marked as kMustNotAlias */
- assert(!(EncodingMap[lir->opcode].flags & IS_STORE));
- *maskPtr |= ENCODE_MUST_NOT_ALIAS;
- break;
- default:
- LOGE("Jit: invalid memref kind - %d", memType);
- assert(0); // Bail if debug build, set worst-case in the field
- *maskPtr |= ENCODE_ALL;
- }
-}
-
-/*
- * Mark load/store instructions that access Dalvik registers through r5FP +
- * offset.
- */
-static void annotateDalvikRegAccess(ArmLIR *lir, int regId, bool isLoad)
-{
- setMemRefType(lir, isLoad, kDalvikReg);
-
- /*
- * Store the Dalvik register id in aliasInfo. Mark he MSB if it is a 64-bit
- * access.
- */
- lir->aliasInfo = regId;
- if (DOUBLEREG(lir->operands[0])) {
- lir->aliasInfo |= 0x80000000;
- }
-}
-
-/*
- * Decode the register id.
- */
-static inline u8 getRegMaskCommon(int reg)
-{
- u8 seed;
- int shift;
- int regId = reg & 0x1f;
-
- /*
- * Each double register is equal to a pair of single-precision FP registers
- */
- seed = DOUBLEREG(reg) ? 3 : 1;
- /* FP register starts at bit position 16 */
- shift = FPREG(reg) ? kFPReg0 : 0;
- /* Expand the double register id into single offset */
- shift += regId;
- return (seed << shift);
-}
-
-/* External version of getRegMaskCommon */
-u8 dvmGetRegResourceMask(int reg)
-{
- return getRegMaskCommon(reg);
-}
-
-/*
- * Mark the corresponding bit(s).
- */
-static inline void setupRegMask(u8 *mask, int reg)
-{
- *mask |= getRegMaskCommon(reg);
-}
-
-/*
- * Set up the proper fields in the resource mask
- */
-static void setupResourceMasks(ArmLIR *lir)
-{
- int opcode = lir->opcode;
- int flags;
-
- if (opcode <= 0) {
- lir->useMask = lir->defMask = 0;
- return;
- }
-
- flags = EncodingMap[lir->opcode].flags;
-
- /* Set up the mask for resources that are updated */
- if (flags & (IS_LOAD | IS_STORE)) {
- /* Default to heap - will catch specialized classes later */
- setMemRefType(lir, flags & IS_LOAD, kHeapRef);
- }
-
- /*
- * Conservatively assume the branch here will call out a function that in
- * turn will trash everything.
- */
- if (flags & IS_BRANCH) {
- lir->defMask = lir->useMask = ENCODE_ALL;
- return;
- }
-
- if (flags & REG_DEF0) {
- setupRegMask(&lir->defMask, lir->operands[0]);
- }
-
- if (flags & REG_DEF1) {
- setupRegMask(&lir->defMask, lir->operands[1]);
- }
-
- if (flags & REG_DEF_SP) {
- lir->defMask |= ENCODE_REG_SP;
- }
-
- if (flags & REG_DEF_LR) {
- lir->defMask |= ENCODE_REG_LR;
- }
-
- if (flags & REG_DEF_LIST0) {
- lir->defMask |= ENCODE_REG_LIST(lir->operands[0]);
- }
-
- if (flags & REG_DEF_LIST1) {
- lir->defMask |= ENCODE_REG_LIST(lir->operands[1]);
- }
-
- if (flags & SETS_CCODES) {
- lir->defMask |= ENCODE_CCODE;
- }
-
- /* Conservatively treat the IT block */
- if (flags & IS_IT) {
- lir->defMask = ENCODE_ALL;
- }
-
- if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) {
- int i;
-
- for (i = 0; i < 4; i++) {
- if (flags & (1 << (kRegUse0 + i))) {
- setupRegMask(&lir->useMask, lir->operands[i]);
- }
- }
- }
-
- if (flags & REG_USE_PC) {
- lir->useMask |= ENCODE_REG_PC;
- }
-
- if (flags & REG_USE_SP) {
- lir->useMask |= ENCODE_REG_SP;
- }
-
- if (flags & REG_USE_LIST0) {
- lir->useMask |= ENCODE_REG_LIST(lir->operands[0]);
- }
-
- if (flags & REG_USE_LIST1) {
- lir->useMask |= ENCODE_REG_LIST(lir->operands[1]);
- }
-
- if (flags & USES_CCODES) {
- lir->useMask |= ENCODE_CCODE;
- }
-
- /* Fixup for kThumbPush/lr and kThumbPop/pc */
- if (opcode == kThumbPush || opcode == kThumbPop) {
- u8 r8Mask = getRegMaskCommon(r8);
- if ((opcode == kThumbPush) && (lir->useMask & r8Mask)) {
- lir->useMask &= ~r8Mask;
- lir->useMask |= ENCODE_REG_LR;
- } else if ((opcode == kThumbPop) && (lir->defMask & r8Mask)) {
- lir->defMask &= ~r8Mask;
- lir->defMask |= ENCODE_REG_PC;
- }
- }
-}
-
-/*
- * Set up the accurate resource mask for branch instructions
- */
-static void relaxBranchMasks(ArmLIR *lir)
-{
- int flags = EncodingMap[lir->opcode].flags;
-
- /* Make sure only branch instructions are passed here */
- assert(flags & IS_BRANCH);
-
- lir->useMask = lir->defMask = ENCODE_REG_PC;
-
- if (flags & REG_DEF_LR) {
- lir->defMask |= ENCODE_REG_LR;
- }
-
- if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) {
- int i;
-
- for (i = 0; i < 4; i++) {
- if (flags & (1 << (kRegUse0 + i))) {
- setupRegMask(&lir->useMask, lir->operands[i]);
- }
- }
- }
-
- if (flags & USES_CCODES) {
- lir->useMask |= ENCODE_CCODE;
- }
-}
-
-/*
- * The following are building blocks to construct low-level IRs with 0 - 4
- * operands.
- */
-static ArmLIR *newLIR0(CompilationUnit *cUnit, ArmOpcode opcode)
-{
- ArmLIR *insn = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
- assert(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND));
- insn->opcode = opcode;
- setupResourceMasks(insn);
- dvmCompilerAppendLIR(cUnit, (LIR *) insn);
- return insn;
-}
-
-static ArmLIR *newLIR1(CompilationUnit *cUnit, ArmOpcode opcode,
- int dest)
-{
- ArmLIR *insn = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
- assert(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP));
- insn->opcode = opcode;
- insn->operands[0] = dest;
- setupResourceMasks(insn);
- dvmCompilerAppendLIR(cUnit, (LIR *) insn);
- return insn;
-}
-
-static ArmLIR *newLIR2(CompilationUnit *cUnit, ArmOpcode opcode,
- int dest, int src1)
-{
- ArmLIR *insn = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
- assert(isPseudoOpcode(opcode) ||
- (EncodingMap[opcode].flags & IS_BINARY_OP));
- insn->opcode = opcode;
- insn->operands[0] = dest;
- insn->operands[1] = src1;
- setupResourceMasks(insn);
- dvmCompilerAppendLIR(cUnit, (LIR *) insn);
- return insn;
-}
-
-static ArmLIR *newLIR3(CompilationUnit *cUnit, ArmOpcode opcode,
- int dest, int src1, int src2)
-{
- ArmLIR *insn = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
- if (!(EncodingMap[opcode].flags & IS_TERTIARY_OP)) {
- LOGE("Bad LIR3: %s[%d]",EncodingMap[opcode].name,opcode);
- }
- assert(isPseudoOpcode(opcode) ||
- (EncodingMap[opcode].flags & IS_TERTIARY_OP));
- insn->opcode = opcode;
- insn->operands[0] = dest;
- insn->operands[1] = src1;
- insn->operands[2] = src2;
- setupResourceMasks(insn);
- dvmCompilerAppendLIR(cUnit, (LIR *) insn);
- return insn;
-}
-
-#if defined(_ARMV7_A) || defined(_ARMV7_A_NEON)
-static ArmLIR *newLIR4(CompilationUnit *cUnit, ArmOpcode opcode,
- int dest, int src1, int src2, int info)
-{
- ArmLIR *insn = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
- assert(isPseudoOpcode(opcode) ||
- (EncodingMap[opcode].flags & IS_QUAD_OP));
- insn->opcode = opcode;
- insn->operands[0] = dest;
- insn->operands[1] = src1;
- insn->operands[2] = src2;
- insn->operands[3] = info;
- setupResourceMasks(insn);
- dvmCompilerAppendLIR(cUnit, (LIR *) insn);
- return insn;
-}
-#endif
-
-/*
- * If the next instruction is a move-result or move-result-long,
- * return the target Dalvik sReg[s] and convert the next to a
- * nop. Otherwise, return INVALID_SREG. Used to optimize method inlining.
- */
-static RegLocation inlinedTarget(CompilationUnit *cUnit, MIR *mir,
- bool fpHint)
-{
- if (mir->next &&
- ((mir->next->dalvikInsn.opcode == OP_MOVE_RESULT) ||
- (mir->next->dalvikInsn.opcode == OP_MOVE_RESULT_OBJECT))) {
- mir->next->dalvikInsn.opcode = OP_NOP;
- return dvmCompilerGetDest(cUnit, mir->next, 0);
- } else {
- RegLocation res = LOC_DALVIK_RETURN_VAL;
- res.fp = fpHint;
- return res;
- }
-}
-
-/*
- * Search the existing constants in the literal pool for an exact or close match
- * within specified delta (greater or equal to 0).
- */
-static ArmLIR *scanLiteralPool(LIR *dataTarget, int value, unsigned int delta)
-{
- while (dataTarget) {
- if (((unsigned) (value - ((ArmLIR *) dataTarget)->operands[0])) <=
- delta)
- return (ArmLIR *) dataTarget;
- dataTarget = dataTarget->next;
- }
- return NULL;
-}
-
-/*
- * The following are building blocks to insert constants into the pool or
- * instruction streams.
- */
-
-/* Add a 32-bit constant either in the constant pool or mixed with code */
-static ArmLIR *addWordData(CompilationUnit *cUnit, LIR **constantListP,
- int value)
-{
- /* Add the constant to the literal pool */
- if (constantListP) {
- ArmLIR *newValue = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
- newValue->operands[0] = value;
- newValue->generic.next = *constantListP;
- *constantListP = (LIR *) newValue;
- return newValue;
- } else {
- /* Add the constant in the middle of code stream */
- newLIR1(cUnit, kArm16BitData, (value & 0xffff));
- newLIR1(cUnit, kArm16BitData, (value >> 16));
- }
- return NULL;
-}
-
-static RegLocation inlinedTargetWide(CompilationUnit *cUnit, MIR *mir,
- bool fpHint)
-{
- if (mir->next &&
- (mir->next->dalvikInsn.opcode == OP_MOVE_RESULT_WIDE)) {
- mir->next->dalvikInsn.opcode = OP_NOP;
- return dvmCompilerGetDestWide(cUnit, mir->next, 0, 1);
- } else {
- RegLocation res = LOC_DALVIK_RETURN_VAL_WIDE;
- res.fp = fpHint;
- return res;
- }
-}
-
-
-/*
- * Generate an kArmPseudoBarrier marker to indicate the boundary of special
- * blocks.
- */
-static void genBarrier(CompilationUnit *cUnit)
-{
- ArmLIR *barrier = newLIR0(cUnit, kArmPseudoBarrier);
- /* Mark all resources as being clobbered */
- barrier->defMask = -1;
-}
-
-/* Create the PC reconstruction slot if not already done */
-static ArmLIR *genCheckCommon(CompilationUnit *cUnit, int dOffset,
- ArmLIR *branch,
- ArmLIR *pcrLabel)
-{
- /* Forget all def info (because we might rollback here. Bug #2367397 */
- dvmCompilerResetDefTracking(cUnit);
-
- /* Set up the place holder to reconstruct this Dalvik PC */
- if (pcrLabel == NULL) {
- int dPC = (int) (cUnit->method->insns + dOffset);
- pcrLabel = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
- pcrLabel->opcode = kArmPseudoPCReconstructionCell;
- pcrLabel->operands[0] = dPC;
- pcrLabel->operands[1] = dOffset;
- /* Insert the place holder to the growable list */
- dvmInsertGrowableList(&cUnit->pcReconstructionList,
- (intptr_t) pcrLabel);
- }
- /* Branch to the PC reconstruction code */
- branch->generic.target = (LIR *) pcrLabel;
-
- /* Clear the conservative flags for branches that punt to the interpreter */
- relaxBranchMasks(branch);
-
- return pcrLabel;
-}