Lines Matching full:cunit
30 static void markCard(CompilationUnit *cUnit, int valReg, int tgtAddrReg)
32 int regCardBase = dvmCompilerAllocTemp(cUnit);
33 int regCardNo = dvmCompilerAllocTemp(cUnit);
34 MipsLIR *branchOver = opCompareBranch(cUnit, kMipsBeq, valReg, r_ZERO);
35 loadWordDisp(cUnit, rSELF, offsetof(Thread, cardTable),
37 opRegRegImm(cUnit, kOpLsr, regCardNo, tgtAddrReg, GC_CARD_SHIFT);
38 storeBaseIndexed(cUnit, regCardBase, regCardNo, regCardBase, 0,
40 MipsLIR *target = newLIR0(cUnit, kMipsPseudoTargetLabel);
43 dvmCompilerFreeTemp(cUnit, regCardBase);
44 dvmCompilerFreeTemp(cUnit, regCardNo);
47 static bool genConversionCall(CompilationUnit *cUnit, MIR *mir, void *funct,
58 dvmCompilerFlushAllRegs(cUnit); /* Send everything to home location */
85 rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
86 loadValueDirectFixed(cUnit, rlSrc, srcReg);
88 rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
89 loadValueDirectWideFixed(cUnit, rlSrc, srcReg, srcRegHi);
91 LOAD_FUNC_ADDR(cUnit, r_T9, (int)funct);
92 opReg(cUnit, kOpBlx, r_T9);
93 newLIR3(cUnit, kMipsLw, r_GP, STACK_OFFSET_GP, r_SP);
94 dvmCompilerClobberCallRegs(cUnit);
97 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
100 rlResult = dvmCompilerGetReturnAlt(cUnit);
102 rlResult = dvmCompilerGetReturn(cUnit);
104 rlResult = dvmCompilerGetReturn(cUnit);
106 storeValue(cUnit, rlDest, rlResult);
109 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
112 rlResult = dvmCompilerGetReturnWideAlt(cUnit);
114 rlResult = dvmCompilerGetReturnWide(cUnit);
116 rlResult = dvmCompilerGetReturnWide(cUnit);
118 storeValueWide(cUnit, rlDest, rlResult);
124 static bool genArithOpFloatPortable(CompilationUnit *cUnit, MIR *mir,
153 genNegFloat(cUnit, rlDest, rlSrc1);
160 dvmCompilerFlushAllRegs(cUnit); /* Send everything to home location */
162 loadValueDirectFixed(cUnit, rlSrc1, r_F12);
163 loadValueDirectFixed(cUnit, rlSrc2, r_F14);
165 loadValueDirectFixed(cUnit, rlSrc1, r_A0);
166 loadValueDirectFixed(cUnit, rlSrc2, r_A1);
168 LOAD_FUNC_ADDR(cUnit, r_T9, (int)funct);
169 opReg(cUnit, kOpBlx, r_T9);
170 newLIR3(cUnit, kMipsLw, r_GP, STACK_OFFSET_GP, r_SP);
171 dvmCompilerClobberCallRegs(cUnit);
173 rlResult = dvmCompilerGetReturnAlt(cUnit);
175 rlResult = dvmCompilerGetReturn(cUnit);
177 storeValue(cUnit, rlDest, rlResult);
181 static bool genArithOpDoublePortable(CompilationUnit *cUnit, MIR *mir,
210 genNegDouble(cUnit, rlDest, rlSrc1);
216 dvmCompilerFlushAllRegs(cUnit); /* Send everything to home location */
217 LOAD_FUNC_ADDR(cUnit, r_T9, (int)funct);
219 loadValueDirectWideFixed(cUnit, rlSrc1, r_F12, r_F13);
220 loadValueDirectWideFixed(cUnit, rlSrc2, r_F14, r_F15);
222 loadValueDirectWideFixed(cUnit, rlSrc1, r_ARG0, r_ARG1);
223 loadValueDirectWideFixed(cUnit, rlSrc2, r_ARG2, r_ARG3);
225 opReg(cUnit, kOpBlx, r_T9);
226 newLIR3(cUnit, kMipsLw, r_GP, STACK_OFFSET_GP, r_SP);
227 dvmCompilerClobberCallRegs(cUnit);
229 rlResult = dvmCompilerGetReturnWideAlt(cUnit);
231 rlResult = dvmCompilerGetReturnWide(cUnit);
233 storeValueWide(cUnit, rlDest, rlResult);
235 cUnit->usesLinkRegister = true;
240 static bool genConversionPortable(CompilationUnit *cUnit, MIR *mir)
246 return genConversionCall(cUnit, mir, (void*)__floatsisf, kWord, kSingle);
248 return genConversionCall(cUnit, mir, (void*)__fixsfsi, kSingle, kWord);
250 return genConversionCall(cUnit, mir, (void*)__truncdfsf2, kDouble, kSingle);
252 return genConversionCall(cUnit, mir, (void*)__extendsfdf2, kSingle, kDouble);
254 return genConversionCall(cUnit, mir, (void*)__floatsidf, kWord, kDouble);
256 return genConversionCall(cUnit, mir, (void*)__fixdfsi, kDouble, kWord);
258 return genConversionCall(cUnit, mir, (void*)__fixsfdi, kSingle, kLong);
260 return genConversionCall(cUnit, mir, (void*)__floatdisf, kLong, kSingle);
262 return genConversionCall(cUnit, mir, (void*)__fixdfdi, kDouble, kLong);
264 return genConversionCall(cUnit, mir, (void*)__floatdidf, kLong, kDouble);
309 static void selfVerificationBranchInsertPass(CompilationUnit *cUnit)
315 for (thisLIR = (MipsLIR *) cUnit->firstLIRInsn;
316 thisLIR != (MipsLIR *) cUnit->lastLIRInsn;
327 if (cUnit->usesLinkRegister) {
328 genSelfVerificationPreBranch(cUnit, thisLIR);
340 if (cUnit->usesLinkRegister) {
341 genSelfVerificationPostBranch(cUnit, thisLIR);
349 static MipsLIR *genConditionalBranchMips(CompilationUnit *cUnit,
353 MipsLIR *branch = opCompareBranch(cUnit, opc, rs, rt);
359 static inline MipsLIR *genTrap(CompilationUnit *cUnit, int dOffset,
362 MipsLIR *branch = opNone(cUnit, kOpUncondBr);
363 return genCheckCommon(cUnit, dOffset, branch, pcrLabel);
367 static void genIGetWide(CompilationUnit *cUnit, MIR *mir, int fieldOffset)
369 RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 0);
370 RegLocation rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
372 rlObj = loadValue(cUnit, rlObj, kCoreReg);
373 int regPtr = dvmCompilerAllocTemp(cUnit);
377 genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
379 opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
380 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
383 loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg);
386 dvmCompilerFreeTemp(cUnit, regPtr);
387 storeValueWide(cUnit, rlDest, rlResult);
391 static void genIPutWide(CompilationUnit *cUnit, MIR *mir, int fieldOffset)
393 RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
394 RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 2);
395 rlObj = loadValue(cUnit, rlObj, kCoreReg);
397 rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
398 genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
400 regPtr = dvmCompilerAllocTemp(cUnit);
401 opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
404 storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
407 dvmCompilerFreeTemp(cUnit, regPtr);
414 static void genIGet(CompilationUnit *cUnit, MIR *mir, OpSize size,
419 RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 0);
420 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
421 rlObj = loadValue(cUnit, rlObj, kCoreReg);
422 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, regClass, true);
423 genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
427 loadBaseDisp(cUnit, mir, rlObj.lowReg, fieldOffset, rlResult.lowReg,
431 dvmCompilerGenMemBarrier(cUnit, 0);
434 storeValue(cUnit, rlDest, rlResult);
441 static void genIPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
445 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
446 RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 1);
447 rlObj = loadValue(cUnit, rlObj, kCoreReg);
448 rlSrc = loadValue(cUnit, rlSrc, regClass);
449 genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
453 dvmCompilerGenMemBarrier(cUnit, 0);
456 storeBaseDisp(cUnit, rlObj.lowReg, fieldOffset, rlSrc.lowReg, size);
459 dvmCompilerGenMemBarrier(cUnit, 0);
463 markCard(cUnit, rlSrc.lowReg, rlObj.lowReg);
471 static void genArrayGet(CompilationUnit *cUnit, MIR *mir, OpSize size,
479 rlArray = loadValue(cUnit, rlArray, kCoreReg);
480 rlIndex = loadValue(cUnit, rlIndex, kCoreReg);
487 pcrLabel = genNullCheck(cUnit, rlArray.sRegLow,
491 regPtr = dvmCompilerAllocTemp(cUnit);
495 opRegRegImm(cUnit, kOpLsl, regPtr, rlIndex.lowReg, scale);
499 int regLen = dvmCompilerAllocTemp(cUnit);
501 loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen);
502 genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir->offset,
504 dvmCompilerFreeTemp(cUnit, regLen);
508 opRegReg(cUnit, kOpAdd, regPtr, rlArray.lowReg);
510 opRegRegReg(cUnit, kOpAdd, regPtr, rlArray.lowReg, rlIndex.lowReg);
513 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, regClass, true);
516 loadBaseDispWide(cUnit, mir, regPtr, dataOffset, rlResult.lowReg,
519 dvmCompilerFreeTemp(cUnit, regPtr);
520 storeValueWide(cUnit, rlDest, rlResult);
523 loadBaseDisp(cUnit, mir, regPtr, dataOffset, rlResult.lowReg,
526 dvmCompilerFreeTemp(cUnit, regPtr);
527 storeValue(cUnit, rlDest, rlResult);
535 static void genArrayPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
544 rlArray = loadValue(cUnit, rlArray, kCoreReg);
545 rlIndex = loadValue(cUnit, rlIndex, kCoreReg);
547 if (dvmCompilerIsTemp(cUnit, rlArray.lowReg)) {
548 dvmCompilerClobber(cUnit, rlArray.lowReg);
551 regPtr = dvmCompilerAllocTemp(cUnit);
552 genRegCopy(cUnit, regPtr, rlArray.lowReg);
559 pcrLabel = genNullCheck(cUnit, rlArray.sRegLow, rlArray.lowReg,
564 int tReg = dvmCompilerAllocTemp(cUnit);
566 opRegRegImm(cUnit, kOpLsl, tReg, rlIndex.lowReg, scale);
570 int regLen = dvmCompilerAllocTemp(cUnit);
573 loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen);
574 genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir->offset,
576 dvmCompilerFreeTemp(cUnit, regLen);
580 opRegReg(cUnit, kOpAdd, tReg, rlArray.lowReg);
582 opRegRegReg(cUnit, kOpAdd, tReg, rlArray.lowReg, rlIndex.lowReg);
587 rlSrc = loadValueWide(cUnit, rlSrc, regClass);
589 storeBaseDispWide(cUnit, tReg, dataOffset, rlSrc.lowReg, rlSrc.highReg)
591 dvmCompilerFreeTemp(cUnit, tReg);
592 dvmCompilerFreeTemp(cUnit, regPtr);
594 rlSrc = loadValue(cUnit, rlSrc, regClass);
596 storeBaseDisp(cUnit, tReg, dataOffset, rlSrc.lowReg, size);
597 dvmCompilerFreeTemp(cUnit, tReg);
607 static void genArrayObjectPut(CompilationUnit *cUnit, MIR *mir,
619 dvmCompilerFlushAllRegs(cUnit);
622 dvmCompilerLockTemp(cUnit, regPtr); // r_S0
623 dvmCompilerLockTemp(cUnit, regIndex); // r_S4
625 loadValueDirectFixed(cUnit, rlArray, regArray);
626 loadValueDirectFixed(cUnit, rlIndex, regIndex);
632 pcrLabel = genNullCheck(cUnit, rlArray.sRegLow, regArray,
638 loadWordDisp(cUnit, regArray, lenOffset, regLen);
640 opRegRegImm(cUnit, kOpAdd, regPtr, regArray, dataOffset);
641 genBoundsCheck(cUnit, regIndex, regLen, mir->offset,
645 opRegRegImm(cUnit, kOpAdd, regPtr, regArray, dataOffset);
649 loadValueDirectFixed(cUnit, rlSrc, r_A0);
650 LOAD_FUNC_ADDR(cUnit, r_T9, (int)dvmCanPutArrayElement);
653 MipsLIR *branchOver = opCompareBranch(cUnit, kMipsBeqz, r_A0, -1);
656 loadWordDisp(cUnit, regArray, offsetof(Object, clazz), r_A1);
657 loadWordDisp(cUnit, r_A0, offsetof(Object, clazz), r_A0);
658 opReg(cUnit, kOpBlx, r_T9);
659 newLIR3(cUnit, kMipsLw, r_GP, STACK_OFFSET_GP, r_SP);
660 dvmCompilerClobberCallRegs(cUnit);
667 dvmCompilerLockTemp(cUnit, r_A0);
668 dvmCompilerLockTemp(cUnit, r_A1);
671 genRegImmCheck(cUnit, kMipsCondEq, r_V0, 0, mir->offset, pcrLabel);
674 loadValueDirectFixed(cUnit, rlSrc, r_A0);
675 loadValueDirectFixed(cUnit, rlArray, r_A1);
677 MipsLIR *target = newLIR0(cUnit, kMipsPseudoTargetLabel);
682 storeBaseIndexed(cUnit, regPtr, regIndex, r_A0,
686 dvmCompilerFreeTemp(cUnit, regPtr);
687 dvmCompilerFreeTemp(cUnit, regIndex);
690 markCard(cUnit, r_A0, r_A1);
693 static bool genShiftOpLong(CompilationUnit *cUnit, MIR *mir,
703 loadValueDirectWideFixed(cUnit, rlSrc1, r_ARG0, r_ARG1);
704 loadValueDirect(cUnit, rlShift, r_A2);
708 genDispatchToHandler(cUnit, TEMPLATE_SHL_LONG);
712 genDispatchToHandler(cUnit, TEMPLATE_SHR_LONG);
716 genDispatchToHandler(cUnit, TEMPLATE_USHR_LONG);
721 rlResult = dvmCompilerGetReturnWide(cUnit);
722 storeValueWide(cUnit, rlDest, rlResult);
726 static bool genArithOpLong(CompilationUnit *cUnit, MIR *mir,
739 rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
740 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
741 opRegReg(cUnit, kOpMvn, rlResult.lowReg, rlSrc2.lowReg);
742 opRegReg(cUnit, kOpMvn, rlResult.highReg, rlSrc2.highReg);
743 storeValueWide(cUnit, rlDest, rlResult);
758 genMulLong(cUnit, rlDest, rlSrc1, rlSrc2);
788 int tReg = dvmCompilerAllocTemp(cUnit);
789 rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
790 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
791 newLIR3(cUnit, kMipsSubu, rlResult.lowReg, r_ZERO, rlSrc2.lowReg);
792 newLIR3(cUnit, kMipsSubu, tReg, r_ZERO, rlSrc2.highReg);
793 newLIR3(cUnit, kMipsSltu, rlResult.highReg, r_ZERO, rlResult.lowReg);
794 newLIR3(cUnit, kMipsSubu, rlResult.highReg, tReg, rlResult.highReg);
795 dvmCompilerFreeTemp(cUnit, tReg);
796 storeValueWide(cUnit, rlDest, rlResult);
802 dvmCompilerAbort(cUnit);
805 genLong3Addr(cUnit, mir, firstOp, secondOp, rlDest, rlSrc1, rlSrc2);
807 dvmCompilerFlushAllRegs(cUnit); /* Send everything to home location */
808 loadValueDirectWideFixed(cUnit, rlSrc2, r_ARG2, r_ARG3);
809 loadValueDirectWideFixed(cUnit, rlSrc1, r_ARG0, r_ARG1);
810 LOAD_FUNC_ADDR(cUnit, r_T9, (int) callTgt);
813 opRegRegReg(cUnit, kOpOr, tReg, r_ARG2, r_ARG3);
814 genRegImmCheck(cUnit, kMipsCondEq, tReg, 0, mir->offset, NULL);
816 opReg(cUnit, kOpBlx, r_T9);
817 newLIR3(cUnit, kMipsLw, r_GP, STACK_OFFSET_GP, r_SP);
818 dvmCompilerClobberCallRegs(cUnit);
819 rlResult = dvmCompilerGetReturnWide(cUnit);
820 storeValueWide(cUnit, rlDest, rlResult);
822 cUnit->usesLinkRegister = true;
828 static bool genArithOpInt(CompilationUnit *cUnit, MIR *mir,
906 dvmCompilerAbort(cUnit);
909 rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
911 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
912 opRegReg(cUnit, op, rlResult.lowReg,
915 rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
917 genNullCheck(cUnit, rlSrc2.sRegLow, rlSrc2.lowReg, mir->offset, NULL);
919 newLIR4(cUnit, kMipsDiv, r_HI, r_LO, rlSrc1.lowReg, rlSrc2.lowReg);
920 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
921 newLIR2(cUnit, opc, rlResult.lowReg, divReg);
923 rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
925 int tReg = dvmCompilerAllocTemp(cUnit);
926 opRegRegImm(cUnit, kOpAnd, tReg, rlSrc2.lowReg, 31);
927 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
928 opRegRegReg(cUnit, op, rlResult.lowReg,
930 dvmCompilerFreeTemp(cUnit, tReg);
932 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
933 opRegRegReg(cUnit, op, rlResult.lowReg,
937 storeValue(cUnit, rlDest, rlResult);
942 static bool genArithOp(CompilationUnit *cUnit, MIR *mir)
950 rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 0);
951 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 1);
953 rlSrc1 = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
954 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 2);
956 rlSrc1 = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
957 rlSrc2 = dvmCompilerGetSrcWide(cUnit, mir, 2, 3);
961 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
964 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
968 return genArithOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
971 return genArithOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
974 return genShiftOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
977 return genShiftOpLong(cUnit,mir, rlDest, rlSrc1, rlSrc2);
980 return genArithOpInt(cUnit,mir, rlDest, rlSrc1, rlSrc2);
983 return genArithOpInt(cUnit,mir, rlDest, rlSrc1, rlSrc2);
986 return genArithOpFloat(cUnit,mir, rlDest, rlSrc1, rlSrc2);
989 return genArithOpFloat(cUnit, mir, rlDest, rlSrc1, rlSrc2);
992 return genArithOpDouble(cUnit,mir, rlDest, rlSrc1, rlSrc2);
995 return genArithOpDouble(cUnit,mir, rlDest, rlSrc1, rlSrc2);
1001 static MipsLIR *genUnconditionalBranch(CompilationUnit *cUnit, MipsLIR *target)
1003 MipsLIR *branch = opNone(cUnit, kOpUncondBr);
1009 void genReturnCommon(CompilationUnit *cUnit, MIR *mir)
1011 genDispatchToHandler(cUnit, gDvmJit.methodTraceSupport ?
1016 int dPC = (int) (cUnit->method->insns + mir->offset);
1018 MipsLIR *branch = genUnconditionalBranch(cUnit, NULL);
1025 dvmInsertGrowableList(&cUnit->pcReconstructionList, (intptr_t) pcrLabel);
1030 static void genProcessArgsNoRange(CompilationUnit *cUnit, MIR *mir,
1044 dvmCompilerLockAllTemps(cUnit);
1047 rlArg = dvmCompilerGetSrc(cUnit, mir, numDone++);
1048 loadValueDirectFixed(cUnit, rlArg, i+r_A0); /* r_A0 thru r_T0 */
1052 opRegRegImm(cUnit, kOpSub, r_S4, rFP,
1056 *pcrLabel = genNullCheck(cUnit, dvmCompilerSSASrc(mir, 0), r_A0,
1059 storeMultiple(cUnit, r_S4, regMask);
1063 static void genProcessArgsRange(CompilationUnit *cUnit, MIR *mir,
1078 dvmCompilerLockAllTemps(cUnit);
1084 opRegRegImm(cUnit, kOpAdd, r4PC, rFP, srcOffset);
1091 if (numArgs != 0) loadMultiple(cUnit, r4PC, regMask);
1093 opRegRegImm(cUnit, kOpSub, r_S4, rFP,
1097 *pcrLabel = genNullCheck(cUnit, dvmCompilerSSASrc(mir, 0), r_A0,
1112 newLIR2(cUnit, kMipsMove, r_T0, r_A0);
1113 newLIR2(cUnit, kMipsMove, r_T1, r_S1);
1117 loadConstant(cUnit, rFP, ((numArgs - 4) >> 2) << 2);
1118 loopLabel = newLIR0(cUnit, kMipsPseudoTargetLabel);
1121 storeMultiple(cUnit, r_S4, regMask);
1126 loadMultiple(cUnit, r4PC, regMask);
1129 opRegImm(cUnit, kOpSub, rFP, 4);
1130 genConditionalBranchMips(cUnit, kMipsBne, rFP, r_ZERO, loopLabel);
1135 if (numArgs != 0) storeMultiple(cUnit, r_S4, regMask);
1144 loadMultiple(cUnit, r4PC, regMask);
1147 newLIR2(cUnit, kMipsMove, r_A0, r_T0);
1148 newLIR2(cUnit, kMipsMove, r_S1, r_T1);
1153 storeMultiple(cUnit, r_S4, regMask);
1161 static void genInvokeSingletonCommon(CompilationUnit *cUnit, MIR *mir,
1171 dvmCompilerLockAllTemps(cUnit);
1175 dvmCompilerLockTemp(cUnit, r_A1);
1176 MipsLIR *addrRetChain = newLIR2(cUnit, kMipsLahi, r_A1, 0);
1178 addrRetChain = newLIR3(cUnit, kMipsLalo, r_A1, r_A1, 0);
1182 loadConstant(cUnit, r4PC,
1183 (int) (cUnit->method->insns + mir->offset));
1190 genDispatchToHandler(cUnit, gDvmJit.methodTraceSupport ?
1197 genDispatchToHandler(cUnit, gDvmJit.methodTraceSupport ?
1204 genUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
1207 genTrap(cUnit, mir->offset, pcrLabel);
1241 static void genInvokeVirtualCommon(CompilationUnit *cUnit, MIR *mir,
1253 dvmCompilerLockAllTemps(cUnit);
1264 loadConstant(cUnit, r4PC,
1265 (int) (cUnit->method->insns + mir->offset));
1268 MipsLIR *addrRetChain = newLIR2(cUnit, kMipsLahi, r_A1, 0);
1270 addrRetChain = newLIR3(cUnit, kMipsLalo, r_A1, r_A1, 0);
1274 MipsLIR *predictedChainingCell = newLIR2(cUnit, kMipsLahi, r_A2, 0);
1276 predictedChainingCell = newLIR3(cUnit, kMipsLalo, r_A2, r_A2, 0);
1279 genDispatchToHandler(cUnit, gDvmJit.methodTraceSupport ?
1284 genUnconditionalBranch(cUnit, predChainingCell);
1291 int dPC = (int) (cUnit->method->insns + mir->offset);
1297 dvmInsertGrowableList(&cUnit->pcReconstructionList,
1302 genUnconditionalBranch(cUnit, pcrLabel);
1314 loadWordDisp(cUnit, r_S4, methodIndex * 4, r_A0);
1317 MipsLIR *bypassRechaining = opCompareBranch(cUnit, kMipsBgtz, r_A1, -1);
1319 LOAD_FUNC_ADDR(cUnit, r_T9, (int) dvmJitToPatchPredictedChain);
1321 genRegCopy(cUnit, r_A1, rSELF);
1332 opReg(cUnit, kOpBlx, r_T9);
1333 newLIR3(cUnit, kMipsLw, r_GP, STACK_OFFSET_GP, r_SP);
1334 newLIR2(cUnit, kMipsMove, r_A0, r_V0);
1337 addrRetChain = newLIR2(cUnit, kMipsLahi, r_A1, 0);
1340 addrRetChain = newLIR3(cUnit, kMipsLalo, r_A1, r_A1, 0);
1348 genDispatchToHandler(cUnit, gDvmJit.methodTraceSupport ?
1355 genTrap(cUnit, mir->offset, pcrLabel);
1359 static void genInvokeVirtualWholeMethod(CompilationUnit *cUnit,
1365 dvmCompilerLockAllTemps(cUnit);
1367 loadClassPointer(cUnit, r_A1, (int) callsiteInfo);
1369 loadWordDisp(cUnit, r_A0, offsetof(Object, clazz), r_A2);
1375 cUnit, kMipsBne, r_A1, r_A2);
1378 loadConstant(cUnit, r_A0, (int) (cUnit->method->insns + mir->offset));
1380 newLIR1(cUnit, kMipsJal, (int) calleeAddr);
1381 genUnconditionalBranch(cUnit, retChainingCell);
1384 MipsLIR *slowPathLabel = newLIR0(cUnit, kMipsPseudoTargetLabel);
1390 cUnit->printMe = true;
1393 static void genInvokeSingletonWholeMethod(CompilationUnit *cUnit,
1399 loadConstant(cUnit, r_A0, (int) (cUnit->method->insns + mir->offset));
1401 newLIR1(cUnit, kMipsJal, (int) calleeAddr);
1402 genUnconditionalBranch(cUnit, retChainingCell);
1405 cUnit->printMe = true;
1409 static void genPuntToInterp(CompilationUnit *cUnit, unsigned int offset)
1412 dvmCompilerFlushAllRegs(cUnit);
1413 loadConstant(cUnit, r_A0, (int) (cUnit->method->insns + offset));
1417 loadWordDisp(cUnit, r_A0, offsetof(Object, clazz), r_A3);
1419 loadWordDisp(cUnit, rSELF, offsetof(Thread,
1422 opReg(cUnit, kOpBlx, r_A1);
1429 static void genInterpSingleStep(CompilationUnit *cUnit, MIR *mir)
1435 if (cUnit->jitMode == kJitLoop) {
1436 cUnit->quitLoopMode = true;
1445 dvmCompilerFlushAllRegs(cUnit);
1448 genPuntToInterp(cUnit, mir->offset);
1453 loadWordDisp(cUnit, rSELF, entryAddr, r_A2);
1455 loadConstant(cUnit, r_A0, (int) (cUnit->method->insns + mir->offset));
1457 loadConstant(cUnit, r_A1, (int) (cUnit->method->insns + mir->next->offset));
1458 opReg(cUnit, kOpBlx, r_A2);
1472 static void genMonitorPortable(CompilationUnit *cUnit, MIR *mir)
1475 genExportPC(cUnit, mir);
1476 dvmCompilerFlushAllRegs(cUnit); /* Send everything to home location */
1477 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
1478 loadValueDirectFixed(cUnit, rlSrc, r_A1);
1479 genRegCopy(cUnit, r_A0, rSELF);
1480 genNullCheck(cUnit, rlSrc.sRegLow, r_A1, mir->offset, NULL);
1483 loadConstant(cUnit, r4PC, (int)(cUnit->method->insns + mir->offset +
1485 genDispatchToHandler(cUnit, TEMPLATE_MONITOR_ENTER);
1487 LOAD_FUNC_ADDR(cUnit, r_T9, (int)dvmUnlockObject);
1489 opReg(cUnit, kOpBlx, r_T9);
1490 newLIR3(cUnit, kMipsLw, r_GP, STACK_OFFSET_GP, r_SP);
1492 MipsLIR *branchOver = opCompareBranch(cUnit, kMipsBne, r_V0, r_ZERO);
1493 loadConstant(cUnit, r_A0,
1494 (int) (cUnit->method->insns + mir->offset +
1496 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
1497 MipsLIR *target = newLIR0(cUnit, kMipsPseudoTargetLabel);
1500 dvmCompilerClobberCallRegs(cUnit);
1509 static void genSuspendPoll(CompilationUnit *cUnit, MIR *mir)
1511 int rTemp = dvmCompilerAllocTemp(cUnit);
1513 ld = loadBaseDisp(cUnit, NULL, rSELF,
1517 genRegImmCheck(cUnit, kMipsCondNe, rTemp, 0, mir->offset, NULL);
1526 static bool handleFmt10t_Fmt20t_Fmt30t(CompilationUnit *cUnit, MIR *mir,
1533 (gDvmJit.genSuspendPoll || cUnit->jitMode == kJitLoop)) {
1534 genSuspendPoll(cUnit, mir);
1544 cUnit->nextCodegenBlock = bb->taken;
1547 genUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
1552 static bool handleFmt10x(CompilationUnit *cUnit, MIR *mir)
1561 dvmCompilerGenMemBarrier(cUnit, 0);
1564 genReturnCommon(cUnit,mir);
1580 static bool handleFmt11n_Fmt31i(CompilationUnit *cUnit, MIR *mir)
1585 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
1587 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1593 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
1594 loadConstantNoClobber(cUnit, rlResult.lowReg, mir->dalvikInsn.vB);
1595 storeValue(cUnit, rlDest, rlResult);
1601 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
1602 loadConstantNoClobber(cUnit, rlResult.lowReg, mir->dalvikInsn.vB);
1603 opRegRegImm(cUnit, kOpAsr, rlResult.highReg,
1605 storeValueWide(cUnit, rlDest, rlResult);
1614 static bool handleFmt21h(CompilationUnit *cUnit, MIR *mir)
1619 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
1621 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1623 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
1627 loadConstantNoClobber(cUnit, rlResult.lowReg,
1629 storeValue(cUnit, rlDest, rlResult);
1633 loadConstantValueWide(cUnit, rlResult.lowReg, rlResult.highReg,
1635 storeValueWide(cUnit, rlDest, rlResult);
1644 static bool handleFmt20bc(CompilationUnit *cUnit, MIR *mir)
1647 genInterpSingleStep(cUnit, mir);
1651 static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
1661 (cUnit->method->clazz->pDvmDex->pResStrings[mir->dalvikInsn.vB]);
1669 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1670 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
1671 loadConstantNoClobber(cUnit, rlResult.lowReg, (int) strPtr );
1672 storeValue(cUnit, rlDest, rlResult);
1677 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
1685 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1686 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
1687 loadConstantNoClobber(cUnit, rlResult.lowReg, (int) classPtr );
1688 storeValue(cUnit, rlDest, rlResult);
1700 int tReg = dvmCompilerAllocTemp(cUnit);
1703 mir->meta.calleeMethod : cUnit->method;
1730 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1731 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
1732 loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
1735 dvmCompilerGenMemBarrier(cUnit, 0);
1738 loadWordDisp(cUnit, tReg, 0, rlResult.lowReg);
1741 storeValue(cUnit, rlDest, rlResult);
1747 mir->meta.calleeMethod : cUnit->method;
1757 int tReg = dvmCompilerAllocTemp(cUnit);
1758 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
1759 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
1760 loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
1763 loadPair(cUnit, tReg, rlResult.lowReg, rlResult.highReg);
1766 storeValueWide(cUnit, rlDest, rlResult);
1778 int tReg = dvmCompilerAllocTemp(cUnit);
1783 mir->meta.calleeMethod : cUnit->method;
1805 rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
1806 rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
1807 loadConstant(cUnit, tReg, (int) fieldPtr);
1809 objHead = dvmCompilerAllocTemp(cUnit);
1810 loadWordDisp(cUnit, tReg, OFFSETOF_MEMBER(Field, clazz), objHead);
1813 dvmCompilerGenMemBarrier(cUnit, 0);
1816 storeWordDisp(cUnit, tReg, valOffset ,rlSrc.lowReg);
1817 dvmCompilerFreeTemp(cUnit, tReg);
1820 dvmCompilerGenMemBarrier(cUnit, 0);
1824 markCard(cUnit, rlSrc.lowReg, objHead);
1825 dvmCompilerFreeTemp(cUnit, objHead);
1831 int tReg = dvmCompilerAllocTemp(cUnit);
1834 mir->meta.calleeMethod : cUnit->method;
1844 rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
1845 rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
1846 loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
1849 storePair(cUnit, tReg, rlSrc.lowReg, rlSrc.highReg);
1859 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
1872 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
1873 genExportPC(cUnit, mir);
1874 LOAD_FUNC_ADDR(cUnit, r_T9, (int)dvmAllocObject);
1875 loadConstant(cUnit, r_A0, (int) classPtr);
1876 loadConstant(cUnit, r_A1, ALLOC_DONT_TRACK);
1877 opReg(cUnit, kOpBlx, r_T9);
1878 newLIR3(cUnit, kMipsLw, r_GP, STACK_OFFSET_GP, r_SP);
1879 dvmCompilerClobberCallRegs(cUnit);
1881 MipsLIR *branchOver = opCompareBranch(cUnit, kMipsBne, r_V0, r_ZERO);
1886 loadConstant(cUnit, r_A0,
1887 (int) (cUnit->method->insns + mir->offset));
1888 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
1891 MipsLIR *target = newLIR0(cUnit, kMipsPseudoTargetLabel);
1894 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1895 rlResult = dvmCompilerGetReturn(cUnit);
1896 storeValue(cUnit, rlDest, rlResult);
1905 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
1917 genInterpSingleStep(cUnit, mir);
1920 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
1921 loadConstant(cUnit, r_A1, (int) classPtr );
1922 rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
1923 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
1924 MipsLIR *branch1 = opCompareBranch(cUnit, kMipsBeqz, rlSrc.lowReg, -1);
1932 loadWordDisp(cUnit, rlSrc.lowReg, offsetof(Object, clazz), r_A0);
1933 LOAD_FUNC_ADDR(cUnit, r_T9, (int)dvmInstanceofNonTrivial);
1934 MipsLIR *branch2 = opCompareBranch(cUnit, kMipsBeq, r_A0, r_A1);
1935 opReg(cUnit, kOpBlx, r_T9);
1936 newLIR3(cUnit, kMipsLw, r_GP, STACK_OFFSET_GP, r_SP);
1937 dvmCompilerClobberCallRegs(cUnit);
1943 genRegCopy(cUnit, r_A0, r_V0);
1944 genZeroCheck(cUnit, r_V0, mir->offset, NULL);
1946 MipsLIR *target = newLIR0(cUnit, kMipsPseudoTargetLabel);
1954 genInterpSingleStep(cUnit, mir);
1962 static bool handleFmt11x(CompilationUnit *cUnit, MIR *mir)
1969 int resetReg = dvmCompilerAllocTemp(cUnit);
1970 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1971 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
1972 loadWordDisp(cUnit, rSELF, exOffset, rlResult.lowReg);
1973 loadConstant(cUnit, resetReg, 0);
1974 storeWordDisp(cUnit, rSELF, exOffset, resetReg);
1975 storeValue(cUnit, rlDest, rlResult);
1983 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
1986 storeValue(cUnit, rlDest, rlSrc);
1993 RegLocation rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
1996 storeValueWide(cUnit, rlDest, rlSrc);
2000 RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
2003 storeValueWide(cUnit, rlDest, rlSrc);
2004 genReturnCommon(cUnit,mir);
2009 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2012 storeValue(cUnit, rlDest, rlSrc);
2013 genReturnCommon(cUnit, mir);
2018 genMonitor(cUnit, mir);
2021 genInterpSingleStep(cUnit, mir);
2029 static bool handleFmt12x(CompilationUnit *cUnit, MIR *mir)
2037 return genArithOp( cUnit, mir );
2041 rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
2043 rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2045 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
2047 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
2060 return genConversion(cUnit, mir);
2063 return genArithOpInt(cUnit, mir, rlDest, rlSrc, rlSrc);
2066 return genArithOpLong(cUnit, mir, rlDest, rlSrc, rlSrc);
2068 return genArithOpFloat(cUnit, mir, rlDest, rlSrc, rlSrc);
2070 return genArithOpDouble(cUnit, mir, rlDest, rlSrc, rlSrc);
2072 storeValueWide(cUnit, rlDest, rlSrc);
2075 rlSrc = dvmCompilerUpdateLoc(cUnit, rlSrc);
2076 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
2079 genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
2081 loadValueDirect(cUnit, rlSrc, rlResult.lowReg);
2083 opRegRegImm(cUnit, kOpAsr, rlResult.highReg,
2085 storeValueWide(cUnit, rlDest, rlResult);
2088 rlSrc = dvmCompilerUpdateLocWide(cUnit, rlSrc);
2089 rlSrc = dvmCompilerWideToNarrow(cUnit, rlSrc);
2093 storeValue(cUnit, rlDest, rlSrc);
2096 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
2097 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
2098 opRegReg(cUnit, kOp2Byte, rlResult.lowReg, rlSrc.lowReg);
2099 storeValue(cUnit, rlDest, rlResult);
2102 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
2103 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
2104 opRegReg(cUnit, kOp2Short, rlResult.lowReg, rlSrc.lowReg);
2105 storeValue(cUnit, rlDest, rlResult);
2108 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
2109 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
2110 opRegReg(cUnit, kOp2Char, rlResult.lowReg, rlSrc.lowReg);
2111 storeValue(cUnit, rlDest, rlResult);
2115 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
2116 genNullCheck(cUnit, rlSrc.sRegLow, rlSrc.lowReg,
2118 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
2119 loadWordDisp(cUnit, rlSrc.lowReg, lenOffset,
2121 storeValue(cUnit, rlDest, rlResult);
2130 static bool handleFmt21s(CompilationUnit *cUnit, MIR *mir)
2137 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
2138 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
2139 loadConstantNoClobber(cUnit, rlResult.lowReg, BBBB);
2141 opRegRegImm(cUnit, kOpAsr, rlResult.highReg, rlResult.lowReg, 31);
2142 storeValueWide(cUnit, rlDest, rlResult);
2144 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
2145 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
2146 loadConstantNoClobber(cUnit, rlResult.lowReg, BBBB);
2147 storeValue(cUnit, rlDest, rlResult);
2154 static bool handleFmt21t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
2164 (gDvmJit.genSuspendPoll || cUnit->jitMode == kJitLoop)) {
2165 genSuspendPoll(cUnit, mir);
2168 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2169 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
2193 dvmCompilerAbort(cUnit);
2195 genConditionalBranchMips(cUnit, opc, rlSrc.lowReg, rt, &labelList[bb->taken->id]);
2197 genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
2227 // Returns true if it added instructions to 'cUnit' to divide 'rlSrc' by 'lit'
2229 static bool handleEasyDivide(CompilationUnit *cUnit, Opcode dalvikOpcode,
2241 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
2242 RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
2244 int tReg = dvmCompilerAllocTemp(cUnit);
2247 opRegRegImm(cUnit, kOpLsr, tReg, rlSrc.lowReg, 32 - k);
2248 opRegRegReg(cUnit, kOpAdd, tReg, tReg, rlSrc.lowReg);
2249 opRegRegImm(cUnit, kOpAsr, rlResult.lowReg, tReg, k);
2251 opRegRegImm(cUnit, kOpAsr, tReg, rlSrc.lowReg, 31);
2252 cUnit, kOpLsr, tReg, tReg, 32 - k);
2253 opRegRegReg(cUnit, kOpAdd, tReg, tReg, rlSrc.lowReg);
2254 opRegRegImm(cUnit, kOpAsr, rlResult.lowReg, tReg, k);
2257 int cReg = dvmCompilerAllocTemp(cUnit);
2258 loadConstant(cUnit, cReg, lit - 1);
2259 int tReg1 = dvmCompilerAllocTemp(cUnit);
2260 int tReg2 = dvmCompilerAllocTemp(cUnit);
2262 opRegRegImm(cUnit, kOpLsr, tReg1, rlSrc.lowReg, 32 - k);
2263 opRegRegReg(cUnit, kOpAdd, tReg2, tReg1, rlSrc.lowReg);
2264 opRegRegReg(cUnit, kOpAnd, tReg2, tReg2, cReg);
2265 opRegRegReg(cUnit, kOpSub, rlResult.lowReg, tReg2, tReg1);
2267 opRegRegImm(cUnit, kOpAsr, tReg1, rlSrc.lowReg, 31);
2268 opRegRegImm(cUnit, kOpLsr, tReg1, tReg1, 32 - k);
2269 opRegRegReg(cUnit, kOpAdd, tReg2, tReg1, rlSrc.lowReg);
2270 opRegRegReg(cUnit, kOpAnd, tReg2, tReg2, cReg);
2271 opRegRegReg(cUnit, kOpSub, rlResult.lowReg, tReg2, tReg1);
2274 storeValue(cUnit, rlDest, rlResult);
2278 // Returns true if it added instructions to 'cUnit' to multiply 'rlSrc' by 'lit'
2280 static bool handleEasyMultiply(CompilationUnit *cUnit,
2299 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
2300 RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
2303 opRegRegImm(cUnit, kOpLsl, rlResult.lowReg, rlSrc.lowReg,
2309 genMultiplyByTwoBitMultiplier(cUnit, rlSrc, rlResult, lit,
2315 int tReg = dvmCompilerAllocTemp(cUnit);
2316 opRegRegImm(cUnit, kOpLsl, tReg, rlSrc.lowReg, lowestSetBit(lit + 1));
2317 opRegRegReg(cUnit, kOpSub, rlResult.lowReg, tReg, rlSrc.lowReg);
2319 storeValue(cUnit, rlDest, rlResult);
2323 static bool handleFmt22b_Fmt22s(CompilationUnit *cUnit, MIR *mir)
2326 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2327 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
2338 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
2339 tReg = dvmCompilerAllocTemp(cUnit);
2340 loadConstant(cUnit, tReg, lit);
2341 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
2342 opRegRegReg(cUnit, kOpSub, rlResult.lowReg,
2344 storeValue(cUnit, rlDest, rlResult);
2355 if (handleEasyMultiply(cUnit, rlSrc, rlDest, lit)) {
2395 genInterpSingleStep(cUnit, mir);
2398 if (handleEasyDivide(cUnit, dalvikOpcode, rlSrc, rlDest, lit)) {
2414 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
2415 int tReg = dvmCompilerAllocTemp(cUnit);
2416 newLIR3(cUnit, kMipsAddiu, tReg, r_ZERO, lit);
2417 newLIR4(cUnit, kMipsDiv, r_HI, r_LO, rlSrc.lowReg, tReg);
2418 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
2419 newLIR2(cUnit, opc, rlResult.lowReg, divReg);
2420 dvmCompilerFreeTemp(cUnit, tReg);
2421 storeValue(cUnit, rlDest, rlResult);
2428 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
2429 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
2432 genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
2434 opRegRegImm(cUnit, op, rlResult.lowReg, rlSrc.lowReg, lit);
2436 storeValue(cUnit, rlDest, rlResult);
2440 static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir)
2475 mir->meta.calleeMethod : cUnit->method;
2501 genInterpSingleStep(cUnit, mir);
2505 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2506 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
2509 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vC]);
2517 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
2518 genExportPC(cUnit, mir);
2519 loadValueDirectFixed(cUnit, rlSrc, r_A1); /* Len */
2520 loadConstant(cUnit, r_A0, (int) classPtr );
2521 LOAD_FUNC_ADDR(cUnit, r_T9, (int)dvmAllocArrayByClass);
2526 genRegImmCheck(cUnit, kMipsCondMi, r_A1, 0, mir->offset, NULL);
2527 loadConstant(cUnit, r_A2, ALLOC_DONT_TRACK);
2528 opReg(cUnit, kOpBlx, r_T9);
2529 newLIR3(cUnit, kMipsLw, r_GP, STACK_OFFSET_GP, r_SP);
2530 dvmCompilerClobberCallRegs(cUnit);
2532 MipsLIR *branchOver = opCompareBranch(cUnit, kMipsBne, r_V0, r_ZERO);
2536 loadConstant(cUnit, r_A0,
2537 (int) (cUnit->method->insns + mir->offset));
2538 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
2541 MipsLIR *target = newLIR0(cUnit, kMipsPseudoTargetLabel);
2544 rlResult = dvmCompilerGetReturn(cUnit);
2545 storeValue(cUnit, rlDest, rlResult);
2550 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2551 RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
2554 (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vC]);
2566 genInterpSingleStep(cUnit, mir);
2569 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
2570 loadValueDirectFixed(cUnit, rlSrc, r_V0); /* Ref */
2571 loadConstant(cUnit, r_A2, (int) classPtr );
2573 MipsLIR *branch1 = opCompareBranch(cUnit, kMipsBeqz, r_V0, -1);
2575 loadWordDisp(cUnit, r_V0, offsetof(Object, clazz), r_A1);
2577 LOAD_FUNC_ADDR(cUnit, r_T9, (int)dvmInstanceofNonTrivial);
2578 loadConstant(cUnit, r_V0, 1); /* Assume true */
2579 MipsLIR *branch2 = opCompareBranch(cUnit, kMipsBeq, r_A1, r_A2);
2580 genRegCopy(cUnit, r_A0, r_A1);
2581 genRegCopy(cUnit, r_A1, r_A2);
2582 opReg(cUnit, kOpBlx, r_T9);
2583 newLIR3(cUnit, kMipsLw, r_GP, STACK_OFFSET_GP, r_SP);
2584 dvmCompilerClobberCallRegs(cUnit);
2586 MipsLIR *target = newLIR0(cUnit, kMipsPseudoTargetLabel);
2588 rlResult = dvmCompilerGetReturn(cUnit);
2589 storeValue(cUnit, rlDest, rlResult);
2595 genIGetWide(cUnit, mir, fieldOffset);
2605 genIGet(cUnit, mir, kWord, fieldOffset, isVolatile);
2608 genIPutWide(cUnit, mir, fieldOffset);
2616 genIPut(cUnit, mir, kWord, fieldOffset, false, isVolatile);
2620 genIPut(cUnit, mir, kWord, fieldOffset, true, isVolatile);
2624 genInterpSingleStep(cUnit, mir);
2632 static bool handleFmt22cs(CompilationUnit *cUnit, MIR *mir)
2639 genIGet(cUnit, mir, kWord, fieldOffset, false);
2642 genIPut(cUnit, mir, kWord, fieldOffset, false, false);
2645 genIPut(cUnit, mir, kWord, fieldOffset, true, false);
2648 genIGetWide(cUnit, mir, fieldOffset);
2651 genIPutWide(cUnit, mir, fieldOffset);
2661 static bool handleFmt22t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
2672 (gDvmJit.genSuspendPoll || cUnit->jitMode == kJitLoop)) {
2673 genSuspendPoll(cUnit, mir);
2676 RegLocation rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 0);
2677 RegLocation rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 1);
2678 rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
2679 rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
2693 tReg = dvmCompilerAllocTemp(cUnit);
2694 test = newLIR3(cUnit, kMipsSlt, tReg, reg1, reg2);
2700 tReg = dvmCompilerAllocTemp(cUnit);
2701 test = newLIR3(cUnit, kMipsSlt, tReg, reg2, reg1);
2707 tReg = dvmCompilerAllocTemp(cUnit);
2708 test = newLIR3(cUnit, kMipsSlt, tReg, reg2, reg1);
2714 tReg = dvmCompilerAllocTemp(cUnit);
2715 test = newLIR3(cUnit, kMipsSlt, tReg, reg1, reg2);
2722 dvmCompilerAbort(cUnit);
2725 genConditionalBranchMips(cUnit, opc, reg1, reg2, &labelList[bb->taken->id]);
2727 genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
2731 static bool handleFmt22x_Fmt32x(CompilationUnit *cUnit, MIR *mir)
2740 storeValue(cUnit, dvmCompilerGetDest(cUnit, mir, 0),
2741 dvmCompilerGetSrc(cUnit, mir, 0));
2746 storeValueWide(cUnit, dvmCompilerGetDestWide(cUnit, mir, 0, 1),
2747 dvmCompilerGetSrcWide(cUnit, mir, 0, 1));
2756 static bool handleFmt23x(CompilationUnit *cUnit, MIR *mir)
2764 return genArithOp( cUnit, mir );
2770 rlDest = dvmCompilerGetSrc(cUnit, mir, 0);
2771 rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 1);
2772 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 2);
2775 rlDest = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
2776 rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 2);
2777 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 3);
2782 rlSrc1 = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
2783 rlSrc2 = dvmCompilerGetSrcWide(cUnit, mir, 2, 3);
2786 rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 0);
2787 rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 1);
2790 rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
2793 rlDest = dvmCompilerGetDest(cUnit, mir, 0);
2802 return genCmpFP(cUnit, mir, rlDest, rlSrc1, rlSrc2);
2804 genCmpLong(cUnit, mir, rlDest, rlSrc1, rlSrc2);
2807 genArrayGet(cUnit, mir, kLong, rlSrc1, rlSrc2, rlDest, 3);
2811 genArrayGet(cUnit, mir, kWord, rlSrc1, rlSrc2, rlDest, 2);
2814 genArrayGet(cUnit, mir, kUnsignedByte, rlSrc1, rlSrc2, rlDest, 0);
2817 genArrayGet(cUnit, mir, kSignedByte, rlSrc1, rlSrc2, rlDest, 0);
2820 genArrayGet(cUnit, mir, kUnsignedHalf, rlSrc1, rlSrc2, rlDest, 1);
2823 genArrayGet(cUnit, mir, kSignedHalf, rlSrc1, rlSrc2, rlDest, 1);
2826 genArrayPut(cUnit, mir, kLong, rlSrc1, rlSrc2, rlDest, 3);
2829 genArrayPut(cUnit, mir, kWord, rlSrc1, rlSrc2, rlDest, 2);
2832 genArrayObjectPut(cUnit, mir, rlSrc1, rlSrc2, rlDest, 2);
2836 genArrayPut(cUnit, mir, kUnsignedHalf, rlSrc1, rlSrc2, rlDest, 1);
2840 genArrayPut(cUnit, mir, kUnsignedByte, rlSrc1, rlSrc2, rlDest, 0);
2990 static bool handleFmt31t(CompilationUnit *cUnit, MIR *mir)
2995 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2997 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
2998 genExportPC(cUnit, mir);
2999 loadValueDirectFixed(cUnit, rlSrc, r_A0);
3000 LOAD_FUNC_ADDR(cUnit, r_T9, (int)dvmInterpHandleFillArrayData);
3001 loadConstant(cUnit, r_A1,
3002 (int) (cUnit->method->insns + mir->offset + mir->dalvikInsn.vB));
3003 opReg(cUnit, kOpBlx, r_T9);
3004 newLIR3(cUnit, kMipsLw, r_GP, STACK_OFFSET_GP, r_SP);
3005 dvmCompilerClobberCallRegs(cUnit);
3007 MipsLIR *branchOver = opCompareBranch(cUnit, kMipsBne, r_V0, r_ZERO);
3008 loadConstant(cUnit, r_A0,
3009 (int) (cUnit->method->insns + mir->offset));
3010 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
3011 MipsLIR *target = newLIR0(cUnit, kMipsPseudoTargetLabel);
3023 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
3024 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
3025 loadValueDirectFixed(cUnit, rlSrc, r_A1);
3026 dvmCompilerLockAllTemps(cUnit);
3029 LOAD_FUNC_ADDR(cUnit, r_T9, (int)findPackedSwitchIndex);
3031 LOAD_FUNC_ADDR(cUnit, r_T9, (int)findSparseSwitchIndex);
3034 loadConstant(cUnit, r_A0,
3035 (int) (cUnit->method->insns + mir->offset + mir->dalvikInsn.vB));
3036 opReg(cUnit, kOpBlx, r_T9);
3037 newLIR3(cUnit, kMipsLw, r_GP, STACK_OFFSET_GP, r_SP);
3038 dvmCompilerClobberCallRegs(cUnit);
3040 newLIR3(cUnit, kMipsAddu, r_A0, r_RA, r_RESULT0);
3041 newLIR2(cUnit, kMipsMove, r_A1, r_RESULT1);
3042 newLIR1(cUnit, kMipsJr, r_A0);
3043 newLIR0(cUnit, kMipsNop); /* for maintaining 20 byte offset */
3057 static void genLandingPadForMispredictedCallee(CompilationUnit *cUnit, MIR *mir,
3069 genUnconditionalBranch(cUnit, &labelList[fallThrough->id]);
3072 dvmCompilerResetRegPool(cUnit);
3073 dvmCompilerClobberAllRegs(cUnit);
3074 dvmCompilerResetNullCheck(cUnit);
3077 MipsLIR *target = newLIR0(cUnit, kMipsPseudoTargetLabel);
3083 static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir,
3107 cUnit->method->clazz->pDvmDex->pResMethods[dInsn->vB]->
3116 genLandingPadForMispredictedCallee(cUnit, mir, bb, labelList);
3120 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
3122 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
3124 genInvokeVirtualCommon(cUnit, mir, methodIndex,
3138 assert(calleeMethod == cUnit->method->clazz->super->vtable[
3139 cUnit->method->clazz->pDvmDex->
3143 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
3145 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
3151 genInvokeSingletonWholeMethod(cUnit, mir, calleeAddr,
3155 loadConstant(cUnit, r_A0, (int) calleeMethod);
3157 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
3168 cUnit->method->clazz->pDvmDex->pResMethods[dInsn->vB]);
3171 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
3173 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
3176 loadConstant(cUnit, r_A0, (int) calleeMethod);
3178 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
3188 cUnit->method->clazz->pDvmDex->pResMethods[dInsn->vB]);
3191 genProcessArgsNoRange(cUnit, mir, dInsn,
3194 genProcessArgsRange(cUnit, mir, dInsn,
3201 genInvokeSingletonWholeMethod(cUnit, mir, calleeAddr,
3205 loadConstant(cUnit, r_A0, (int) calleeMethod);
3207 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
3324 genLandingPadForMispredictedCallee(cUnit, mir, bb, labelList);
3328 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
3330 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
3335 loadConstant(cUnit, r4PC,
3336 (int) (cUnit->method->insns + mir->offset));
3339 MipsLIR *addrRetChain = newLIR2(cUnit, kMipsLahi, r_A1, 0);
3341 addrRetChain = newLIR3(cUnit, kMipsLalo, r_A1, r_A1, 0);
3346 MipsLIR *predictedChainingCell = newLIR2(cUnit, kMipsLahi, r_A2, 0);
3348 predictedChainingCell = newLIR3(cUnit, kMipsLalo, r_A2, r_A2, 0);
3351 genDispatchToHandler(cUnit, gDvmJit.methodTraceSupport ?
3356 genUnconditionalBranch(cUnit, predChainingCell);
3363 int dPC = (int) (cUnit->method->insns + mir->offset);
3369 dvmInsertGrowableList(&cUnit->pcReconstructionList,
3374 genUnconditionalBranch(cUnit, pcrLabel);
3386 genRegCopy(cUnit, r_S5, r_A1);
3387 genRegCopy(cUnit, r_S6, r_A2);
3388 genRegCopy(cUnit, r_S7, r_A3);
3391 genRegCopy(cUnit, r_A0, r_A3);
3394 loadConstant(cUnit, r_A1, dInsn->vB);
3397 loadConstant(cUnit, r_A2, (int) cUnit->method);
3400 loadConstant(cUnit, r_A3, (int) cUnit->method->clazz->pDvmDex);
3402 LOAD_FUNC_ADDR(cUnit, r_T9,
3404 opReg(cUnit, kOpBlx, r_T9);
3405 newLIR3(cUnit, kMipsLw, r_GP, STACK_OFFSET_GP, r_SP);
3407 genRegCopy(cUnit, r_A0, r_V0);
3409 dvmCompilerClobberCallRegs(cUnit);
3411 MipsLIR *branchOver = opCompareBranch(cUnit, kMipsBne, r_V0, r_ZERO);
3415 loadConstant(cUnit, r_A0,
3416 (int) (cUnit->method->insns + mir->offset));
3417 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
3420 MipsLIR *target = newLIR0(cUnit, kMipsPseudoTargetLabel);
3424 genRegCopy(cUnit, r_A1, r_S5);
3427 MipsLIR *bypassRechaining = opCompareBranch(cUnit, kMipsBgtz, r_S5, -1);
3429 LOAD_FUNC_ADDR(cUnit, r_T9, (int) dvmJitToPatchPredictedChain);
3431 genRegCopy(cUnit, r_A1, rSELF);
3432 genRegCopy(cUnit, r_A2, r_S6);
3433 genRegCopy(cUnit, r_A3, r_S7);
3444 opReg(cUnit, kOpBlx, r_T9);
3445 newLIR3(cUnit, kMipsLw, r_GP, STACK_OFFSET_GP, r_SP);
3446 genRegCopy(cUnit, r_A0, r_V0);
3449 addrRetChain = newLIR2(cUnit, kMipsLahi, r_A1, 0);
3452 addrRetChain = newLIR3(cUnit, kMipsLalo, r_A1, r_A1, 0);
3461 genDispatchToHandler(cUnit, gDvmJit.methodTraceSupport ?
3469 genTrap(cUnit, mir->offset, pcrLabel);
3476 genInterpSingleStep(cUnit, mir);
3485 static bool handleFmt35ms_3rms(CompilationUnit *cUnit, MIR *mir,
3509 genLandingPadForMispredictedCallee(cUnit, mir, bb, labelList);
3513 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
3515 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
3521 genInvokeVirtualWholeMethod(cUnit, mir, calleeAddr,
3525 genInvokeVirtualCommon(cUnit, mir, methodIndex,
3537 cUnit->method->clazz->super->vtable[dInsn->vB]);
3540 genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
3542 genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
3545 loadConstant(cUnit, r_A0, (int) calleeMethod);
3547 genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
3563 static bool genInlinedCompareTo(CompilationUnit *cUnit, MIR *mir)
3566 return handleExecuteInlineC(cUnit, mir);
3569 RegLocation rlThis = dvmCompilerGetSrc(cUnit, mir, 0);
3570 RegLocation rlComp = dvmCompilerGetSrc(cUnit, mir, 1);
3572 loadValueDirectFixed(cUnit, rlThis, r_A0);
3573 loadValueDirectFixed(cUnit, rlComp, r_A1);
3575 rollback = genNullCheck(cUnit, rlThis.sRegLow, r_A0, mir->offset, NULL);
3576 genNullCheck(cUnit, rlComp.sRegLow, r_A1, mir->offset, rollback);
3582 genDispatchToHandler(cUnit, TEMPLATE_STRING_COMPARETO);
3583 storeValue(cUnit, inlinedTarget(cUnit, mir, false),
3584 dvmCompilerGetReturn(cUnit));
3589 static bool genInlinedFastIndexOf(CompilationUnit *cUnit, MIR *mir)
3592 return handleExecuteInlineC(cUnit, mir);
3594 RegLocation rlThis = dvmCompilerGetSrc(cUnit, mir, 0);
3595 RegLocation rlChar = dvmCompilerGetSrc(cUnit, mir, 1);
3597 loadValueDirectFixed(cUnit, rlThis, r_A0);
3598 loadValueDirectFixed(cUnit, rlChar, r_A1);
3600 RegLocation rlStart = dvmCompilerGetSrc(cUnit, mir, 2);
3601 loadValueDirectFixed(cUnit, rlStart, r_A2);
3604 genNullCheck(cUnit, rlThis.sRegLow, r_A0, mir->offset, NULL);
3605 genDispatchToHandler(cUnit, TEMPLATE_STRING_INDEXOF);
3606 storeValue(cUnit, inlinedTarget(cUnit, mir, false),
3607 dvmCompilerGetReturn(cUnit));
3613 static bool genInlinedStringIsEmptyOrLength(CompilationUnit *cUnit, MIR *mir,
3617 RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 0);
3618 RegLocation rlDest = inlinedTarget(cUnit, mir, false);
3619 rlObj = loadValue(cUnit, rlObj, kCoreReg);
3620 RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
3621 genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset, NULL);
3622 loadWordDisp(cUnit, rlObj.lowReg, gDvm.offJavaLangString_count,
3626 int tReg = dvmCompilerAllocTemp(cUnit);
3627 newLIR3(cUnit, kMipsSltu, tReg, r_ZERO, rlResult.lowReg);
3628 opRegRegImm(cUnit, kOpXor, rlResult.lowReg, tReg, 1);
3630 storeValue(cUnit, rlDest, rlResult);
3634 static bool genInlinedStringLength(CompilationUnit *cUnit, MIR *mir)
3636 return genInlinedStringIsEmptyOrLength(cUnit, mir, false);
3639 static bool genInlinedStringIsEmpty(CompilationUnit *cUnit, MIR *mir)
3641 return genInlinedStringIsEmptyOrLength(cUnit, mir, true);
3644 static bool genInlinedStringCharAt(CompilationUnit *cUnit, MIR *mir)
3647 RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 0);
3648 RegLocation rlIdx = dvmCompilerGetSrc(cUnit, mir, 1);
3649 RegLocation rlDest = inlinedTarget(cUnit, mir, false);
3651 rlObj = loadValue(cUnit, rlObj, kCoreReg);
3652 rlIdx = loadValue(cUnit, rlIdx, kCoreReg);
3653 int regMax = dvmCompilerAllocTemp(cUnit);
3654 int regOff = dvmCompilerAllocTemp(cUnit);
3655 int regPtr = dvmCompilerAllocTemp(cUnit);
3656 MipsLIR *pcrLabel = genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg,
3658 loadWordDisp(cUnit, rlObj.lowReg, gDvm.offJavaLangString_count, regMax);
3659 loadWordDisp(cUnit, rlObj.lowReg, gDvm.offJavaLangString_offset, regOff);
3660 loadWordDisp(cUnit, rlObj.lowReg, gDvm.offJavaLangString_value, regPtr);
3661 genBoundsCheck(cUnit, rlIdx.lowReg, regMax, mir->offset, pcrLabel);
3662 dvmCompilerFreeTemp(cUnit, regMax);
3663 opRegImm(cUnit, kOpAdd, regPtr, contents);
3664 opRegReg(cUnit, kOpAdd, regOff, rlIdx.lowReg);
3665 rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
3666 loadBaseIndexed(cUnit, regPtr, regOff, rlResult.lowReg, 1, kUnsignedHalf);
3667 storeValue(cUnit, rlDest, rlResult);
3671 static bool genInlinedAbsInt(CompilationUnit *cUnit, MIR *mir)
3673 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
3674 rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
3675 RegLocation rlDest = inlinedTarget(cUnit, mir, false);
3676 RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
3677 int signReg = dvmCompilerAllocTemp(cUnit);
3683 opRegRegImm(cUnit, kOpAsr, signReg, rlSrc.lowReg, 31);
3684 opRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, signReg);
3685 opRegReg(cUnit, kOpXor, rlResult.lowReg, signReg);
3686 storeValue(cUnit, rlDest, rlResult);
3690 static bool genInlinedAbsLong(CompilationUnit *cUnit, MIR *mir)
3692 RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
3693 RegLocation rlDest = inlinedTargetWide(cUnit, mir, false);
3694 rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg);
3695 RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
3696 int signReg = dvmCompilerAllocTemp(cUnit);
3697 int tReg = dvmCompilerAllocTemp(cUnit);
3704 opRegRegImm(cUnit, kOpAsr, signReg, rlSrc.highReg, 31);
3705 opRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, signReg);
3706 newLIR3(cUnit, kMipsSltu, tReg, rlResult.lowReg, signReg);
3707 opRegRegReg(cUnit, kOpAdd, rlResult.highReg, rlSrc.highReg, signReg);
3708 opRegRegReg(cUnit, kOpAdd, rlResult.highReg, rlResult.highReg, tReg);
3709 opRegReg(cUnit, kOpXor, rlResult.lowReg, signReg);
3710 opRegReg(cUnit, kOpXor, rlResult.highReg, signReg);
3711 dvmCompilerFreeTemp(cUnit, signReg);
3712 dvmCompilerFreeTemp(cUnit, tReg);
3713 storeValueWide(cUnit, rlDest, rlResult);
3717 static bool genInlinedIntFloatConversion(CompilationUnit *cUnit, MIR *mir)
3720 RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
3721 RegLocation rlDest = inlinedTarget(cUnit, mir, false);
3722 storeValue(cUnit, rlDest, rlSrc);
3726 static bool genInlinedLongDoubleConversion(CompilationUnit *cUnit, MIR *mir)
3729 RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
3730 RegLocation rlDest = inlinedTargetWide(cUnit, mir, false);
3731 storeValueWide(cUnit, rlDest, rlSrc);
3739 static bool handleExecuteInlineC(CompilationUnit *cUnit, MIR *mir)
3747 dvmCompilerAbort(cUnit);
3749 dvmCompilerFlushAllRegs(cUnit); /* Everything to home location */
3750 dvmCompilerClobberCallRegs(cUnit);
3751 dvmCompilerClobber(cUnit, r4PC);
3752 dvmCompilerClobber(cUnit, rINST);
3754 opRegRegImm(cUnit, kOpAdd, r4PC, rSELF, offset);
3755 newLIR3(cUnit, kMipsSw, r4PC, 16, r_SP); /* sp has plenty of space */
3756 genExportPC(cUnit, mir);
3759 loadValueDirect(cUnit, dvmCompilerGetSrc(cUnit, mir, i), i+r_A0);
3761 LOAD_FUNC_ADDR(cUnit, r_T9, fn);
3762 opReg(cUnit, kOpBlx, r_T9);
3763 newLIR3(cUnit, kMipsLw, r_GP, STACK_OFFSET_GP, r_SP);
3765 MipsLIR *branchOver = opCompareBranch(cUnit, kMipsBne, r_V0, r_ZERO);
3766 loadConstant(cUnit, r_A0, (int) (cUnit->method->insns + mir->offset));
3767 genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
3768 MipsLIR *target = newLIR0(cUnit, kMipsPseudoTargetLabel);
3778 static bool handleExecuteInline(CompilationUnit *cUnit, MIR *mir)
3790 return genInlinedStringCharAt(cUnit, mir);
3792 return genInlinedStringLength(cUnit, mir);
3794 return genInlinedStringIsEmpty(cUnit, mir);
3796 return genInlinedCompareTo(cUnit, mir);
3798 return genInlinedFastIndexOf(cUnit, mir);
3802 return genInlinedAbsInt(cUnit, mir);
3805 return genInlinedAbsLong(cUnit, mir);
3808 return genInlinedMinMaxInt(cUnit, mir, true);
3811 return genInlinedMinMaxInt(cUnit, mir, false);
3814 return genInlineSqrt(cUnit, mir);
3817 return genInlinedAbsFloat(cUnit, mir);
3820 return genInlinedAbsDouble(cUnit, mir);
3824 return genInlinedIntFloatConversion(cUnit, mir);
3827 return genInlinedLongDoubleConversion(cUnit, mir);
3838 return handleExecuteInlineC(cUnit, mir);
3840 dvmCompilerAbort(cUnit);
3844 static bool handleFmt51l(CompilationUnit *cUnit, MIR *mir)
3847 RegLocation rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
3848 RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
3849 loadConstantNoClobber(cUnit, rlResult.lowReg,
3851 loadConstantNoClobber(cUnit, rlResult.highReg,
3853 storeValueWide(cUnit, rlDest, rlResult);
3864 static void handleNormalChainingCell(CompilationUnit *cUnit,
3867 newLIR3(cUnit, kMipsLw, r_A0,
3870 newLIR2(cUnit, kMipsJalr, r_RA, r_A0);
3871 addWordData(cUnit, NULL, (int) (cUnit->method->insns + offset));
3878 static void handleHotChainingCell(CompilationUnit *cUnit,
3881 newLIR3(cUnit, kMipsLw, r_A0,
3884 newLIR2(cUnit, kMipsJalr, r_RA, r_A0);
3885 addWordData(cUnit, NULL, (int) (cUnit->method->insns + offset));
3889 static void handleBackwardBranchChainingCell(CompilationUnit *cUnit,
3897 newLIR3(cUnit, kMipsLw, r_A0,
3901 newLIR3(cUnit, kMipsLw, r_A0,
3905 newLIR2(cUnit, kMipsJalr, r_RA, r_A0);
3906 addWordData(cUnit, NULL, (int) (cUnit->method->insns + offset));
3910 static void handleInvokeSingletonChainingCell(CompilationUnit *cUnit,
3913 newLIR3(cUnit, kMipsLw, r_A0,
3916 newLIR2(cUnit, kMipsJalr, r_RA, r_A0);
3917 addWordData(cUnit, NULL, (int) (callee->insns));
3921 static void handleInvokePredictedChainingCell(CompilationUnit *cUnit)
3924 addWordData(cUnit, NULL, PREDICTED_CHAIN_BX_PAIR_INIT);
3926 addWordData(cUnit, NULL, PREDICTED_CHAIN_DELAY_SLOT_INIT);
3928 addWordData(cUnit, NULL, PREDICTED_CHAIN_CLAZZ_INIT);
3930 addWordData(cUnit, NULL, PREDICTED_CHAIN_METHOD_INIT);
3935 addWordData(cUnit, NULL, PREDICTED_CHAIN_COUNTER_INIT);
3939 static void handlePCReconstruction(CompilationUnit *cUnit,
3943 (MipsLIR **) cUnit->pcReconstructionList.elemList;
3944 int numElems = cUnit->pcReconstructionList.numUsed;
3952 newLIR0(cUnit, kMipsUndefined);
3956 dvmCompilerAppendLIR(cUnit, (LIR *) pcrLabel[i]);
3958 loadConstant(cUnit, r_A0, pcrLabel[i]->operands[0]);
3959 genUnconditionalBranch(cUnit, targetLabel);
3980 static void genHoistedChecksForCountUpLoop(CompilationUnit *cUnit, MIR *mir)
3992 RegLocation rlArray = cUnit->regLocation[mir->dalvikInsn.vA];
3993 RegLocation rlIdxEnd = cUnit->regLocation[mir->dalvikInsn.vC];
3996 rlArray = loadValue(cUnit, rlArray, kCoreReg);
3997 rlIdxEnd = loadValue(cUnit, rlIdxEnd, kCoreReg);
3998 genRegImmCheck(cUnit, kMipsCondEq, rlArray.lowReg, 0, 0,
3999 (MipsLIR *) cUnit->loopAnalysis->branchToPCR);
4002 regLength = dvmCompilerAllocTemp(cUnit);
4003 loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLength);
4015 int tReg = dvmCompilerAllocTemp(cUnit);
4016 opRegRegImm(cUnit, kOpAdd, tReg, rlIdxEnd.lowReg, delta);
4018 dvmCompilerFreeTemp(cUnit, tReg);
4021 genRegRegCheck(cUnit, kMipsCondGe, rlIdxEnd.lowReg, regLength, 0,
4022 (MipsLIR *) cUnit->loopAnalysis->branchToPCR);
4033 static void genHoistedChecksForCountDownLoop(CompilationUnit *cUnit, MIR *mir)
4037 const int regLength = dvmCompilerAllocTemp(cUnit);
4039 RegLocation rlArray = cUnit->regLocation[mir->dalvikInsn.vA];
4040 RegLocation rlIdxInit = cUnit->regLocation[mir->dalvikInsn.vB];
4043 rlArray = loadValue(cUnit, rlArray, kCoreReg);
4044 rlIdxInit = loadValue(cUnit, rlIdxInit, kCoreReg);
4045 genRegImmCheck(cUnit, kMipsCondEq, rlArray.lowReg, 0, 0,
4046 (MipsLIR *) cUnit->loopAnalysis->branchToPCR);
4049 loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLength);
4052 int tReg = dvmCompilerAllocTemp(cUnit);
4053 opRegRegImm(cUnit, kOpAdd, tReg, rlIdxInit.lowReg, maxC);
4055 dvmCompilerFreeTemp(cUnit, tReg);
4059 genRegRegCheck(cUnit, kMipsCondGe, rlIdxInit.lowReg, regLength, 0,
4060 (MipsLIR *) cUnit->loopAnalysis->branchToPCR);
4067 static void genHoistedLowerBoundCheck(CompilationUnit *cUnit, MIR *mir)
4071 RegLocation rlIdx = cUnit->regLocation[mir->dalvikInsn.vA];
4074 rlIdx = loadValue(cUnit, rlIdx, kCoreReg);
4077 genRegImmCheck(cUnit, kMipsCondLt, rlIdx.lowReg, -minC, 0,
4078 (MipsLIR *) cUnit->loopAnalysis->branchToPCR);
4182 static void genValidationForPredictedInline(CompilationUnit *cUnit, MIR *mir)
4185 RegLocation rlThis = cUnit->regLocation[mir->dalvikInsn.vC];
4187 rlThis = loadValue(cUnit, rlThis, kCoreReg);
4188 int regPredictedClass = dvmCompilerAllocTemp(cUnit);
4189 loadClassPointer(cUnit, regPredictedClass, (int) callsiteInfo);
4190 genNullCheck(cUnit, rlThis.sRegLow, rlThis.lowReg, mir->offset,
4192 int regActualClass = dvmCompilerAllocTemp(cUnit);
4193 loadWordDisp(cUnit, rlThis.lowReg, offsetof(Object, clazz), regActualClass);
4194 // opRegReg(cUnit, kOpCmp, regPredictedClass, regActualClass);
4199 callsiteInfo->misPredBranchOver = (LIR *) opCompareBranch(cUnit, kMipsBne, regPredictedClass, regActualClass);
4203 static void handleExtendedMIR(CompilationUnit *cUnit, MIR *mir)
4209 newLIR1(cUnit, kMipsPseudoExtended, (int) msg);
4213 char *ssaString = dvmCompilerGetSSAString(cUnit, mir->ssaRep);
4214 newLIR1(cUnit, kMipsPseudoSSARep, (int) ssaString);
4218 genHoistedChecksForCountUpLoop(cUnit, mir);
4222 genHoistedChecksForCountDownLoop(cUnit, mir);
4226 genHoistedLowerBoundCheck(cUnit, mir);
4230 genUnconditionalBranch(cUnit,
4231 (MipsLIR *) cUnit->loopAnalysis->branchToPCR);
4235 genValidationForPredictedInline(cUnit, mir);
4250 static void setupLoopEntryBlock(CompilationUnit *cUnit, BasicBlock *entry,
4257 (int) (cUnit->method->insns + entry->startOffset);
4260 dvmInsertGrowableList(&cUnit->pcReconstructionList, (intptr_t) pcrLabel);
4270 cUnit->loopAnalysis->branchToBody = (LIR *) branchToBody;
4276 cUnit->loopAnalysis->branchToPCR = (LIR *) branchToPCR;
4307 void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
4311 (MipsLIR *) dvmCompilerNew(sizeof(MipsLIR) * cUnit->numBlocks, true);
4324 dvmCompilerDataFlowAnalysisDispatcher(cUnit, dvmCompilerClearVisitedFlag,
4328 dvmGrowableListIteratorInit(&cUnit->blockList, &iterator);
4331 cUnit->profileCodeSize = genTraceProfileEntry(cUnit);
4345 newLIR0(cUnit, kMipsPseudoPseudoAlign4);
4351 dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[i]);
4359 setupLoopEntryBlock(cUnit, bb,
4369 dvmCompilerResetRegPool(cUnit);
4370 dvmCompilerClobberAllRegs(cUnit);
4371 dvmCompilerResetNullCheck(cUnit);
4414 handlePCReconstruction(cUnit,
4415 &labelList[cUnit->puntBlock->id]);
4419 if (cUnit->pcReconstructionList.numUsed) {
4420 loadWordDisp(cUnit, rSELF, offsetof(Thread,
4423 opReg(cUnit, kOpBlx, r_A1);
4445 for (BasicBlock *nextBB = bb; nextBB != NULL; nextBB = cUnit->nextCodegenBlock) {
4448 cUnit->nextCodegenBlock = NULL;
4452 dvmCompilerResetRegPool(cUnit);
4454 dvmCompilerClobberAllRegs(cUnit);
4458 dvmCompilerResetDefTracking(cUnit);
4462 handleExtendedMIR(cUnit, mir);
4481 newLIR2(cUnit, kMipsPseudoDalvikByteCodeBoundary,
4486 char *ssaString = dvmCompilerGetSSAString(cUnit, mir->ssaRep);
4487 newLIR1(cUnit, kMipsPseudoSSARep, (int) ssaString);
4508 if (singleStepMe || cUnit->allSingleStep) {
4510 genInterpSingleStep(cUnit, mir);
4517 notHandled = handleFmt10t_Fmt20t_Fmt30t(cUnit,
4521 notHandled = handleFmt10x(cUnit, mir);
4525 notHandled = handleFmt11n_Fmt31i(cUnit, mir);
4528 notHandled = handleFmt11x(cUnit, mir);
4531 notHandled = handleFmt12x(cUnit, mir);
4534 notHandled = handleFmt20bc(cUnit, mir);
4538 notHandled = handleFmt21c_Fmt31c(cUnit, mir);
4541 notHandled = handleFmt21h(cUnit, mir);
4544 notHandled = handleFmt21s(cUnit, mir);
4547 notHandled = handleFmt21t(cUnit, mir, bb,
4552 notHandled = handleFmt22b_Fmt22s(cUnit, mir);
4555 notHandled = handleFmt22c(cUnit, mir);
4558 notHandled = handleFmt22cs(cUnit, mir);
4561 notHandled = handleFmt22t(cUnit, mir, bb,
4566 notHandled = handleFmt22x_Fmt32x(cUnit, mir);
4569 notHandled = handleFmt23x(cUnit, mir);
4572 notHandled = handleFmt31t(cUnit, mir);
4576 notHandled = handleFmt35c_3rc(cUnit, mir, bb,
4581 notHandled = handleFmt35ms_3rms(cUnit, mir,bb,
4586 notHandled = handleExecuteInline(cUnit, mir);
4589 notHandled = handleFmt51l(cUnit, mir);
4601 dvmCompilerAbort(cUnit);
4608 dvmCompilerAppendLIR(cUnit,
4609 (LIR *) cUnit->loopAnalysis->branchToBody);
4610 dvmCompilerAppendLIR(cUnit,
4611 (LIR *) cUnit->loopAnalysis->branchToPCR);
4619 dvmCompilerApplyLocalOptimizations(cUnit, (LIR *) headLIR,
4620 cUnit->lastLIRInsn);
4631 genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
4640 cUnit->numChainingCells[i] = chainingListByType[i].numUsed;
4643 if (cUnit->numChainingCells[i] == 0)
4647 cUnit->firstChainingLIR[i] = (LIR *) &labelList[blockIdList[0]];
4652 (BasicBlock *) dvmGrowableListGetElement(&cUnit->blockList,
4656 newLIR0(cUnit, kMipsPseudoPseudoAlign4);
4659 dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[blockId]);
4664 handleNormalChainingCell(cUnit, chainingBlock->startOffset);
4667 handleInvokeSingletonChainingCell(cUnit,
4671 handleInvokePredictedChainingCell(cUnit);
4674 handleHotChainingCell(cUnit, chainingBlock->startOffset);
4677 handleBackwardBranchChainingCell(cUnit,
4682 dvmCompilerAbort(cUnit);
4688 cUnit->chainingCellBottom = (LIR *) newLIR0(cUnit, kMipsChainingCellBottom);
4694 if (cUnit->switchOverflowPad) {
4695 loadConstant(cUnit, r_A0, (int) cUnit->switchOverflowPad);
4696 loadWordDisp(cUnit, rSELF, offsetof(Thread,
4698 opRegReg(cUnit, kOpAdd, r_A1, r_A1);
4699 opRegRegReg(cUnit, kOpAdd, r4PC, r_A0, r_A1);
4701 loadConstant(cUnit, r_A0, kSwitchOverflow);
4703 opReg(cUnit, kOpBlx, r_A2);
4706 dvmCompilerApplyGlobalOptimizations(cUnit);
4709 selfVerificationBranchInsertPass(cUnit);
4840 MipsLIR* dvmCompilerRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc)
4842 return genRegCopyNoInsert(cUnit, rDest, rSrc);
4846 MipsLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
4848 return genRegCopy(cUnit, rDest, rSrc);
4852 void dvmCompilerRegCopyWide(CompilationUnit *cUnit, int destLo, int destHi,
4855 genRegCopyWide(cUnit, destLo, destHi, srcLo, srcHi);
4858 void dvmCompilerFlushRegImpl(CompilationUnit *cUnit, int rBase,
4861 storeBaseDisp(cUnit, rBase, displacement, rSrc, size);
4864 void dvmCompilerFlushRegWideImpl(CompilationUnit *cUnit, int rBase,
4867 storeBaseDispWide(cUnit, rBase, displacement, rSrcLo, rSrcHi);