static bool genInlineSqrt(CompilationUnit *cUnit, MIR *mir) { ArmLIR *branch; RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1); RegLocation rlDest = inlinedTargetWide(cUnit, mir, true); rlSrc = loadValueWide(cUnit, rlSrc, kFPReg); RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true); newLIR2(cUnit, kThumb2Vsqrtd, S2D(rlResult.lowReg, rlResult.highReg), S2D(rlSrc.lowReg, rlSrc.highReg)); newLIR2(cUnit, kThumb2Vcmpd, S2D(rlResult.lowReg, rlResult.highReg), S2D(rlResult.lowReg, rlResult.highReg)); newLIR0(cUnit, kThumb2Fmstat); branch = newLIR2(cUnit, kThumbBCond, 0, kArmCondEq); dvmCompilerClobberCallRegs(cUnit); LOAD_FUNC_ADDR(cUnit, r2, (int) (double (*)(double)) sqrt); newLIR3(cUnit, kThumb2Fmrrd, r0, r1, S2D(rlSrc.lowReg, rlSrc.highReg)); newLIR1(cUnit, kThumbBlxR, r2); newLIR3(cUnit, kThumb2Fmdrr, S2D(rlResult.lowReg, rlResult.highReg), r0, r1); ArmLIR *label = newLIR0(cUnit, kArmPseudoTargetLabel); label->defMask = ENCODE_ALL; branch->generic.target = (LIR *)label; storeValueWide(cUnit, rlDest, rlResult); return false; }
/* * For monitor unlock, we don't have to use ldrex/strex. Once * we've determined that the lock is thin and that we own it with * a zero recursion count, it's safe to punch it back to the * initial, unlock thin state with a store word. */ static void genMonitorExit(CompilationUnit *cUnit, MIR *mir) { RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0); ArmLIR *target; ArmLIR *branch; ArmLIR *hopTarget; ArmLIR *hopBranch; assert(LW_SHAPE_THIN == 0); loadValueDirectFixed(cUnit, rlSrc, r1); // Get obj dvmCompilerLockAllTemps(cUnit); // Prepare for explicit register usage dvmCompilerFreeTemp(cUnit, r4PC); // Free up r4 for general use genNullCheck(cUnit, rlSrc.sRegLow, r1, mir->offset, NULL); loadWordDisp(cUnit, r1, offsetof(Object, lock), r2); // Get object->lock loadWordDisp(cUnit, r6SELF, offsetof(Thread, threadId), r3); // Get threadId // Is lock unheld on lock or held by us (==threadId) on unlock? opRegRegImm(cUnit, kOpAnd, r7, r2, (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT)); opRegImm(cUnit, kOpLsl, r3, LW_LOCK_OWNER_SHIFT); // Align owner newLIR3(cUnit, kThumb2Bfc, r2, LW_HASH_STATE_SHIFT, LW_LOCK_OWNER_SHIFT - 1); opRegReg(cUnit, kOpSub, r2, r3); hopBranch = opCondBranch(cUnit, kArmCondNe); dvmCompilerGenMemBarrier(cUnit, kSY); storeWordDisp(cUnit, r1, offsetof(Object, lock), r7); branch = opNone(cUnit, kOpUncondBr); hopTarget = newLIR0(cUnit, kArmPseudoTargetLabel); hopTarget->defMask = ENCODE_ALL; hopBranch->generic.target = (LIR *)hopTarget; // Export PC (part 1) loadConstant(cUnit, r3, (int) (cUnit->method->insns + mir->offset)); LOAD_FUNC_ADDR(cUnit, r7, (int)dvmUnlockObject); genRegCopy(cUnit, r0, r6SELF); // Export PC (part 2) newLIR3(cUnit, kThumb2StrRRI8Predec, r3, r5FP, sizeof(StackSaveArea) - offsetof(StackSaveArea, xtra.currentPc)); opReg(cUnit, kOpBlx, r7); /* Did we throw? */ ArmLIR *branchOver = genCmpImmBranch(cUnit, kArmCondNe, r0, 0); loadConstant(cUnit, r0, (int) (cUnit->method->insns + mir->offset + dexGetWidthFromOpcode(OP_MONITOR_EXIT))); genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON); // Resume here target = newLIR0(cUnit, kArmPseudoTargetLabel); target->defMask = ENCODE_ALL; branch->generic.target = (LIR *)target; branchOver->generic.target = (LIR *) target; }