/* * Similar to loadValueDirect, but clobbers and allocates the target * registers. Should be used when loading to a fixed registers (for example, * loading arguments to an out of line call. */ static void loadValueDirectWideFixed(CompilationUnit *cUnit, RegLocation rlSrc, int regLo, int regHi) { dvmCompilerClobber(cUnit, regLo); dvmCompilerClobber(cUnit, regHi); dvmCompilerMarkInUse(cUnit, regLo); dvmCompilerMarkInUse(cUnit, regHi); loadValueDirectWide(cUnit, rlSrc, regLo, regHi); }
static void genLong3Addr(CompilationUnit *cUnit, MIR *mir, OpKind firstOp, OpKind secondOp, RegLocation rlDest, RegLocation rlSrc1, RegLocation rlSrc2) { RegLocation rlResult; 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) { // Already 2-operand rlResult = loadValueWide(cUnit, rlDest, kCoreReg); rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg); opRegReg(cUnit, firstOp, rlResult.lowReg, rlSrc2.lowReg); opRegReg(cUnit, secondOp, rlResult.highReg, rlSrc2.highReg); storeValueWide(cUnit, rlDest, rlResult); } else if (rlDest.sRegLow == rlSrc2.sRegLow) { // Bad case - must use/clobber Src1 and reassign Dest rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg); rlResult = loadValueWide(cUnit, rlDest, kCoreReg); opRegReg(cUnit, firstOp, rlSrc1.lowReg, rlResult.lowReg); opRegReg(cUnit, secondOp, rlSrc1.highReg, rlResult.highReg); // Old reg assignments are now invalid dvmCompilerClobber(cUnit, rlResult.lowReg); dvmCompilerClobber(cUnit, rlResult.highReg); dvmCompilerClobber(cUnit, rlSrc1.lowReg); dvmCompilerClobber(cUnit, rlSrc1.highReg); rlDest.location = kLocDalvikFrame; assert(rlSrc1.location == kLocPhysReg); // Reassign registers - rlDest will now get rlSrc1's old regs storeValueWide(cUnit, rlDest, rlSrc1); } else { // Copy Src1 to Dest rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg); rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, false); loadValueDirectWide(cUnit, rlSrc1, rlResult.lowReg, rlResult.highReg); rlResult.location = kLocPhysReg; opRegReg(cUnit, firstOp, rlResult.lowReg, rlSrc2.lowReg); opRegReg(cUnit, secondOp, rlResult.highReg, rlSrc2.highReg); storeValueWide(cUnit, rlDest, rlResult); } }
static RegLocation loadValueWide(CompilationUnit *cUnit, RegLocation rlSrc, RegisterClass opKind) { assert(rlSrc.wide); rlSrc = dvmCompilerEvalLoc(cUnit, rlSrc, opKind, false); // if (rlSrc.location == kLocDalvikFrame) { loadValueDirectWide(cUnit, rlSrc, rlSrc.lowReg, rlSrc.highReg); rlSrc.location = kLocPhysReg; dvmCompilerMarkLive(cUnit, rlSrc.lowReg, rlSrc.sRegLow); dvmCompilerMarkLive(cUnit, rlSrc.highReg, dvmCompilerSRegHi(rlSrc.sRegLow)); // } else if (rlSrc.location == kLocRetval) { // loadBaseDispWide(cUnit, NULL, rGLUE, offsetof(InterpState, retval), // rlSrc.lowReg, rlSrc.highReg, INVALID_SREG); // rlSrc.location = kLocPhysReg; // dvmCompilerClobber(cUnit, rlSrc.lowReg); // dvmCompilerClobber(cUnit, rlSrc.highReg); // } return rlSrc; }
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); } } }