/* * 64-bit 3way compare function. * mov r7, #-1 * cmp op1hi, op2hi * blt done * bgt flip * sub r7, op1lo, op2lo (treat as unsigned) * beq done * ite hi * mov(hi) r7, #-1 * mov(!hi) r7, #1 * flip: * neg r7 * done: */ static void genCmpLong(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest, RegLocation rlSrc1, RegLocation rlSrc2) { RegLocation rlTemp = LOC_C_RETURN; // Just using as template, will change ArmLIR *target1; ArmLIR *target2; rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg); rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg); rlTemp.lowReg = dvmCompilerAllocTemp(cUnit); loadConstant(cUnit, rlTemp.lowReg, -1); opRegReg(cUnit, kOpCmp, rlSrc1.highReg, rlSrc2.highReg); ArmLIR *branch1 = opCondBranch(cUnit, kArmCondLt); ArmLIR *branch2 = opCondBranch(cUnit, kArmCondGt); opRegRegReg(cUnit, kOpSub, rlTemp.lowReg, rlSrc1.lowReg, rlSrc2.lowReg); ArmLIR *branch3 = opCondBranch(cUnit, kArmCondEq); genIT(cUnit, kArmCondHi, "E"); newLIR2(cUnit, kThumb2MovImmShift, rlTemp.lowReg, modifiedImmediate(-1)); loadConstant(cUnit, rlTemp.lowReg, 1); genBarrier(cUnit); target2 = newLIR0(cUnit, kArmPseudoTargetLabel); target2->defMask = -1; opRegReg(cUnit, kOpNeg, rlTemp.lowReg, rlTemp.lowReg); target1 = newLIR0(cUnit, kArmPseudoTargetLabel); target1->defMask = -1; storeValue(cUnit, rlDest, rlTemp); branch1->generic.target = (LIR *)target1; branch2->generic.target = (LIR *)target2; branch3->generic.target = branch1->generic.target; }
/* * 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 loadWordDisp(cUnit, rGLUE, offsetof(InterpState, self), r0); // Get self genNullCheck(cUnit, rlSrc.sRegLow, r1, mir->offset, NULL); loadWordDisp(cUnit, r1, offsetof(Object, lock), r2); // Get object->lock loadWordDisp(cUnit, r0, 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); 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); // Export PC (part 2) newLIR3(cUnit, kThumb2StrRRI8Predec, r3, rFP, sizeof(StackSaveArea) - offsetof(StackSaveArea, xtra.currentPc)); opReg(cUnit, kOpBlx, r7); opRegImm(cUnit, kOpCmp, r0, 0); /* Did we throw? */ ArmLIR *branchOver = opCondBranch(cUnit, kArmCondNe); loadConstant(cUnit, r0, (int) (cUnit->method->insns + mir->offset + dexGetInstrWidthAbs(gDvm.instrWidth, 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; }
/* * Perform a "reg cmp reg" operation and jump to the PCR region if condition * satisfies. */ static ArmLIR *genRegRegCheck(CompilationUnit *cUnit, ArmConditionCode cond, int reg1, int reg2, int dOffset, ArmLIR *pcrLabel) { ArmLIR *res; res = opRegReg(cUnit, kOpCmp, reg1, reg2); ArmLIR *branch = opCondBranch(cUnit, cond); genCheckCommon(cUnit, dOffset, branch, pcrLabel); return res; }