static bool genCmpFP(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest, RegLocation rlSrc1, RegLocation rlSrc2) { bool isDouble; int defaultResult; bool ltNaNBias; RegLocation rlResult; switch(mir->dalvikInsn.opCode) { case OP_CMPL_FLOAT: isDouble = false; defaultResult = -1; break; case OP_CMPG_FLOAT: isDouble = false; defaultResult = 1; break; case OP_CMPL_DOUBLE: isDouble = true; defaultResult = -1; break; case OP_CMPG_DOUBLE: isDouble = true; defaultResult = 1; break; default: return true; } if (isDouble) { rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg); rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg); dvmCompilerClobberSReg(cUnit, rlDest.sRegLow); rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true); loadConstant(cUnit, rlResult.lowReg, defaultResult); newLIR2(cUnit, kThumb2Vcmpd, S2D(rlSrc1.lowReg, r1Src2.highReg), S2D(rlSrc2.lowReg, rlSrc2.highReg)); } else { rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg); rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg); dvmCompilerClobberSReg(cUnit, rlDest.sRegLow); rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true); loadConstant(cUnit, rlResult.lowReg, defaultResult); newLIR2(cUnit, kThumb2Vcmps, rlSrc1.lowReg, rlSrc2.lowReg); } assert(!FPREG(rlResult.lowReg)); newLIR0(cUnit, kThumb2Fmstat); genIT(cUnit, (defaultResult == -1) ? kArmCondGt : kArmCondMi, ""); newLIR2(cUnit, kThumb2MovImmShift, rlResult.lowReg, modifiedImmediate(-defaultResult)); // Must not alter ccodes genIT(cUnit, kArmCondEq, ""); loadConstant(cUnit, rlResult.lowReg, 0); storeValue(cUnit, rlDest, rlResult); return false; }
/* * Decode the register id. */ static inline u8 getRegMaskCommon(int reg) { u8 seed; int shift; int regId = reg & 0x1f; /* * Each double register is equal to a pair of single-precision FP registers */ seed = DOUBLEREG(reg) ? 3 : 1; /* FP register starts at bit position 16 */ shift = FPREG(reg) ? kFPReg0 : 0; /* Expand the double register id into single offset */ shift += regId; return (seed << shift); }
static void storeValueWide(CompilationUnit *cUnit, RegLocation rlDest, RegLocation rlSrc) { LIR *defStart; LIR *defEnd; assert(FPREG(rlSrc.lowReg)==FPREG(rlSrc.highReg)); assert(rlDest.wide); assert(rlSrc.wide); // dvmCompilerKillNullCheckedLoc(cUnit, rlDest); if (rlSrc.location == kLocPhysReg) { if (dvmCompilerIsLive(cUnit, rlSrc.lowReg) || dvmCompilerIsLive(cUnit, rlSrc.highReg) || (rlDest.location == kLocPhysReg)) { // Src is live or Dest has assigned reg. rlDest = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, false); genRegCopyWide(cUnit, rlDest.lowReg, rlDest.highReg, rlSrc.lowReg, rlSrc.highReg); } else { // Just re-assign the registers. Dest gets Src's regs rlDest.lowReg = rlSrc.lowReg; rlDest.highReg = rlSrc.highReg; dvmCompilerClobber(cUnit, rlSrc.lowReg); dvmCompilerClobber(cUnit, rlSrc.highReg); } } else { // Load Src either into promoted Dest or temps allocated for Dest rlDest = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, false); loadValueDirectWide(cUnit, rlSrc, rlDest.lowReg, rlDest.highReg); } // Dest is now live and dirty (until/if we flush it to home location) dvmCompilerMarkLive(cUnit, rlDest.lowReg, rlDest.sRegLow); dvmCompilerMarkLive(cUnit, rlDest.highReg, dvmCompilerSRegHi(rlDest.sRegLow)); dvmCompilerMarkDirty(cUnit, rlDest.lowReg); dvmCompilerMarkDirty(cUnit, rlDest.highReg); dvmCompilerMarkPair(cUnit, rlDest.lowReg, rlDest.highReg); if (rlDest.location == kLocRetval) { //storeBaseDispWide(cUnit, rGLUE, offsetof(InterpState, retval), // rlDest.lowReg, rlDest.highReg); storeBaseDispWide(cUnit, rGLUE, 8, rlDest.lowReg, rlDest.highReg); dvmCompilerClobber(cUnit, rlDest.lowReg); dvmCompilerClobber(cUnit, rlDest.highReg); } else { dvmCompilerResetDefLocWide(cUnit, rlDest); if (dvmCompilerLiveOut(cUnit, rlDest.sRegLow) || dvmCompilerLiveOut(cUnit, dvmCompilerSRegHi(rlDest.sRegLow))) { //defStart = (LIR *)cUnit->lastLIRInsn; int vReg = dvmCompilerS2VReg(cUnit, rlDest.sRegLow); assert((vReg+1) == dvmCompilerS2VReg(cUnit, dvmCompilerSRegHi(rlDest.sRegLow))); storeBaseDispWide(cUnit, rFP, vReg << 2, rlDest.lowReg, rlDest.highReg); dvmCompilerMarkClean(cUnit, rlDest.lowReg); dvmCompilerMarkClean(cUnit, rlDest.highReg); //defEnd = (LIR *)cUnit->lastLIRInsn; //dvmCompilerMarkDefWide(cUnit, rlDest, defStart, defEnd); } } }