diff options
Diffstat (limited to 'src/compiler/codegen')
20 files changed, 831 insertions, 3114 deletions
| diff --git a/src/compiler/codegen/CodegenUtil.cc b/src/compiler/codegen/CodegenUtil.cc index 4eccf04814..96a9b2176f 100644 --- a/src/compiler/codegen/CodegenUtil.cc +++ b/src/compiler/codegen/CodegenUtil.cc @@ -154,6 +154,7 @@ void setupResourceMasks(LIR* lir)          lir->defMask |= ENCODE_REG_LIST(lir->operands[1]);      } +#if defined(TARGET_ARM)      if (flags & REG_DEF_FPCS_LIST0) {          lir->defMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);      } @@ -163,6 +164,7 @@ void setupResourceMasks(LIR* lir)              setupRegMask(&lir->defMask, lir->operands[1] + i);          }      } +#endif      if (flags & SETS_CCODES) {          lir->defMask |= ENCODE_CCODE; @@ -201,6 +203,7 @@ void setupResourceMasks(LIR* lir)          lir->useMask |= ENCODE_REG_LIST(lir->operands[1]);      } +#if defined(TARGET_ARM)      if (flags & REG_USE_FPCS_LIST0) {          lir->useMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);      } @@ -210,6 +213,7 @@ void setupResourceMasks(LIR* lir)              setupRegMask(&lir->useMask, lir->operands[1] + i);          }      } +#endif      if (flags & USES_CCODES) {          lir->useMask |= ENCODE_CCODE; @@ -231,10 +235,186 @@ void setupResourceMasks(LIR* lir)  }  /* + * Debugging macros + */ +#define DUMP_RESOURCE_MASK(X) +#define DUMP_SSA_REP(X) + +/* Pretty-print a LIR instruction */ +void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr) +{ +    LIR* lir = (LIR*) arg; +    int offset = lir->offset; +    int dest = lir->operands[0]; +    const bool dumpNop = false; + +    /* Handle pseudo-ops individually, and all regular insns as a group */ +    switch(lir->opcode) { +        case kPseudoMethodEntry: +            LOG(INFO) << "-------- method entry " << +                PrettyMethod(cUnit->method_idx, *cUnit->dex_file); +            break; +        case kPseudoMethodExit: +            LOG(INFO) << "-------- Method_Exit"; +            break; +        case kPseudoBarrier: +            LOG(INFO) << "-------- BARRIER"; +            break; +        case kPseudoExtended: +            LOG(INFO) << "-------- " << (char* ) dest; +            break; +        case kPseudoSSARep: +            DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " <<  (char* ) dest); +            break; +        case kPseudoEntryBlock: +            LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest; +            break; +        case kPseudoDalvikByteCodeBoundary: +            LOG(INFO) << "-------- dalvik offset: 0x" << std::hex << +                 lir->dalvikOffset << " @ " << (char* )lir->operands[0]; +            break; +        case kPseudoExitBlock: +            LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest; +            break; +        case kPseudoPseudoAlign4: +            LOG(INFO) << (intptr_t)baseAddr + offset << " (0x" << std::hex << +                offset << "): .align4"; +            break; +        case kPseudoEHBlockLabel: +            LOG(INFO) << "Exception_Handling:"; +            break; +        case kPseudoTargetLabel: +        case kPseudoNormalBlockLabel: +            LOG(INFO) << "L" << (intptr_t)lir << ":"; +            break; +        case kPseudoThrowTarget: +            LOG(INFO) << "LT" << (intptr_t)lir << ":"; +            break; +        case kPseudoSuspendTarget: +            LOG(INFO) << "LS" << (intptr_t)lir << ":"; +            break; +        case kPseudoCaseLabel: +            LOG(INFO) << "LC" << (intptr_t)lir << ": Case target 0x" << +                std::hex << lir->operands[0] << "|" << std::dec << +                lir->operands[0]; +            break; +        default: +            if (lir->flags.isNop && !dumpNop) { +                break; +            } else { +                std::string op_name(buildInsnString(EncodingMap[lir->opcode].name, lir, baseAddr)); +                std::string op_operands(buildInsnString(EncodingMap[lir->opcode].fmt, lir, baseAddr)); +                LOG(INFO) << StringPrintf("%p (%04x): %-9s%s%s", baseAddr + offset, offset, +                    op_name.c_str(), op_operands.c_str(), lir->flags.isNop ? "(nop)" : ""); +            } +            break; +    } + +    if (lir->useMask && (!lir->flags.isNop || dumpNop)) { +        DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, +                                               lir->useMask, "use")); +    } +    if (lir->defMask && (!lir->flags.isNop || dumpNop)) { +        DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, +                                               lir->defMask, "def")); +    } +} + +void oatDumpPromotionMap(CompilationUnit *cUnit) +{ +    for (int i = 0; i < cUnit->numDalvikRegisters; i++) { +        PromotionMap vRegMap = cUnit->promotionMap[i]; +        char buf[100]; +        if (vRegMap.fpLocation == kLocPhysReg) { +            snprintf(buf, 100, " : s%d", vRegMap.fpReg & FP_REG_MASK); +        } else { +            buf[0] = 0; +        } +        char buf2[100]; +        snprintf(buf2, 100, "V[%02d] -> %s%d%s", i, +                 vRegMap.coreLocation == kLocPhysReg ? +                 "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ? +                 vRegMap.coreReg : oatSRegOffset(cUnit, i), buf); +        LOG(INFO) << buf2; +    } +} + +void oatDumpFullPromotionMap(CompilationUnit *cUnit) +{ +    for (int i = 0; i < cUnit->numDalvikRegisters; i++) { +        PromotionMap vRegMap = cUnit->promotionMap[i]; +        LOG(INFO) << i << " -> " << "CL:" << (int)vRegMap.coreLocation << +            ", CR:" << (int)vRegMap.coreReg << ", FL:" << +            (int)vRegMap.fpLocation << ", FR:" << (int)vRegMap.fpReg << +            ", - " << (int)vRegMap.firstInPair; +    } +} + +/* Dump instructions and constant pool contents */ +void oatCodegenDump(CompilationUnit* cUnit) +{ +    LOG(INFO) << "/*"; +    LOG(INFO) << "Dumping LIR insns for " +        << PrettyMethod(cUnit->method_idx, *cUnit->dex_file); +    LIR* lirInsn; +    LIR* thisLIR; +    int insnsSize = cUnit->insnsSize; + +    LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs; +    LOG(INFO) << "Ins                  : " << cUnit->numIns; +    LOG(INFO) << "Outs                 : " << cUnit->numOuts; +    LOG(INFO) << "CoreSpills           : " << cUnit->numCoreSpills; +    LOG(INFO) << "FPSpills             : " << cUnit->numFPSpills; +    LOG(INFO) << "Padding              : " << cUnit->numPadding; +    LOG(INFO) << "Frame size           : " << cUnit->frameSize; +    LOG(INFO) << "Start of ins         : " << cUnit->insOffset; +    LOG(INFO) << "Start of regs        : " << cUnit->regsOffset; +    LOG(INFO) << "code size is " << cUnit->totalSize << +        " bytes, Dalvik size is " << insnsSize * 2; +    LOG(INFO) << "expansion factor: " << +         (float)cUnit->totalSize / (float)(insnsSize * 2); +    oatDumpPromotionMap(cUnit); +    for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) { +        oatDumpLIRInsn(cUnit, lirInsn, 0); +    } +    for (lirInsn = cUnit->classPointerList; lirInsn; lirInsn = lirInsn->next) { +        thisLIR = (LIR*) lirInsn; +        LOG(INFO) << StringPrintf("%x (%04x): .class (%s)", +            thisLIR->offset, thisLIR->offset, +            ((CallsiteInfo *) thisLIR->operands[0])->classDescriptor); +    } +    for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) { +        thisLIR = (LIR*) lirInsn; +        LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)", +            thisLIR->offset, thisLIR->offset, thisLIR->operands[0]); +    } + +    const DexFile::MethodId& method_id = +        cUnit->dex_file->GetMethodId(cUnit->method_idx); +    std::string signature(cUnit->dex_file->GetMethodSignature(method_id)); +    std::string name(cUnit->dex_file->GetMethodName(method_id)); +    std::string descriptor(cUnit->dex_file->GetMethodDeclaringClassDescriptor(method_id)); + +    // Dump mapping table +    if (cUnit->mappingTable.size() > 0) { +        std::string line(StringPrintf("\n    MappingTable %s%s_%s_mappingTable[%zu] = {", +            descriptor.c_str(), name.c_str(), signature.c_str(), cUnit->mappingTable.size())); +        std::replace(line.begin(), line.end(), ';', '_'); +        LOG(INFO) << line; +        for (uint32_t i = 0; i < cUnit->mappingTable.size(); i+=2) { +            line = StringPrintf("        {0x%08x, 0x%04x},", +                cUnit->mappingTable[i], cUnit->mappingTable[i+1]); +            LOG(INFO) << line; +        } +        LOG(INFO) <<"    };\n\n"; +    } +} + +/*   * The following are building blocks to construct low-level IRs with 0 - 4   * operands.   */ -LIR* newLIR0(CompilationUnit* cUnit, ArmOpcode opcode) +LIR* newLIR0(CompilationUnit* cUnit, int opcode)  {      LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);      DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND)); @@ -245,7 +425,7 @@ LIR* newLIR0(CompilationUnit* cUnit, ArmOpcode opcode)      return insn;  } -LIR* newLIR1(CompilationUnit* cUnit, ArmOpcode opcode, +LIR* newLIR1(CompilationUnit* cUnit, int opcode,                             int dest)  {      LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR); @@ -258,7 +438,7 @@ LIR* newLIR1(CompilationUnit* cUnit, ArmOpcode opcode,      return insn;  } -LIR* newLIR2(CompilationUnit* cUnit, ArmOpcode opcode, +LIR* newLIR2(CompilationUnit* cUnit, int opcode,                             int dest, int src1)  {      LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR); @@ -273,7 +453,7 @@ LIR* newLIR2(CompilationUnit* cUnit, ArmOpcode opcode,      return insn;  } -LIR* newLIR3(CompilationUnit* cUnit, ArmOpcode opcode, +LIR* newLIR3(CompilationUnit* cUnit, int opcode,                             int dest, int src1, int src2)  {      LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR); @@ -293,7 +473,7 @@ LIR* newLIR3(CompilationUnit* cUnit, ArmOpcode opcode,  }  #if defined(TARGET_ARM) -LIR* newLIR4(CompilationUnit* cUnit, ArmOpcode opcode, +LIR* newLIR4(CompilationUnit* cUnit, int opcode,                             int dest, int src1, int src2, int info)  {      LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR); @@ -350,7 +530,7 @@ LIR* scanLiteralPoolWide(LIR* dataTarget, int valLo, int valHi)   * instruction streams.   */ -/* Add a 32-bit constant either in the constant pool or mixed with code */ +/* Add a 32-bit constant either in the constant pool */  LIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP,                             int value)  { @@ -362,10 +542,6 @@ LIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP,          newValue->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;  } @@ -374,17 +550,10 @@ LIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP,  LIR* addWideData(CompilationUnit* cUnit, LIR* *constantListP,                             int valLo, int valHi)  { -    LIR* res;      //FIXME: hard-coded little endian, need BE variant -    if (constantListP == NULL) { -        res = addWordData(cUnit, NULL, valLo); -        addWordData(cUnit, NULL, valHi); -    } else { -        // Insert high word into list first -        addWordData(cUnit, constantListP, valHi); -        res = addWordData(cUnit, constantListP, valLo); -    } -    return res; +    // Insert high word into list first +    addWordData(cUnit, constantListP, valHi); +    return addWordData(cUnit, constantListP, valLo);  }  void pushWord(std::vector<uint16_t>&buf, int data) { diff --git a/src/compiler/codegen/CompilerCodegen.h b/src/compiler/codegen/CompilerCodegen.h index ae85bb3d15..26dad8240c 100644 --- a/src/compiler/codegen/CompilerCodegen.h +++ b/src/compiler/codegen/CompilerCodegen.h @@ -35,6 +35,9 @@ int oatAssignInsnOffsets(CompilationUnit* cUnit);  void oatCodegenDump(CompilationUnit* cUnit);  void oatDumpPromotionMap(CompilationUnit* cUnit);  void oatDumpFullPromotionMap(CompilationUnit* cUnit); +std::string buildInsnString(const char* fmt, LIR* lir, +                            unsigned char* baseAddr); +  /* Implemented in codegen/<target>/Ralloc.c */  void oatSimpleRegAlloc(CompilationUnit* cUnit); diff --git a/src/compiler/codegen/GenCommon.cc b/src/compiler/codegen/GenCommon.cc index 7af1aa033c..511c47bdae 100644 --- a/src/compiler/codegen/GenCommon.cc +++ b/src/compiler/codegen/GenCommon.cc @@ -43,19 +43,23 @@ void genBarrier(CompilationUnit* cUnit)      barrier->defMask = -1;  } -/* Generate conditional branch instructions */ -LIR* genConditionalBranch(CompilationUnit* cUnit, ConditionCode cond, -                          LIR* target) + +/* Generate unconditional branch instructions */ +LIR* genUnconditionalBranch(CompilationUnit* cUnit, LIR* target)  { -    LIR* branch = opCondBranch(cUnit, cond); +    LIR* branch = opNone(cUnit, kOpUncondBr);      branch->target = (LIR*) target;      return branch;  } -/* Generate unconditional branch instructions */ -LIR* genUnconditionalBranch(CompilationUnit* cUnit, LIR* target) +// FIXME: need to do some work to split out targets with +// condition codes and those without +#if defined(TARGET_ARM) || defined(TARGET_X86) +/* Generate conditional branch instructions */ +LIR* genConditionalBranch(CompilationUnit* cUnit, ConditionCode cond, +                          LIR* target)  { -    LIR* branch = opNone(cUnit, kOpUncondBr); +    LIR* branch = opCondBranch(cUnit, cond);      branch->target = (LIR*) target;      return branch;  } @@ -72,6 +76,7 @@ LIR* genCheck(CompilationUnit* cUnit, ConditionCode cCode, MIR* mir,      oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt);      return branch;  } +#endif  LIR* genImmedCheck(CompilationUnit* cUnit, ConditionCode cCode,                     int reg, int immVal, MIR* mir, ThrowKind kind) @@ -112,8 +117,12 @@ LIR* genRegRegCheck(CompilationUnit* cUnit, ConditionCode cCode,      tgt->operands[1] = mir ? mir->offset : 0;      tgt->operands[2] = reg1;      tgt->operands[3] = reg2; +#if defined(TARGET_MIPS) +    LIR* branch = genCompareBranch(cUnit, cCode, reg1, reg2); +#else      opRegReg(cUnit, kOpCmp, reg1, reg2);      LIR* branch = genConditionalBranch(cUnit, cCode, tgt); +#endif      // Remember branch target - will process later      oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt);      return branch; @@ -125,7 +134,6 @@ void genCompareAndBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,      ConditionCode cond;      rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);      rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg); -    opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg);      Opcode opcode = mir->dalvikInsn.opcode;      switch(opcode) {          case OP_IF_EQ: @@ -150,7 +158,13 @@ void genCompareAndBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,              cond = (ConditionCode)0;              LOG(FATAL) << "Unexpected opcode " << (int)opcode;      } +#if defined(TARGET_MIPS) +    LIR* branch = genCompareBranch(cUnit, cond, rlSrc1.lowReg, rlSrc2.lowReg); +    branch->target = &labelList[bb->taken->id]; +#else +    opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg);      genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]); +#endif      genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);  } @@ -159,7 +173,6 @@ void genCompareZeroAndBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,  {      ConditionCode cond;      rlSrc = loadValue(cUnit, rlSrc, kCoreReg); -    opRegImm(cUnit, kOpCmp, rlSrc.lowReg, 0);      Opcode opcode = mir->dalvikInsn.opcode;      switch(opcode) {          case OP_IF_EQZ: @@ -184,7 +197,13 @@ void genCompareZeroAndBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,              cond = (ConditionCode)0;              LOG(FATAL) << "Unexpected opcode " << (int)opcode;      } +#if defined(TARGET_MIPS) +    LIR* branch = genCmpImmBranch(cUnit, cond, rlSrc.lowReg, 0); +    branch->target = &labelList[bb->taken->id]; +#else +    opRegImm(cUnit, kOpCmp, rlSrc.lowReg, 0);      genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]); +#endif      genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);  } @@ -319,7 +338,11 @@ void genFilledNewArray(CompilationUnit* cUnit, MIR* mir, bool isRange)          int rSrc = oatAllocTemp(cUnit);          int rDst = oatAllocTemp(cUnit);          int rIdx = oatAllocTemp(cUnit); +#if defined(TARGET_ARM)          int rVal = rLR;  // Using a lot of temps, rLR is known free here +#else +        int rVal = oatAllocTemp(cUnit); +#endif          // Set up source pointer          RegLocation rlFirst = oatGetSrc(cUnit, mir, 0);          opRegRegImm(cUnit, kOpAdd, rSrc, rSP, @@ -340,8 +363,9 @@ void genFilledNewArray(CompilationUnit* cUnit, MIR* mir, bool isRange)          newLIR3(cUnit, kThumb2SubsRRI12, rIdx, rIdx, 1);          LIR* branch = opCondBranch(cUnit, kCondGe);  #else +        oatFreeTemp(cUnit, rVal);          opRegImm(cUnit, kOpSub, rIdx, 1); -        LIR* branch = opCompareBranchImm(cUnit, kCondGe, rIdx, 0); +        LIR* branch = genCmpImmBranch(cUnit, kCondGe, rIdx, 0);  #endif          branch->target = (LIR*)target;      } else if (!isRange) { @@ -637,11 +661,11 @@ void handleThrowLaunchpads(CompilationUnit *cUnit)                  funcOffset = OFFSETOF_MEMBER(Thread, pThrowNullPointerFromCode);                  break;              case kThrowArrayBounds: -                if (v2 != r0) { +                if (v2 != rARG0) {                      genRegCopy(cUnit, rARG0, v1);                      genRegCopy(cUnit, rARG1, v2);                  } else { -                    if (v1 == r1) { +                    if (v1 == rARG1) {  #if defined(TARGET_ARM)                          int rTmp = r12;  #else @@ -860,7 +884,7 @@ void genConstClass(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,              // TUNING: move slow path to end & remove unconditional branch              LIR* target1 = newLIR0(cUnit, kPseudoTargetLabel);              target1->defMask = ENCODE_ALL; -            // Call out to helper, which will return resolved type in r0 +            // Call out to helper, which will return resolved type in rARG0              int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,                                    pInitializeTypeFromCode));              genRegCopy(cUnit, rARG1, mReg); @@ -909,7 +933,7 @@ void genConstString(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,          genRegCopy(cUnit, rARG0, rARG2);   // .eq          opReg(cUnit, kOpBlx, rTgt);        // .eq, helper(Method*, string_idx)  #else -        LIR* branch = genCmpImmBranch(cUnit, kCondNe, 0); +        LIR* branch = genCmpImmBranch(cUnit, kCondNe, rRET0, 0);          genRegCopy(cUnit, rARG0, rARG2);   // .eq          opReg(cUnit, kOpBlx, rTgt);          LIR* target = newLIR0(cUnit, kPseudoTargetLabel); @@ -961,22 +985,22 @@ void genInstanceof(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,      // May generate a call - use explicit registers      oatLockCallTemps(cUnit);      uint32_t type_idx = mir->dalvikInsn.vC; -    loadCurrMethodDirect(cUnit, rARG1);  // r1 <= current Method* +    loadCurrMethodDirect(cUnit, rARG1);  // rARG1 <= current Method*      int classReg = rARG2;  // rARG2 will hold the Class*      if (!cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method_idx,                                                       cUnit->dex_cache,                                                       *cUnit->dex_file,                                                       type_idx)) {          // Check we have access to type_idx and if not throw IllegalAccessError, -        // returns Class* in r0 +        // returns Class* in rARG0          int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,                                pInitializeTypeAndVerifyAccessFromCode));          loadConstant(cUnit, rARG0, type_idx);          callRuntimeHelper(cUnit, rTgt);  // InitializeTypeAndVerifyAccess(idx, method)          genRegCopy(cUnit, classReg, rRET0);  // Align usage with fast path -        loadValueDirectFixed(cUnit, rlSrc, rARG0);  // r0 <= ref +        loadValueDirectFixed(cUnit, rlSrc, rARG0);  // rARG0 <= ref      } else { -        // Load dex cache entry into classReg (r2) +        // Load dex cache entry into classReg (rARG2)          loadValueDirectFixed(cUnit, rlSrc, rARG0);  // rARG0 <= ref          loadWordDisp(cUnit, rARG1,                       Method::DexCacheResolvedTypesOffset().Int32Value(), @@ -995,7 +1019,7 @@ void genInstanceof(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,                                    pInitializeTypeFromCode));              loadConstant(cUnit, rARG0, type_idx);              callRuntimeHelper(cUnit, rTgt);  // InitializeTypeFromCode(idx, method) -            genRegCopy(cUnit, r2, rRET0); // Align usage with fast path +            genRegCopy(cUnit, rARG2, rRET0); // Align usage with fast path              loadValueDirectFixed(cUnit, rlSrc, rARG0);  /* reload Ref */              // Rejoin code paths              LIR* hopTarget = newLIR0(cUnit, kPseudoTargetLabel); @@ -1021,6 +1045,7 @@ void genInstanceof(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,      genBarrier(cUnit);      oatClobberCalleeSave(cUnit);  #else +    (void)rTgt;      // Perhaps a general-purpose kOpSelect operator?      UNIMPLEMENTED(FATAL) << "Need non IT implementation";  #endif @@ -1065,18 +1090,18 @@ void genCheckCast(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)              // Need to test presence of type in dex cache at runtime              LIR* hopBranch = genCmpImmBranch(cUnit, kCondNe, classReg, 0);              // Not resolved -            // Call out to helper, which will return resolved type in r0 -            loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pInitializeTypeFromCode), rLR); -            loadConstant(cUnit, r0, type_idx); -            callRuntimeHelper(cUnit, rLR);  // InitializeTypeFromCode(idx, method) -            genRegCopy(cUnit, classReg, r0); // Align usage with fast path +            // Call out to helper, which will return resolved type in rARG0 +            int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread, pInitializeTypeFromCode)); +            loadConstant(cUnit, rARG0, type_idx); +            callRuntimeHelper(cUnit, rTgt);  // InitializeTypeFromCode(idx, method) +            genRegCopy(cUnit, classReg, rARG0); // Align usage with fast path              // Rejoin code paths              LIR* hopTarget = newLIR0(cUnit, kPseudoTargetLabel);              hopTarget->defMask = ENCODE_ALL;              hopBranch->target = (LIR*)hopTarget;          }      } -    // At this point, classReg (r2) has class +    // At this point, classReg (rARG2) has class      loadValueDirectFixed(cUnit, rlSrc, rARG0);  // rARG0 <= ref      /* Null is OK - continue */      LIR* branch1 = genCmpImmBranch(cUnit, kCondEq, rARG0, 0); @@ -1086,8 +1111,12 @@ void genCheckCast(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)      /* rARG1 now contains object->clazz */      int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,                            pCheckCastFromCode)); +#if defined(TARGET_MIPS) +    LIR* branch2 = genCompareBranch(cUnit, kCondEq, rARG1, classReg); +#else      opRegReg(cUnit, kOpCmp, rARG1, classReg);      LIR* branch2 = opCondBranch(cUnit, kCondEq); /* If equal, trivial yes */ +#endif      genRegCopy(cUnit, rARG0, rARG1);      genRegCopy(cUnit, rARG1, rARG2);      callRuntimeHelper(cUnit, rTgt); @@ -1430,7 +1459,7 @@ bool genArithOpInt(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,              funcOffset = OFFSETOF_MEMBER(Thread, pIdiv);              retReg = rRET0;              break; -        /* NOTE: returns in r1 */ +        /* NOTE: returns in rARG1 */          case OP_REM_INT:          case OP_REM_INT_2ADDR:              callOut = true; @@ -1598,8 +1627,12 @@ void genMultiplyByTwoBitMultiplier(CompilationUnit* cUnit, RegLocation rlSrc,                                     RegLocation rlResult, int lit,                                     int firstBit, int secondBit)  { +#if defined(TARGET_MIPS) +    UNIMPLEMENTED(FATAL) << "Need shift & add primative"; +#else      opRegRegRegShift(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, rlSrc.lowReg,                       encodeShift(kArmLsl, secondBit - firstBit)); +#endif      if (firstBit != 0) {          opRegRegImm(cUnit, kOpLsl, rlResult.lowReg, rlResult.lowReg, firstBit);      } @@ -1882,7 +1915,7 @@ bool genArithOpLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,              genCheck(cUnit, kCondEq, mir, kThrowDivZero);  #else              opRegRegReg(cUnit, kOpOr, tReg, rARG2, rARG3); -            genImmedCheck(cUnit, kCondEq, mir, tReg, 0, mir, kThrowDivZero); +            genImmedCheck(cUnit, kCondEq, tReg, 0, mir, kThrowDivZero);              oatFreeTemp(cUnit, tReg);  #endif          } else { @@ -2116,7 +2149,7 @@ void genSuspendTest(CompilationUnit* cUnit, MIR* mir)          branch = opCondBranch(cUnit, kCondEq);  #else          opRegImm(cUnit, kOpSub, rSUSPEND, 1); -        branch = opCompareBranchImm(cUnit, kCondEq, rSUSPEND, 0); +        branch = genCmpImmBranch(cUnit, kCondEq, rSUSPEND, 0);  #endif      }      LIR* retLab = newLIR0(cUnit, kPseudoTargetLabel); diff --git a/src/compiler/codegen/MethodCodegenDriver.cc b/src/compiler/codegen/MethodCodegenDriver.cc index 6de3a9c3d9..38c2117036 100644 --- a/src/compiler/codegen/MethodCodegenDriver.cc +++ b/src/compiler/codegen/MethodCodegenDriver.cc @@ -102,7 +102,11 @@ void genInvoke(CompilationUnit* cUnit, MIR* mir, InvokeType type, bool isRange)      if (DISPLAY_MISSING_TARGETS) {          genShowTarget(cUnit);      } +#if defined(TARGET_MIPS) +    UNIMPLEMENTED(FATAL) << "Need to handle common target register"; +#else      opReg(cUnit, kOpBlx, rLR); +#endif      oatClobberCalleeSave(cUnit);  } diff --git a/src/compiler/codegen/arm/ArchUtility.cc b/src/compiler/codegen/arm/ArchUtility.cc index e1eba44138..be6b44de71 100644 --- a/src/compiler/codegen/arm/ArchUtility.cc +++ b/src/compiler/codegen/arm/ArchUtility.cc @@ -321,180 +321,5 @@ void oatDumpResourceMask(LIR* lir, u8 mask, const char* prefix)      }  } -/* - * Debugging macros - */ -#define DUMP_RESOURCE_MASK(X) -#define DUMP_SSA_REP(X) - -/* Pretty-print a LIR instruction */ -void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr) -{ -    LIR* lir = (LIR*) arg; -    int offset = lir->offset; -    int dest = lir->operands[0]; -    const bool dumpNop = false; - -    /* Handle pseudo-ops individually, and all regular insns as a group */ -    switch(lir->opcode) { -        case kPseudoMethodEntry: -            LOG(INFO) << "-------- method entry " << -                PrettyMethod(cUnit->method_idx, *cUnit->dex_file); -            break; -        case kPseudoMethodExit: -            LOG(INFO) << "-------- Method_Exit"; -            break; -        case kPseudoBarrier: -            LOG(INFO) << "-------- BARRIER"; -            break; -        case kPseudoExtended: -            LOG(INFO) << "-------- " << (char* ) dest; -            break; -        case kPseudoSSARep: -            DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " <<  (char* ) dest); -            break; -        case kPseudoEntryBlock: -            LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest; -            break; -        case kPseudoDalvikByteCodeBoundary: -            LOG(INFO) << "-------- dalvik offset: 0x" << std::hex << -                 lir->dalvikOffset << " @ " << (char* )lir->operands[0]; -            break; -        case kPseudoExitBlock: -            LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest; -            break; -        case kPseudoPseudoAlign4: -            LOG(INFO) << (intptr_t)baseAddr + offset << " (0x" << std::hex << -                offset << "): .align4"; -            break; -        case kPseudoEHBlockLabel: -            LOG(INFO) << "Exception_Handling:"; -            break; -        case kPseudoTargetLabel: -        case kPseudoNormalBlockLabel: -            LOG(INFO) << "L" << (intptr_t)lir << ":"; -            break; -        case kPseudoThrowTarget: -            LOG(INFO) << "LT" << (intptr_t)lir << ":"; -            break; -        case kPseudoSuspendTarget: -            LOG(INFO) << "LS" << (intptr_t)lir << ":"; -            break; -        case kPseudoCaseLabel: -            LOG(INFO) << "LC" << (intptr_t)lir << ": Case target 0x" << -                std::hex << lir->operands[0] << "|" << std::dec << -                lir->operands[0]; -            break; -        default: -            if (lir->flags.isNop && !dumpNop) { -                break; -            } else { -                std::string op_name(buildInsnString(EncodingMap[lir->opcode].name, lir, baseAddr)); -                std::string op_operands(buildInsnString(EncodingMap[lir->opcode].fmt, lir, baseAddr)); -                LOG(INFO) << StringPrintf("%p (%04x): %-9s%s%s", baseAddr + offset, offset, -                    op_name.c_str(), op_operands.c_str(), lir->flags.isNop ? "(nop)" : ""); -            } -            break; -    } - -    if (lir->useMask && (!lir->flags.isNop || dumpNop)) { -        DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, -                                               lir->useMask, "use")); -    } -    if (lir->defMask && (!lir->flags.isNop || dumpNop)) { -        DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, -                                               lir->defMask, "def")); -    } -} - -void oatDumpPromotionMap(CompilationUnit *cUnit) -{ -    for (int i = 0; i < cUnit->numDalvikRegisters; i++) { -        PromotionMap vRegMap = cUnit->promotionMap[i]; -        char buf[100]; -        if (vRegMap.fpLocation == kLocPhysReg) { -            snprintf(buf, 100, " : s%d", vRegMap.fpReg & FP_REG_MASK); -        } else { -            buf[0] = 0; -        } -        char buf2[100]; -        snprintf(buf2, 100, "V[%02d] -> %s%d%s", i, -                 vRegMap.coreLocation == kLocPhysReg ? -                 "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ? -                 vRegMap.coreReg : oatSRegOffset(cUnit, i), buf); -        LOG(INFO) << buf2; -    } -} - -void oatDumpFullPromotionMap(CompilationUnit *cUnit) -{ -    for (int i = 0; i < cUnit->numDalvikRegisters; i++) { -        PromotionMap vRegMap = cUnit->promotionMap[i]; -        LOG(INFO) << i << " -> " << "CL:" << (int)vRegMap.coreLocation << -            ", CR:" << (int)vRegMap.coreReg << ", FL:" << -            (int)vRegMap.fpLocation << ", FR:" << (int)vRegMap.fpReg << -            ", - " << (int)vRegMap.firstInPair; -    } -} - -/* Dump instructions and constant pool contents */ -void oatCodegenDump(CompilationUnit* cUnit) -{ -    LOG(INFO) << "/*"; -    LOG(INFO) << "Dumping LIR insns for " -        << PrettyMethod(cUnit->method_idx, *cUnit->dex_file); -    LIR* lirInsn; -    LIR* armLIR; -    int insnsSize = cUnit->insnsSize; - -    LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs; -    LOG(INFO) << "Ins                  : " << cUnit->numIns; -    LOG(INFO) << "Outs                 : " << cUnit->numOuts; -    LOG(INFO) << "CoreSpills           : " << cUnit->numCoreSpills; -    LOG(INFO) << "FPSpills             : " << cUnit->numFPSpills; -    LOG(INFO) << "Padding              : " << cUnit->numPadding; -    LOG(INFO) << "Frame size           : " << cUnit->frameSize; -    LOG(INFO) << "Start of ins         : " << cUnit->insOffset; -    LOG(INFO) << "Start of regs        : " << cUnit->regsOffset; -    LOG(INFO) << "code size is " << cUnit->totalSize << -        " bytes, Dalvik size is " << insnsSize * 2; -    LOG(INFO) << "expansion factor: " << -         (float)cUnit->totalSize / (float)(insnsSize * 2); -    oatDumpPromotionMap(cUnit); -    for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) { -        oatDumpLIRInsn(cUnit, lirInsn, 0); -    } -    for (lirInsn = cUnit->classPointerList; lirInsn; lirInsn = lirInsn->next) { -        armLIR = (LIR*) lirInsn; -        LOG(INFO) << StringPrintf("%x (%04x): .class (%s)", -            armLIR->offset, armLIR->offset, -            ((CallsiteInfo *) armLIR->operands[0])->classDescriptor); -    } -    for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) { -        armLIR = (LIR*) lirInsn; -        LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)", -            armLIR->offset, armLIR->offset, armLIR->operands[0]); -    } - -    const DexFile::MethodId& method_id = -        cUnit->dex_file->GetMethodId(cUnit->method_idx); -    std::string signature(cUnit->dex_file->GetMethodSignature(method_id)); -    std::string name(cUnit->dex_file->GetMethodName(method_id)); -    std::string descriptor(cUnit->dex_file->GetMethodDeclaringClassDescriptor(method_id)); - -    // Dump mapping table -    if (cUnit->mappingTable.size() > 0) { -        std::string line(StringPrintf("\n    MappingTable %s%s_%s_mappingTable[%zu] = {", -            descriptor.c_str(), name.c_str(), signature.c_str(), cUnit->mappingTable.size())); -        std::replace(line.begin(), line.end(), ';', '_'); -        LOG(INFO) << line; -        for (uint32_t i = 0; i < cUnit->mappingTable.size(); i+=2) { -            line = StringPrintf("        {0x%08x, 0x%04x},", -                cUnit->mappingTable[i], cUnit->mappingTable[i+1]); -            LOG(INFO) << line; -        } -        LOG(INFO) <<"    };\n\n"; -    } -}  }  // namespace art diff --git a/src/compiler/codegen/arm/ArmLIR.h b/src/compiler/codegen/arm/ArmLIR.h index 196bddb37f..e4e9eb83b1 100644 --- a/src/compiler/codegen/arm/ArmLIR.h +++ b/src/compiler/codegen/arm/ArmLIR.h @@ -745,22 +745,6 @@ typedef enum ArmTargetOptHints {  extern const ArmEncodingMap EncodingMap[kArmLast]; -typedef struct SwitchTable { -    int offset; -    const u2* table;            // Original dex table -    int vaddr;                  // Dalvik offset of switch opcode -    LIR* bxInst;                // Switch indirect branch instruction -    LIR** targets;              // Array of case targets -} SwitchTable; - -typedef struct FillArrayData { -    int offset; -    const u2* table;           // Original dex table -    int size; -    int vaddr;                 // Dalvik offset of OP_FILL_ARRAY_DATA opcode -} FillArrayData; - -  }  // namespace art  #endif  // ART_SRC_COMPILER_CODEGEN_ARM_ARMLIR_H_ diff --git a/src/compiler/codegen/arm/ArmRallocUtil.cc b/src/compiler/codegen/arm/ArmRallocUtil.cc index a020687210..d44d7cf970 100644 --- a/src/compiler/codegen/arm/ArmRallocUtil.cc +++ b/src/compiler/codegen/arm/ArmRallocUtil.cc @@ -116,6 +116,22 @@ void oatClobberCalleeSave(CompilationUnit *cUnit)      oatClobber(cUnit, r3);      oatClobber(cUnit, r12);      oatClobber(cUnit, r14lr); +    oatClobber(cUnit, fr0); +    oatClobber(cUnit, fr1); +    oatClobber(cUnit, fr2); +    oatClobber(cUnit, fr3); +    oatClobber(cUnit, fr4); +    oatClobber(cUnit, fr5); +    oatClobber(cUnit, fr6); +    oatClobber(cUnit, fr7); +    oatClobber(cUnit, fr8); +    oatClobber(cUnit, fr9); +    oatClobber(cUnit, fr10); +    oatClobber(cUnit, fr11); +    oatClobber(cUnit, fr12); +    oatClobber(cUnit, fr13); +    oatClobber(cUnit, fr14); +    oatClobber(cUnit, fr15);  }  extern RegLocation oatGetReturnWide(CompilationUnit* cUnit) diff --git a/src/compiler/codegen/arm/Codegen.h b/src/compiler/codegen/arm/Codegen.h index a565cb1f37..49e39db837 100644 --- a/src/compiler/codegen/arm/Codegen.h +++ b/src/compiler/codegen/arm/Codegen.h @@ -1,5 +1,5 @@  /* - * Copyright (C) 2011 The Android Open Source Project + * Copyright (C) 2012 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. diff --git a/src/compiler/codegen/mips/ArchFactory.cc b/src/compiler/codegen/mips/ArchFactory.cc index cb9645de56..2cb0731e0c 100644 --- a/src/compiler/codegen/mips/ArchFactory.cc +++ b/src/compiler/codegen/mips/ArchFactory.cc @@ -22,1096 +22,68 @@   *   */ -#define SLOW_FIELD_PATH (cUnit->enableDebug & (1 << kDebugSlowFieldPath)) -#define SLOW_INVOKE_PATH (cUnit->enableDebug & (1 << kDebugSlowInvokePath)) -#define SLOW_STRING_PATH (cUnit->enableDebug & (1 << kDebugSlowStringPath)) -#define SLOW_TYPE_PATH (cUnit->enableDebug & (1 << kDebugSlowTypePath)) -#define EXERCISE_SLOWEST_FIELD_PATH (cUnit->enableDebug & \ -    (1 << kDebugSlowestFieldPath)) -#define EXERCISE_SLOWEST_STRING_PATH (cUnit->enableDebug & \ -    (1 << kDebugSlowestStringPath)) -#define EXERCISE_RESOLVE_METHOD (cUnit->enableDebug & \ -    (1 << kDebugExerciseResolveMethod)) - -// FIXME - this is the Mips version, change to MIPS -  namespace art { -STATIC void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset); - -/* Generate unconditional branch instructions */ -STATIC MipsLIR* genUnconditionalBranch(CompilationUnit* cUnit, MipsLIR* target) -{ -    MipsLIR* branch = opNone(cUnit, kOpUncondBr); -    branch->generic.target = (LIR*) target; -    return branch; -} - -STATIC MipsLIR* callRuntimeHelper(CompilationUnit* cUnit, int reg) -{ -    oatClobberCalleeSave(cUnit); -    return opReg(cUnit, kOpBlx, reg); -} - -/* - * Mark garbage collection card. Skip if the value we're storing is null. - */ -STATIC void markGCCard(CompilationUnit* cUnit, int valReg, int tgtAddrReg) -{ -    int regCardBase = oatAllocTemp(cUnit); -    int regCardNo = oatAllocTemp(cUnit); -    MipsLIR* branchOver = opCompareBranchCC(cUnit, kMipsCondEq, valReg, r_ZERO); -    loadWordDisp(cUnit, rSELF, Thread::CardTableOffset().Int32Value(), -                 regCardBase); -    opRegRegImm(cUnit, kOpLsr, regCardNo, tgtAddrReg, GC_CARD_SHIFT); -    storeBaseIndexed(cUnit, regCardBase, regCardNo, regCardBase, 0, -                     kUnsignedByte); -    MipsLIR* target = newLIR0(cUnit, kPseudoTargetLabel); -    target->defMask = ENCODE_ALL; -    branchOver->generic.target = (LIR*)target; -    oatFreeTemp(cUnit, regCardBase); -    oatFreeTemp(cUnit, regCardNo); -} - -/* - * Utiltiy to load the current Method*.  Broken out - * to allow easy change between placing the current Method* in a - * dedicated register or its home location in the frame. - */ -STATIC void loadCurrMethodDirect(CompilationUnit *cUnit, int rTgt) -{ -#if defined(METHOD_IN_REG) -    genRegCopy(cUnit, rTgt, rMETHOD); -#else -    loadWordDisp(cUnit, rSP, 0, rTgt); -#endif -} - -STATIC int loadCurrMethod(CompilationUnit *cUnit) -{ -#if defined(METHOD_IN_REG) -    return rMETHOD; -#else -    int mReg = oatAllocTemp(cUnit); -    loadCurrMethodDirect(cUnit, mReg); -    return mReg; -#endif -} - -STATIC MipsLIR* genImmedCheck(CompilationUnit* cUnit, MipsConditionCode cCode, -                             int reg, int immVal, MIR* mir, MipsThrowKind kind) -{ -    MipsLIR* tgt = (MipsLIR*)oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR); -    tgt->opcode = kPseudoThrowTarget; -    tgt->operands[0] = kind; -    tgt->operands[1] = mir->offset; -    MipsLIR* branch; -    if (cCode == kMipsCondAl) { -        branch = genUnconditionalBranch(cUnit, tgt); -    } else { -        int tReg; -        if (immVal == 0) { -            tReg = r_ZERO; -        } else { -            tReg = oatAllocTemp(cUnit); -            loadConstant(cUnit, tReg, immVal); -        } -        branch = opCompareBranchCC(cUnit, cCode, reg, tReg); -        branch->generic.target = (LIR*)tgt; -    } -    // Remember branch target - will process later -    oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt); -    return branch; -} - -/* Perform null-check on a register.  */ -STATIC MipsLIR* genNullCheck(CompilationUnit* cUnit, int sReg, int mReg, -                             MIR* mir) -{ -    if (!(cUnit->disableOpt & (1 << kNullCheckElimination)) && -        mir->optimizationFlags & MIR_IGNORE_NULL_CHECK) { -        return NULL; -    } -    return genImmedCheck(cUnit, kMipsCondEq, mReg, 0, mir, kMipsThrowNullPointer); -} - -/* Perform check on two registers */ -STATIC TGT_LIR* genRegRegCheck(CompilationUnit* cUnit, MipsConditionCode cCode, -                               int reg1, int reg2, MIR* mir, MipsThrowKind kind) -{ -    MipsLIR* tgt = (MipsLIR*)oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR); -    tgt->opcode = kPseudoThrowTarget; -    tgt->operands[0] = kind; -    tgt->operands[1] = mir ? mir->offset : 0; -    tgt->operands[2] = reg1; -    tgt->operands[3] = reg2; -    opRegReg(cUnit, kOpCmp, reg1, reg2); -    MipsLIR* branch = genConditionalBranch(cUnit, cCode, tgt); -    // Remember branch target - will process later -    oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt); -    return branch; -} - -/* - * Let helper function take care of everything.  Will call - * Array::AllocFromCode(type_idx, method, count); - * Note: AllocFromCode will handle checks for errNegativeArraySize. - */ -STATIC void genNewArray(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, -                        RegLocation rlSrc) -{ -    oatFlushAllRegs(cUnit);    /* Everything to home location */ -    oatLockCallTemps(cUnit); -    int addrReg = oatAllocTemp(cUnit); -    uint32_t type_idx = mir->dalvikInsn.vC; -    if (cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method_idx, -                                                    cUnit->dex_cache, -                                                    *cUnit->dex_file, -                                                    type_idx)) { -        loadWordDisp(cUnit, rSELF, -                     OFFSETOF_MEMBER(Thread, pAllocArrayFromCode), addrReg); -    } else { -        loadWordDisp(cUnit, rSELF, -                     OFFSETOF_MEMBER(Thread, pAllocArrayFromCodeWithAccessCheck), addrReg); -    } -    loadCurrMethodDirect(cUnit, r_ARG1);              // arg1 <- Method* -    loadConstant(cUnit, r_ARG0, type_idx);            // arg0 <- type_id -    loadValueDirectFixed(cUnit, rlSrc, r_ARG2);       // arg2 <- count -    callRuntimeHelper(cUnit, addrReg); -    RegLocation rlResult = oatGetReturn(cUnit); -    storeValue(cUnit, rlDest, rlResult); -} - -/* - * Similar to genNewArray, but with post-allocation initialization. - * Verifier guarantees we're dealing with an array class.  Current - * code throws runtime exception "bad Filled array req" for 'D' and 'J'. - * Current code also throws internal unimp if not 'L', '[' or 'I'. - */ -STATIC void genFilledNewArray(CompilationUnit* cUnit, MIR* mir, bool isRange) -{ -    DecodedInstruction* dInsn = &mir->dalvikInsn; -    int elems = dInsn->vA; -    int typeId = dInsn->vB; -    oatFlushAllRegs(cUnit);    /* Everything to home location */ -    oatLockCallTemps(cUnit); -    int addrReg = oatAllocTemp(cUnit); -    if (cUnit->compiler->CanAccessTypeWithoutChecks(cUnit->method_idx, -                                                    cUnit->dex_cache, -                                                    *cUnit->dex_file, -                                                    typeId)) { -        loadWordDisp(cUnit, rSELF, -                     OFFSETOF_MEMBER(Thread, pCheckAndAllocArrayFromCode), -                                     addrReg); -    } else { -        loadWordDisp(cUnit, rSELF, -                     OFFSETOF_MEMBER(Thread, -                     pCheckAndAllocArrayFromCodeWithAccessCheck), addrReg); -    } -    loadCurrMethodDirect(cUnit, r_ARG1);              // arg1 <- Method* -    loadConstant(cUnit, r_ARG0, typeId);              // arg0 <- type_id -    loadConstant(cUnit, r_ARG2, elems);               // arg2 <- count -    callRuntimeHelper(cUnit, addrReg); -    /* -     * NOTE: the implicit target for OP_FILLED_NEW_ARRAY is the -     * return region.  Because AllocFromCode placed the new array -     * in r_V0, we'll just lock it into place.  When debugger support is -     * added, it may be necessary to additionally copy all return -     * values to a home location in thread-local storage -     */ -    oatLockTemp(cUnit, r_V0); - -    // Having a range of 0 is legal -    if (isRange && (dInsn->vA > 0)) { -        /* -         * Bit of ugliness here.  We're going generate a mem copy loop -         * on the register range, but it is possible that some regs -         * in the range have been promoted.  This is unlikely, but -         * before generating the copy, we'll just force a flush -         * of any regs in the source range that have been promoted to -         * home location. -         */ -        for (unsigned int i = 0; i < dInsn->vA; i++) { -            RegLocation loc = oatUpdateLoc(cUnit, -                oatGetSrc(cUnit, mir, i)); -            if (loc.location == kLocPhysReg) { -                storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, loc.sRegLow), -                              loc.lowReg, kWord); -            } -        } -        /* -         * TUNING note: generated code here could be much improved, but -         * this is an uncommon operation and isn't especially performance -         * critical. -         */ -        int rSrc = oatAllocTemp(cUnit); -        int rDst = oatAllocTemp(cUnit); -        int rIdx = oatAllocTemp(cUnit); -        int rVal = oatAllocTemp(cUnit); -        // Set up source pointer -        RegLocation rlFirst = oatGetSrc(cUnit, mir, 0); -        opRegRegImm(cUnit, kOpAdd, rSrc, rSP, -                    oatSRegOffset(cUnit, rlFirst.sRegLow)); -        // Set up the target pointer -        opRegRegImm(cUnit, kOpAdd, rDst, r_V0, -                    Array::DataOffset().Int32Value()); -        // Set up the loop counter (known to be > 0) -        loadConstant(cUnit, rIdx, dInsn->vA - 1); -        // Generate the copy loop.  Going backwards for convenience -        MipsLIR* target = newLIR0(cUnit, kPseudoTargetLabel); -        target->defMask = ENCODE_ALL; -        // Copy next element -        loadBaseIndexed(cUnit, rSrc, rIdx, rVal, 2, kWord); -        storeBaseIndexed(cUnit, rDst, rIdx, rVal, 2, kWord); -        opRegImm(cUnit, kOpSub, rIdx, 1); -        MipsLIR* branch = opCompareBranchCC(cUnit, kMipsCondGe, rIdx, r_ZERO); -        branch->generic.target = (LIR*)target; -    } else if (!isRange) { -        // TUNING: interleave -        for (unsigned int i = 0; i < dInsn->vA; i++) { -            RegLocation rlArg = loadValue(cUnit, -                oatGetSrc(cUnit, mir, i), kCoreReg); -            storeBaseDisp(cUnit, r_V0, -                          Array::DataOffset().Int32Value() + -                          i * 4, rlArg.lowReg, kWord); -            // If the loadValue caused a temp to be allocated, free it -            if (oatIsTemp(cUnit, rlArg.lowReg)) { -                oatFreeTemp(cUnit, rlArg.lowReg); -            } -        } -    } -} - -STATIC void genSput(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc, -                    bool isLongOrDouble, bool isObject) -{ -    int fieldOffset; -    int ssbIndex; -    bool isVolatile; -    bool isReferrersClass; -    uint32_t fieldIdx = mir->dalvikInsn.vB; -    bool fastPath = -        cUnit->compiler->ComputeStaticFieldInfo(fieldIdx, cUnit, -                                                fieldOffset, ssbIndex, -                                                isReferrersClass, isVolatile, true); -    if (fastPath && !SLOW_FIELD_PATH) { -        DCHECK_GE(fieldOffset, 0); -        int rBase; -        int rMethod; -        if (isReferrersClass) { -            // Fast path, static storage base is this method's class -            rMethod  = loadCurrMethod(cUnit); -            rBase = oatAllocTemp(cUnit); -            loadWordDisp(cUnit, rMethod, -                         Method::DeclaringClassOffset().Int32Value(), rBase); -        } else { -            // Medium path, static storage base in a different class which -            // requires checks that the other class is initialized. -            DCHECK_GE(ssbIndex, 0); -            // May do runtime call so everything to home locations. -            oatFlushAllRegs(cUnit); -            // Using fixed register to sync with possible call to runtime -            // support. -            oatLockCallTemps(cUnit); -            rMethod = r1; -            oatLockTemp(cUnit, rMethod); -            loadCurrMethodDirect(cUnit, rMethod); -            rBase = r0; -            oatLockTemp(cUnit, rBase); -            loadWordDisp(cUnit, rMethod, -                Method::DexCacheInitializedStaticStorageOffset().Int32Value(), -                rBase); -            loadWordDisp(cUnit, rBase, -                         Array::DataOffset().Int32Value() + sizeof(int32_t*) * -                         ssbIndex, rBase); -            // rBase now points at appropriate static storage base (Class*) -            // or NULL if not initialized. Check for NULL and call helper if NULL. -            // TUNING: fast path should fall through -            MipsLIR* branchOver = opCmpImmBranchCC(cUnit, kMipsCondNe, -                                                   rBase, 0); -            loadWordDisp(cUnit, rSELF, -                         OFFSETOF_MEMBER(Thread, pInitializeStaticStorage), rLR); -            loadConstant(cUnit, r0, ssbIndex); -            callRuntimeHelper(cUnit, rLR); -            MipsLIR* skipTarget = newLIR0(cUnit, kPseudoTargetLabel); -            skipTarget->defMask = ENCODE_ALL; -            branchOver->generic.target = (LIR*)skipTarget; -        } -        // rBase now holds static storage base -        oatFreeTemp(cUnit, rMethod); -        if (isLongOrDouble) { -            rlSrc = oatGetSrcWide(cUnit, mir, 0, 1); -            rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg); -        } else { -            rlSrc = oatGetSrc(cUnit, mir, 0); -            rlSrc = loadValue(cUnit, rlSrc, kAnyReg); -        } -        if (isVolatile) { -            oatGenMemBarrier(cUnit, kST); -        } -        if (isLongOrDouble) { -            storeBaseDispWide(cUnit, rBase, fieldOffset, rlSrc.lowReg, -                              rlSrc.highReg); -        } else { -            storeWordDisp(cUnit, rBase, fieldOffset, rlSrc.lowReg); -        } -        if (isVolatile) { -            oatGenMemBarrier(cUnit, kSY); -        } -        if (isObject) { -            markGCCard(cUnit, rlSrc.lowReg, rBase); -        } -        oatFreeTemp(cUnit, rBase); -    } else { -        oatFlushAllRegs(cUnit);  // Everything to home locations -        int setterOffset = isLongOrDouble ? OFFSETOF_MEMBER(Thread, pSet64Static) : -                           (isObject ? OFFSETOF_MEMBER(Thread, pSetObjStatic) -                                     : OFFSETOF_MEMBER(Thread, pSet32Static)); -        loadWordDisp(cUnit, rSELF, setterOffset, rLR); -        loadConstant(cUnit, r0, fieldIdx); -        if (isLongOrDouble) { -            loadValueDirectWideFixed(cUnit, rlSrc, r2, r3); -        } else { -            loadValueDirect(cUnit, rlSrc, r1); -        } -        callRuntimeHelper(cUnit, rLR); -    } -} - -STATIC void genSget(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, -                    bool isLongOrDouble, bool isObject) -{ -    UNIMPLEMENTED(FATAL) << "Needs mips version"; -#if 0 -    int fieldOffset; -    int ssbIndex; -    bool isVolatile; -    bool isReferrersClass; -    uint32_t fieldIdx = mir->dalvikInsn.vB; -    bool fastPath = -        cUnit->compiler->ComputeStaticFieldInfo(fieldIdx, cUnit, -                                                fieldOffset, ssbIndex, -                                                isReferrersClass, isVolatile, false); -    if (fastPath && !SLOW_FIELD_PATH) { -        DCHECK_GE(fieldOffset, 0); -        int rBase; -        int rMethod; -        if (isReferrersClass) { -            // Fast path, static storage base is this method's class -            rMethod  = loadCurrMethod(cUnit); -            rBase = oatAllocTemp(cUnit); -            loadWordDisp(cUnit, rMethod, -                         Method::DeclaringClassOffset().Int32Value(), rBase); -        } else { -            // Medium path, static storage base in a different class which -            // requires checks that the other class is initialized -            DCHECK_GE(ssbIndex, 0); -            // May do runtime call so everything to home locations. -            oatFlushAllRegs(cUnit); -            // Using fixed register to sync with possible call to runtime -            // support -            rMethod = r1; -            oatLockTemp(cUnit, rMethod); -            loadCurrMethodDirect(cUnit, rMethod); -            rBase = r0; -            oatLockTemp(cUnit, rBase); -            loadWordDisp(cUnit, rMethod, -                Method::DexCacheInitializedStaticStorageOffset().Int32Value(), -                rBase); -            loadWordDisp(cUnit, rBase, -                         Array::DataOffset().Int32Value() + sizeof(int32_t*) * ssbIndex, -                         rBase); -            // rBase now points at appropriate static storage base (Class*) -            // or NULL if not initialized. Check for NULL and call helper if NULL. -            // TUNING: fast path should fall through -            MipsLIR* branchOver = opCmpImmBranchCC(cUnit, kMipsCondNe, rBase, 0); -            loadWordDisp(cUnit, rSELF, -                         OFFSETOF_MEMBER(Thread, pInitializeStaticStorage), rLR); -            loadConstant(cUnit, r0, ssbIndex); -            callRuntimeHelper(cUnit, rLR); -            MipsLIR* skipTarget = newLIR0(cUnit, kPseudoTargetLabel); -            skipTarget->defMask = ENCODE_ALL; -            branchOver->generic.target = (LIR*)skipTarget; -        } -        // rBase now holds static storage base -        oatFreeTemp(cUnit, rMethod); -        rlDest = isLongOrDouble ? oatGetDestWide(cUnit, mir, 0, 1) -                                : oatGetDest(cUnit, mir, 0); -        RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true); -        if (isVolatile) { -            oatGenMemBarrier(cUnit, kSY); -        } -        if (isLongOrDouble) { -            loadBaseDispWide(cUnit, NULL, rBase, fieldOffset, rlResult.lowReg, -                             rlResult.highReg, INVALID_SREG); -        } else { -            loadWordDisp(cUnit, rBase, fieldOffset, rlResult.lowReg); -        } -        oatFreeTemp(cUnit, rBase); -        if (isLongOrDouble) { -            storeValueWide(cUnit, rlDest, rlResult); -        } else { -            storeValue(cUnit, rlDest, rlResult); -        } -    } else { -        oatFlushAllRegs(cUnit);  // Everything to home locations -        int getterOffset = isLongOrDouble ? OFFSETOF_MEMBER(Thread, pGet64Static) : -                           (isObject ? OFFSETOF_MEMBER(Thread, pGetObjStatic) -                                     : OFFSETOF_MEMBER(Thread, pGet32Static)); -        loadWordDisp(cUnit, rSELF, getterOffset, rLR); -        loadConstant(cUnit, r0, fieldIdx); -        callRuntimeHelper(cUnit, rLR); -        if (isLongOrDouble) { -            RegLocation rlResult = oatGetReturnWide(cUnit); -            storeValueWide(cUnit, rlDest, rlResult); -        } else { -            RegLocation rlResult = oatGetReturn(cUnit); -            storeValue(cUnit, rlDest, rlResult); -        } -    } -#endif -} - -typedef int (*NextCallInsn)(CompilationUnit*, MIR*, int, uint32_t dexIdx, -                            uint32_t methodIdx); - -/* - * Bit of a hack here - in leiu of a real scheduling pass, - * emit the next instruction in static & direct invoke sequences. - */ -STATIC int nextSDCallInsn(CompilationUnit* cUnit, MIR* mir, -                          int state, uint32_t dexIdx, uint32_t unused) -{ -    UNIMPLEMENTED(FATAL) << "Needs mips version"; -#if 0 -    switch(state) { -        case 0:  // Get the current Method* [sets r0] -            loadCurrMethodDirect(cUnit, r0); -            break; -        case 1:  // Get method->code_and_direct_methods_ -            loadWordDisp(cUnit, r0, -                Method::GetDexCacheCodeAndDirectMethodsOffset().Int32Value(), -                r0); -            break; -        case 2:  // Grab target method* and target code_ -            loadWordDisp(cUnit, r0, -                CodeAndDirectMethods::CodeOffsetInBytes(dexIdx), rLR); -            loadWordDisp(cUnit, r0, -                CodeAndDirectMethods::MethodOffsetInBytes(dexIdx), r0); -            break; -        default: -            return -1; -    } -#endif -    return state + 1; -} - -/* - * Bit of a hack here - in leiu of a real scheduling pass, - * emit the next instruction in a virtual invoke sequence. - * We can use rLR as a temp prior to target address loading - * Note also that we'll load the first argument ("this") into - * r1 here rather than the standard loadArgRegs. - */ -STATIC int nextVCallInsn(CompilationUnit* cUnit, MIR* mir, -                         int state, uint32_t dexIdx, uint32_t methodIdx) -{ -    UNIMPLEMENTED(FATAL) << "Needs mips version"; -#if 0 -    RegLocation rlArg; -    /* -     * This is the fast path in which the target virtual method is -     * fully resolved at compile time. -     */ -    switch(state) { -        case 0:  // Get "this" [set r1] -            rlArg = oatGetSrc(cUnit, mir, 0); -            loadValueDirectFixed(cUnit, rlArg, r1); -            break; -        case 1: // Is "this" null? [use r1] -            genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir); -            // get this->klass_ [use r1, set rLR] -            loadWordDisp(cUnit, r1, Object::ClassOffset().Int32Value(), rLR); -            break; -        case 2: // Get this->klass_->vtable [usr rLR, set rLR] -            loadWordDisp(cUnit, rLR, Class::VTableOffset().Int32Value(), rLR); -            break; -        case 3: // Get target method [use rLR, set r0] -            loadWordDisp(cUnit, rLR, (methodIdx * 4) + -                         Array::DataOffset().Int32Value(), r0); -            break; -        case 4: // Get the target compiled code address [uses r0, sets rLR] -            loadWordDisp(cUnit, r0, Method::GetCodeOffset().Int32Value(), rLR); -            break; -        default: -            return -1; -    } -#endif -    return state + 1; -} +void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset);  /* - * Interleave launch code for INVOKE_SUPER.  See comments - * for nextVCallIns. + * In the Arm code a it is typical to use the link register + * to hold the target address.  However, for Mips we must + * ensure that all branch instructions can be restarted if + * there is a trap in the shadow.  Allocate a temp register.   */ -STATIC int nextSuperCallInsn(CompilationUnit* cUnit, MIR* mir, -                             int state, uint32_t dexIdx, uint32_t methodIdx) -{ -    UNIMPLEMENTED(FATAL) << "Needs mips version"; -#if 0 -    /* -     * This is the fast path in which the target virtual method is -     * fully resolved at compile time.  Note also that this path assumes -     * that the check to verify that the target method index falls -     * within the size of the super's vtable has been done at compile-time. -     */ -    RegLocation rlArg; -    switch(state) { -        case 0: // Get current Method* [set r0] -            loadCurrMethodDirect(cUnit, r0); -            // Load "this" [set r1] -            rlArg = oatGetSrc(cUnit, mir, 0); -            loadValueDirectFixed(cUnit, rlArg, r1); -            // Get method->declaring_class_ [use r0, set rLR] -            loadWordDisp(cUnit, r0, Method::DeclaringClassOffset().Int32Value(), -                         rLR); -            // Is "this" null? [use r1] -            genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir); -            break; -        case 1: // Get method->declaring_class_->super_class [usr rLR, set rLR] -            loadWordDisp(cUnit, rLR, Class::SuperClassOffset().Int32Value(), -                         rLR); -            break; -        case 2: // Get ...->super_class_->vtable [u/s rLR] -            loadWordDisp(cUnit, rLR, Class::VTableOffset().Int32Value(), rLR); -            break; -        case 3: // Get target method [use rLR, set r0] -            loadWordDisp(cUnit, rLR, (methodIdx * 4) + -                         Array::DataOffset().Int32Value(), r0); -            break; -        case 4: // Get the target compiled code address [uses r0, sets rLR] -            loadWordDisp(cUnit, r0, Method::GetCodeOffset().Int32Value(), rLR); -            break; -        default: -            return -1; -    } -#endif -    return state + 1; -} - -STATIC int nextInvokeInsnSP(CompilationUnit* cUnit, MIR* mir, int trampoline, -                            int state, uint32_t dexIdx, uint32_t methodIdx) -{ -    UNIMPLEMENTED(FATAL) << "Needs mips version"; -#if 0 -    /* -     * This handles the case in which the base method is not fully -     * resolved at compile time, we bail to a runtime helper. -     */ -    if (state == 0) { -        // Load trampoline target -        loadWordDisp(cUnit, rSELF, trampoline, rLR); -        // Load r0 with method index -        loadConstant(cUnit, r0, dexIdx); -        return 1; -    } -#endif -    return -1; -} - -STATIC int nextStaticCallInsnSP(CompilationUnit* cUnit, MIR* mir, -                                int state, uint32_t dexIdx, uint32_t methodIdx) -{ -  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeStaticTrampolineWithAccessCheck); -  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0); -} - -STATIC int nextDirectCallInsnSP(CompilationUnit* cUnit, MIR* mir, -                                int state, uint32_t dexIdx, uint32_t methodIdx) +int loadHelper(CompilationUnit* cUnit, int offset)  { -  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeDirectTrampolineWithAccessCheck); -  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0); +    int tReg = oatAllocTemp(cUnit); +    loadWordDisp(cUnit, rSELF, offset, tReg); +    return tReg;  } -STATIC int nextSuperCallInsnSP(CompilationUnit* cUnit, MIR* mir, -                               int state, uint32_t dexIdx, uint32_t methodIdx) +void spillCoreRegs(CompilationUnit* cUnit)  { -  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeSuperTrampolineWithAccessCheck); -  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0); -} - -STATIC int nextVCallInsnSP(CompilationUnit* cUnit, MIR* mir, -                           int state, uint32_t dexIdx, uint32_t methodIdx) -{ -  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeVirtualTrampolineWithAccessCheck); -  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0); -} - -/* - * All invoke-interface calls bounce off of art_invoke_interface_trampoline, - * which will locate the target and continue on via a tail call. - */ -STATIC int nextInterfaceCallInsn(CompilationUnit* cUnit, MIR* mir, -                                 int state, uint32_t dexIdx, uint32_t unused) -{ -  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeInterfaceTrampoline); -  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0); -} - -STATIC int nextInterfaceCallInsnWithAccessCheck(CompilationUnit* cUnit, -                                                MIR* mir, int state, -                                                uint32_t dexIdx, -                                                uint32_t unused) -{ -  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeInterfaceTrampolineWithAccessCheck); -  return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0); -} - -STATIC int loadArgRegs(CompilationUnit* cUnit, MIR* mir, -                          DecodedInstruction* dInsn, int callState, -                          NextCallInsn nextCallInsn, uint32_t dexIdx, -                          uint32_t methodIdx, bool skipThis) -{ -    UNIMPLEMENTED(FATAL) << "Needs mips version"; -#if 0 -    int nextReg = r1; -    int nextArg = 0; -    if (skipThis) { -        nextReg++; -        nextArg++; -    } -    for (; (nextReg <= r3) && (nextArg < mir->ssaRep->numUses); nextReg++) { -        RegLocation rlArg = oatGetRawSrc(cUnit, mir, nextArg++); -        rlArg = oatUpdateRawLoc(cUnit, rlArg); -        if (rlArg.wide && (nextReg <= r2)) { -            loadValueDirectWideFixed(cUnit, rlArg, nextReg, nextReg + 1); -            nextReg++; -            nextArg++; -        } else { -            rlArg.wide = false; -            loadValueDirectFixed(cUnit, rlArg, nextReg); -        } -        callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx); +    if (cUnit->numCoreSpills == 0) { +        return;      } -#endif -    return callState; -} - -/* - * Load up to 5 arguments, the first three of which will be in - * r1 .. r3.  On entry r0 contains the current method pointer, - * and as part of the load sequence, it must be replaced with - * the target method pointer.  Note, this may also be called - * for "range" variants if the number of arguments is 5 or fewer. - */ -STATIC int genDalvikArgsNoRange(CompilationUnit* cUnit, MIR* mir, -                                DecodedInstruction* dInsn, int callState, -                                MipsLIR** pcrLabel, NextCallInsn nextCallInsn, -                                uint32_t dexIdx, uint32_t methodIdx, -                                bool skipThis) -{ -    UNIMPLEMENTED(FATAL) << "Needs mips version"; -#if 0 -    RegLocation rlArg; - -    /* If no arguments, just return */ -    if (dInsn->vA == 0) -        return callState; - -    callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx); - -    DCHECK_LE(dInsn->vA, 5U); -    if (dInsn->vA > 3) { -        uint32_t nextUse = 3; -        //Detect special case of wide arg spanning arg3/arg4 -        RegLocation rlUse0 = oatGetRawSrc(cUnit, mir, 0); -        RegLocation rlUse1 = oatGetRawSrc(cUnit, mir, 1); -        RegLocation rlUse2 = oatGetRawSrc(cUnit, mir, 2); -        if (((!rlUse0.wide && !rlUse1.wide) || rlUse0.wide) && -            rlUse2.wide) { -            int reg; -            // Wide spans, we need the 2nd half of uses[2]. -            rlArg = oatUpdateLocWide(cUnit, rlUse2); -            if (rlArg.location == kLocPhysReg) { -                reg = rlArg.highReg; -            } else { -                // r2 & r3 can safely be used here -                reg = r3; -                loadWordDisp(cUnit, rSP, -                             oatSRegOffset(cUnit, rlArg.sRegLow) + 4, reg); -                callState = nextCallInsn(cUnit, mir, callState, dexIdx, -                                         methodIdx); -            } -            storeBaseDisp(cUnit, rSP, (nextUse + 1) * 4, reg, kWord); -            storeBaseDisp(cUnit, rSP, 16 /* (3+1)*4 */, reg, kWord); -            callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx); -            nextUse++; -        } -        // Loop through the rest -        while (nextUse < dInsn->vA) { -            int lowReg; -            int highReg; -            rlArg = oatGetRawSrc(cUnit, mir, nextUse); -            rlArg = oatUpdateRawLoc(cUnit, rlArg); -            if (rlArg.location == kLocPhysReg) { -                lowReg = rlArg.lowReg; -                highReg = rlArg.highReg; -            } else { -                lowReg = r2; -                highReg = r3; -                if (rlArg.wide) { -                    loadValueDirectWideFixed(cUnit, rlArg, lowReg, highReg); -                } else { -                    loadValueDirectFixed(cUnit, rlArg, lowReg); -                } -                callState = nextCallInsn(cUnit, mir, callState, dexIdx, -                                         methodIdx); -            } -            int outsOffset = (nextUse + 1) * 4; -            if (rlArg.wide) { -                storeBaseDispWide(cUnit, rSP, outsOffset, lowReg, highReg); -                nextUse += 2; -            } else { -                storeWordDisp(cUnit, rSP, outsOffset, lowReg); -                nextUse++; -            } -            callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx); +    uint32_t mask = cUnit->coreSpillMask; +    int offset = cUnit->numCoreSpills * 4; +    opRegImm(cUnit, kOpSub, rSP, offset); +    for (int reg = 0; mask; mask >>= 1, reg++) { +        if (mask & 0x1) { +            offset -= 4; +            storeWordDisp(cUnit, rSP, offset, reg);          }      } - -    callState = loadArgRegs(cUnit, mir, dInsn, callState, nextCallInsn, -                            dexIdx, methodIdx, skipThis); - -    if (pcrLabel) { -        *pcrLabel = genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir); -    } -#endif -    return callState;  } -/* - * May have 0+ arguments (also used for jumbo).  Note that - * source virtual registers may be in physical registers, so may - * need to be flushed to home location before copying.  This - * applies to arg3 and above (see below). - * - * Two general strategies: - *    If < 20 arguments - *       Pass args 3-18 using vldm/vstm block copy - *       Pass arg0, arg1 & arg2 in r1-r3 - *    If 20+ arguments - *       Pass args arg19+ using memcpy block copy - *       Pass arg0, arg1 & arg2 in r1-r3 - * - */ -STATIC int genDalvikArgsRange(CompilationUnit* cUnit, MIR* mir, -                              DecodedInstruction* dInsn, int callState, -                              MipsLIR** pcrLabel, NextCallInsn nextCallInsn, -                              uint32_t dexIdx, uint32_t methodIdx, -                              bool skipThis) +void unSpillCoreRegs(CompilationUnit* cUnit)  { -    UNIMPLEMENTED(FATAL) << "Needs mips version"; -#if 0 -    int firstArg = dInsn->vC; -    int numArgs = dInsn->vA; - -    // If we can treat it as non-range (Jumbo ops will use range form) -    if (numArgs <= 5) -        return genDalvikArgsNoRange(cUnit, mir, dInsn, callState, pcrLabel, -                                    nextCallInsn, dexIdx, methodIdx, -                                    skipThis); -    /* -     * Make sure range list doesn't span the break between in normal -     * Dalvik vRegs and the ins. -     */ -    int highestArg = oatGetSrc(cUnit, mir, numArgs-1).sRegLow; -    int boundaryReg = cUnit->numDalvikRegisters - cUnit->numIns; -    if ((firstArg < boundaryReg) && (highestArg >= boundaryReg)) { -        LOG(FATAL) << "Argument list spanned locals & args"; -    } - -    /* -     * First load the non-register arguments.  Both forms expect all -     * of the source arguments to be in their home frame location, so -     * scan the sReg names and flush any that have been promoted to -     * frame backing storage. -     */ -    // Scan the rest of the args - if in physReg flush to memory -    for (int nextArg = 0; nextArg < numArgs;) { -        RegLocation loc = oatGetRawSrc(cUnit, mir, nextArg); -        if (loc.wide) { -            loc = oatUpdateLocWide(cUnit, loc); -            if ((nextArg >= 2) && (loc.location == kLocPhysReg)) { -                storeBaseDispWide(cUnit, rSP, -                                  oatSRegOffset(cUnit, loc.sRegLow), -                                  loc.lowReg, loc.highReg); -            } -            nextArg += 2; -        } else { -            loc = oatUpdateLoc(cUnit, loc); -            if ((nextArg >= 3) && (loc.location == kLocPhysReg)) { -                storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, loc.sRegLow), -                              loc.lowReg, kWord); -            } -            nextArg++; -        } -    } - -    int startOffset = oatSRegOffset(cUnit, -        cUnit->regLocation[mir->ssaRep->uses[3]].sRegLow); -    int outsOffset = 4 /* Method* */ + (3 * 4); -    if (numArgs >= 20) { -        // Generate memcpy -        opRegRegImm(cUnit, kOpAdd, r0, rSP, outsOffset); -        opRegRegImm(cUnit, kOpAdd, r1, rSP, startOffset); -        loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pMemcpy), rLR); -        loadConstant(cUnit, r2, (numArgs - 3) * 4); -        callRuntimeHelper(cUnit, rLR); -        // Restore Method* -        loadCurrMethodDirect(cUnit, r0); -    } else { -        // Use vldm/vstm pair using r3 as a temp -        int regsLeft = std::min(numArgs - 3, 16); -        callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx); -        opRegRegImm(cUnit, kOpAdd, r3, rSP, startOffset); -        MipsLIR* ld = newLIR3(cUnit, kThumb2Vldms, r3, fr0, regsLeft); -        //TUNING: loosen barrier -        ld->defMask = ENCODE_ALL; -        setMemRefType(ld, true /* isLoad */, kDalvikReg); -        callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx); -        opRegRegImm(cUnit, kOpAdd, r3, rSP, 4 /* Method* */ + (3 * 4)); -        callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx); -        MipsLIR* st = newLIR3(cUnit, kThumb2Vstms, r3, fr0, regsLeft); -        setMemRefType(st, false /* isLoad */, kDalvikReg); -        st->defMask = ENCODE_ALL; -        callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx); -    } - -    callState = loadArgRegs(cUnit, mir, dInsn, callState, nextCallInsn, -                            dexIdx, methodIdx, skipThis); - -    callState = nextCallInsn(cUnit, mir, callState, dexIdx, methodIdx); -    if (pcrLabel) { -        *pcrLabel = genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir); -    } -#endif -    return callState; -} - -// Debugging routine - if null target, branch to DebugMe -STATIC void genShowTarget(CompilationUnit* cUnit) -{ -    UNIMPLEMENTED(FATAL) << "Needs mips version"; -#if 0 -    MipsLIR* branchOver = opCmpImmBranch(cUnit, kMipsCondNe, rLR, 0); -    loadWordDisp(cUnit, rSELF, -                 OFFSETOF_MEMBER(Thread, pDebugMe), rLR); -    MipsLIR* target = newLIR0(cUnit, kPseudoTargetLabel); -    target->defMask = -1; -    branchOver->generic.target = (LIR*)target; -#endif -} - -STATIC void genThrowVerificationError(CompilationUnit* cUnit, MIR* mir) -{ -    UNIMPLEMENTED(FATAL) << "Needs mips version"; -#if 0 -    loadWordDisp(cUnit, rSELF, -                 OFFSETOF_MEMBER(Thread, pThrowVerificationErrorFromCode), rLR); -    loadConstant(cUnit, r0, mir->dalvikInsn.vA); -    loadConstant(cUnit, r1, mir->dalvikInsn.vB); -    callRuntimeHelper(cUnit, rLR); -#endif -} - -STATIC void genCompareAndBranch(CompilationUnit* cUnit, BasicBlock* bb, -                                MIR* mir, RegLocation rlSrc1, -                                RegLocation rlSrc2, MipsLIR* labelList) -{ -    UNIMPLEMENTED(FATAL) << "Needs mips version"; -#if 0 -    MipsConditionCode cond; -    rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg); -    rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg); -    opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg); -    Opcode opcode = mir->dalvikInsn.opcode; -    switch(opcode) { -        case OP_IF_EQ: -            cond = kMipsCondEq; -            break; -        case OP_IF_NE: -            cond = kMipsCondNe; -            break; -        case OP_IF_LT: -            cond = kMipsCondLt; -            break; -        case OP_IF_GE: -            cond = kMipsCondGe; -            break; -        case OP_IF_GT: -            cond = kMipsCondGt; -            break; -        case OP_IF_LE: -            cond = kMipsCondLe; -            break; -        default: -            cond = (MipsConditionCode)0; -            LOG(FATAL) << "Unexpected opcode " << (int)opcode; -    } -    genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]); -    genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]); -#endif -} - -STATIC void genCompareZeroAndBranch(CompilationUnit* cUnit, BasicBlock* bb, -                                   MIR* mir, RegLocation rlSrc, -                                   MipsLIR* labelList) -{ -    UNIMPLEMENTED(FATAL) << "Needs mips version"; -#if 0 -    MipsConditionCode cond; -    rlSrc = loadValue(cUnit, rlSrc, kCoreReg); -    opRegImm(cUnit, kOpCmp, rlSrc.lowReg, 0); -    Opcode opcode = mir->dalvikInsn.opcode; -    switch(opcode) { -        case OP_IF_EQZ: -            cond = kMipsCondEq; -            break; -        case OP_IF_NEZ: -            cond = kMipsCondNe; -            break; -        case OP_IF_LTZ: -            cond = kMipsCondLt; -            break; -        case OP_IF_GEZ: -            cond = kMipsCondGe; -            break; -        case OP_IF_GTZ: -            cond = kMipsCondGt; -            break; -        case OP_IF_LEZ: -            cond = kMipsCondLe; -            break; -        default: -            cond = (MipsConditionCode)0; -            LOG(FATAL) << "Unexpected opcode " << (int)opcode; -    } -    genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]); -    genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]); -#endif -} - -STATIC void genIntToLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, -                         RegLocation rlSrc) -{ -    UNIMPLEMENTED(FATAL) << "Needs mips version"; -#if 0 -    RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); -    if (rlSrc.location == kLocPhysReg) { -        genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg); -    } else { -        loadValueDirect(cUnit, rlSrc, rlResult.lowReg); -    } -    opRegRegImm(cUnit, kOpAsr, rlResult.highReg, -                rlResult.lowReg, 31); -    storeValueWide(cUnit, rlDest, rlResult); -#endif -} - -STATIC void genIntNarrowing(CompilationUnit* cUnit, MIR* mir, -                            RegLocation rlDest, RegLocation rlSrc) -{ -    UNIMPLEMENTED(FATAL) << "Needs mips version"; -#if 0 -     rlSrc = loadValue(cUnit, rlSrc, kCoreReg); -     RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); -     OpKind op = kOpInvalid; -     switch(mir->dalvikInsn.opcode) { -         case OP_INT_TO_BYTE: -             op = kOp2Byte; -             break; -         case OP_INT_TO_SHORT: -              op = kOp2Short; -              break; -         case OP_INT_TO_CHAR: -              op = kOp2Char; -              break; -         default: -             LOG(ERROR) << "Bad int conversion type"; -     } -     opRegReg(cUnit, op, rlResult.lowReg, rlSrc.lowReg); -     storeValue(cUnit, rlDest, rlResult); -#endif -} - -/* - * If there are any ins passed in registers that have not been promoted - * to a callee-save register, flush them to the frame.  Perform intial - * assignment of promoted arguments. - */ -STATIC void flushIns(CompilationUnit* cUnit) -{ -    UNIMPLEMENTED(FATAL) << "Needs mips version"; -#if 0 -    if (cUnit->numIns == 0) +    if (cUnit->numCoreSpills == 0) {          return; -    int firstArgReg = r1; -    int lastArgReg = r3; -    int startVReg = cUnit->numDalvikRegisters - cUnit->numIns; -    /* -     * Arguments passed in registers should be flushed -     * to their backing locations in the frame for now. -     * Also, we need to do initial assignment for promoted -     * arguments.  NOTE: an older version of dx had an issue -     * in which it would reuse static method argument registers. -     * This could result in the same Dalvik virtual register -     * being promoted to both core and fp regs.  In those -     * cases, copy argument to both.  This will be uncommon -     * enough that it isn't worth attempting to optimize. -     */ -    for (int i = 0; i < cUnit->numIns; i++) { -        PromotionMap vMap = cUnit->promotionMap[startVReg + i]; -        if (i <= (lastArgReg - firstArgReg)) { -            // If arriving in register -            if (vMap.coreLocation == kLocPhysReg) { -                genRegCopy(cUnit, vMap.coreReg, firstArgReg + i); -            } -            if (vMap.fpLocation == kLocPhysReg) { -                genRegCopy(cUnit, vMap.fpReg, firstArgReg + i); -            } -            // Also put a copy in memory in case we're partially promoted -            storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i), -                          firstArgReg + i, kWord); -        } else { -            // If arriving in frame & promoted -            if (vMap.coreLocation == kLocPhysReg) { -                loadWordDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i), -                             vMap.coreReg); -            } -            if (vMap.fpLocation == kLocPhysReg) { -                loadWordDisp(cUnit, rSP, oatSRegOffset(cUnit, startVReg + i), -                             vMap.fpReg); -            } +    } +    uint32_t mask = cUnit->coreSpillMask; +    int offset = cUnit->frameSize; +    for (int reg = 0; mask; mask >>= 1, reg++) { +        if (mask & 0x1) { +            offset -= 4; +            loadWordDisp(cUnit, rSP, offset, reg);          }      } -#endif +    opRegImm(cUnit, kOpAdd, rSP, cUnit->frameSize);  } -STATIC void genEntrySequence(CompilationUnit* cUnit, BasicBlock* bb) +void genEntrySequence(CompilationUnit* cUnit, BasicBlock* bb)  { -    UNIMPLEMENTED(FATAL) << "Needs mips version"; -#if 0      int spillCount = cUnit->numCoreSpills + cUnit->numFPSpills;      /* -     * On entry, r0, r1, r2 & r3 are live.  Let the register allocation -     * mechanism know so it doesn't try to use any of them when +     * On entry, rARG0, rARG1, rARG2 & rARG3 are live.  Let the register +     * allocation mechanism know so it doesn't try to use any of them when       * expanding the frame or flushing.  This leaves the utility       * code with a single temp: r12.  This should be enough.       */ -    oatLockTemp(cUnit, r0); -    oatLockTemp(cUnit, r1); -    oatLockTemp(cUnit, r2); -    oatLockTemp(cUnit, r3); +    oatLockTemp(cUnit, rARG0); +    oatLockTemp(cUnit, rARG1); +    oatLockTemp(cUnit, rARG2); +    oatLockTemp(cUnit, rARG3);      /*       * We can safely skip the stack overflow check if we're @@ -1121,33 +93,28 @@ STATIC void genEntrySequence(CompilationUnit* cUnit, BasicBlock* bb)                                ((size_t)cUnit->frameSize <                                Thread::kStackOverflowReservedBytes));      newLIR0(cUnit, kPseudoMethodEntry); +    int checkReg = oatAllocTemp(cUnit); +    int newSP = oatAllocTemp(cUnit);      if (!skipOverflowCheck) {          /* Load stack limit */          loadWordDisp(cUnit, rSELF, -                     Thread::StackEndOffset().Int32Value(), r12); +                     Thread::StackEndOffset().Int32Value(), checkReg);      }      /* Spill core callee saves */ -    newLIR1(cUnit, kThumb2Push, cUnit->coreSpillMask); -    /* Need to spill any FP regs? */ -    if (cUnit->numFPSpills) { -        /* -         * NOTE: fp spills are a little different from core spills in that -         * they are pushed as a contiguous block.  When promoting from -         * the fp set, we must allocate all singles from s16..highest-promoted -         */ -        newLIR1(cUnit, kThumb2VPushCS, cUnit->numFPSpills); -    } +    spillCoreRegs(cUnit); +    /* NOTE: promotion of FP regs currently unsupported, thus no FP spill */ +    DCHECK_EQ(cUnit->numFPSpills, 0);      if (!skipOverflowCheck) { -        opRegRegImm(cUnit, kOpSub, rLR, rSP, +        opRegRegImm(cUnit, kOpSub, newSP, rSP,                      cUnit->frameSize - (spillCount * 4)); -        genRegRegCheck(cUnit, kMipsCondCc, rLR, r12, NULL, -                       kMipsThrowStackOverflow); -        genRegCopy(cUnit, rSP, rLR);         // Establish stack +        genRegRegCheck(cUnit, kCondCc, newSP, checkReg, NULL, +                       kThrowStackOverflow); +        genRegCopy(cUnit, rSP, newSP);         // Establish stack      } else {          opRegImm(cUnit, kOpSub, rSP,                   cUnit->frameSize - (spillCount * 4));      } -    storeBaseDisp(cUnit, rSP, 0, r0, kWord); +    storeBaseDisp(cUnit, rSP, 0, rARG0, kWord);      flushIns(cUnit);      if (cUnit->genDebugger) { @@ -1157,46 +124,28 @@ STATIC void genEntrySequence(CompilationUnit* cUnit, BasicBlock* bb)          genDebuggerUpdate(cUnit, DEBUGGER_METHOD_ENTRY);      } -    oatFreeTemp(cUnit, r0); -    oatFreeTemp(cUnit, r1); -    oatFreeTemp(cUnit, r2); -    oatFreeTemp(cUnit, r3); -#endif +    oatFreeTemp(cUnit, rARG0); +    oatFreeTemp(cUnit, rARG1); +    oatFreeTemp(cUnit, rARG2); +    oatFreeTemp(cUnit, rARG3);  } -STATIC void genExitSequence(CompilationUnit* cUnit, BasicBlock* bb) +void genExitSequence(CompilationUnit* cUnit, BasicBlock* bb)  { -    UNIMPLEMENTED(FATAL) << "Needs mips version"; -#if 0 -    int spillCount = cUnit->numCoreSpills + cUnit->numFPSpills;      /* -     * In the exit path, r0/r1 are live - make sure they aren't +     * In the exit path, rRET0/rRET1 are live - make sure they aren't       * allocated by the register utilities as temps.       */ -    oatLockTemp(cUnit, r0); -    oatLockTemp(cUnit, r1); +    oatLockTemp(cUnit, rRET0); +    oatLockTemp(cUnit, rRET1);      newLIR0(cUnit, kPseudoMethodExit);      /* If we're compiling for the debugger, generate an update callout */      if (cUnit->genDebugger) {          genDebuggerUpdate(cUnit, DEBUGGER_METHOD_EXIT);      } -    opRegImm(cUnit, kOpAdd, rSP, cUnit->frameSize - (spillCount * 4)); -    /* Need to restore any FP callee saves? */ -    if (cUnit->numFPSpills) { -        newLIR1(cUnit, kThumb2VPopCS, cUnit->numFPSpills); -    } -    if (cUnit->coreSpillMask & (1 << rLR)) { -        /* Unspill rLR to rPC */ -        cUnit->coreSpillMask &= ~(1 << rLR); -        cUnit->coreSpillMask |= (1 << rPC); -    } -    newLIR1(cUnit, kThumb2Pop, cUnit->coreSpillMask); -    if (!(cUnit->coreSpillMask & (1 << rPC))) { -        /* We didn't pop to rPC, so must do a bv rLR */ -        newLIR1(cUnit, kThumbBx, rLR); -    } -#endif +    unSpillCoreRegs(cUnit); +    opReg(cUnit, kOpBx, rLINK);  }  /* @@ -1206,18 +155,15 @@ STATIC void genExitSequence(CompilationUnit* cUnit, BasicBlock* bb)   */  void removeRedundantBranches(CompilationUnit* cUnit)  { -    UNIMPLEMENTED(FATAL) << "Needs mips version"; -#if 0 -    MipsLIR* thisLIR; +    LIR* thisLIR; -    for (thisLIR = (MipsLIR*) cUnit->firstLIRInsn; -         thisLIR != (MipsLIR*) cUnit->lastLIRInsn; +    for (thisLIR = (LIR*) cUnit->firstLIRInsn; +         thisLIR != (LIR*) cUnit->lastLIRInsn;           thisLIR = NEXT_LIR(thisLIR)) {          /* Branch to the next instruction */ -        if ((thisLIR->opcode == kThumbBUncond) || -            (thisLIR->opcode == kThumb2BUncond)) { -            MipsLIR* nextLIR = thisLIR; +        if (thisLIR->opcode == kMipsB) { +            LIR* nextLIR = thisLIR;              while (true) {                  nextLIR = NEXT_LIR(nextLIR); @@ -1225,7 +171,7 @@ void removeRedundantBranches(CompilationUnit* cUnit)                  /*                   * Is the branch target the next instruction?                   */ -                if (nextLIR == (MipsLIR*) thisLIR->generic.target) { +                if (nextLIR == (LIR*) thisLIR->target) {                      thisLIR->flags.isNop = true;                      break;                  } @@ -1236,116 +182,13 @@ void removeRedundantBranches(CompilationUnit* cUnit)                   * might be the last real instruction.                   */                  if (!isPseudoOpcode(nextLIR->opcode) || -                    (nextLIR = (MipsLIR*) cUnit->lastLIRInsn)) +                    (nextLIR = (LIR*) cUnit->lastLIRInsn))                      break;              }          }      } -#endif  } -STATIC void handleSuspendLaunchpads(CompilationUnit *cUnit) -{ -    UNIMPLEMENTED(FATAL) << "Needs mips version"; -#if 0 -    MipsLIR** suspendLabel = -        (MipsLIR **) cUnit->suspendLaunchpads.elemList; -    int numElems = cUnit->suspendLaunchpads.numUsed; - -    for (int i = 0; i < numElems; i++) { -        /* TUNING: move suspend count load into helper */ -        MipsLIR* lab = suspendLabel[i]; -        MipsLIR* resumeLab = (MipsLIR*)lab->operands[0]; -        cUnit->currentDalvikOffset = lab->operands[1]; -        oatAppendLIR(cUnit, (LIR *)lab); -        loadWordDisp(cUnit, rSELF, -                     OFFSETOF_MEMBER(Thread, pTestSuspendFromCode), rLR); -        if (!cUnit->genDebugger) { -            // use rSUSPEND for suspend count -            loadWordDisp(cUnit, rSELF, -                         Thread::SuspendCountOffset().Int32Value(), rSUSPEND); -        } -        opReg(cUnit, kOpBlx, rLR); -        if ( cUnit->genDebugger) { -            // use rSUSPEND for update debugger -            loadWordDisp(cUnit, rSELF, -                         OFFSETOF_MEMBER(Thread, pUpdateDebuggerFromCode), rSUSPEND); -        } -        genUnconditionalBranch(cUnit, resumeLab); -    } -#endif -} - -STATIC void handleThrowLaunchpads(CompilationUnit *cUnit) -{ -    UNIMPLEMENTED(FATAL) << "Needs mips version"; -#if 0 -    MipsLIR** throwLabel = -        (MipsLIR **) cUnit->throwLaunchpads.elemList; -    int numElems = cUnit->throwLaunchpads.numUsed; -    int i; - -    for (i = 0; i < numElems; i++) { -        MipsLIR* lab = throwLabel[i]; -        cUnit->currentDalvikOffset = lab->operands[1]; -        oatAppendLIR(cUnit, (LIR *)lab); -        int funcOffset = 0; -        int v1 = lab->operands[2]; -        int v2 = lab->operands[3]; -        switch(lab->operands[0]) { -            case kMipsThrowNullPointer: -                funcOffset = OFFSETOF_MEMBER(Thread, pThrowNullPointerFromCode); -                break; -            case kMipsThrowArrayBounds: -                if (v2 != r0) { -                    genRegCopy(cUnit, r0, v1); -                    genRegCopy(cUnit, r1, v2); -                } else { -                    if (v1 == r1) { -                        genRegCopy(cUnit, r12, v1); -                        genRegCopy(cUnit, r1, v2); -                        genRegCopy(cUnit, r0, r12); -                    } else { -                        genRegCopy(cUnit, r1, v2); -                        genRegCopy(cUnit, r0, v1); -                    } -                } -                funcOffset = OFFSETOF_MEMBER(Thread, pThrowArrayBoundsFromCode); -                break; -            case kMipsThrowDivZero: -                funcOffset = OFFSETOF_MEMBER(Thread, pThrowDivZeroFromCode); -                break; -            case kMipsThrowVerificationError: -                loadConstant(cUnit, r0, v1); -                loadConstant(cUnit, r1, v2); -                funcOffset = -                    OFFSETOF_MEMBER(Thread, pThrowVerificationErrorFromCode); -                break; -            case kMipsThrowNegArraySize: -                genRegCopy(cUnit, r0, v1); -                funcOffset = -                    OFFSETOF_MEMBER(Thread, pThrowNegArraySizeFromCode); -                break; -            case kMipsThrowNoSuchMethod: -                genRegCopy(cUnit, r0, v1); -                funcOffset = -                    OFFSETOF_MEMBER(Thread, pThrowNoSuchMethodFromCode); -                break; -            case kMipsThrowStackOverflow: -                funcOffset = -                    OFFSETOF_MEMBER(Thread, pThrowStackOverflowFromCode); -                // Restore stack alignment -                opRegImm(cUnit, kOpAdd, rSP, -                         (cUnit->numCoreSpills + cUnit->numFPSpills) * 4); -                break; -            default: -                LOG(FATAL) << "Unexpected throw kind: " << lab->operands[0]; -        } -        loadWordDisp(cUnit, rSELF, funcOffset, rLR); -        callRuntimeHelper(cUnit, rLR); -    } -#endif -}  /* Common initialization routine for an architecture family */  bool oatArchInit() @@ -1363,10 +206,4 @@ bool oatArchInit()      return oatArchVariantInit();  } -/* Needed by the Assembler */ -void oatSetupResourceMasks(MipsLIR* lir) -{ -    setupResourceMasks(lir); -} -  }  // namespace art diff --git a/src/compiler/codegen/mips/ArchUtility.cc b/src/compiler/codegen/mips/ArchUtility.cc index 2e8d4170d5..7f7aeb3b90 100644 --- a/src/compiler/codegen/mips/ArchUtility.cc +++ b/src/compiler/codegen/mips/ArchUtility.cc @@ -22,6 +22,33 @@  namespace art { +MipsConditionCode oatMipsConditionEncoding(ConditionCode code) +{ +    MipsConditionCode res; +    switch(code) { +        case kCondEq: res = kMipsCondEq; break; +        case kCondNe: res = kMipsCondNe; break; +        case kCondCs: res = kMipsCondCs; break; +        case kCondCc: res = kMipsCondCc; break; +        case kCondMi: res = kMipsCondMi; break; +        case kCondPl: res = kMipsCondPl; break; +        case kCondVs: res = kMipsCondVs; break; +        case kCondVc: res = kMipsCondVc; break; +        case kCondHi: res = kMipsCondHi; break; +        case kCondLs: res = kMipsCondLs; break; +        case kCondGe: res = kMipsCondGe; break; +        case kCondLt: res = kMipsCondLt; break; +        case kCondGt: res = kMipsCondGt; break; +        case kCondLe: res = kMipsCondLe; break; +        case kCondAl: res = kMipsCondAl; break; +        case kCondNv: res = kMipsCondNv; break; +        default: +            LOG(FATAL) << "Bad condition code" << (int)code; +            res = (MipsConditionCode)0;  // Quiet gcc +    } +    return res; +} +  /* For dumping instructions */  #define MIPS_REG_COUNT 32  static const char *mipsRegName[MIPS_REG_COUNT] = { @@ -35,7 +62,7 @@ static const char *mipsRegName[MIPS_REG_COUNT] = {   * Interpret a format string and build a string no longer than size   * See format key in Assemble.c.   */ -STATIC std::string buildInsnString(const char *fmt, MipsLIR *lir, unsigned char* baseAddr) +std::string buildInsnString(const char *fmt, LIR *lir, unsigned char* baseAddr)  {      std::string buf;      int i; @@ -118,9 +145,9 @@ STATIC std::string buildInsnString(const char *fmt, MipsLIR *lir, unsigned char*                         break;                     case 't':                         sprintf(tbuf,"0x%08x (L%p)", -                               (int) baseAddr + lir->generic.offset + 4 + +                               (int) baseAddr + lir->offset + 4 +                                 (operand << 2), -                               lir->generic.target); +                               lir->target);                         break;                     case 'T':                         sprintf(tbuf,"0x%08x", @@ -130,7 +157,7 @@ STATIC std::string buildInsnString(const char *fmt, MipsLIR *lir, unsigned char*                         int offset_1 = lir->operands[0];                         int offset_2 = NEXT_LIR(lir)->operands[0];                         intptr_t target = -                           ((((intptr_t) baseAddr + lir->generic.offset + 4) & +                           ((((intptr_t) baseAddr + lir->offset + 4) &                              ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &                             0xfffffffc;                         sprintf(tbuf, "%p", (void *) target); @@ -163,7 +190,7 @@ void oatDumpResourceMask(LIR *lir, u8 mask, const char *prefix)  {      char buf[256];      buf[0] = 0; -    MipsLIR *mipsLIR = (MipsLIR *) lir; +    LIR *mipsLIR = (LIR *) lir;      if (mask == ENCODE_ALL) {          strcpy(buf, "all"); @@ -205,180 +232,4 @@ void oatDumpResourceMask(LIR *lir, u8 mask, const char *prefix)      }  } -/* - * Debugging macros - */ -#define DUMP_RESOURCE_MASK(X) -#define DUMP_SSA_REP(X) - -/* Pretty-print a LIR instruction */ -void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr) -{ -    MipsLIR* lir = (MipsLIR*) arg; -    int offset = lir->generic.offset; -    int dest = lir->operands[0]; -    const bool dumpNop = false; - -    /* Handle pseudo-ops individually, and all regular insns as a group */ -    switch(lir->opcode) { -        case kPseudoMethodEntry: -            LOG(INFO) << "-------- method entry " << -                PrettyMethod(cUnit->method_idx, *cUnit->dex_file); -            break; -        case kPseudoMethodExit: -            LOG(INFO) << "-------- Method_Exit"; -            break; -        case kPseudoBarrier: -            LOG(INFO) << "-------- BARRIER"; -            break; -        case kPseudoExtended: -            LOG(INFO) << "-------- " << (char* ) dest; -            break; -        case kPseudoSSARep: -            DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " <<  (char* ) dest); -            break; -        case kPseudoEntryBlock: -            LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest; -            break; -        case kPseudoDalvikByteCodeBoundary: -            LOG(INFO) << "-------- dalvik offset: 0x" << std::hex << -                 lir->generic.dalvikOffset << " @ " << (char* )lir->operands[0]; -            break; -        case kPseudoExitBlock: -            LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest; -            break; -        case kPseudoPseudoAlign4: -            LOG(INFO) << (intptr_t)baseAddr + offset << " (0x" << std::hex << -                offset << "): .align4"; -            break; -        case kPseudoEHBlockLabel: -            LOG(INFO) << "Exception_Handling:"; -            break; -        case kPseudoTargetLabel: -        case kPseudoNormalBlockLabel: -            LOG(INFO) << "L" << (intptr_t)lir << ":"; -            break; -        case kPseudoThrowTarget: -            LOG(INFO) << "LT" << (intptr_t)lir << ":"; -            break; -        case kPseudoSuspendTarget: -            LOG(INFO) << "LS" << (intptr_t)lir << ":"; -            break; -        case kPseudoCaseLabel: -            LOG(INFO) << "LC" << (intptr_t)lir << ": Case target 0x" << -                std::hex << lir->operands[0] << "|" << std::dec << -                lir->operands[0]; -            break; -        default: -            if (lir->flags.isNop && !dumpNop) { -                break; -            } else { -                std::string op_name(buildInsnString(EncodingMap[lir->opcode].name, lir, baseAddr)); -                std::string op_operands(buildInsnString(EncodingMap[lir->opcode].fmt, lir, baseAddr)); -                LOG(INFO) << StringPrintf("%p (%04x): %-9s%s%s", baseAddr + offset, offset, -                    op_name.c_str(), op_operands.c_str(), lir->flags.isNop ? "(nop)" : ""); -            } -            break; -    } - -    if (lir->useMask && (!lir->flags.isNop || dumpNop)) { -        DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, -                                               lir->useMask, "use")); -    } -    if (lir->defMask && (!lir->flags.isNop || dumpNop)) { -        DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir, -                                               lir->defMask, "def")); -    } -} - -void oatDumpPromotionMap(CompilationUnit *cUnit) -{ -    for (int i = 0; i < cUnit->numDalvikRegisters; i++) { -        PromotionMap vRegMap = cUnit->promotionMap[i]; -        char buf[100]; -        if (vRegMap.fpLocation == kLocPhysReg) { -            snprintf(buf, 100, " : s%d", vRegMap.fpReg & FP_REG_MASK); -        } else { -            buf[0] = 0; -        } -        char buf2[100]; -        snprintf(buf2, 100, "V[%02d] -> %s%d%s", i, -                 vRegMap.coreLocation == kLocPhysReg ? -                 "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ? -                 vRegMap.coreReg : oatSRegOffset(cUnit, i), buf); -        LOG(INFO) << buf2; -    } -} - -void oatDumpFullPromotionMap(CompilationUnit *cUnit) -{ -    for (int i = 0; i < cUnit->numDalvikRegisters; i++) { -        PromotionMap vRegMap = cUnit->promotionMap[i]; -        LOG(INFO) << i << " -> " << "CL:" << (int)vRegMap.coreLocation << -            ", CR:" << (int)vRegMap.coreReg << ", FL:" << -            (int)vRegMap.fpLocation << ", FR:" << (int)vRegMap.fpReg << -            ", - " << (int)vRegMap.firstInPair; -    } -} - -/* Dump instructions and constant pool contents */ -void oatCodegenDump(CompilationUnit* cUnit) -{ -    LOG(INFO) << "/*"; -    LOG(INFO) << "Dumping LIR insns for " -        << PrettyMethod(cUnit->method_idx, *cUnit->dex_file); -    LIR* lirInsn; -    MipsLIR* mipsLIR; -    int insnsSize = cUnit->insnsSize; - -    LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs; -    LOG(INFO) << "Ins                  : " << cUnit->numIns; -    LOG(INFO) << "Outs                 : " << cUnit->numOuts; -    LOG(INFO) << "CoreSpills           : " << cUnit->numCoreSpills; -    LOG(INFO) << "FPSpills             : " << cUnit->numFPSpills; -    LOG(INFO) << "Padding              : " << cUnit->numPadding; -    LOG(INFO) << "Frame size           : " << cUnit->frameSize; -    LOG(INFO) << "Start of ins         : " << cUnit->insOffset; -    LOG(INFO) << "Start of regs        : " << cUnit->regsOffset; -    LOG(INFO) << "code size is " << cUnit->totalSize << -        " bytes, Dalvik size is " << insnsSize * 2; -    LOG(INFO) << "expansion factor: " << -         (float)cUnit->totalSize / (float)(insnsSize * 2); -    oatDumpPromotionMap(cUnit); -    for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) { -        oatDumpLIRInsn(cUnit, lirInsn, 0); -    } -    for (lirInsn = cUnit->classPointerList; lirInsn; lirInsn = lirInsn->next) { -        mipsLIR = (MipsLIR*) lirInsn; -        LOG(INFO) << StringPrintf("%x (%04x): .class (%s)", -            mipsLIR->generic.offset, mipsLIR->generic.offset, -            ((CallsiteInfo *) mipsLIR->operands[0])->classDescriptor); -    } -    for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) { -        mipsLIR = (MipsLIR*) lirInsn; -        LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)", -            mipsLIR->generic.offset, mipsLIR->generic.offset, mipsLIR->operands[0]); -    } - -    const DexFile::MethodId& method_id = -        cUnit->dex_file->GetMethodId(cUnit->method_idx); -    std::string signature(cUnit->dex_file->GetMethodSignature(method_id)); -    std::string name(cUnit->dex_file->GetMethodName(method_id)); -    std::string descriptor(cUnit->dex_file->GetMethodDeclaringClassDescriptor(method_id)); - -    // Dump mapping table -    if (cUnit->mappingTable.size() > 0) { -        std::string line(StringPrintf("\n    MappingTable %s%s_%s_mappingTable[%zu] = {", -            descriptor.c_str(), name.c_str(), signature.c_str(), cUnit->mappingTable.size())); -        std::replace(line.begin(), line.end(), ';', '_'); -        LOG(INFO) << line; -        for (uint32_t i = 0; i < cUnit->mappingTable.size(); i+=2) { -            line = StringPrintf("        {0x%08x, 0x%04x},", -                cUnit->mappingTable[i], cUnit->mappingTable[i+1]); -            LOG(INFO) << line; -        } -        LOG(INFO) <<"    };\n\n"; -    } -} -  } // namespace art diff --git a/src/compiler/codegen/mips/Assemble.cc b/src/compiler/codegen/mips/Assemble.cc index 5b6e6ed771..cb355c0b31 100644 --- a/src/compiler/codegen/mips/Assemble.cc +++ b/src/compiler/codegen/mips/Assemble.cc @@ -75,7 +75,7 @@ namespace art {   *   *  [!] escape.  To insert "!", use "!!"   */ -/* NOTE: must be kept in sync with enum MipsOpcode from MipsLIR.h */ +/* NOTE: must be kept in sync with enum MipsOpcode from LIR.h */  MipsEncodingMap EncodingMap[kMipsLast] = {      ENCODING_MAP(kMips32BitData, 0x00000000,                   kFmtBitBlt, 31, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, @@ -406,12 +406,10 @@ MipsEncodingMap EncodingMap[kMipsLast] = {  AssemblerStatus oatAssembleInstructions(CompilationUnit *cUnit,                                          intptr_t startAddr)  { -    UNIMPLEMENTED(FATAL) << "Rework for art code buffer"; -#if 0 -    int *bufferAddr = (int *) cUnit->codeBuffer; -    MipsLIR *lir; +    LIR *lir; +    AssemblerStatus res = kSuccess;  // Assume success -    for (lir = (MipsLIR *) cUnit->firstLIRInsn; lir; lir = NEXT_LIR(lir)) { +    for (lir = (LIR *) cUnit->firstLIRInsn; lir; lir = NEXT_LIR(lir)) {          if (lir->opcode < 0) {              continue;          } @@ -422,43 +420,43 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit *cUnit,          }          if (lir->opcode == kMipsB || lir->opcode == kMipsBal) { -            MipsLIR *targetLIR = (MipsLIR *) lir->generic.target; -            intptr_t pc = lir->generic.offset + 4; -            intptr_t target = targetLIR->generic.offset; +            LIR *targetLIR = (LIR *) lir->target; +            intptr_t pc = lir->offset + 4; +            intptr_t target = targetLIR->offset;              int delta = target - pc;              if (delta & 0x3) {                  LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;              }              if (delta > 131068 || delta < -131069) { -                LOG(FATAL) << "Unconditional branch out of range: " << delta; +                UNIMPLEMENTED(FATAL) << "B out of range, need long sequence: " << delta;              }              lir->operands[0] = delta >> 2;          } else if (lir->opcode >= kMipsBeqz && lir->opcode <= kMipsBnez) { -            MipsLIR *targetLIR = (MipsLIR *) lir->generic.target; -            intptr_t pc = lir->generic.offset + 4; -            intptr_t target = targetLIR->generic.offset; +            LIR *targetLIR = (LIR *) lir->target; +            intptr_t pc = lir->offset + 4; +            intptr_t target = targetLIR->offset;              int delta = target - pc;              if (delta & 0x3) {                  LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;              }              if (delta > 131068 || delta < -131069) { -                LOG(FATAL) << "Conditional branch out of range: " << delta; +                UNIMPLEMENTED(FATAL) << "B[eq|ne]z needs long sequence: " << delta;              }              lir->operands[1] = delta >> 2;          } else if (lir->opcode == kMipsBeq || lir->opcode == kMipsBne) { -            MipsLIR *targetLIR = (MipsLIR *) lir->generic.target; -            intptr_t pc = lir->generic.offset + 4; -            intptr_t target = targetLIR->generic.offset; +            LIR *targetLIR = (LIR *) lir->target; +            intptr_t pc = lir->offset + 4; +            intptr_t target = targetLIR->offset;              int delta = target - pc;              if (delta & 0x3) {                  LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;              }              if (delta > 131068 || delta < -131069) { -                LOG(FATAL) << "Conditional branch out of range: " << delta; +                UNIMPLEMENTED(FATAL) << "B[eq|ne] needs long sequence: " << delta;              }              lir->operands[2] = delta >> 2;          } else if (lir->opcode == kMipsJal) { -            intptr_t curPC = (startAddr + lir->generic.offset + 4) & ~3; +            intptr_t curPC = (startAddr + lir->offset + 4) & ~3;              intptr_t target = lir->operands[0];              /* ensure PC-region branch can be used */              DCHECK_EQ((curPC & 0xF0000000), (target & 0xF0000000)); @@ -467,16 +465,24 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit *cUnit,              }              lir->operands[0] =  target >> 2;          } else if (lir->opcode == kMipsLahi) { /* load address hi (via lui) */ -            MipsLIR *targetLIR = (MipsLIR *) lir->generic.target; -            intptr_t target = startAddr + targetLIR->generic.offset; +            LIR *targetLIR = (LIR *) lir->target; +            intptr_t target = startAddr + targetLIR->offset;              lir->operands[1] = target >> 16;          } else if (lir->opcode == kMipsLalo) { /* load address lo (via ori) */ -            MipsLIR *targetLIR = (MipsLIR *) lir->generic.target; -            intptr_t target = startAddr + targetLIR->generic.offset; +            LIR *targetLIR = (LIR *) lir->target; +            intptr_t target = startAddr + targetLIR->offset;              lir->operands[2] = lir->operands[2] + target;          } -        MipsEncodingMap *encoder = &EncodingMap[lir->opcode]; +        /* +         * If one of the pc-relative instructions expanded we'll have +         * to make another pass.  Don't bother to fully assemble the +         * instruction. +         */ +        if (res != kSuccess) { +            continue; +        } +        const MipsEncodingMap *encoder = &EncodingMap[lir->opcode];          u4 bits = encoder->skeleton;          int i;          for (i = 0; i < 4; i++) { @@ -497,7 +503,7 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit *cUnit,                      break;                  case kFmtDfp: {                      DCHECK(DOUBLEREG(operand)); -                    DCHECK_EQ((operand & 0x1), 0); +                    DCHECK((operand & 0x1) == 0);                      value = ((operand & FP_REG_MASK) << encoder->fieldLoc[i].start) &                              ((1 << (encoder->fieldLoc[i].end + 1)) - 1);                      bits |= value; @@ -511,14 +517,15 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit *cUnit,                      break;                  default:                      LOG(FATAL) << "Bad encoder format: " -                               << encoder->fieldLoc[i].kind; +                               << (int)encoder->fieldLoc[i].kind;              }          }          DCHECK_EQ(encoder->size, 2); -        *bufferAddr++ = bits; +        // FIXME: need multi-endian handling here +        cUnit->codeBuffer.push_back((bits >> 16) & 0xffff); +        cUnit->codeBuffer.push_back(bits & 0xffff);      } -#endif -    return kSuccess; +    return res;  }  /* @@ -528,13 +535,13 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit *cUnit,   */  int oatAssignInsnOffsets(CompilationUnit* cUnit)  { -    MipsLIR* mipsLIR; +    LIR* mipsLIR;      int offset = 0; -    for (mipsLIR = (MipsLIR *) cUnit->firstLIRInsn; -         mipsLIR; -         mipsLIR = NEXT_LIR(mipsLIR)) { -        mipsLIR->generic.offset = offset; +    for (mipsLIR = (LIR *) cUnit->firstLIRInsn; +        mipsLIR; +        mipsLIR = NEXT_LIR(mipsLIR)) { +        mipsLIR->offset = offset;          if (mipsLIR->opcode >= 0) {              if (!mipsLIR->flags.isNop) {                  mipsLIR->flags.size = EncodingMap[mipsLIR->opcode].size * 2; diff --git a/src/compiler/codegen/mips/Codegen.h b/src/compiler/codegen/mips/Codegen.h index b350dae035..355693c678 100644 --- a/src/compiler/codegen/mips/Codegen.h +++ b/src/compiler/codegen/mips/Codegen.h @@ -27,30 +27,72 @@  namespace art {  #if defined(_CODEGEN_C) -/* - * loadConstant() sometimes needs to add a small imm to a pre-existing constant - */ -STATIC MipsLIR *opRegImm(CompilationUnit* cUnit, OpKind op, int rDestSrc1, -                        int value); -STATIC MipsLIR *opRegReg(CompilationUnit* cUnit, OpKind op, int rDestSrc1, -                        int rSrc2); +LIR *opRegImm(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int value); +LIR *opRegReg(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int rSrc2); -/* Forward decalraton the portable versions due to circular dependency */ -STATIC bool genArithOpFloatPortable(CompilationUnit* cUnit, MIR* mir, +/* Forward declaraton the portable versions due to circular dependency */ +bool genArithOpFloatPortable(CompilationUnit* cUnit, MIR* mir,                                      RegLocation rlDest, RegLocation rlSrc1,                                      RegLocation rlSrc2); -STATIC bool genArithOpDoublePortable(CompilationUnit* cUnit, MIR* mir, +bool genArithOpDoublePortable(CompilationUnit* cUnit, MIR* mir,                                       RegLocation rlDest, RegLocation rlSrc1,                                       RegLocation rlSrc2); -STATIC bool genConversionPortable(CompilationUnit* cUnit, MIR* mir); +bool genConversionPortable(CompilationUnit* cUnit, MIR* mir); + +MipsConditionCode oatMipsConditionEncoding(ConditionCode code); + +int loadHelper(CompilationUnit* cUnit, int offset); +LIR* callRuntimeHelper(CompilationUnit* cUnit, int reg); +RegLocation getRetLoc(CompilationUnit* cUnit); +LIR* loadConstant(CompilationUnit* cUnit, int reg, int immVal); +void genRegCopyWide(CompilationUnit* cUnit, int destLo, int destHi, +                    int srcLo, int srcHi); +LIR* genRegCopy(CompilationUnit* cUnit, int rDest, int rSrc); +LIR* genCmpImmBranch(CompilationUnit* cUnit, ConditionCode cond, int reg, +                     int checkValue); +void freeRegLocTemps(CompilationUnit* cUnit, RegLocation rlKeep, +                     RegLocation rlFree); + + +/* + * Return most flexible allowed register class based on size. + * Bug: 2813841 + * Must use a core register for data types narrower than word (due + * to possible unaligned load/store. + */ +inline RegisterClass oatRegClassBySize(OpSize size) +{ +    return (size == kUnsignedHalf || +            size == kSignedHalf || +            size == kUnsignedByte || +            size == kSignedByte ) ? kCoreReg : kAnyReg; +} + +/* + * Construct an s4 from two consecutive half-words of switch data. + * This needs to check endianness because the DEX optimizer only swaps + * half-words in instruction stream. + * + * "switchData" must be 32-bit aligned. + */ +#if __BYTE_ORDER == __LITTLE_ENDIAN +inline s4 s4FromSwitchData(const void* switchData) { +    return *(s4*) switchData; +} +#else +inline s4 s4FromSwitchData(const void* switchData) { +    u2* data = switchData; +    return data[0] | (((s4) data[1]) << 16); +} +#endif  #endif -extern void oatSetupResourceMasks(MipsLIR* lir); +extern void oatSetupResourceMasks(LIR* lir); -extern MipsLIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest, +extern LIR* oatRegCopyNoInsert(CompilationUnit* cUnit, int rDest,                                            int rSrc);  }  // namespace art diff --git a/src/compiler/codegen/mips/CodegenCommon.cc b/src/compiler/codegen/mips/CodegenCommon.cc deleted file mode 100644 index 8dbb9a3506..0000000000 --- a/src/compiler/codegen/mips/CodegenCommon.cc +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -namespace art { - -/* - * This file contains codegen and support common to all supported - * Mips 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. - */ - -static void setMemRefType(MipsLIR *lir, bool isLoad, int memType) -{ -    /* MIPSTODO simplify setMemRefType() */ -    u8 *maskPtr; -    u8 mask = ENCODE_MEM;; -    DCHECK(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: -            DCHECK(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 */ -            DCHECK(!(EncodingMap[lir->opcode].flags & IS_STORE)); -            *maskPtr |= ENCODE_MUST_NOT_ALIAS; -            break; -        default: -            LOG(FATAL) << "Oat: invalid memref kind - " << memType; -    } -} - -/* - * Mark load/store instructions that access Dalvik registers through rFP + - * offset. - */ -STATIC void annotateDalvikRegAccess(MipsLIR *lir, int regId, bool isLoad) -{ -    /* MIPSTODO simplify annotateDalvikRegAccess() */ -    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 -     */ -    if (!DOUBLEREG(reg)) { -        seed = 1; -    } else { -        DCHECK_EQ((regId & 1), 0); /* double registers must be even */ -        seed = 3; -    } - -    if (FPREG(reg)) { -       DCHECK_LT(regId, 16); /* only 16 fp regs */ -       shift = kFPReg0; -    } else if (EXTRAREG(reg)) { -       DCHECK_LT(regId, 3); /* only 3 extra regs */ -       shift = kFPRegEnd; -    } else { -       shift = 0; -    } - -    /* Expand the double register id into single offset */ -    shift += regId; -    return (seed << shift); -} - -/* - * 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(MipsLIR *lir) -{ -    /* MIPSTODO simplify setupResourceMasks() */ -    int opcode = lir->opcode; -    int flags; - -    if (opcode <= 0) { -        lir->useMask = lir->defMask = 0; -        return; -    } - -    flags = EncodingMap[lir->opcode].flags; - -    // TODO: do we need this for MIPS?  if so, add to inst table defs -#if 0 -    if (flags & NEEDS_FIXUP) { -        lir->flags.pcRelFixup = true; -    } -#endif - -    /* 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; -    } - -    // TODO: needed for MIPS? -    /* 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; -    } -} - -/* - * The following are building blocks to construct low-level IRs with 0 - 4 - * operands. - */ -MipsLIR *newLIR0(CompilationUnit *cUnit, MipsOpCode opcode) -{ -    MipsLIR *insn = (MipsLIR *) oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR); -    DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND)); -    insn->opcode = opcode; -    setupResourceMasks(insn); -    insn->generic.dalvikOffset = cUnit->currentDalvikOffset; -    oatAppendLIR(cUnit, (LIR *) insn); -    return insn; -} - -MipsLIR *newLIR1(CompilationUnit *cUnit, MipsOpCode opcode, -                           int dest) -{ -    MipsLIR *insn = (MipsLIR *) oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR); -    DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP)); -    insn->opcode = opcode; -    insn->operands[0] = dest; -    setupResourceMasks(insn); -    insn->generic.dalvikOffset = cUnit->currentDalvikOffset; -    oatAppendLIR(cUnit, (LIR *) insn); -    return insn; -} - -MipsLIR *newLIR2(CompilationUnit *cUnit, MipsOpCode opcode, -                           int dest, int src1) -{ -    MipsLIR *insn = (MipsLIR *) oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR); -    DCHECK(isPseudoOpcode(opcode) || -           (EncodingMap[opcode].flags & IS_BINARY_OP)); -    insn->opcode = opcode; -    insn->operands[0] = dest; -    insn->operands[1] = src1; -    setupResourceMasks(insn); -    insn->generic.dalvikOffset = cUnit->currentDalvikOffset; -    oatAppendLIR(cUnit, (LIR *) insn); -    return insn; -} - -MipsLIR *newLIR3(CompilationUnit *cUnit, MipsOpCode opcode, -                           int dest, int src1, int src2) -{ -    MipsLIR *insn = (MipsLIR *) oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR); -    if (!(EncodingMap[opcode].flags & IS_TERTIARY_OP)) { -        LOG(FATAL) << "Bad LIR3: " << EncodingMap[opcode].name; -    } -    DCHECK(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); -    insn->generic.dalvikOffset = cUnit->currentDalvikOffset; -    oatAppendLIR(cUnit, (LIR *) insn); -    return insn; -} - -MipsLIR *newLIR4(CompilationUnit *cUnit, MipsOpCode opcode, -                           int dest, int src1, int src2, int info) -{ -    MipsLIR *insn = (MipsLIR *) oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR); -    DCHECK(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); -    insn->generic.dalvikOffset = cUnit->currentDalvikOffset; -    oatAppendLIR(cUnit, (LIR *) insn); -    return insn; -} - -/* - * Generate an kPseudoBarrier marker to indicate the boundary of special - * blocks. - */ -static void genBarrier(CompilationUnit *cUnit) -{ -    MipsLIR *barrier = newLIR0(cUnit, kPseudoBarrier); -    /* Mark all resources as being clobbered */ -    barrier->defMask = -1; -} - -} // namespace art diff --git a/src/compiler/codegen/mips/FP/MipsFP.cc b/src/compiler/codegen/mips/FP/MipsFP.cc index 7eb2a1ae68..acbac7f6d9 100644 --- a/src/compiler/codegen/mips/FP/MipsFP.cc +++ b/src/compiler/codegen/mips/FP/MipsFP.cc @@ -16,42 +16,8 @@  namespace art { -extern void oatFlushRegWideForV5TEVFP(CompilationUnit *cUnit, -                                              int reg1, int reg2); -extern void oatFlushRegForV5TEVFP(CompilationUnit *cUnit, int reg); - -/* First, flush any registers associated with this value */ -void loadValueAddress(CompilationUnit *cUnit, RegLocation rlSrc, -                             int rDest) -{ -    UNIMPLEMENTED(FATAL) << "Need Mips implementation"; -#if 0 -     rlSrc = rlSrc.wide ? oatUpdateLocWide(cUnit, rlSrc) : -                          oatUpdateLoc(cUnit, rlSrc); -     if (rlSrc.location == kLocPhysReg) { -         if (rlSrc.wide) { -             oatFlushRegWideForV5TEVFP(cUnit, rlSrc.lowReg, -                                               rlSrc.highReg); -         } else { -             oatFlushRegForV5TEVFP(cUnit, rlSrc.lowReg); -         } -     } -     opRegRegImm(cUnit, kOpAdd, rDest, rFP, -                 oatS2VReg(cUnit, rlSrc.sRegLow) << 2); -#endif -} - -/* - * TUNING: On some implementations, it is quicker to pass addresses - * to the handlers rather than load the operands into core registers - * and then move the values to FP regs in the handlers.  Other implementations - * may prefer passing data in registers (and the latter approach would - * yeild cleaner register handling - avoiding the requirement that operands - * be flushed to memory prior to the call). - */ -static bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir, -                            RegLocation rlDest, RegLocation rlSrc1, -                            RegLocation rlSrc2) +bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest, +                     RegLocation rlSrc1, RegLocation rlSrc2)  {  #ifdef __mips_hard_float      int op = kMipsNop; @@ -89,60 +55,14 @@ static bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir,      rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);      rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);      rlResult = oatEvalLoc(cUnit, rlDest, kFPReg, true); -    newLIR3(cUnit, (MipsOpCode)op, rlResult.lowReg, rlSrc1.lowReg, rlSrc2.lowReg); +    newLIR3(cUnit, (MipsOpCode)op, rlResult.lowReg, rlSrc1.lowReg, +                    rlSrc2.lowReg);      storeValue(cUnit, rlDest, rlResult);      return false;  #else -    UNIMPLEMENTED(FATAL) << "Need Mips implementation"; +    UNIMPLEMENTED(FATAL) << "Need Mips soft float implementation";      return false; -#if 0 -    TemplateOpcode opcode; - -    /* -     * Don't attempt to optimize register usage since these opcodes call out to -     * the handlers. -     */ -    switch (mir->dalvikInsn.opcode) { -        case OP_ADD_FLOAT_2ADDR: -        case OP_ADD_FLOAT: -            opcode = TEMPLATE_ADD_FLOAT_VFP; -            break; -        case OP_SUB_FLOAT_2ADDR: -        case OP_SUB_FLOAT: -            opcode = TEMPLATE_SUB_FLOAT_VFP; -            break; -        case OP_DIV_FLOAT_2ADDR: -        case OP_DIV_FLOAT: -            opcode = TEMPLATE_DIV_FLOAT_VFP; -            break; -        case OP_MUL_FLOAT_2ADDR: -        case OP_MUL_FLOAT: -            opcode = TEMPLATE_MUL_FLOAT_VFP; -            break; -        case OP_REM_FLOAT_2ADDR: -        case OP_REM_FLOAT: -        case OP_NEG_FLOAT: { -            return genArithOpFloatPortable(cUnit, mir, rlDest, rlSrc1, rlSrc2); -        } -        default: -            return true; -    } -    loadValueAddress(cUnit, rlDest, r_A0); -    oatClobber(cUnit, r_A0); -    loadValueAddress(cUnit, rlSrc1, r_A1); -    oatClobber(cUnit, r_A1); -    loadValueAddress(cUnit, rlSrc2, r_A2); -    UNIMP(FATAL) << "Need callout to handler"; -#if 0 -    genDispatchToHandler(cUnit, opcode); -#endif -    rlDest = oatUpdateLoc(cUnit, rlDest); -    if (rlDest.location == kLocPhysReg) { -        oatClobber(cUnit, rlDest.lowReg); -    } -    return false; -#endif  #endif  } @@ -192,64 +112,19 @@ static bool genArithOpDouble(CompilationUnit *cUnit, MIR *mir,      storeValueWide(cUnit, rlDest, rlResult);      return false;  #else -    UNIMPLEMENTED(FATAL) << "Need Mips implementation"; -    return false; -#if 0 -    TemplateOpcode opcode; - -    switch (mir->dalvikInsn.opcode) { -        case OP_ADD_DOUBLE_2ADDR: -        case OP_ADD_DOUBLE: -            opcode = TEMPLATE_ADD_DOUBLE_VFP; -            break; -        case OP_SUB_DOUBLE_2ADDR: -        case OP_SUB_DOUBLE: -            opcode = TEMPLATE_SUB_DOUBLE_VFP; -            break; -        case OP_DIV_DOUBLE_2ADDR: -        case OP_DIV_DOUBLE: -            opcode = TEMPLATE_DIV_DOUBLE_VFP; -            break; -        case OP_MUL_DOUBLE_2ADDR: -        case OP_MUL_DOUBLE: -            opcode = TEMPLATE_MUL_DOUBLE_VFP; -            break; -        case OP_REM_DOUBLE_2ADDR: -        case OP_REM_DOUBLE: -        case OP_NEG_DOUBLE: { -            return genArithOpDoublePortable(cUnit, mir, rlDest, rlSrc1, -                                               rlSrc2); -        } -        default: -            return true; -    } -    loadValueAddress(cUnit, rlDest, r_A0); -    oatClobber(cUnit, r_A0); -    loadValueAddress(cUnit, rlSrc1, r_A1); -    oatClobber(cUnit, r_A1); -    loadValueAddress(cUnit, rlSrc2, r_A2); -    UNIMP(FATAL) << "Need callout to handler"; -#if 0 -    genDispatchToHandler(cUnit, opcode); -#endif -    rlDest = oatUpdateLocWide(cUnit, rlDest); -    if (rlDest.location == kLocPhysReg) { -        oatClobber(cUnit, rlDest.lowReg); -        oatClobber(cUnit, rlDest.highReg); -    } +    UNIMPLEMENTED(FATAL) << "Need Mips soft float implementation";      return false;  #endif -#endif  }  static bool genConversion(CompilationUnit *cUnit, MIR *mir)  { +#ifdef __mips_hard_float      Opcode opcode = mir->dalvikInsn.opcode;      bool longSrc = false;      bool longDest = false;      RegLocation rlSrc;      RegLocation rlDest; -#ifdef __mips_hard_float      int op = kMipsNop;      int srcReg;      RegLocation rlResult; @@ -306,77 +181,8 @@ static bool genConversion(CompilationUnit *cUnit, MIR *mir)      }      return false;  #else -    UNIMPLEMENTED(FATAL) << "Need Mips implementation"; +    UNIMPLEMENTED(FATAL) << "Need Mips soft float implementation";      return false; -#if 0 -    TemplateOpcode templateOpcode; -    switch (opcode) { -        case OP_INT_TO_FLOAT: -            longSrc = false; -            longDest = false; -            templateOpcode = TEMPLATE_INT_TO_FLOAT_VFP; -            break; -        case OP_FLOAT_TO_INT: -            longSrc = false; -            longDest = false; -            templateOpcode = TEMPLATE_FLOAT_TO_INT_VFP; -            break; -        case OP_DOUBLE_TO_FLOAT: -            longSrc = true; -            longDest = false; -            templateOpcode = TEMPLATE_DOUBLE_TO_FLOAT_VFP; -            break; -        case OP_FLOAT_TO_DOUBLE: -            longSrc = false; -            longDest = true; -            templateOpcode = TEMPLATE_FLOAT_TO_DOUBLE_VFP; -            break; -        case OP_INT_TO_DOUBLE: -            longSrc = false; -            longDest = true; -            templateOpcode = TEMPLATE_INT_TO_DOUBLE_VFP; -            break; -        case OP_DOUBLE_TO_INT: -            longSrc = true; -            longDest = false; -            templateOpcode = TEMPLATE_DOUBLE_TO_INT_VFP; -            break; -        case OP_LONG_TO_DOUBLE: -        case OP_FLOAT_TO_LONG: -        case OP_LONG_TO_FLOAT: -        case OP_DOUBLE_TO_LONG: -            return genConversionPortable(cUnit, mir); -        default: -            return true; -    } - -    if (longSrc) { -        rlSrc = oatGetSrcWide(cUnit, mir, 0, 1); -    } else { -        rlSrc = oatGetSrc(cUnit, mir, 0); -    } - -    if (longDest) { -        rlDest = oatGetDestWide(cUnit, mir, 0, 1); -    } else { -        rlDest = oatGetDest(cUnit, mir, 0); -    } -    loadValueAddress(cUnit, rlDest, r_A0); -    oatClobber(cUnit, r_A0); -    loadValueAddress(cUnit, rlSrc, r_A1); -    UNIMP(FATAL) << "Need callout to handler"; -#if 0 -    genDispatchToHandler(cUnit, templateOpcode); -#endif -    if (rlDest.wide) { -        rlDest = oatUpdateLocWide(cUnit, rlDest); -        oatClobber(cUnit, rlDest.highReg); -    } else { -        rlDest = oatUpdateLoc(cUnit, rlDest); -    } -    oatClobber(cUnit, rlDest.lowReg); -    return false; -#endif  #endif  } diff --git a/src/compiler/codegen/mips/Mips32/Factory.cc b/src/compiler/codegen/mips/Mips32/Factory.cc index f76adff3bd..71220c0be7 100644 --- a/src/compiler/codegen/mips/Mips32/Factory.cc +++ b/src/compiler/codegen/mips/Mips32/Factory.cc @@ -38,19 +38,24 @@ static int fpTemps[] = {r_F0, r_F1, r_F2, r_F3, r_F4, r_F5, r_F6, r_F7,                          r_F8, r_F9, r_F10, r_F11, r_F12, r_F13, r_F14, r_F15};  #endif +void genBarrier(CompilationUnit *cUnit); +LIR* genCompareBranch(CompilationUnit* cUnit, ConditionCode cond, int src1, +                      int src2); +LIR* opCompareBranch(CompilationUnit* cUnit, MipsOpCode opc, int src1, +                      int src2);  void storePair(CompilationUnit *cUnit, int base, int lowReg,                 int highReg);  void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg); -MipsLIR *loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement, +LIR *loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,                        int rDest); -MipsLIR *storeWordDisp(CompilationUnit *cUnit, int rBase, +LIR *storeWordDisp(CompilationUnit *cUnit, int rBase,                         int displacement, int rSrc); -MipsLIR *loadConstant(CompilationUnit *cUnit, int rDest, int value); +LIR *loadConstant(CompilationUnit *cUnit, int rDest, int value);  #ifdef __mips_hard_float -MipsLIR *fpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc) +LIR *fpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)  { -    MipsLIR* res = (MipsLIR *) oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR); +    LIR* res = (LIR *) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);      res->operands[0] = rDest;      res->operands[1] = rSrc;      if (rDest == rSrc) { @@ -90,10 +95,10 @@ MipsLIR *fpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)   * 1) rDest is freshly returned from oatAllocTemp or   * 2) The codegen is under fixed register usage   */ -MipsLIR *loadConstantNoClobber(CompilationUnit *cUnit, int rDest, +LIR *loadConstantNoClobber(CompilationUnit *cUnit, int rDest,                                 int value)  { -    MipsLIR *res; +    LIR *res;  #ifdef __mips_hard_float      int rDestSave = rDest; @@ -127,22 +132,9 @@ MipsLIR *loadConstantNoClobber(CompilationUnit *cUnit, int rDest,      return res;  } -/* - * Load an immediate value into a fixed or temp register.  Target - * register is clobbered, and marked inUse. - */ -MipsLIR *loadConstant(CompilationUnit *cUnit, int rDest, int value) -{ -    if (oatIsTemp(cUnit, rDest)) { -        oatClobber(cUnit, rDest); -        oatMarkInUse(cUnit, rDest); -    } -    return loadConstantNoClobber(cUnit, rDest, value); -} - -MipsLIR *opNone(CompilationUnit *cUnit, OpKind op) +LIR *opNone(CompilationUnit *cUnit, OpKind op)  { -    MipsLIR *res; +    LIR *res;      MipsOpCode opcode = kMipsNop;      switch (op) {          case kOpUncondBr: @@ -156,28 +148,28 @@ MipsLIR *opNone(CompilationUnit *cUnit, OpKind op)  } -MipsLIR *opCmpBranchCC(CompilationUnit *cUnit, MipsConditionCode cc, +LIR *opCmpBranchCC(CompilationUnit *cUnit, MipsConditionCode cc,                             int rs, int rt)  {      UNIMPLEMENTED(FATAL);      return 0;  } -MipsLIR *opCmpImmBranchCC(CompilationUnit *cUnit, MipsConditionCode cc, +LIR *opCmpImmBranchCC(CompilationUnit *cUnit, MipsConditionCode cc,                             int rs, int immVal)  {      UNIMPLEMENTED(FATAL);      return 0;  } -MipsLIR *opCmpImmBranch(CompilationUnit *cUnit, MipsOpCode cc, +LIR *opCmpImmBranch(CompilationUnit *cUnit, MipsOpCode cc,                             int rs, int immVal)  {      UNIMPLEMENTED(FATAL);      return 0;  } -MipsLIR *opCmpBranch(CompilationUnit *cUnit, MipsOpCode opc, int rs, int rt) +LIR *opCmpBranch(CompilationUnit *cUnit, MipsOpCode opc, int rs, int rt)  { -    MipsLIR *res; +    LIR *res;      if (rt < 0) {        DCHECK(opc >= kMipsBeqz && opc <= kMipsBnez);        res = newLIR1(cUnit, opc, rs); @@ -188,9 +180,9 @@ MipsLIR *opCmpBranch(CompilationUnit *cUnit, MipsOpCode opc, int rs, int rt)      return res;  } -MipsLIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask); +LIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask); -MipsLIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc) +LIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc)  {      MipsOpCode opcode = kMipsNop;      switch (op) { @@ -203,12 +195,12 @@ MipsLIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc)      return newLIR2(cUnit, opcode, r_RA, rDestSrc);  } -MipsLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest, +LIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,                       int rSrc1, int value); -MipsLIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1, +LIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1,                    int value)  { -    MipsLIR *res; +    LIR *res;      bool neg = (value < 0);      int absValue = (neg) ? -value : value;      bool shortForm = (absValue & 0xff) == absValue; @@ -237,7 +229,7 @@ MipsLIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1,      return res;  } -MipsLIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest, +LIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,                             int rSrc1, int rSrc2)  {      MipsOpCode opcode = kMipsNop; @@ -276,10 +268,10 @@ MipsLIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,      return newLIR3(cUnit, opcode, rDest, rSrc1, rSrc2);  } -MipsLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest, +LIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,                             int rSrc1, int value)  { -    MipsLIR *res; +    LIR *res;      MipsOpCode opcode = kMipsNop;      bool shortForm = true; @@ -366,11 +358,11 @@ MipsLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,      return res;  } -MipsLIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1, +LIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1,                    int rSrc2)  {      MipsOpCode opcode = kMipsNop; -    MipsLIR *res; +    LIR *res;      switch (op) {          case kOpMov:              opcode = kMipsMove; @@ -411,21 +403,21 @@ MipsLIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1,      return newLIR2(cUnit, opcode, rDestSrc1, rSrc2);  } -MipsLIR *loadConstantValueWide(CompilationUnit *cUnit, int rDestLo, +LIR *loadConstantValueWide(CompilationUnit *cUnit, int rDestLo,                                       int rDestHi, int valLo, int valHi)  { -    MipsLIR *res; +    LIR *res;      res = loadConstantNoClobber(cUnit, rDestLo, valLo);      loadConstantNoClobber(cUnit, rDestHi, valHi);      return res;  }  /* Load value from base + scaled index. */ -MipsLIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase, +LIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,                                 int rIndex, int rDest, int scale, OpSize size)  { -    MipsLIR *first = NULL; -    MipsLIR *res; +    LIR *first = NULL; +    LIR *res;      MipsOpCode opcode = kMipsNop;      int tReg = oatAllocTemp(cUnit); @@ -478,11 +470,11 @@ MipsLIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,  }  /* store value base base + scaled index. */ -MipsLIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase, +LIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase,                                  int rIndex, int rSrc, int scale, OpSize size)  { -    MipsLIR *first = NULL; -    MipsLIR *res; +    LIR *first = NULL; +    LIR *res;      MipsOpCode opcode = kMipsNop;      int rNewIndex = rIndex;      int tReg = oatAllocTemp(cUnit); @@ -530,11 +522,11 @@ MipsLIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase,      return first;  } -MipsLIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask) +LIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask)  {      int i;      int loadCnt = 0; -    MipsLIR *res = NULL ; +    LIR *res = NULL ;      genBarrier(cUnit);      for (i = 0; i < 8; i++, rMask >>= 1) { @@ -552,11 +544,11 @@ MipsLIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask)      return res; /* NULL always returned which should be ok since no callers use it */  } -MipsLIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask) +LIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask)  {      int i;      int storeCnt = 0; -    MipsLIR *res = NULL ; +    LIR *res = NULL ;      genBarrier(cUnit);      for (i = 0; i < 8; i++, rMask >>= 1) { @@ -574,7 +566,7 @@ MipsLIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask)      return res; /* NULL always returned which should be ok since no callers use it */  } -MipsLIR *loadBaseDispBody(CompilationUnit *cUnit, MIR *mir, int rBase, +LIR *loadBaseDispBody(CompilationUnit *cUnit, MIR *mir, int rBase,                                  int displacement, int rDest, int rDestHi,                                  OpSize size, int sReg)  /* @@ -586,9 +578,9 @@ MipsLIR *loadBaseDispBody(CompilationUnit *cUnit, MIR *mir, int rBase,   * rlp and then restore.   */  { -    MipsLIR *res; -    MipsLIR *load = NULL; -    MipsLIR *load2 = NULL; +    LIR *res; +    LIR *load = NULL; +    LIR *load2 = NULL;      MipsOpCode opcode = kMipsNop;      bool shortForm = IS_SIMM16(displacement);      bool pair = false; @@ -680,7 +672,7 @@ MipsLIR *loadBaseDispBody(CompilationUnit *cUnit, MIR *mir, int rBase,      return load;  } -MipsLIR *loadBaseDisp(CompilationUnit *cUnit, MIR *mir, int rBase, +LIR *loadBaseDisp(CompilationUnit *cUnit, MIR *mir, int rBase,                              int displacement, int rDest, OpSize size,                              int sReg)  { @@ -688,7 +680,7 @@ MipsLIR *loadBaseDisp(CompilationUnit *cUnit, MIR *mir, int rBase,                              size, sReg);  } -MipsLIR *loadBaseDispWide(CompilationUnit *cUnit, MIR *mir, int rBase, +LIR *loadBaseDispWide(CompilationUnit *cUnit, MIR *mir, int rBase,                            int displacement, int rDestLo, int rDestHi,                                  int sReg)  { @@ -696,13 +688,13 @@ MipsLIR *loadBaseDispWide(CompilationUnit *cUnit, MIR *mir, int rBase,                              kLong, sReg);  } -MipsLIR *storeBaseDispBody(CompilationUnit *cUnit, int rBase, +LIR *storeBaseDispBody(CompilationUnit *cUnit, int rBase,                                   int displacement, int rSrc, int rSrcHi,                                   OpSize size)  { -    MipsLIR *res; -    MipsLIR *store = NULL; -    MipsLIR *store2 = NULL; +    LIR *res; +    LIR *store = NULL; +    LIR *store2 = NULL;      MipsOpCode opcode = kMipsNop;      bool shortForm = IS_SIMM16(displacement);      bool pair = false; @@ -785,13 +777,13 @@ MipsLIR *storeBaseDispBody(CompilationUnit *cUnit, int rBase,      return res;  } -MipsLIR *storeBaseDisp(CompilationUnit *cUnit, int rBase, +LIR *storeBaseDisp(CompilationUnit *cUnit, int rBase,                         int displacement, int rSrc, OpSize size)  {      return storeBaseDispBody(cUnit, rBase, displacement, rSrc, -1, size);  } -MipsLIR *storeBaseDispWide(CompilationUnit *cUnit, int rBase, +LIR *storeBaseDispWide(CompilationUnit *cUnit, int rBase,                             int displacement, int rSrcLo, int rSrcHi)  {      return storeBaseDispBody(cUnit, rBase, displacement, rSrcLo, rSrcHi, kLong); @@ -803,83 +795,12 @@ void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg)      loadWordDisp(cUnit, base, HIWORD_OFFSET , highReg);  } -MipsLIR* genRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc) -{ -    MipsLIR* res; -    MipsOpCode opcode; -#ifdef __mips_hard_float -    if (FPREG(rDest) || FPREG(rSrc)) -        return fpRegCopy(cUnit, rDest, rSrc); -#endif -    res = (MipsLIR *) oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR); -    opcode = kMipsMove; -    DCHECK(LOWREG(rDest) && LOWREG(rSrc)); -    res->operands[0] = rDest; -    res->operands[1] = rSrc; -    res->opcode = opcode; -    setupResourceMasks(res); -    if (rDest == rSrc) { -        res->flags.isNop = true; -    } -    return res; -} - -MipsLIR* genRegCopy(CompilationUnit *cUnit, int rDest, int rSrc) -{ -    MipsLIR *res = genRegCopyNoInsert(cUnit, rDest, rSrc); -    oatAppendLIR(cUnit, (LIR*)res); -    return res; -} - -void genRegCopyWide(CompilationUnit *cUnit, int destLo, int destHi, -                           int srcLo, int srcHi) -{ -#ifdef __mips_hard_float -    bool destFP = FPREG(destLo) && FPREG(destHi); -    bool srcFP = FPREG(srcLo) && FPREG(srcHi); -    DCHECK_EQ(FPREG(srcLo), FPREG(srcHi)); -    DCHECK_EQ(FPREG(destLo), FPREG(destHi)); -    if (destFP) { -        if (srcFP) { -            genRegCopy(cUnit, S2D(destLo, destHi), S2D(srcLo, srcHi)); -        } else { -           /* note the operands are swapped for the mtc1 instr */ -            newLIR2(cUnit, kMipsMtc1, srcLo, destLo); -            newLIR2(cUnit, kMipsMtc1, srcHi, destHi); -        } -    } else { -        if (srcFP) { -            newLIR2(cUnit, kMipsMfc1, destLo, srcLo); -            newLIR2(cUnit, kMipsMfc1, destHi, srcHi); -        } else { -            // Handle overlap -            if (srcHi == destLo) { -                genRegCopy(cUnit, destHi, srcHi); -                genRegCopy(cUnit, destLo, srcLo); -            } else { -                genRegCopy(cUnit, destLo, srcLo); -                genRegCopy(cUnit, destHi, srcHi); -            } -        } -    } -#else -    // Handle overlap -    if (srcHi == destLo) { -        genRegCopy(cUnit, destHi, srcHi); -        genRegCopy(cUnit, destLo, srcLo); -    } else { -        genRegCopy(cUnit, destLo, srcLo); -        genRegCopy(cUnit, destHi, srcHi); -    } -#endif -} - -inline MipsLIR *genRegImmCheck(CompilationUnit *cUnit, +LIR *genRegImmCheck(CompilationUnit *cUnit,                                 MipsConditionCode cond, int reg,                                 int checkValue, int dOffset, -                               MipsLIR *pcrLabel) +                               LIR *pcrLabel)  { -    MipsLIR *branch = NULL; +    LIR *branch = NULL;      if (checkValue == 0) {          MipsOpCode opc = kMipsNop; @@ -918,9 +839,9 @@ inline MipsLIR *genRegImmCheck(CompilationUnit *cUnit,      if (cUnit->jitMode == kJitMethod) {          BasicBlock *bb = cUnit->curBlock;          if (bb->taken) { -            MipsLIR  *exceptionLabel = (MipsLIR *) cUnit->blockLabelList; +            LIR  *exceptionLabel = (LIR *) cUnit->blockLabelList;              exceptionLabel += bb->taken->id; -            branch->generic.target = (LIR *) exceptionLabel; +            branch->target = (LIR *) exceptionLabel;              return exceptionLabel;          } else {              LOG(FATAL) <<  "Catch blocks not handled yet"; diff --git a/src/compiler/codegen/mips/Mips32/Gen.cc b/src/compiler/codegen/mips/Mips32/Gen.cc index 880169272e..0b2b15ac45 100644 --- a/src/compiler/codegen/mips/Mips32/Gen.cc +++ b/src/compiler/codegen/mips/Mips32/Gen.cc @@ -24,377 +24,6 @@  namespace art { -// FIXME: need the following: -void genSuspendTest(CompilationUnit* cUnit, MIR* mir) {} -void genMonitorEnter(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) {} -void genMonitorExit(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) {} -void genCheckCast(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) {} -void genInstanceof(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, -                   RegLocation rlSrc) {} -void genNewInstance(CompilationUnit* cUnit, MIR* mir, -                           RegLocation rlDest) {} -void genThrow(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) {} -void genConstString(CompilationUnit* cUnit, MIR* mir, -                           RegLocation rlDest, RegLocation rlSrc) {} -void genConstClass(CompilationUnit* cUnit, MIR* mir, -                          RegLocation rlDest, RegLocation rlSrc) {} -void genArrayGet(CompilationUnit* cUnit, MIR* mir, OpSize size, -                        RegLocation rlArray, RegLocation rlIndex, -                        RegLocation rlDest, int scale) {} -void genArrayPut(CompilationUnit* cUnit, MIR* mir, OpSize size, -                        RegLocation rlArray, RegLocation rlIndex, -                        RegLocation rlSrc, int scale) {} -void genArrayObjPut(CompilationUnit* cUnit, MIR* mir, -                           RegLocation rlArray, RegLocation rlIndex, -                           RegLocation rlSrc, int scale) {} -void genIPut(CompilationUnit* cUnit, MIR* mir, OpSize size, -                    RegLocation rlSrc, RegLocation rlObj, -                    bool isLongOrDouble, bool isObject) {} -bool genArithOpInt(CompilationUnit* cUnit, MIR* mir, -                          RegLocation rlDest, RegLocation rlSrc1, -                          RegLocation rlSrc2) { return 0; } -bool genArithOpLong(CompilationUnit* cUnit, MIR* mir, -                           RegLocation rlDest, RegLocation rlSrc1, -                           RegLocation rlSrc2) { return 0; } -bool genShiftOpLong(CompilationUnit* cUnit, MIR* mir, -                           RegLocation rlDest, RegLocation rlSrc1, -                           RegLocation rlShift) { return 0; } -bool genArithOpIntLit(CompilationUnit* cUnit, MIR* mir, -                             RegLocation rlDest, RegLocation rlSrc, -                             int lit) { return 0; } -void oatArchDump(void) {}; -void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset) {}; - - - - -STATIC bool genConversionCall(CompilationUnit* cUnit, MIR* mir, int funcOffset, -                                     int srcSize, int tgtSize) -{ -    UNIMPLEMENTED(FATAL) << "Need Mips implementation"; -    return 0; -#if 0 -    /* -     * Don't optimize the register usage since it calls out to support -     * functions -     */ -    RegLocation rlSrc; -    RegLocation rlDest; -    oatFlushAllRegs(cUnit);   /* Send everything to home location */ -    loadWordDisp(cUnit, rSELF, funcOffset, rLR); -    if (srcSize == 1) { -        rlSrc = oatGetSrc(cUnit, mir, 0); -        loadValueDirectFixed(cUnit, rlSrc, r0); -    } else { -        rlSrc = oatGetSrcWide(cUnit, mir, 0, 1); -        loadValueDirectWideFixed(cUnit, rlSrc, r0, r1); -    } -    callRuntimeHelper(cUnit, rLR); -    if (tgtSize == 1) { -        RegLocation rlResult; -        rlDest = oatGetDest(cUnit, mir, 0); -        rlResult = oatGetReturn(cUnit); -        storeValue(cUnit, rlDest, rlResult); -    } else { -        RegLocation rlResult; -        rlDest = oatGetDestWide(cUnit, mir, 0, 1); -        rlResult = oatGetReturnWide(cUnit); -        storeValueWide(cUnit, rlDest, rlResult); -    } -    return false; -#endif -} - -bool genArithOpFloatPortable(CompilationUnit* cUnit, MIR* mir, -                                    RegLocation rlDest, RegLocation rlSrc1, -                                    RegLocation rlSrc2) -{ -    UNIMPLEMENTED(FATAL) << "Need Mips implementation"; -    return 0; -#if 0 -    RegLocation rlResult; -    int funcOffset; - -    switch (mir->dalvikInsn.opcode) { -        case OP_ADD_FLOAT_2ADDR: -        case OP_ADD_FLOAT: -            funcOffset = OFFSETOF_MEMBER(Thread, pFadd); -            break; -        case OP_SUB_FLOAT_2ADDR: -        case OP_SUB_FLOAT: -            funcOffset = OFFSETOF_MEMBER(Thread, pFsub); -            break; -        case OP_DIV_FLOAT_2ADDR: -        case OP_DIV_FLOAT: -            funcOffset = OFFSETOF_MEMBER(Thread, pFdiv); -            break; -        case OP_MUL_FLOAT_2ADDR: -        case OP_MUL_FLOAT: -            funcOffset = OFFSETOF_MEMBER(Thread, pFmul); -            break; -        case OP_REM_FLOAT_2ADDR: -        case OP_REM_FLOAT: -            funcOffset = OFFSETOF_MEMBER(Thread, pFmodf); -            break; -        case OP_NEG_FLOAT: { -            genNegFloat(cUnit, rlDest, rlSrc1); -            return false; -        } -        default: -            return true; -    } -    oatFlushAllRegs(cUnit);   /* Send everything to home location */ -    loadWordDisp(cUnit, rSELF, funcOffset, rLR); -    loadValueDirectFixed(cUnit, rlSrc1, r0); -    loadValueDirectFixed(cUnit, rlSrc2, r1); -    callRuntimeHelper(cUnit, rLR); -    rlResult = oatGetReturn(cUnit); -    storeValue(cUnit, rlDest, rlResult); -    return false; -#endif -} - -bool genArithOpDoublePortable(CompilationUnit* cUnit, MIR* mir, -                                     RegLocation rlDest, RegLocation rlSrc1, -                                     RegLocation rlSrc2) -{ -    UNIMPLEMENTED(FATAL) << "Need Mips implementation"; -    return 0; -#if 0 -    RegLocation rlResult; -    int funcOffset; - -    switch (mir->dalvikInsn.opcode) { -        case OP_ADD_DOUBLE_2ADDR: -        case OP_ADD_DOUBLE: -            funcOffset = OFFSETOF_MEMBER(Thread, pDadd); -            break; -        case OP_SUB_DOUBLE_2ADDR: -        case OP_SUB_DOUBLE: -            funcOffset = OFFSETOF_MEMBER(Thread, pDsub); -            break; -        case OP_DIV_DOUBLE_2ADDR: -        case OP_DIV_DOUBLE: -            funcOffset = OFFSETOF_MEMBER(Thread, pDdiv); -            break; -        case OP_MUL_DOUBLE_2ADDR: -        case OP_MUL_DOUBLE: -            funcOffset = OFFSETOF_MEMBER(Thread, pDmul); -            break; -        case OP_REM_DOUBLE_2ADDR: -        case OP_REM_DOUBLE: -            funcOffset = OFFSETOF_MEMBER(Thread, pFmod); -            break; -        case OP_NEG_DOUBLE: { -            genNegDouble(cUnit, rlDest, rlSrc1); -            return false; -        } -        default: -            return true; -    } -    oatFlushAllRegs(cUnit);   /* Send everything to home location */ -    loadWordDisp(cUnit, rSELF, funcOffset, rLR); -    loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1); -    loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3); -    callRuntimeHelper(cUnit, rLR); -    rlResult = oatGetReturnWide(cUnit); -    storeValueWide(cUnit, rlDest, rlResult); -    return false; -#endif -} - -bool genConversionPortable(CompilationUnit* cUnit, MIR* mir) -{ -    UNIMPLEMENTED(FATAL) << "Need Mips implementation"; -    return 0; -#if 0 -    Opcode opcode = mir->dalvikInsn.opcode; - -    switch (opcode) { -        case OP_INT_TO_FLOAT: -            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pI2f), -                                     1, 1); -        case OP_FLOAT_TO_INT: -            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pF2iz), -                                     1, 1); -        case OP_DOUBLE_TO_FLOAT: -            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pD2f), -                                     2, 1); -        case OP_FLOAT_TO_DOUBLE: -            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pF2d), -                                     1, 2); -        case OP_INT_TO_DOUBLE: -            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pI2d), -                                     1, 2); -        case OP_DOUBLE_TO_INT: -            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pD2iz), -                                     2, 1); -        case OP_FLOAT_TO_LONG: -            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, -                                     pF2l), 1, 2); -        case OP_LONG_TO_FLOAT: -            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pL2f), -                                     2, 1); -        case OP_DOUBLE_TO_LONG: -            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, -                                     pD2l), 2, 2); -        case OP_LONG_TO_DOUBLE: -            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pL2d), -                                     2, 2); -        default: -            return true; -    } -    return false; -#endif -} - - - - - -STATIC RegLocation getRetLoc(CompilationUnit* cUnit); - -void warnIfUnresolved(CompilationUnit* cUnit, int fieldIdx, Field* field) { -  if (field == NULL) { -    const DexFile::FieldId& field_id = cUnit->dex_file->GetFieldId(fieldIdx); -    std::string class_name(cUnit->dex_file->GetFieldDeclaringClassDescriptor(field_id)); -    std::string field_name(cUnit->dex_file->GetFieldName(field_id)); -    LOG(INFO) << "Field " << PrettyDescriptor(class_name) << "." << field_name -              << " unresolved at compile time"; -  } else { -    // We also use the slow path for wide volatile fields. -  } -} - -/* - * Construct an s4 from two consecutive half-words of switch data. - * This needs to check endianness because the DEX optimizer only swaps - * half-words in instruction stream. - * - * "switchData" must be 32-bit aligned. - */ -#if __BYTE_ORDER == __LITTLE_ENDIAN -STATIC inline s4 s4FromSwitchData(const void* switchData) { -    return *(s4*) switchData; -} -#else -STATIC inline s4 s4FromSwitchData(const void* switchData) { -    u2* data = switchData; -    return data[0] | (((s4) data[1]) << 16); -} -#endif -/* - * Insert a kPseudoCaseLabel at the beginning of the Dalvik - * offset vaddr.  This label will be used to fix up the case - * branch table during the assembly phase.  Be sure to set - * all resource flags on this to prevent code motion across - * target boundaries.  KeyVal is just there for debugging. - */ -STATIC MipsLIR* insertCaseLabel(CompilationUnit* cUnit, int vaddr, int keyVal) -{ -    std::map<unsigned int, LIR*>::iterator it; -    it = cUnit->boundaryMap.find(vaddr); -    if (it == cUnit->boundaryMap.end()) { -        LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr; -    } -    MipsLIR* newLabel = (MipsLIR*)oatNew(cUnit, sizeof(MipsLIR), true, kAllocLIR); -    newLabel->generic.dalvikOffset = vaddr; -    newLabel->opcode = kPseudoCaseLabel; -    newLabel->operands[0] = keyVal; -    oatInsertLIRAfter(it->second, (LIR*)newLabel); -    return newLabel; -} - -STATIC void markPackedCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec) -{ -    const u2* table = tabRec->table; -    int baseVaddr = tabRec->vaddr; -    int *targets = (int*)&table[4]; -    int entries = table[1]; -    int lowKey = s4FromSwitchData(&table[2]); -    for (int i = 0; i < entries; i++) { -        tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i], -                                             i + lowKey); -    } -} - -STATIC void markSparseCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec) -{ -    const u2* table = tabRec->table; -    int baseVaddr = tabRec->vaddr; -    int entries = table[1]; -    int* keys = (int*)&table[2]; -    int* targets = &keys[entries]; -    for (int i = 0; i < entries; i++) { -        tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i], -                                             keys[i]); -    } -} - -void oatProcessSwitchTables(CompilationUnit* cUnit) -{ -    GrowableListIterator iterator; -    oatGrowableListIteratorInit(&cUnit->switchTables, &iterator); -    while (true) { -        SwitchTable *tabRec = (SwitchTable *) oatGrowableListIteratorNext( -             &iterator); -        if (tabRec == NULL) break; -        if (tabRec->table[0] == kPackedSwitchSignature) -            markPackedCaseLabels(cUnit, tabRec); -        else if (tabRec->table[0] == kSparseSwitchSignature) -            markSparseCaseLabels(cUnit, tabRec); -        else { -            LOG(FATAL) << "Invalid switch table"; -        } -    } -} - -STATIC void dumpSparseSwitchTable(const u2* table) -    /* -     * Sparse switch data format: -     *  ushort ident = 0x0200   magic value -     *  ushort size             number of entries in the table; > 0 -     *  int keys[size]          keys, sorted low-to-high; 32-bit aligned -     *  int targets[size]       branch targets, relative to switch opcode -     * -     * Total size is (2+size*4) 16-bit code units. -     */ -{ -    u2 ident = table[0]; -    int entries = table[1]; -    int* keys = (int*)&table[2]; -    int* targets = &keys[entries]; -    LOG(INFO) <<  "Sparse switch table - ident:0x" << std::hex << ident << -       ", entries: " << std::dec << entries; -    for (int i = 0; i < entries; i++) { -        LOG(INFO) << "    Key[" << keys[i] << "] -> 0x" << std::hex << -        targets[i]; -    } -} - -STATIC void dumpPackedSwitchTable(const u2* table) -    /* -     * Packed switch data format: -     *  ushort ident = 0x0100   magic value -     *  ushort size             number of entries in the table -     *  int first_key           first (and lowest) switch case value -     *  int targets[size]       branch targets, relative to switch opcode -     * -     * Total size is (4+size*2) 16-bit code units. -     */ -{ -    u2 ident = table[0]; -    int* targets = (int*)&table[4]; -    int entries = table[1]; -    int lowKey = s4FromSwitchData(&table[2]); -    LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident << -        ", entries: " << std::dec << entries << ", lowKey: " << lowKey; -    for (int i = 0; i < entries; i++) { -        LOG(INFO) << "    Key[" << (i + lowKey) << "] -> 0x" << std::hex << -            targets[i]; -    } -} -  /*   * The sparse table in the literal pool is an array of <key,displacement>   * pairs.  For each set, we'll load them as a pair using ldmia. @@ -414,10 +43,9 @@ STATIC void dumpPackedSwitchTable(const u2* table)   *   add   rPC, rDisp   ; This is the branch from which we compute displacement   *   cbnz  rIdx, lp   */ -STATIC void genSparseSwitch(CompilationUnit* cUnit, MIR* mir, -                            RegLocation rlSrc) +void genSparseSwitch(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)  { -    UNIMPLEMENTED(FATAL) << "Need Mips implementation"; +    UNIMPLEMENTED(FATAL) << "Needs Mips sparse switch";  #if 0      const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;      if (cUnit->printMe) { @@ -429,8 +57,8 @@ STATIC void genSparseSwitch(CompilationUnit* cUnit, MIR* mir,      tabRec->table = table;      tabRec->vaddr = mir->offset;      int size = table[1]; -    tabRec->targets = (MipsLIR* *)oatNew(cUnit, size * sizeof(MipsLIR*), true, -                                        kAllocLIR); +    tabRec->targets = (LIR* *)oatNew(cUnit, size * sizeof(LIR*), true, +                                     kAllocLIR);      oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec);      // Get the switch value @@ -451,26 +79,26 @@ STATIC void genSparseSwitch(CompilationUnit* cUnit, MIR* mir,      int rIdx = oatAllocTemp(cUnit);      loadConstant(cUnit, rIdx, size);      // Establish loop branch target -    MipsLIR* target = newLIR0(cUnit, kPseudoTargetLabel); +    LIR* target = newLIR0(cUnit, kPseudoTargetLabel);      target->defMask = ENCODE_ALL;      // Load next key/disp      newLIR2(cUnit, kThumb2LdmiaWB, rBase, (1 << rKey) | (1 << rDisp));      opRegReg(cUnit, kOpCmp, rKey, rlSrc.lowReg);      // Go if match. NOTE: No instruction set switch here - must stay Thumb2 -    genIT(cUnit, kMipsCondEq, ""); -    MipsLIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, rDisp); +    genIT(cUnit, kArmCondEq, ""); +    LIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, rDisp);      tabRec->bxInst = switchBranch;      // Needs to use setflags encoding here      newLIR3(cUnit, kThumb2SubsRRI12, rIdx, rIdx, 1); -    MipsLIR* branch = opCondBranch(cUnit, kMipsCondNe); -    branch->generic.target = (LIR*)target; +    LIR* branch = opCondBranch(cUnit, kCondNe); +    branch->target = (LIR*)target;  #endif  } -STATIC void genPackedSwitch(CompilationUnit* cUnit, MIR* mir, -                            RegLocation rlSrc) + +void genPackedSwitch(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)  { -    UNIMPLEMENTED(FATAL) << "Need Mips implementation"; +    UNIMPLEMENTED(FATAL) << "Need Mips packed switch";  #if 0      const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;      if (cUnit->printMe) { @@ -482,7 +110,7 @@ STATIC void genPackedSwitch(CompilationUnit* cUnit, MIR* mir,      tabRec->table = table;      tabRec->vaddr = mir->offset;      int size = table[1]; -    tabRec->targets = (MipsLIR* *)oatNew(cUnit, size * sizeof(MipsLIR*), true, +    tabRec->targets = (LIR* *)oatNew(cUnit, size * sizeof(LIR*), true,                                          kAllocLIR);      oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec); @@ -502,20 +130,20 @@ STATIC void genPackedSwitch(CompilationUnit* cUnit, MIR* mir,      }      // Bounds check - if < 0 or >= size continue following switch      opRegImm(cUnit, kOpCmp, keyReg, size-1); -    MipsLIR* branchOver = opCondBranch(cUnit, kMipsCondHi); +    LIR* branchOver = opCondBranch(cUnit, kCondHi);      // Load the displacement from the switch table      int dispReg = oatAllocTemp(cUnit);      loadBaseIndexed(cUnit, tableBase, keyReg, dispReg, 2, kWord);      // ..and go! NOTE: No instruction set switch here - must stay Thumb2 -    MipsLIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, dispReg); +    LIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, dispReg);      tabRec->bxInst = switchBranch;      /* branchOver target here */ -    MipsLIR* target = newLIR0(cUnit, kPseudoTargetLabel); +    LIR* target = newLIR0(cUnit, kPseudoTargetLabel);      target->defMask = ENCODE_ALL; -    branchOver->generic.target = (LIR*)target; +    branchOver->target = (LIR*)target;  #endif  } @@ -529,10 +157,9 @@ STATIC void genPackedSwitch(CompilationUnit* cUnit, MIR* mir,   *   * Total size is 4+(width * size + 1)/2 16-bit code units.   */ -STATIC void genFillArrayData(CompilationUnit* cUnit, MIR* mir, -                              RegLocation rlSrc) +void genFillArrayData(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)  { -    UNIMPLEMENTED(FATAL) << "Need Mips implementation"; +    UNIMPLEMENTED(FATAL) << "Needs Mips FillArrayData";  #if 0      const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;      // Add the table to the list - we'll process it later @@ -548,7 +175,7 @@ STATIC void genFillArrayData(CompilationUnit* cUnit, MIR* mir,      // Making a call - use explicit registers      oatFlushAllRegs(cUnit);   /* Everything to home location */ -    loadValueDirectFixed(cUnit, rlSrc, r0); +    loadValueDirectFixed(cUnit, rlSrc, rARG0);      loadWordDisp(cUnit, rSELF,                   OFFSETOF_MEMBER(Thread, pHandleFillArrayDataFromCode), rLR);      // Materialize a pointer to the fill data image @@ -557,275 +184,186 @@ STATIC void genFillArrayData(CompilationUnit* cUnit, MIR* mir,  #endif  } -STATIC void genIGet(CompilationUnit* cUnit, MIR* mir, OpSize size, -                    RegLocation rlDest, RegLocation rlObj, -                    bool isLongOrDouble, bool isObject) +/* + * TODO: implement fast path to short-circuit thin-lock case + */ +void genMonitorEnter(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)  { -    UNIMPLEMENTED(FATAL) << "Need Mips implementation"; -#if 0 -    int fieldOffset; -    bool isVolatile; -    uint32_t fieldIdx = mir->dalvikInsn.vC; -    bool fastPath = -        cUnit->compiler->ComputeInstanceFieldInfo(fieldIdx, cUnit, -                                                  fieldOffset, isVolatile, false); -    if (fastPath && !SLOW_FIELD_PATH) { -        RegLocation rlResult; -        RegisterClass regClass = oatRegClassBySize(size); -        DCHECK_GE(fieldOffset, 0); -        rlObj = loadValue(cUnit, rlObj, kCoreReg); -        if (isLongOrDouble) { -            DCHECK(rlDest.wide); -            genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null obj? */ -            int regPtr = oatAllocTemp(cUnit); -            opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset); -            rlResult = oatEvalLoc(cUnit, rlDest, regClass, true); -            loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg); -            if (isVolatile) { -                oatGenMemBarrier(cUnit, kSY); -            } -            oatFreeTemp(cUnit, regPtr); -            storeValueWide(cUnit, rlDest, rlResult); -        } else { -            rlResult = oatEvalLoc(cUnit, rlDest, regClass, true); -            genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null object? */ -            loadBaseDisp(cUnit, mir, rlObj.lowReg, fieldOffset, rlResult.lowReg, -                         kWord, rlObj.sRegLow); -            if (isVolatile) { -                oatGenMemBarrier(cUnit, kSY); -            } -            storeValue(cUnit, rlDest, rlResult); -        } -    } else { -        int getterOffset = isLongOrDouble ? OFFSETOF_MEMBER(Thread, pGet64Instance) : -                           (isObject ? OFFSETOF_MEMBER(Thread, pGetObjInstance) -                                     : OFFSETOF_MEMBER(Thread, pGet32Instance)); -        loadWordDisp(cUnit, rSELF, getterOffset, rLR); -        loadValueDirect(cUnit, rlObj, r1); -        loadConstant(cUnit, r0, fieldIdx); -        callRuntimeHelper(cUnit, rLR); -        if (isLongOrDouble) { -            RegLocation rlResult = oatGetReturnWide(cUnit); -            storeValueWide(cUnit, rlDest, rlResult); -        } else { -            RegLocation rlResult = oatGetReturn(cUnit); -            storeValue(cUnit, rlDest, rlResult); -        } -    } -#endif +    oatFlushAllRegs(cUnit); +    loadValueDirectFixed(cUnit, rlSrc, rARG0);  // Get obj +    oatLockCallTemps(cUnit);  // Prepare for explicit register usage +    genNullCheck(cUnit, rlSrc.sRegLow, rARG0, mir); +    // Go expensive route - artLockObjectFromCode(self, obj); +    int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread, pLockObjectFromCode)); +    callRuntimeHelper(cUnit, rTgt);  }  /* - * Perform a "reg cmp imm" operation and jump to the PCR region if condition - * satisfies. + * TODO: implement fast path to short-circuit thin-lock case   */ -STATIC void genNegFloat(CompilationUnit *cUnit, RegLocation rlDest, -                        RegLocation rlSrc) +void genMonitorExit(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)  { -    RegLocation rlResult; -    rlSrc = loadValue(cUnit, rlSrc, kCoreReg); -    rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); -    opRegRegImm(cUnit, kOpAdd, rlResult.lowReg, -                rlSrc.lowReg, 0x80000000); -    storeValue(cUnit, rlDest, rlResult); +    oatFlushAllRegs(cUnit); +    loadValueDirectFixed(cUnit, rlSrc, rARG0);  // Get obj +    oatLockCallTemps(cUnit);  // Prepare for explicit register usage +    genNullCheck(cUnit, rlSrc.sRegLow, rARG0, mir); +    // Go expensive route - UnlockObjectFromCode(obj); +    int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread, pUnlockObjectFromCode)); +    callRuntimeHelper(cUnit, rTgt);  } -STATIC void genNegDouble(CompilationUnit *cUnit, RegLocation rlDest, -                         RegLocation rlSrc) +/* + * Compare two 64-bit values + *    x = y     return  0 + *    x < y     return -1 + *    x > y     return  1 + * + *    slt   t0,  x.hi, y.hi;        # (x.hi < y.hi) ? 1:0 + *    sgt   t1,  x.hi, y.hi;        # (y.hi > x.hi) ? 1:0 + *    subu  res, t0, t1             # res = -1:1:0 for [ < > = ] + *    bnez  res, finish + *    sltu  t0, x.lo, y.lo + *    sgtu  r1, x.lo, y.lo + *    subu  res, t0, t1 + * finish: + * + */ +void genCmpLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, +                RegLocation rlSrc1, RegLocation rlSrc2)  { -    RegLocation rlResult; -    rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg); -    rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); -    opRegRegImm(cUnit, kOpAdd, rlResult.highReg, rlSrc.highReg, -                        0x80000000); -    genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg); -    storeValueWide(cUnit, rlDest, rlResult); +    rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg); +    rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg); +    int t0 = oatAllocTemp(cUnit); +    int t1 = oatAllocTemp(cUnit); +    RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); +    newLIR3(cUnit, kMipsSlt, t0, rlSrc1.highReg, rlSrc2.highReg); +    newLIR3(cUnit, kMipsSlt, t1, rlSrc2.highReg, rlSrc1.highReg); +    newLIR3(cUnit, kMipsSubu, rlResult.lowReg, t1, t0); +    LIR* branch = genCmpImmBranch(cUnit, kCondNe, rlResult.lowReg, 0); +    newLIR3(cUnit, kMipsSltu, t0, rlSrc1.lowReg, rlSrc2.lowReg); +    newLIR3(cUnit, kMipsSltu, t1, rlSrc2.lowReg, rlSrc1.lowReg); +    newLIR3(cUnit, kMipsSubu, rlResult.lowReg, t1, t0); +    oatFreeTemp(cUnit, t0); +    oatFreeTemp(cUnit, t1); +    LIR* target = newLIR0(cUnit, kPseudoTargetLabel); +    target->defMask = ENCODE_ALL; +    branch->target = (LIR*)target; +    storeValue(cUnit, rlDest, rlResult);  } -STATIC void genMulLong(CompilationUnit *cUnit, RegLocation rlDest, -                       RegLocation rlSrc1, RegLocation rlSrc2) +LIR* genCompareBranch(CompilationUnit* cUnit, ConditionCode cond, int src1, +                      int src2)  { -    UNIMPLEMENTED(FATAL) << "Need Mips implementation"; -#if 0 -    RegLocation rlResult; -    loadValueDirectWideFixed(cUnit, rlSrc1, r_ARG0, r_ARG1); -    loadValueDirectWideFixed(cUnit, rlSrc2, r_ARG2, r_ARG3); -    genDispatchToHandler(cUnit, TEMPLATE_MUL_LONG); -    rlResult = oatGetReturnWide(cUnit); -    storeValueWide(cUnit, rlDest, rlResult); -#endif +    if (cond == kCondEq) { +        return newLIR2(cUnit, kMipsBeq, src1, src2); +    } else if (cond == kCondNe) { +        return newLIR2(cUnit, kMipsBne, src1, src2); +    } +    //int rRes = oatAllocTemp(cUnit); +    switch(cond) { +        case kCondEq: return newLIR2(cUnit, kMipsBeq, src1, src2); +        case kCondNe: return newLIR2(cUnit, kMipsBne, src1, src2); +        default: +            UNIMPLEMENTED(FATAL) << "Need to flesh out genCompareBranch"; +            return NULL; +    }  } -STATIC bool partialOverlap(int sreg1, int sreg2) +LIR* genCmpImmBranch(CompilationUnit* cUnit, ConditionCode cond, int reg, +                     int checkValue)  { -    return abs(sreg1 - sreg2) == 1; +    if (checkValue != 0) { +        // TUNING: handle s16 & kCondLt/Mi case using slti +        int tReg = oatAllocTemp(cUnit); +        loadConstant(cUnit, tReg, checkValue); +        return genCompareBranch(cUnit, cond, reg, tReg); +    } +    MipsOpCode opc; +    switch(cond) { +        case kCondEq: opc = kMipsBeqz; break; +        case kCondGe: opc = kMipsBgez; break; +        case kCondGt: opc = kMipsBgtz; break; +        case kCondLe: opc = kMipsBlez; break; +        //case KCondMi: +        case kCondLt: opc = kMipsBltz; break; +        case kCondNe: opc = kMipsBnez; break; +        default: +            int tReg = oatAllocTemp(cUnit); +            loadConstant(cUnit, tReg, checkValue); +            return genCompareBranch(cUnit, cond, reg, tReg); +    } +    return newLIR1(cUnit, opc, reg);  } -STATIC void withCarryHelper(CompilationUnit *cUnit, MipsOpCode opc, -                            RegLocation rlDest, RegLocation rlSrc1, -                            RegLocation rlSrc2, int sltuSrc1, int sltuSrc2) +LIR* genRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc)  { -    int tReg = oatAllocTemp(cUnit); -    newLIR3(cUnit, opc, rlDest.lowReg, rlSrc1.lowReg, rlSrc2.lowReg); -    newLIR3(cUnit, kMipsSltu, tReg, sltuSrc1, sltuSrc2); -    newLIR3(cUnit, opc, rlDest.highReg, rlSrc1.highReg, rlSrc2.highReg); -    newLIR3(cUnit, opc, rlDest.highReg, rlDest.highReg, tReg); -    oatFreeTemp(cUnit, tReg); +    LIR* res; +    MipsOpCode opcode; +#ifdef __mips_hard_float +    if (FPREG(rDest) || FPREG(rSrc)) +        return fpRegCopy(cUnit, rDest, rSrc); +#endif +    res = (LIR *) oatNew(cUnit, sizeof(LIR), true, kAllocLIR); +    opcode = kMipsMove; +    assert(LOWREG(rDest) && LOWREG(rSrc)); +    res->operands[0] = rDest; +    res->operands[1] = rSrc; +    res->opcode = opcode; +    setupResourceMasks(res); +    if (rDest == rSrc) { +        res->flags.isNop = true; +    } +    return res;  } -STATIC void genLong3Addr(CompilationUnit *cUnit, MIR *mir, OpKind firstOp, -                         OpKind secondOp, RegLocation rlDest, -                         RegLocation rlSrc1, RegLocation rlSrc2) +LIR* genRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)  { -    UNIMPLEMENTED(FATAL) << "Need Mips implementation"; -#if 0 -    RegLocation rlResult; -    int carryOp = (secondOp == kOpAdc || secondOp == kOpSbc); +    LIR *res = genRegCopyNoInsert(cUnit, rDest, rSrc); +    oatAppendLIR(cUnit, (LIR*)res); +    return res; +} -    if (partialOverlap(rlSrc1.sRegLow,rlSrc2.sRegLow) || -        partialOverlap(rlSrc1.sRegLow,rlDest.sRegLow) || -        partialOverlap(rlSrc2.sRegLow,rlDest.sRegLow)) { -        // Rare case - not enough registers to properly handle -        genInterpSingleStep(cUnit, mir); -    } else if (rlDest.sRegLow == rlSrc1.sRegLow) { -        rlResult = loadValueWide(cUnit, rlDest, kCoreReg); -        rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg); -        if (!carryOp) { -            opRegRegReg(cUnit, firstOp, rlResult.lowReg, rlResult.lowReg, rlSrc2.lowReg); -            opRegRegReg(cUnit, secondOp, rlResult.highReg, rlResult.highReg, rlSrc2.highReg); -        } else if (secondOp == kOpAdc) { -            withCarryHelper(cUnit, kMipsAddu, rlResult, rlResult, rlSrc2, -                            rlResult.lowReg, rlSrc2.lowReg); -        } else { -            int tReg = oatAllocTemp(cUnit); -            newLIR2(cUnit, kMipsMove, tReg, rlResult.lowReg); -            withCarryHelper(cUnit, kMipsSubu, rlResult, rlResult, rlSrc2, -                            tReg, rlResult.lowReg); -            oatFreeTemp(cUnit, tReg); -        } -        storeValueWide(cUnit, rlDest, rlResult); -    } else if (rlDest.sRegLow == rlSrc2.sRegLow) { -        rlResult = loadValueWide(cUnit, rlDest, kCoreReg); -        rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg); -        if (!carryOp) { -            opRegRegReg(cUnit, firstOp, rlResult.lowReg, rlSrc1.lowReg, rlResult.lowReg); -            opRegRegReg(cUnit, secondOp, rlResult.highReg, rlSrc1.highReg, rlResult.highReg); -        } else if (secondOp == kOpAdc) { -            withCarryHelper(cUnit, kMipsAddu, rlResult, rlSrc1, rlResult, -                            rlResult.lowReg, rlSrc1.lowReg); +void genRegCopyWide(CompilationUnit *cUnit, int destLo, int destHi, +                    int srcLo, int srcHi) +{ +#ifdef __mips_hard_float +    bool destFP = FPREG(destLo) && FPREG(destHi); +    bool srcFP = FPREG(srcLo) && FPREG(srcHi); +    assert(FPREG(srcLo) == FPREG(srcHi)); +    assert(FPREG(destLo) == FPREG(destHi)); +    if (destFP) { +        if (srcFP) { +            genRegCopy(cUnit, S2D(destLo, destHi), S2D(srcLo, srcHi));          } else { -            withCarryHelper(cUnit, kMipsSubu, rlResult, rlSrc1, rlResult, -                            rlSrc1.lowReg, rlResult.lowReg); +           /* note the operands are swapped for the mtc1 instr */ +            newLIR2(cUnit, kMipsMtc1, srcLo, destLo); +            newLIR2(cUnit, kMipsMtc1, srcHi, destHi);          } -        storeValueWide(cUnit, rlDest, rlResult);      } else { -        rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg); -        rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg); -        rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); -        if (!carryOp) { -            opRegRegReg(cUnit, firstOp, rlResult.lowReg, rlSrc1.lowReg, rlSrc2.lowReg); -            opRegRegReg(cUnit, secondOp, rlResult.highReg, rlSrc1.highReg, rlSrc2.highReg); -        } else if (secondOp == kOpAdc) { -            withCarryHelper(cUnit, kMipsAddu, rlResult, rlSrc1, rlSrc2, -                            rlResult.lowReg, rlSrc1.lowReg); +        if (srcFP) { +            newLIR2(cUnit, kMipsMfc1, destLo, srcLo); +            newLIR2(cUnit, kMipsMfc1, destHi, srcHi);          } else { -            withCarryHelper(cUnit, kMipsSubu, rlResult, rlSrc1, rlSrc2, -                            rlSrc1.lowReg, rlResult.lowReg); +            // Handle overlap +            if (srcHi == destLo) { +                genRegCopy(cUnit, destHi, srcHi); +                genRegCopy(cUnit, destLo, srcLo); +            } else { +                genRegCopy(cUnit, destLo, srcLo); +                genRegCopy(cUnit, destHi, srcHi); +            }          } -        storeValueWide(cUnit, rlDest, rlResult);      } -#endif -} - -void oatInitializeRegAlloc(CompilationUnit* cUnit) -{ -    int numRegs = sizeof(coreRegs)/sizeof(*coreRegs); -    int numReserved = sizeof(reservedRegs)/sizeof(*reservedRegs); -    int numTemps = sizeof(coreTemps)/sizeof(*coreTemps); -#ifdef __mips_hard_float -    int numFPRegs = sizeof(fpRegs)/sizeof(*fpRegs); -    int numFPTemps = sizeof(fpTemps)/sizeof(*fpTemps);  #else -    int numFPRegs = 0; -    int numFPTemps = 0; -#endif -    RegisterPool *pool = (RegisterPool *)oatNew(cUnit, sizeof(*pool), true, -                                                kAllocRegAlloc); -    cUnit->regPool = pool; -    pool->numCoreRegs = numRegs; -    pool->coreRegs = (RegisterInfo *) -            oatNew(cUnit, numRegs * sizeof(*cUnit->regPool->coreRegs), -                   true, kAllocRegAlloc); -    pool->numFPRegs = numFPRegs; -    pool->FPRegs = numFPRegs == 0 ? NULL : (RegisterInfo *) -            oatNew(cUnit, numFPRegs * sizeof(*cUnit->regPool->FPRegs), true, -                   kAllocRegAlloc); -    oatInitPool(pool->coreRegs, coreRegs, pool->numCoreRegs); -    oatInitPool(pool->FPRegs, fpRegs, pool->numFPRegs); -    // Keep special registers from being allocated -    for (int i = 0; i < numReserved; i++) { -        if (NO_SUSPEND && !cUnit->genDebugger && -            (reservedRegs[i] == rSUSPEND)) { -            //To measure cost of suspend check -            continue; -        } -        oatMarkInUse(cUnit, reservedRegs[i]); -    } -    // Mark temp regs - all others not in use can be used for promotion -    for (int i = 0; i < numTemps; i++) { -        oatMarkTemp(cUnit, coreTemps[i]); -    } -    for (int i = 0; i < numFPTemps; i++) { -        oatMarkTemp(cUnit, fpTemps[i]); -    } -    // Construct the alias map. -    cUnit->phiAliasMap = (int*)oatNew(cUnit, cUnit->numSSARegs * -                                      sizeof(cUnit->phiAliasMap[0]), false, -                                      kAllocDFInfo); -    for (int i = 0; i < cUnit->numSSARegs; i++) { -        cUnit->phiAliasMap[i] = i; -    } -    for (MIR* phi = cUnit->phiList; phi; phi = phi->meta.phiNext) { -        int defReg = phi->ssaRep->defs[0]; -        for (int i = 0; i < phi->ssaRep->numUses; i++) { -           for (int j = 0; j < cUnit->numSSARegs; j++) { -               if (cUnit->phiAliasMap[j] == phi->ssaRep->uses[i]) { -                   cUnit->phiAliasMap[j] = defReg; -               } -           } -        } +    // Handle overlap +    if (srcHi == destLo) { +        genRegCopy(cUnit, destHi, srcHi); +        genRegCopy(cUnit, destLo, srcLo); +    } else { +        genRegCopy(cUnit, destLo, srcLo); +        genRegCopy(cUnit, destHi, srcHi);      } -} - -STATIC void genMonitor(CompilationUnit *cUnit, MIR *mir) -{ -    UNIMPLEMENTED(FATAL) << "Need Mips implementation"; -#if 0 -    genMonitorPortable(cUnit, mir);  #endif  } -STATIC void genCmpLong(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest, -                       RegLocation rlSrc1, RegLocation rlSrc2) -{ -    UNIMPLEMENTED(FATAL) << "Need Mips implementation"; -#if 0 -    RegLocation rlResult; -    loadValueDirectWideFixed(cUnit, rlSrc1, r_ARG0, r_ARG1); -    loadValueDirectWideFixed(cUnit, rlSrc2, r_ARG2, r_ARG3); -    genDispatchToHandler(cUnit, TEMPLATE_CMP_LONG); -    rlResult = oatGetReturn(cUnit); -    storeValue(cUnit, rlDest, rlResult); -#endif -} - -STATIC void genMultiplyByTwoBitMultiplier(CompilationUnit *cUnit, -        RegLocation rlSrc, RegLocation rlResult, int lit, -        int firstBit, int secondBit) -{ -    // We can't implement "add src, src, src, lsl#shift" on Thumb, so we have -    // to do a regular multiply. -    opRegRegImm(cUnit, kOpMul, rlResult.lowReg, rlSrc.lowReg, lit); -} -  }  // namespace art diff --git a/src/compiler/codegen/mips/Mips32/Ralloc.cc b/src/compiler/codegen/mips/Mips32/Ralloc.cc index e0912d77b8..f8440a45da 100644 --- a/src/compiler/codegen/mips/Mips32/Ralloc.cc +++ b/src/compiler/codegen/mips/Mips32/Ralloc.cc @@ -61,4 +61,76 @@ int oatAllocTypedTemp(CompilationUnit *cUnit, bool fpHint, int regClass)      return oatAllocTemp(cUnit);  } +void oatInitializeRegAlloc(CompilationUnit* cUnit) +{ +    int numRegs = sizeof(coreRegs)/sizeof(*coreRegs); +    int numReserved = sizeof(reservedRegs)/sizeof(*reservedRegs); +    int numTemps = sizeof(coreTemps)/sizeof(*coreTemps); +#ifdef __mips_hard_float +    int numFPRegs = sizeof(fpRegs)/sizeof(*fpRegs); +    int numFPTemps = sizeof(fpTemps)/sizeof(*fpTemps); +#else +    int numFPRegs = 0; +    int numFPTemps = 0; +#endif +    RegisterPool *pool = (RegisterPool *)oatNew(cUnit, sizeof(*pool), true, +                                                kAllocRegAlloc); +    cUnit->regPool = pool; +    pool->numCoreRegs = numRegs; +    pool->coreRegs = (RegisterInfo *) +            oatNew(cUnit, numRegs * sizeof(*cUnit->regPool->coreRegs), +                   true, kAllocRegAlloc); +    pool->numFPRegs = numFPRegs; +    pool->FPRegs = (RegisterInfo *) +            oatNew(cUnit, numFPRegs * sizeof(*cUnit->regPool->FPRegs), true, +                   kAllocRegAlloc); +    oatInitPool(pool->coreRegs, coreRegs, pool->numCoreRegs); +    oatInitPool(pool->FPRegs, fpRegs, pool->numFPRegs); +    // Keep special registers from being allocated +    for (int i = 0; i < numReserved; i++) { +        if (NO_SUSPEND && !cUnit->genDebugger && +            (reservedRegs[i] == rSUSPEND)) { +            //To measure cost of suspend check +            continue; +        } +        oatMarkInUse(cUnit, reservedRegs[i]); +    } +    // Mark temp regs - all others not in use can be used for promotion +    for (int i = 0; i < numTemps; i++) { +        oatMarkTemp(cUnit, coreTemps[i]); +    } +    for (int i = 0; i < numFPTemps; i++) { +        oatMarkTemp(cUnit, fpTemps[i]); +    } +    // Construct the alias map. +    cUnit->phiAliasMap = (int*)oatNew(cUnit, cUnit->numSSARegs * +                                      sizeof(cUnit->phiAliasMap[0]), false, +                                      kAllocDFInfo); +    for (int i = 0; i < cUnit->numSSARegs; i++) { +        cUnit->phiAliasMap[i] = i; +    } +    for (MIR* phi = cUnit->phiList; phi; phi = phi->meta.phiNext) { +        int defReg = phi->ssaRep->defs[0]; +        for (int i = 0; i < phi->ssaRep->numUses; i++) { +           for (int j = 0; j < cUnit->numSSARegs; j++) { +               if (cUnit->phiAliasMap[j] == phi->ssaRep->uses[i]) { +                   cUnit->phiAliasMap[j] = defReg; +               } +           } +        } +    } +} + +void freeRegLocTemps(CompilationUnit* cUnit, RegLocation rlKeep, +                     RegLocation rlFree) +{ +    if ((rlFree.lowReg != rlKeep.lowReg) && (rlFree.lowReg != rlKeep.highReg) && +        (rlFree.highReg != rlKeep.lowReg) && (rlFree.highReg != rlKeep.highReg)) { +        // No overlap, free both +        oatFreeTemp(cUnit, rlFree.lowReg); +        oatFreeTemp(cUnit, rlFree.highReg); +    } +} + +  }  // namespace art diff --git a/src/compiler/codegen/mips/MipsLIR.h b/src/compiler/codegen/mips/MipsLIR.h index 44f0c5a2b9..93956d5d5f 100644 --- a/src/compiler/codegen/mips/MipsLIR.h +++ b/src/compiler/codegen/mips/MipsLIR.h @@ -149,10 +149,10 @@ namespace art {                        INVALID_SREG}  #define LOC_C_RETURN_ALT {kLocPhysReg, 0, 0, 0, 0, 0, 1, r_F0, INVALID_REG, \                        INVALID_SREG} -#define LOC_C_RETURN_WIDE {kLocPhysReg, 1, 0, 0, 0, 0, 1, r_V0, r_V1,\ -                           INVALID_SREG} -#define LOC_C_RETURN_WIDE_ALT {kLocPhysReg, 1, 0, 0, 0, 0, 1, r_F0, r_F1,\ +#define LOC_C_RETURN_WIDE {kLocPhysReg, 1, 0, 0, 0, 0, 1, r_RESULT0, r_RESULT1,\                             INVALID_SREG} +#define LOC_C_RETURN_WIDE_ALT {kLocPhysReg, 1, 0, 0, 0, 0, 1, r_FRESULT0,\ +                               r_FRESULT1, INVALID_SREG}  typedef enum ResourceEncodingPos {      kGPReg0     = 0, @@ -194,25 +194,6 @@ typedef enum ResourceEncodingPos {  #define DECODE_ALIAS_INFO_WIDE(X)       ((X & 0x80000000) ? 1 : 0)  /* - * FIXME: - * Originally had r4PC as r_S0, rFP as r_S1, rSELF as r_S2, rINST as r_S4 - * Remap - don't need r4PC, rFP or rINST.  Might make sense to keep - * Method* in one of these since we have so many registers to play with. - */ - -#define rSUSPEND r_S0 -#define rSELF r_S1 -#define rSP r_SP - -#define rARG0 r_ARG0 -#define rARG1 r_ARG1 -#define rARG2 r_ARG2 -#define rARG3 r_ARG3 - -#define rRET0 r_V0 -#define rRET1 r_V1 - -/*   * Annotate special-purpose core registers:   */ @@ -307,6 +288,21 @@ typedef enum NativeRegisterPool {      r_PC,  } NativeRegisterPool; +/* + * Target-independent aliases + */ + +#define rSUSPEND r_S0 +#define rSELF r_S1 +#define rSP r_SP +#define rARG0 r_ARG0 +#define rARG1 r_ARG1 +#define rARG2 r_ARG2 +#define rARG3 r_ARG3 +#define rRET0 r_RESULT0 +#define rRET1 r_RESULT1 +#define rLINK r_RA +  /* Shift encodings */  typedef enum MipsShiftEncodings {      kMipsLsl = 0x0, @@ -335,15 +331,9 @@ typedef enum MipsConditionCode {      kMipsCondNv = 0xf,    /* 1111 */  } MipsConditionCode; -typedef enum MipsThrowKind { -    kMipsThrowNullPointer, -    kMipsThrowDivZero, -    kMipsThrowArrayBounds, -    kMipsThrowVerificationError, -    kMipsThrowNegArraySize, -    kMipsThrowNoSuchMethod, -    kMipsThrowStackOverflow, -} MipsThrowKind; +// FIXME: Need support for barriers.  Adding these defines to allow compile +#define kST 0 +#define kSY 1  #define isPseudoOpcode(opCode) ((int)(opCode) < 0) @@ -487,6 +477,8 @@ typedef enum MipsOpFeatureFlags {      kUsesCCodes,      kMemLoad,      kMemStore, +    kPCRelFixup, +// FIXME: add NEEDS_FIXUP to instruction attributes  } MipsOpFeatureFlags;  #define IS_LOAD         (1 << kMemLoad) @@ -514,6 +506,12 @@ typedef enum MipsOpFeatureFlags {  #define IS_IT           (1 << kIsIT)  #define SETS_CCODES     (1 << kSetsCCodes)  #define USES_CCODES     (1 << kUsesCCodes) +#define NEEDS_FIXUP      (1 << kPCRelFixup) + +/*  attributes, included for compatibility */ +#define REG_DEF_FPCS_LIST0   (0) +#define REG_DEF_FPCS_LIST2   (0) +  /* Common combo register usage patterns */  #define REG_USE01       (REG_USE0 | REG_USE1) @@ -559,63 +557,6 @@ typedef enum MipsTargetOptHints {  extern MipsEncodingMap EncodingMap[kMipsLast]; -/* - * Each instance of this struct holds a pseudo or real LIR instruction: - * - pseudo ones (eg labels and marks) and will be discarded by the assembler. - * - real ones will be assembled - * - * FIXME: notes below are Arm-specific.  We have 32 core registers instead - * of 16, and no IT blocks.  Must widen this or overload in order to - * support all 32 FP regs.  Perhaps use r0 for ccodes, eliminate IT block - * and overload gp with fp status word? (or just use a single bit for - * both core and fp condition code/status word? - * - * Machine resources are encoded into a 64-bit vector, where the encodings are - * as following: - * - [ 0..15]: general purpose registers including PC, SP, and LR - * - [16..47]: floating-point registers where d0 is expanded to s[01] and s0 - *   starts at bit 16 - * - [48]: IT block - * - [49]: integer condition code - * - [50]: floatint-point status word - */ -typedef struct MipsLIR { -    LIR generic; -    MipsOpCode opcode; -    int operands[4];            // [0..3] = [dest, src1, src2, extra] -    struct { -        bool isNop:1;           // LIR is optimized away -        bool pcRelFixup:1;      // May need pc-relative fixup -        unsigned int age:4;     // default is 0, set lazily by the optimizer -        unsigned int size:3;    // in bytes -        unsigned int unused:23; -    } flags; -    int aliasInfo;              // For Dalvik register access & litpool disambiguation -    u8 useMask;                 // Resource mask for use -    u8 defMask;                 // Resource mask for def -} MipsLIR; - -typedef struct SwitchTable { -    int offset; -    const u2* table;            // Original dex table -    int vaddr;                  // Dalvik offset of switch opcode -    MipsLIR* bxInst;             // Switch indirect branch instruction -    MipsLIR** targets;           // Array of case targets -} SwitchTable; - -typedef struct FillArrayData { -    int offset; -    const u2* table;           // Original dex table -    int size; -    int vaddr;                 // Dalvik offset of OP_FILL_ARRAY_DATA opcode -} FillArrayData; - -/* Utility macros to traverse the LIR/MipsLIR list */ -#define NEXT_LIR(lir) ((MipsLIR *) lir->generic.next) -#define PREV_LIR(lir) ((MipsLIR *) lir->generic.prev) - -#define NEXT_LIR_LVALUE(lir) (lir)->generic.next -#define PREV_LIR_LVALUE(lir) (lir)->generic.prev  #define IS_UIMM16(v) ((0 <= (v)) && ((v) <= 65535))  #define IS_SIMM16(v) ((-32768 <= (v)) && ((v) <= 32766)) diff --git a/src/compiler/codegen/mips/MipsRallocUtil.cc b/src/compiler/codegen/mips/MipsRallocUtil.cc index 0dfbfa5065..504375b572 100644 --- a/src/compiler/codegen/mips/MipsRallocUtil.cc +++ b/src/compiler/codegen/mips/MipsRallocUtil.cc @@ -48,20 +48,6 @@ void oatAdjustSpillMask(CompilationUnit* cUnit)  void oatMarkPreservedSingle(CompilationUnit* cUnit, int sReg, int reg)  {      UNIMPLEMENTED(FATAL) << "No support yet for promoted FP regs"; -#if 0 -    DCHECK_GE(reg, FP_REG_MASK + FP_CALLEE_SAVE_BASE); -    reg = (reg & FP_REG_MASK) - FP_CALLEE_SAVE_BASE; -    // Ensure fpVmapTable is large enough -    int tableSize = cUnit->fpVmapTable.size(); -    for (int i = tableSize; i < (reg + 1); i++) { -        cUnit->fpVmapTable.push_back(INVALID_VREG); -    } -    // Add the current mapping -    cUnit->fpVmapTable[reg] = sReg; -    // Size of fpVmapTable is high-water mark, use to set mask -    cUnit->numFPSpills = cUnit->fpVmapTable.size(); -    cUnit->fpSpillMask = ((1 << cUnit->numFPSpills) - 1) << FP_CALLEE_SAVE_BASE; -#endif  }  void oatFlushRegWide(CompilationUnit* cUnit, int reg1, int reg2) @@ -159,10 +145,10 @@ extern void oatClobberCalleeSave(CompilationUnit *cUnit)  extern RegLocation oatGetReturnWide(CompilationUnit* cUnit)  {      RegLocation res = LOC_C_RETURN_WIDE; -    oatClobber(cUnit, r_V0); -    oatClobber(cUnit, r_V1); -    oatMarkInUse(cUnit, r_V0); -    oatMarkInUse(cUnit, r_V1); +    oatClobber(cUnit, res.lowReg); +    oatClobber(cUnit, res.highReg); +    oatMarkInUse(cUnit, res.lowReg); +    oatMarkInUse(cUnit, res.highReg);      oatMarkPair(cUnit, res.lowReg, res.highReg);      return res;  } @@ -170,10 +156,10 @@ extern RegLocation oatGetReturnWide(CompilationUnit* cUnit)  extern RegLocation oatGetReturnWideAlt(CompilationUnit* cUnit)  {      RegLocation res = LOC_C_RETURN_WIDE_ALT; -    oatClobber(cUnit, r_F0); -    oatClobber(cUnit, r_F1); -    oatMarkInUse(cUnit, r_F0); -    oatMarkInUse(cUnit, r_F1); +    oatClobber(cUnit, res.lowReg); +    oatClobber(cUnit, res.highReg); +    oatMarkInUse(cUnit, res.lowReg); +    oatMarkInUse(cUnit, res.highReg);      oatMarkPair(cUnit, res.lowReg, res.highReg);      return res;  } @@ -181,16 +167,16 @@ extern RegLocation oatGetReturnWideAlt(CompilationUnit* cUnit)  extern RegLocation oatGetReturn(CompilationUnit* cUnit)  {      RegLocation res = LOC_C_RETURN; -    oatClobber(cUnit, r_V0); -    oatMarkInUse(cUnit, r_V0); +    oatClobber(cUnit, res.lowReg); +    oatMarkInUse(cUnit, res.lowReg);      return res;  }  extern RegLocation oatGetReturnAlt(CompilationUnit* cUnit)  {      RegLocation res = LOC_C_RETURN_ALT; -    oatClobber(cUnit, r_F0); -    oatMarkInUse(cUnit, r_F0); +    oatClobber(cUnit, res.lowReg); +    oatMarkInUse(cUnit, res.lowReg);      return res;  } @@ -203,25 +189,25 @@ extern RegisterInfo* oatGetRegInfo(CompilationUnit* cUnit, int reg)  /* To be used when explicitly managing register use */  extern void oatLockCallTemps(CompilationUnit* cUnit)  { -    oatLockTemp(cUnit, r_A0); -    oatLockTemp(cUnit, r_A1); -    oatLockTemp(cUnit, r_A2); -    oatLockTemp(cUnit, r_A3); +    oatLockTemp(cUnit, rARG0); +    oatLockTemp(cUnit, rARG1); +    oatLockTemp(cUnit, rARG2); +    oatLockTemp(cUnit, rARG3);  }  /* To be used when explicitly managing register use */  extern void oatFreeCallTemps(CompilationUnit* cUnit)  { -    oatFreeTemp(cUnit, r_A0); -    oatFreeTemp(cUnit, r_A1); -    oatFreeTemp(cUnit, r_A2); -    oatFreeTemp(cUnit, r_A3); +    oatFreeTemp(cUnit, rARG0); +    oatFreeTemp(cUnit, rARG1); +    oatFreeTemp(cUnit, rARG2); +    oatFreeTemp(cUnit, rARG3);  }  /* Convert an instruction to a NOP */ -STATIC void oatNopLIR( LIR* lir) +void oatNopLIR( LIR* lir)  { -    ((MipsLIR*)lir)->flags.isNop = true; +    ((LIR*)lir)->flags.isNop = true;  }  }  // namespace art diff --git a/src/compiler/codegen/mips/mips/Codegen.cc b/src/compiler/codegen/mips/mips/Codegen.cc index 22a7c94209..71f43e55fd 100644 --- a/src/compiler/codegen/mips/mips/Codegen.cc +++ b/src/compiler/codegen/mips/mips/Codegen.cc @@ -15,7 +15,7 @@   */  #define _CODEGEN_C -#define TGT_LIR MipsLIR +#define TARGET_MIPS  #include "../../../Dalvik.h"  #include "../../../CompilerInternals.h" @@ -24,12 +24,16 @@  #include "../Codegen.h"  /* Mips codegen building blocks */ -#include "../CodegenCommon.cc" +#include "../../CodegenUtil.cc"  /* Mips-specific factory utilities */  #include "../Mips32/Factory.cc" -/* Target indepedent factory utilities */ +/* Target independent factory utilities */  #include "../../CodegenFactory.cc" +/* Target independent gen routines */ +#include "../../GenCommon.cc" +/* Shared invoke gen routines */ +#include "../../GenInvoke.cc"  /* Mips-specific factory utilities */  #include "../ArchFactory.cc" @@ -47,8 +51,5 @@  /* Target-independent local optimizations */  #include "../../LocalOptimizations.cc" -/* Common codegen utility code */ -#include "../../CodegenUtil.cc" -  /* Architecture manifest */  #include "ArchVariant.cc" |