Skip to content
Snippets Groups Projects
SMPInstr.cpp 640 KiB
Newer Older
		BaseOpnd.type = o_reg; // Change type and reg fields
		BaseOpnd.reg = R_cx;
		BaseOpnd.clr_showed();
		BaseOpnd.dtyp = this->GetOperandDtypField();
clc5q's avatar
clc5q committed
		this->Defs.SetRef(BaseOpnd, NUMERIC);
		this->Uses.SetRef(BaseOpnd, NUMERIC);
	if ((opcode == NN_cmps) || (opcode == NN_scas) || (opcode == NN_movs) || (opcode == NN_stos)) {
		// ESI and EDI are USEd and DEFed to point to source and dest strings for CMPS/MOVS.
		//  Only EDI is involved with SCAS/STOS.
		BaseOpnd.type = o_reg; // Change type and reg fields
		BaseOpnd.clr_showed();
		BaseOpnd.dtyp = this->GetOperandDtypField();
		if ((opcode == NN_cmps) || (opcode == NN_movs)) {
clc5q's avatar
clc5q committed
			this->Defs.SetRef(BaseOpnd, POINTER);
			this->Uses.SetRef(BaseOpnd, POINTER);
clc5q's avatar
clc5q committed
		this->Defs.SetRef(BaseOpnd, POINTER);
		this->Uses.SetRef(BaseOpnd, POINTER);
	else if ((NN_loopw <= opcode) && (NN_loopqne >= opcode)) {
		op_t LoopCounterOp = InitOp;
		LoopCounterOp.type = o_reg;
		LoopCounterOp.reg = R_cx;
		LoopCounterOp.dtyp = this->GetOperandDtypField();
		this->Defs.SetRef(LoopCounterOp, NUMERIC);
		this->Uses.SetRef(LoopCounterOp, NUMERIC);
	}
	// Now, handle special instruction categories that have implicit operands.
		// x86 Compare and Exchange conditionally sets EAX. We must keep data flow analysis
		//  sound by declaring that EAX is always a DEF.
		this->MDAddRegDef(R_ax, false);
	} // end if NN_cmpxchg
	else if ((this->type == CALL) || (this->type == INDIR_CALL) || this->IsTailCall()) {
		// We want to add the caller-saved registers to the USEs and DEFs lists
		for (list<uint16>::iterator RegIter = GetFirstCallerSavedReg(); RegIter != GetLastCallerSavedReg(); ++RegIter) {
			uint16 RegNum = (*RegIter);
			this->MDAddRegDef(RegNum, false);
			this->MDAddRegUse(RegNum, false);
		}

			this->MDAddRegDef(R_bx, false);
			this->MDAddRegUse(R_bx, false);
			this->MDAddRegDef(R_si, false);
			this->MDAddRegUse(R_si, false);
	else if (this->MDIsPopInstr() || this->MDIsPushInstr() || this->MDIsReturnInstr()) {
		// IDA does not include the stack pointer in the DEFs or USEs.
		this->MDAddRegDef(R_sp, false);
		this->MDAddRegUse(R_sp, false);
		if (!this->MDIsReturnInstr()) {
			// We always reference [esp+0] or [esp-4], so add it to the DEF or USE list.
			op_t StackOp = InitOp;
			StackOp.type = o_displ;
			StackOp.reg = R_sp;
			StackOp.dtyp = this->GetOperandDtypField();

			if (this->MDIsPopInstr()) {
				StackOp.addr = 0;  // [ESP+0]
				this->Uses.SetRef(StackOp);  // USE
			}
			else {
				StackOp.addr = (- ((ea_t) STARS_ISA_Bytewidth));  // [ESP-4]
				this->Defs.SetRef(StackOp); // DEF
			}
		}
	}
	else if (this->MDIsEnterInstr() || this->MDIsLeaveInstr()) {
		// Entire function prologue or epilogue microcoded.
		this->MDAddRegDef(MD_STACK_POINTER_REG, false);
		this->MDAddRegUse(MD_STACK_POINTER_REG, false);
		this->MDAddRegDef(MD_FRAME_POINTER_REG, false);
		this->MDAddRegUse(MD_FRAME_POINTER_REG, false);
	else if ((opcode == NN_maskmovq) || (opcode == NN_maskmovdqu)) {
clc5q's avatar
clc5q committed
		this->MDAddRegUse(R_di, false, POINTER);
	else if (8 == this->GetOptType()) {
		// This category implicitly writes to EDX:EAX.
		this->MDAddRegDef(R_dx, false);
		this->MDAddRegDef(R_ax, false);
	} // end else if (8 == GetOptType)
	else if (7 == this->GetOptType()) {
		// Category 7 instructions sometimes write implicitly to EDX:EAX or DX:AX.
		//  DX is the same as EDX to IDA Pro (and SMP); ditto for EAX and AX.
		// DIV, IDIV, and MUL all have hidden EAX or AX operands (hidden in the IDA Pro
		//  sense, because they are not displayed in the disassembly text). For example:
		//  mul ebx means EDX:EAX <-- EAX*EBX, and mul bx means DX:AX <-- AX*BX. If the
		//  source operand is only 8 bits wide, there is room to hold the result in AX
		//  without using DX:  mul bl means AX <-- AL*BL.
		// IMUL has forms with a hidden EAX or AX operand and forms with no implicit
		//  operands:  imul ebx means EDX:EAX <-- EAX*EBX, but imul ebx,edx means that
		//  EBX*EDX gets truncated and the result placed in EBX (no hidden operands).
		for (OpNum = 0; OpNum < UA_MAXOP; ++OpNum) {
			op_t TempUse = this->SMPcmd.Operands[OpNum];
			if (!TempUse.showed()) { // hidden operand
				if (TempUse.is_reg(R_ax)) { // not R_al, so it is not 8 bits
					if ((NN_div == this->SMPcmd.itype) || (NN_idiv == this->SMPcmd.itype)) {
						this->MDAddRegUse(R_dx, false);
					}
					this->MDAddRegDef(R_ax, false);
					this->MDAddRegDef(R_dx, false);
				}
			}
		}
	} // end else if (7 == OptType)
#if 0
	// The floating point instructions in type categories 14 and 15 often USE and DEF
	//  the floating point register stack, e.g. pushing a value onto that stack is a
	//  massive copy downward of stack locations. We don't really care about the USE of
	//  the stack if the value being pushed came from elsewhere than the stack. For example,
	//  an "fld" opcode pushes its source onto the stack. We build RTLs with a simple
	//  move structure, but the RTL building can be fooled by seeing two "source" operands
	//  in the USE list.
	if ((14 == SMPTypeCategory[this->SMPcmd.itype])
		|| (15 == SMPTypeCategory[this->SMPcmd.itype])) {
	}
#endif

#if 0  // Not true for LOOP instructions that use only the ECX counter register.
	// The return value register EAX is not quite like a caller-save or callee-save
	//  register (technically, it is caller-save). Within a callee, it might appear
	//  that EAX has become dead by the time a return instruction is reached, but
	//  the USE that would make it not dead is in the caller. To prevent type inference
	//  from mistakenly thinking that all USEs of EAX have been seen in the callee,
	//  we add EAX to the USE list for all return instructions, as well as for all
	//  tail calls, which are essentially returns in terms of data flow analysis.
	// This USE of EAX will always be of type UNINIT unless its DEF has a known type
	//  that propagates to it. Thus, it will prevent an invalid back inference of the
	//  DEF type from "all" USE types that are visible in the callee; even if they
	//  were all NUMERIC, this return USE will be UNINIT and inhibit the invalid
	//  type inference. EAX could be loaded with a pointer from memory, for example,
	//  and USEd only in a comparison instruction, making it falsely appear to be
	//  a NUMERIC, without this extra USE at the return instruction.
	// Because some of the library functions pass values around in EBX, EDI, etc.,
	//  we will add these general purpose registers to the USE list for returns
	//  in order to prevent erroneous analyses of dead registers or unused
	//  metadata.
	if ((this->type == RETURN) || this->IsTailCall()) {
		this->MDAddRegUse(R_bx, false);
		this->MDAddRegUse(R_cx, false);
		this->MDAddRegUse(R_dx, false);
			this->MDAddRegUse(MD_FRAME_POINTER_REG, false);
		this->MDAddRegUse(R_si, false);
		this->MDAddRegUse(R_di, false);
	// Next, add the flags register to the DEFs and USEs for those instructions that
	//  are marked as defining or using flags.
	if (!this->IsDefsFlags() && SMPDefsFlags[opcode]) {
		this->MDAddRegDef(X86_FLAGS_REG, false);
		this->SetDefsFlags();
	if (!this->IsUsesFlags() && SMPUsesFlags[opcode]) {
		this->MDAddRegUse(X86_FLAGS_REG, false);
		this->SetUsesFlags();
		// Clear the DEFs and USEs for no-ops.
		//  These include machine idioms for no-ops, e.g. mov esi,esi
		//  or xchg ax,ax or lea esi,[esi].
		this->Defs.clear();
		this->Uses.clear();
		this->MoveSource = InitOp;
		this->DEFMemOp = InitOp;
		this->USEMemOp = InitOp;
		this->SetLeaMemUseOp(InitOp);
	if (DebugFlag) {
		SMP_msg("DEBUG after MDFixupDefUseLists:\n");
		this->Dump();
	}
	return;
} // end of SMPInstr::MDFixupDefUseLists()

// Erase DEFs and USEs of callee-preserved registers in call instructions.
void SMPInstr::MDFixupCallDefUseLists(void) {
	if ((this->type == CALL) || (this->type == INDIR_CALL) || this->IsTailCall()) {
		// We want to add the caller-saved registers to the USEs and DEFs lists
		if ((NULL != this->GetBlock()) && (!this->MDIsInterruptCall())) {
			ea_t CalledFuncAddr = this->SMPcmd.Operands[0].addr;
			SMPFunction *CalleeFunc = this->GetBlock()->GetFunc()->GetProg()->FindFunction(CalledFuncAddr);
			if (NULL != CalleeFunc) {
				// If CalleeFunc has preserved registers by saving them on entry and restoring them before 
				//  all return points, then there is no need to conservatively consider these registers to
				//  be USEs or DEFs. They essentially are untouched by the callee.
				set<DefOrUse, LessDefUse>::iterator DefIter, UseIter;
				op_t SearchOp = InitOp;
				SearchOp.type = o_reg;
				SearchOp.dtyp = this->GetOperandDtypField();
				bool CalleeAnalyzed = (CalleeFunc->HasSTARSStackPtrAnalysisCompleted() && CalleeFunc->StackPtrAnalysisSucceeded() && (!CalleeFunc->HasUnresolvedIndirectJumps()) && (!CalleeFunc->HasSharedChunks()));
				for (list<uint16>::iterator RegIter = GetFirstCallerSavedReg(); RegIter != GetLastCallerSavedReg(); ++RegIter) {
					uint16 RegNum = (*RegIter);
					SearchOp.reg = RegNum;
					bool ErasedDEF = false;
					if (CalleeFunc->IsRegPreserved(RegNum)) {
						DefIter = this->FindDef(SearchOp);
						assert(DefIter != this->GetLastDef());
						this->EraseDef(DefIter);
						ErasedDEF = true;
						UseIter = this->FindUse(SearchOp);
						assert(UseIter != this->GetLastUse());
						this->EraseUse(UseIter);
					}
					else if (CalleeAnalyzed && (!CalleeFunc->IsLiveIn(SearchOp))) {
						// Callee stack analysis was successful, so function LiveIn set was computed,
						//  but this register is not LiveIn. We should remove it from the USE list of the call.
						UseIter = this->FindUse(SearchOp);
						if (UseIter == this->GetLastUse()) {
							// Might happen if IDA Pro has chunked a function incorrectly and created what
							//  looks like a tail call as a result.
							assert(this->IsTailCall());
						}
						else {
							this->EraseUse(UseIter);
						}
					}
					if ((!ErasedDEF) && CalleeAnalyzed && (!CalleeFunc->IsVarKill(SearchOp))) {
						// Callee has been analyzed, and register is not killed. We should remove it from the DEFs.
						DefIter = this->FindDef(SearchOp);
						if (DefIter == this->GetLastDef()) {
							// Might happen if IDA Pro has chunked a function incorrectly and created what
							//  looks like a tail call as a result.
							assert(this->IsTailCall());
						}
						else {
							this->EraseDef(DefIter);
						}
					}
// If we can definitely identify which part of the addressing expression
//  used in MemOp is the POINTER type, and it is not a STACKPTR or GLOBALPTR
//  immediate, set the USE type for that register to POINTER and return true.
//  If we can find definite NUMERIC addressing registers that are not already
//  typed as NUMERIC, set their USE types to NUMERIC and return true.
bool SMPInstr::MDFindPointerUse(op_t MemOp, bool UseFP) {
	bool changed = false;
	int BaseReg;
	int IndexReg;
	op_t BaseOp = InitOp;
	op_t IndexOp = InitOp;
	SMPOperandType BaseType = UNKNOWN;
	SMPOperandType IndexType = UNKNOWN;
	ushort ScaleFactor;
	ea_t offset;
	set<DefOrUse, LessDefUse>::iterator BaseIter;
	set<DefOrUse, LessDefUse>::iterator IndexIter;

	if (NN_lea == this->SMPcmd.itype)
		return false;  // lea instruction really has no memory operands
	if (NN_fnop == this->SMPcmd.itype)
		return false;  // SSA marker instruction

	MDExtractAddressFields(MemOp, BaseReg, IndexReg, ScaleFactor, offset);
	if (R_none != IndexReg) {
		IndexOp.type = o_reg;
		IndexOp.reg = MDCanonicalizeSubReg((ushort) IndexReg);
		IndexOp.dtyp = this->GetOperandDtypField(); // Canonical reg width
		IndexIter = this->FindUse(IndexOp);
		assert(IndexIter != this->GetLastUse());
		IndexType = IndexIter->GetType();
	}
	if (R_none != BaseReg) {
		BaseOp.type = o_reg;
		BaseOp.reg = MDCanonicalizeSubReg((ushort) BaseReg);
		BaseOp.dtyp = this->GetOperandDtypField(); // Canonical reg width
		BaseIter = this->FindUse(BaseOp);
		assert(BaseIter != this->GetLastUse());
		BaseType = BaseIter->GetType();
	}
	if (MDIsStackPtrReg(BaseReg, UseFP)) {
		if ((R_none != IndexReg) && (!IsNumeric(IndexType))) {
			// We have an indexed access into the stack frame.
			//  Set IndexReg USE type to NUMERIC.
			changed = true;
			IndexIter = this->SetUseType(IndexOp, NUMERIC);
			assert(IndexIter != this->GetLastUse());
		}
		return changed; // stack accesses will get STACKPTR type in SetImmedTypes()
	}
	if (MDIsStackPtrReg(IndexReg, UseFP)) {
		if ((R_none != BaseReg) && (!IsNumeric(BaseType))) {
			// We have an indexed access into the stack frame.
			//  Set BaseReg USE type to NUMERIC.
			// Note that BaseReg is really an IndexReg and vice versa.
			changed = true;
			BaseIter = this->SetUseType(BaseOp, NUMERIC);
			assert(BaseIter != this->GetLastUse());
			SMP_msg("WARNING: BaseReg is index, IndexReg is base: %s\n",
				DisAsmText.GetDisAsm(this->GetAddr()));
		}
		return changed; // stack accesses will get STACKPTR type in SetImmedTypes()
	}
	if (IsImmedGlobalAddress(offset)) {
		if ((R_none != IndexReg) && (!IsNumeric(IndexType))) {
			// We have an indexed access into a global.
			//  Set IndexReg USE type to NUMERIC.
			changed = true;
			IndexIter = this->SetUseType(IndexOp, NUMERIC);
			assert(IndexIter != this->GetLastUse());
		}
		if ((R_none != BaseReg) && (!IsNumeric(BaseType))) {
			// We have an indexed access into a global.
			//  Set BaseReg USE type to NUMERIC.
			// Note that BaseReg is really an index register.
			changed = true;
			BaseIter = this->SetUseType(BaseOp, NUMERIC);
			assert(BaseIter != this->GetLastUse());
clc5q's avatar
clc5q committed
#if SMP_VERBOSE_FIND_POINTERS
			SMP_msg("WARNING: BaseReg used as index: %s\n", DisAsmText.GetDisAsm(this->GetAddr()));
clc5q's avatar
clc5q committed
#endif
		return changed;  // global immediate is handled in SetImmedTypes()
	// At this point, we must have a base address in a register, not used
	//  to directly address the stack or a global.
	if ((0 < ScaleFactor) || (R_none == IndexReg)) {
		// IndexReg is scaled, meaning it is NUMERIC, so BaseReg must
		//  be a POINTER; or IndexReg is not present, so BaseReg is the
		//  only possible holder of an address.
		if (R_none != BaseReg) {
			if (UNINIT == BaseIter->GetType()) {
				BaseIter = this->SetUseType(BaseOp, POINTER);
				assert(BaseIter != this->GetLastUse());
		}
	}
	else if (R_none == BaseReg) {
		// We have an unscaled IndexReg and no BaseReg and offset was
		//  not a global offset, so IndexReg must be a POINTER.
		if (R_none != IndexReg) {
			if (UNINIT == IndexType) {
				IndexIter = this->SetUseType(IndexOp, POINTER);
				assert(IndexIter != this->GetLastUse());
			}
		}
	}
	else { // We have BaseReg and an unscaled IndexReg.
		// The only hope for typing something like [ebx+edx] is for
		//  one register to already be typed NUMERIC, in which case
		//  the other one must be a POINTER, or if one register is
		//  already POINTER, then the other one must be NUMERIC.
		if (IsNumeric(BaseType)) {
			if (UNINIT == IndexType) {
				// Set to POINTER or PROF_POINTER
				changed = true;
				IndexIter = this->SetUseType(IndexOp, POINTER);
				assert(IndexIter != this->GetLastUse());
			}
			else if (IsNumeric(IndexType)) {
				SMP_msg("ERROR: BaseReg and IndexReg both NUMERIC at %lx: %s\n",
					(unsigned long) this->address, DisAsmText.GetDisAsm(this->GetAddr()));
			if (UNINIT == BaseType) { // BaseReg is UNINIT
				if (IsNumeric(IndexType)) {
					BaseIter = this->SetUseType(BaseOp, POINTER);
					assert(BaseIter != this->GetLastUse());
				}
				else if (IsDataPtr(IndexType)) {
					// IndexReg is POINTER, so make BaseReg NUMERIC.
					changed = true;
					BaseIter = this->SetUseType(BaseOp, NUMERIC);
					assert(BaseIter != this->GetLastUse());
				}
			}
			else if (IsDataPtr(BaseType)) {
				// BaseReg was a pointer type. IndexReg must be NUMERIC.
				if (UNINIT == IndexType) {
					changed = true;
					IndexIter = this->SetUseType(IndexOp, NUMERIC);
					assert(IndexIter != this->GetLastUse());
				}
				else if (IsDataPtr(IndexType)) {
					SMP_msg("ERROR: BaseReg and IndexReg both POINTER at %lx: %s\n",
						(unsigned long) this->address, DisAsmText.GetDisAsm(this->GetAddr()));
		}
	}

	return changed;
} // end of SMPInstr::MDFindPointerUse()

// Are all DEFs typed to something besides UNINIT?
bool SMPInstr::AllDEFsTyped(void) {
	if (this->AreDEFsTyped()) {
		return true;
	}
	bool FoundUNINIT = false;
	set<DefOrUse, LessDefUse>::iterator DefIter;
	for (DefIter = this->GetFirstDef(); DefIter != this->GetLastDef(); ++DefIter) {
		if (IsEqType(UNINIT, DefIter->GetType())) {
			FoundUNINIT = true;
			break;
		}
	}
	if (!FoundUNINIT) {
		this->SetDEFsTyped();
	}
	return (!FoundUNINIT);
} // end of SMPInstr::AllDEFsTyped()

// Are all USEs typed to something besides UNINIT?
bool SMPInstr::AllUSEsTyped(void) {
	if (this->AreUSEsTyped()) {
		return true;
	}
	bool FoundUNINIT = false;
	set<DefOrUse, LessDefUse>::iterator UseIter;
	for (UseIter = this->GetFirstUse(); UseIter != this->GetLastUse(); ++UseIter) {
		if (IsEqType(UNINIT, UseIter->GetType())) {
			FoundUNINIT = true;
			break;
		}
	}
	if (!FoundUNINIT) {
		this->SetUSEsTyped();
	}
	return (!FoundUNINIT);
} // end of SMPInstr::AllUSEsTyped()

// Return true if UseOp is a USE reg, not just an address reg in a memory USE
bool SMPInstr::IsNonAddressReg(op_t UseOp) const { 
	bool FoundUse = false;
	ushort SearchReg = MDCanonicalizeSubReg(UseOp.reg);
	for (size_t OpNum = 0; OpNum < UA_MAXOP; ++OpNum) {
		op_t Opnd = this->SMPcmd.Operands[OpNum];
		if (this->features & UseMacros[OpNum]) { // USE
			if (Opnd.type == o_reg) {
				ushort TestReg = MDCanonicalizeSubReg(Opnd.reg);
				if (TestReg == SearchReg) {
					FoundUse = true;
					break;
				}
			}
		}
	}
	return FoundUse;
} // end of SMPInstr::IsNonAddressReg()
clc5q's avatar
clc5q committed

uval_t SMPInstr::MDGetShiftCount(void) const {
	uval_t ShiftCount = 0;

	if (this->MDIsShiftOrRotate()) {
		SMPRegTransfer *CurrRT = this->RTL.GetRT(0);
		assert(CurrRT->HasRightSubTree());
		CurrRT = CurrRT->GetRightTree();
		op_t ShiftCountOp = CurrRT->GetRightOperand();
		if (o_imm == ShiftCountOp.type) {
			ShiftCount = ShiftCountOp.value;
		}
	}

	return ShiftCount;
} // end of SMPInstr::MDGetShiftCount()
clc5q's avatar
clc5q committed
// RTL shows DEF operand is subreg.
bool SMPInstr::IsReducedWidthDef(void) const {
	SMPRegTransfer *CurrRT = this->RTL.GetRT(0);
	op_t DefOp = CurrRT->GetLeftOperand();
	return ((o_void != DefOp.type) && (DefOp.dtyp < 2));
}

// Is a sub-register of UseOp used as a shift counter in the RTL?
//  For example, UseOp could be ECX on an x86 machine, and CL
//  could be used as a shift or rotate counter.
bool SMPInstr::IsSubRegUsedAsShiftCount(op_t UseOp) {
	bool ShiftCounter = false;

	if ((o_reg == UseOp.type) && this->MDIsShiftOrRotate()) {
		SMPRegTransfer *CurrRT = this->RTL.GetRT(0);
		assert(CurrRT->HasRightSubTree());
		CurrRT = CurrRT->GetRightTree();
		op_t ShiftCountOp = CurrRT->GetRightOperand();
		if (o_reg == ShiftCountOp.type) {
			ushort UseReg = UseOp.reg;
			ushort ShiftCountReg = ShiftCountOp.reg;
			ushort WideUseReg = MDCanonicalizeSubReg(UseReg);
			ushort WideShiftCountReg = MDCanonicalizeSubReg(ShiftCountReg);
			if ((UseReg != ShiftCountReg) && (WideUseReg == WideShiftCountReg)) {
				// Registers were not equal, but their canonical enclosing
				//  registers are equal. Because shift counters that are not
				//  immediate are the 8-bit subregister in x86 (MD here !!!!!!)
				//  it must be that the ShiftCountReg is a subreg of UseReg.
				//  This is the condition we are looking for.
				ShiftCounter = true;
			}
		}
	}

	return ShiftCounter;
} // end of SMPInstr::IsSubRegUsedAsShiftCount()

clc5q's avatar
clc5q committed
// Does UseOp ultimately come from a small positive constant?
bool SMPInstr::IsOpSourceSmallPositiveConstant(op_t UseOp, int UseSSANum) {
	bool UseFP = this->GetBlock()->GetFunc()->UsesFramePointer();
	if ((UseSSANum == -1) || (!MDIsDataFlowOpnd(UseOp, UseFP))) {
	bool FoundSmallConst = false;
	bool RegDef = (o_reg == UseOp.type);
clc5q's avatar
clc5q committed
	bool LocalName = this->GetBlock()->IsLocalName(UseOp);
	bool IndirectMemAccess = MDIsIndirectMemoryOpnd(UseOp, UseFP);
	bool AboveStackFrame = (!RegDef && !IndirectMemAccess && (this->GetBlock()->GetFunc()->WritesAboveLocalFrame(UseOp, this->AreDefsNormalized())));
clc5q's avatar
clc5q committed
	ea_t UseAddr = this->GetAddr();
	ea_t FirstFuncAddr = this->GetBlock()->GetFunc()->GetFirstFuncAddr();
	ea_t UseDefAddr = this->GetBlock()->GetDefAddrFromUseAddr(UseOp, UseAddr, UseSSANum, LocalName);
	bool UpExposedUse = (UseDefAddr == (this->GetBlock()->GetFirstAddr() - 1));
	if (!LocalName && !AboveStackFrame && !IndirectMemAccess && ((UseDefAddr == BADADDR) || UpExposedUse)) {
		// Try to find in the function level.
		UseDefAddr = this->GetBlock()->GetFunc()->GetGlobalDefAddr(UseOp, UseSSANum);
	}

	if ((UseDefAddr == (FirstFuncAddr - 1)) || AboveStackFrame
		|| (UseDefAddr == BADADDR) || IndirectMemAccess) {
		// Cannot search for general memory DEFs; must be stack or register.
		//  FirstFuncAddr - 1 signifies the pseudo-inst to hold DEFs of regs
		//  that are LiveIn to the function; pseudo-inst is not a bitwise not.
		//  First block addr - 1 is pseudo-location that indicates live-in, UpExposed, 
		//   and LocalName means we will not find a DEF anywhere besides this block.
		//   AboveStackFrame means an incoming arg, whose DEF will not be seen.
clc5q's avatar
clc5q committed
		FoundSmallConst = false; 
	}
	else if (UseDefAddr < this->GetBlock()->GetFunc()->GetNumBlocks()) {
		// A block number was returned. That means the DEF is in a Phi Function.
		//  We could trace all Phi USEs and see if all of them come from small constants
		//  but we only need one of the Phi USEs to come from
		//  a small constant to potentially lead to a false positive numeric error. We
		//  will recurse on all Phi USEs, declaring success if we find a single one of them
		//  to come from a small constant.
		size_t BlockNum = (size_t) UseDefAddr;
		assert(!LocalName);
		SMPBasicBlock *PhiDefBlock = this->GetBlock()->GetFunc()->GetBlockByNum(BlockNum);
		assert(NULL != PhiDefBlock);
		if (!PhiDefBlock->IsProcessed()) { // Prevent infinite recursion
			set<SMPPhiFunction, LessPhi>::iterator DefPhiIter = PhiDefBlock->FindPhi(UseOp);
			assert(DefPhiIter != PhiDefBlock->GetLastPhi());
			size_t PhiListSize = DefPhiIter->GetPhiListSize();
			PhiDefBlock->SetProcessed(true); // Prevent infinite recursion
			for (size_t UseIndex = 0; UseIndex < PhiListSize; ++UseIndex) {
				int PhiUseSSANum = DefPhiIter->GetUseSSANum(UseIndex);
				if (this->IsOpSourceSmallPositiveConstant(UseOp, PhiUseSSANum)) {
					FoundSmallConst = true; // only one success on all Phi USEs is needed
					break;
				}
			}
		}
	}
clc5q's avatar
clc5q committed
	else {
		bool ValueFound;
		uval_t ConstValue;
		SMPInstr *DefInst = this->GetBlock()->GetFunc()->GetInstFromAddr(UseDefAddr);
		if (DefInst->MDIsSimpleAssignment(ValueFound, ConstValue)) {
			FoundSmallConst = (ValueFound && (ConstValue <= 2));
			if (!FoundSmallConst && !ValueFound && DefInst->MDIsMoveInstr()) {
				// We have a non-immediate move. Trace back through move source to find small const.
				op_t CopyUseOp = DefInst->GetMoveSource();
				CanonicalizeOpnd(CopyUseOp);
				set<DefOrUse, LessDefUse>::iterator UseIter = DefInst->FindUse(CopyUseOp);
				assert(UseIter != DefInst->GetLastUse());
				int CopyUseSSANum = UseIter->GetSSANum();
				FoundSmallConst = DefInst->IsOpSourceSmallPositiveConstant(CopyUseOp, CopyUseSSANum);
			}
clc5q's avatar
clc5q committed
		}
	}

	return FoundSmallConst;
} // end of SMPInstr::IsOpSourceSmallPositiveConstant()

// Does UseOp ultimately come from a bitwise not instruction?
bool SMPInstr::IsOpSourceBitwiseNot(op_t UseOp, int UseSSANum) {
	bool UseFP = this->GetBlock()->GetFunc()->UsesFramePointer();
	if ((UseSSANum == -1) || (!MDIsDataFlowOpnd(UseOp, UseFP))) {
		return false;
	}

	bool FoundBitwiseNotInst = false;
	bool RegDef = (o_reg == UseOp.type);
	bool LocalName = this->GetBlock()->IsLocalName(UseOp);
	bool IndirectMemAccess = MDIsIndirectMemoryOpnd(UseOp, UseFP);
	bool AboveStackFrame = (!RegDef && !IndirectMemAccess && (this->GetBlock()->GetFunc()->WritesAboveLocalFrame(UseOp, this->AreDefsNormalized())));
	ea_t UseAddr = this->GetAddr();
	ea_t FirstFuncAddr = this->GetBlock()->GetFunc()->GetFirstFuncAddr();
	ea_t UseDefAddr = this->GetBlock()->GetDefAddrFromUseAddr(UseOp, UseAddr, UseSSANum, LocalName);
	bool UpExposedUse = (UseDefAddr == (this->GetBlock()->GetFirstAddr() - 1));

	if (!LocalName && !AboveStackFrame && !IndirectMemAccess && ((UseDefAddr == BADADDR) || UpExposedUse)) {
		// Try to find in the function level.
		UseDefAddr = this->GetBlock()->GetFunc()->GetGlobalDefAddr(UseOp, UseSSANum);
	}

	if ((UseDefAddr == (FirstFuncAddr - 1)) || AboveStackFrame
		|| (UseDefAddr == BADADDR) || IndirectMemAccess) {
		// Cannot search for general memory DEFs; must be stack or register.
		//  FirstFuncAddr - 1 signifies the pseudo-inst to hold DEFs of regs
		//  that are LiveIn to the function; pseudo-inst is not a bitwise not.
		//  First block addr - 1 is pseudo-location that indicates live-in, UpExposed, 
		//   and LocalName means we will not find a DEF anywhere besides this block.
		//   AboveStackFrame means an incoming arg, whose DEF will not be seen.
		FoundBitwiseNotInst = false;
	}
	else if (UseDefAddr < this->GetBlock()->GetFunc()->GetNumBlocks()) {
		// A block number was returned. That means the DEF is in a Phi Function.
		//  We could trace all Phi USEs and see if all of them come from bitwise nots
		//  but we only need one of the Phi USEs to come from
		//  a bitwise not to potentially lead to a false positive numeric error. We
		//  will recurse on all Phi USEs, declaring success if we find a single one of them
		size_t BlockNum = (size_t) UseDefAddr;
		assert(!LocalName);
		SMPBasicBlock *PhiDefBlock = this->GetBlock()->GetFunc()->GetBlockByNum(BlockNum);
		assert(NULL != PhiDefBlock);
		if (!PhiDefBlock->IsProcessed()) { // Prevent infinite recursion
			set<SMPPhiFunction, LessPhi>::iterator DefPhiIter = PhiDefBlock->FindPhi(UseOp);
			assert(DefPhiIter != PhiDefBlock->GetLastPhi());
			size_t PhiListSize = DefPhiIter->GetPhiListSize();
			PhiDefBlock->SetProcessed(true); // Prevent infinite recursion
			for (size_t UseIndex = 0; UseIndex < PhiListSize; ++UseIndex) {
				int PhiUseSSANum = DefPhiIter->GetUseSSANum(UseIndex);
				if (this->IsOpSourceBitwiseNot(UseOp, PhiUseSSANum)) {
					FoundBitwiseNotInst = true; // only one success on all Phi USEs is needed
					break;
				}
			}
		}
	}
	else {
		SMPInstr *DefInst = this->GetBlock()->GetFunc()->GetInstFromAddr(UseDefAddr);
		if (DefInst->MDIsBitwiseNotOpcode()) {
			FoundBitwiseNotInst = true;
		}
		else if (DefInst->MDIsMoveInstr()) {
			op_t MoveUseOp = DefInst->GetMoveSource();
			if (MDIsDataFlowOpnd(MoveUseOp, UseFP)) { // pattern is simple; don't try to follow through non-stack memory
				CanonicalizeOpnd(MoveUseOp);
				set<DefOrUse, LessDefUse>::iterator MoveUseIter = DefInst->FindUse(MoveUseOp);
				assert(MoveUseIter != DefInst->GetLastUse());
				int MoveUseSSANum = MoveUseIter->GetSSANum();
				FoundBitwiseNotInst = DefInst->IsOpSourceBitwiseNot(MoveUseOp, MoveUseSSANum); // recurse
			}
		}
		else {
			// Not a move, not a bitwise not. We must return false.
			FoundBitwiseNotInst = false;
		}
	}

	return FoundBitwiseNotInst;
} // end of SMPInstr::IsOpSourceBitwiseNot()
// Does UseOp ultimately come from a set-condition-code instruction?
bool SMPInstr::IsOpSourceConditionCode(op_t UseOp, int UseSSANum) {
	bool UseFP = this->GetBlock()->GetFunc()->UsesFramePointer();
	if ((UseSSANum == -1) || (!MDIsDataFlowOpnd(UseOp, UseFP))) {
	bool LocalName = this->GetBlock()->IsLocalName(UseOp);
	bool IndirectMemAccess = MDIsIndirectMemoryOpnd(UseOp, UseFP);
	bool AboveStackFrame = (!RegDef && !IndirectMemAccess && (this->GetBlock()->GetFunc()->WritesAboveLocalFrame(UseOp, this->AreDefsNormalized())));
	ea_t FirstFuncAddr = this->GetBlock()->GetFunc()->GetFirstFuncAddr();
	ea_t UseDefAddr = this->GetBlock()->GetDefAddrFromUseAddr(UseOp, UseAddr, UseSSANum, LocalName);
	bool UpExposedUse = (UseDefAddr == (this->GetBlock()->GetFirstAddr() - 1));
	if (!LocalName && !AboveStackFrame && !IndirectMemAccess && ((UseDefAddr == BADADDR) || UpExposedUse)) {
		// Try to find in the function level.
		UseDefAddr = this->GetBlock()->GetFunc()->GetGlobalDefAddr(UseOp, UseSSANum);
	}

	if ((UseDefAddr == (FirstFuncAddr - 1)) || AboveStackFrame
		|| (UseDefAddr == BADADDR) || IndirectMemAccess) {
		// Cannot search for general memory DEFs; must be stack or register.
clc5q's avatar
clc5q committed
		//  FirstFuncAddr - 1 signifies the pseudo-inst to hold DEFs of regs
		//  that are LiveIn to the function; pseudo-inst is not a bitwise not.
		//  First block addr - 1 is pseudo-location that indicates live-in, UpExposed, 
		//   and LocalName means we will not find a DEF anywhere besides this block.
		//   AboveStackFrame means an incoming arg, whose DEF will not be seen.
clc5q's avatar
clc5q committed
		FoundConditionalSetInst = false; 
	}
	else if (UseDefAddr < this->GetBlock()->GetFunc()->GetNumBlocks()) {
		// A block number was returned. That means the DEF is in a Phi Function.
		//  We could trace all Phi USEs and see if all of them come from condition codes
		//  but we only need one of the Phi USEs to come from
		//  a condition code to potentially lead to a false positive numeric error. We
		//  will recurse on all Phi USEs, declaring success if we find a single one of them
		//  to come from a condition code.
clc5q's avatar
clc5q committed
		size_t BlockNum = (size_t) UseDefAddr;
		assert(!LocalName);
		SMPBasicBlock *PhiDefBlock = this->GetBlock()->GetFunc()->GetBlockByNum(BlockNum);
		assert(NULL != PhiDefBlock);
		if (!PhiDefBlock->IsProcessed()) { // Prevent infinite recursion
			set<SMPPhiFunction, LessPhi>::iterator DefPhiIter = PhiDefBlock->FindPhi(UseOp);
			assert(DefPhiIter != PhiDefBlock->GetLastPhi());
			size_t PhiListSize = DefPhiIter->GetPhiListSize();
			PhiDefBlock->SetProcessed(true); // Prevent infinite recursion
			for (size_t UseIndex = 0; UseIndex < PhiListSize; ++UseIndex) {
				int PhiUseSSANum = DefPhiIter->GetUseSSANum(UseIndex);
				if (this->IsOpSourceConditionCode(UseOp, PhiUseSSANum)) {
					FoundConditionalSetInst = true; // only one success on all Phi USEs is needed
					break;
	}
	else {
		SMPInstr *DefInst = this->GetBlock()->GetFunc()->GetInstFromAddr(UseDefAddr);
		if (DefInst->MDIsAnySetValue()) {
			FoundConditionalSetInst = true;
		else if (DefInst->MDIsMoveInstr()) {
			op_t MoveUseOp = DefInst->GetMoveSource();
			if (MDIsDataFlowOpnd(MoveUseOp, UseFP)) { // pattern is simple; don't try to follow through non-stack memory
				CanonicalizeOpnd(MoveUseOp);
				set<DefOrUse, LessDefUse>::iterator MoveUseIter = DefInst->FindUse(MoveUseOp);
				assert(MoveUseIter != DefInst->GetLastUse());
				int MoveUseSSANum = MoveUseIter->GetSSANum();
				FoundConditionalSetInst = DefInst->IsOpSourceConditionCode(MoveUseOp, MoveUseSSANum); // recurse
		}
		else {
			// Not a move, not a condition code transfer. We must return false.
			FoundConditionalSetInst = false;
		}
	}

	return FoundConditionalSetInst;
} // end of SMPInstr::IsOpSourceConditionCode()

// Does UseOp ultimately come from a shift left instruction?
bool SMPInstr::IsOpSourceLeftShift(op_t UseOp, int UseSSANum, op_t &ShiftCounterOp, op_t &ShiftedOp, ea_t &ShiftInstAddr) {
	bool UseFP = this->GetBlock()->GetFunc()->UsesFramePointer();
	if ((UseSSANum == -1) || (!MDIsDataFlowOpnd(UseOp, UseFP))) {
		return false;
	}

	bool FoundLeftShiftInst = false;
	bool RegDef = (o_reg == UseOp.type);
	bool LocalName = this->GetBlock()->IsLocalName(UseOp);
	bool IndirectMemAccess = MDIsIndirectMemoryOpnd(UseOp, UseFP);
	bool AboveStackFrame = (!RegDef && !IndirectMemAccess && (this->GetBlock()->GetFunc()->WritesAboveLocalFrame(UseOp, this->AreDefsNormalized())));
	ea_t UseAddr = this->GetAddr();
	ea_t FirstFuncAddr = this->GetBlock()->GetFunc()->GetFirstFuncAddr();
	ea_t UseDefAddr = this->GetBlock()->GetDefAddrFromUseAddr(UseOp, UseAddr, UseSSANum, LocalName);
	bool UpExposedUse = (UseDefAddr == (this->GetBlock()->GetFirstAddr() - 1));

	if (!LocalName && !AboveStackFrame && !IndirectMemAccess && ((UseDefAddr == BADADDR) || UpExposedUse)) {
		// Try to find in the function level.
		UseDefAddr = this->GetBlock()->GetFunc()->GetGlobalDefAddr(UseOp, UseSSANum);
	}

	if ((UseDefAddr == (FirstFuncAddr - 1)) || AboveStackFrame
		|| (UseDefAddr == BADADDR) || IndirectMemAccess) {
		// Cannot search for general memory DEFs; must be stack or register.
		//  FirstFuncAddr - 1 signifies the pseudo-inst to hold DEFs of regs
		//  that are LiveIn to the function; pseudo-inst is not a bitwise not.
		//  First block addr - 1 is pseudo-location that indicates live-in, UpExposed, 
		//   and LocalName means we will not find a DEF anywhere besides this block.
		//   AboveStackFrame means an incoming arg, whose DEF will not be seen.
		FoundLeftShiftInst = false; 
	}
	else if (UseDefAddr < this->GetBlock()->GetFunc()->GetNumBlocks()) {
		// A block number was returned. That means the DEF is in a Phi Function.
		//  We could trace all Phi USEs and see if all of them come from condition codes
		//  but we only need one of the Phi USEs to come from
		//  a condition code to potentially lead to a false positive numeric error. We
		//  will recurse on all Phi USEs, declaring success if we find a single one of them
		//  to come from a condition code.
		size_t BlockNum = (size_t) UseDefAddr;
		assert(!LocalName);
		SMPBasicBlock *PhiDefBlock = this->GetBlock()->GetFunc()->GetBlockByNum(BlockNum);
		assert(NULL != PhiDefBlock);
		if (!PhiDefBlock->IsProcessed()) { // Prevent infinite recursion
			set<SMPPhiFunction, LessPhi>::iterator DefPhiIter = PhiDefBlock->FindPhi(UseOp);
			assert(DefPhiIter != PhiDefBlock->GetLastPhi());
			size_t PhiListSize = DefPhiIter->GetPhiListSize();
			PhiDefBlock->SetProcessed(true); // Prevent infinite recursion
			for (size_t UseIndex = 0; UseIndex < PhiListSize; ++UseIndex) {
				int PhiUseSSANum = DefPhiIter->GetUseSSANum(UseIndex);
				if (this->IsOpSourceLeftShift(UseOp, PhiUseSSANum, ShiftCounterOp, ShiftedOp, ShiftInstAddr)) {
					FoundLeftShiftInst = true; // only one success on all Phi USEs is needed
					break;
				}
			}
		}
	}
	else {
		SMPInstr *DefInst = this->GetBlock()->GetFunc()->GetInstFromAddr(UseDefAddr);
		if (DefInst->MDIsLeftShift()) {
			FoundLeftShiftInst = true;
			ShiftInstAddr = UseDefAddr;
			DefInst->GetShiftOperands(ShiftedOp, ShiftCounterOp);
		}
		else if (DefInst->MDIsMoveInstr()) {
			op_t MoveUseOp = DefInst->GetMoveSource();
			if (MDIsDataFlowOpnd(MoveUseOp, UseFP)) { // pattern is simple; don't try to follow through non-stack memory
				CanonicalizeOpnd(MoveUseOp);
				set<DefOrUse, LessDefUse>::iterator MoveUseIter = DefInst->FindUse(MoveUseOp);
				assert(MoveUseIter != DefInst->GetLastUse());
				int MoveUseSSANum = MoveUseIter->GetSSANum();
				FoundLeftShiftInst = DefInst->IsOpSourceLeftShift(MoveUseOp, MoveUseSSANum, ShiftCounterOp, ShiftedOp, ShiftInstAddr); // recurse
			}
		}
		else {
			// Not a move, not a condition code transfer. We must return false.
			FoundLeftShiftInst = false;
		}
	}

	return FoundLeftShiftInst;
} // end of SMPInstr::IsOpSourceLeftShift()

// Does UseOp ultimately come from a move-with-zero-extension instruction?
clc5q's avatar
clc5q committed
bool SMPInstr::IsOpSourceZeroExtendedMove(op_t UseOp, int UseSSANum, bool TruncationCheck) {
	bool UseFP = this->GetBlock()->GetFunc()->UsesFramePointer();
	if ((UseSSANum == -1) || (!MDIsDataFlowOpnd(UseOp, UseFP))) {
	bool LocalName = this->GetBlock()->IsLocalName(UseOp);
	bool IndirectMemAccess = MDIsIndirectMemoryOpnd(UseOp, UseFP);
	bool AboveStackFrame = (!RegDef && !IndirectMemAccess && (this->GetBlock()->GetFunc()->WritesAboveLocalFrame(UseOp, this->AreDefsNormalized())));
	ea_t UseAddr = this->GetAddr();
	ea_t FirstFuncAddr = this->GetBlock()->GetFunc()->GetFirstFuncAddr();
	ea_t UseDefAddr = this->GetBlock()->GetDefAddrFromUseAddr(UseOp, UseAddr, UseSSANum, LocalName);
	bool UpExposedUse = (UseDefAddr == (this->GetBlock()->GetFirstAddr() - 1));
	if (!LocalName && !AboveStackFrame && !IndirectMemAccess && ((UseDefAddr == BADADDR) || UpExposedUse)) {
		// Try to find in the function level.
		UseDefAddr = this->GetBlock()->GetFunc()->GetGlobalDefAddr(UseOp, UseSSANum);
	}

	if ((UseDefAddr == (FirstFuncAddr - 1)) || AboveStackFrame
		|| (UseDefAddr == BADADDR) || IndirectMemAccess) {
		// Cannot search for general memory DEFs; must be stack or register.
clc5q's avatar
clc5q committed
		//  FirstFuncAddr - 1 signifies the pseudo-inst to hold DEFs of regs
		//  that are LiveIn to the function; pseudo-inst is not a bitwise not.
		//  First block addr - 1 is pseudo-location that indicates live-in, UpExposed, 
		//   and LocalName means we will not find a DEF anywhere besides this block.
		//   AboveStackFrame means an incoming arg, whose DEF will not be seen.
clc5q's avatar
clc5q committed
		FoundMoveZX = false; 
	}
	else if (UseDefAddr < this->GetBlock()->GetFunc()->GetNumBlocks()) {
		// A block number was returned. That means the DEF is in a Phi Function.
		//  We could trace all Phi USEs and see if all of them come from zero-extended
		//  moves into the UseOp register, but we only need one of the Phi USEs to come from
		//  a zero-extended move to potentially lead to a false positive numeric error. We
		//  will recurse on all Phi USEs, declaring success if we find a single one of them
		//  to come from a zero-extended move.
clc5q's avatar
clc5q committed
		size_t BlockNum = (size_t) UseDefAddr;
		assert(!LocalName);
		SMPBasicBlock *PhiDefBlock = this->GetBlock()->GetFunc()->GetBlockByNum(BlockNum);
		assert(NULL != PhiDefBlock);
		if (!PhiDefBlock->IsProcessed()) { // Prevent infinite recursion
			set<SMPPhiFunction, LessPhi>::iterator DefPhiIter = PhiDefBlock->FindPhi(UseOp);
			assert(DefPhiIter != PhiDefBlock->GetLastPhi());
			size_t PhiListSize = DefPhiIter->GetPhiListSize();
			PhiDefBlock->SetProcessed(true); // Prevent infinite recursion
			for (size_t UseIndex = 0; UseIndex < PhiListSize; ++UseIndex) {
				int PhiUseSSANum = DefPhiIter->GetUseSSANum(UseIndex);
				if (this->IsOpSourceZeroExtendedMove(UseOp, PhiUseSSANum, TruncationCheck)) {
					FoundMoveZX = true; // only one success on all Phi USEs is needed
					break;
		}
	}
	else {
		SMPInstr *DefInst = this->GetBlock()->GetFunc()->GetInstFromAddr(UseDefAddr);
		unsigned short SignMask;
		if (DefInst->MDIsSignedLoad(SignMask)) {
			FoundMoveZX = (FG_MASK_UNSIGNED == SignMask);
		}
		else if (DefInst->MDIsMoveInstr()) {
			op_t MoveUseOp = DefInst->GetMoveSource();
			if (MDIsDataFlowOpnd(MoveUseOp, UseFP)) { // pattern is simple; don't try to follow through non-stack memory
				CanonicalizeOpnd(MoveUseOp);
				set<DefOrUse, LessDefUse>::iterator MoveUseIter = DefInst->FindUse(MoveUseOp);
				assert(MoveUseIter != DefInst->GetLastUse());
				int MoveUseSSANum = MoveUseIter->GetSSANum();
clc5q's avatar
clc5q committed
				FoundMoveZX = DefInst->IsOpSourceZeroExtendedMove(MoveUseOp, MoveUseSSANum, TruncationCheck); // recurse
			}
		}
		else if (TruncationCheck && DefInst->MDIsNonOverflowingBitManipulation()) {
clc5q's avatar
clc5q committed
			// Not a move, not a zero-extended move. We must return false for the non-truncation case,
			//  but we allow non-overflowing bit manipulation instructions in the chain for truncation checks.
			//  This is because of a benign code pattern:
			//   reg: = zero-extended move
			//   reg := reg AND bit pattern
			//   reg := reg OR bit pattern
			//   store lower bits of reg
			//  Compilers like to do 32-bit arithmetic. There was never any good reason otherwise to zero-extend the
			//   value in the first instruction in the pattern. The lower bits that are stored at the end of the code
			//   sequence are the only bits that ever mattered, so this is not really a truncation.
			set<DefOrUse, LessDefUse>::iterator BitUseIter = DefInst->FindUse(UseOp);
			if (BitUseIter != DefInst->GetLastUse()) {
				int BitUseSSANum = BitUseIter->GetSSANum();
				FoundMoveZX = DefInst->IsOpSourceZeroExtendedMove(UseOp, BitUseSSANum, true); // recurse up the chain
	return FoundMoveZX;
} // end of SMPInstr::IsOpSourceZeroExtendedMove()
// Does UseOp ultimately come from a move-with-zero-extension instruction OR from a condition code OR from a right shift?
bool SMPInstr::IsOpSourceZeroExtendedMoveShiftRightOrConditionCode(op_t UseOp, int UseSSANum, bool TruncationCheck) {
	bool UseFP = this->GetBlock()->GetFunc()->UsesFramePointer();
	if ((UseSSANum == -1) || (!MDIsDataFlowOpnd(UseOp, UseFP))) {
	bool LocalName = this->GetBlock()->IsLocalName(UseOp);
	bool IndirectMemAccess = MDIsIndirectMemoryOpnd(UseOp, UseFP);
	bool AboveStackFrame = (!RegDef && !IndirectMemAccess && (this->GetBlock()->GetFunc()->WritesAboveLocalFrame(UseOp, this->AreDefsNormalized())));
	ea_t UseAddr = this->GetAddr();
	ea_t FirstFuncAddr = this->GetBlock()->GetFunc()->GetFirstFuncAddr();
	ea_t UseDefAddr = this->GetBlock()->GetDefAddrFromUseAddr(UseOp, UseAddr, UseSSANum, LocalName);
	bool UpExposedUse = (UseDefAddr == (this->GetBlock()->GetFirstAddr() - 1));
	if (!LocalName && !AboveStackFrame && !IndirectMemAccess && ((UseDefAddr == BADADDR) || UpExposedUse)) {
		// Try to find in the function level.
		UseDefAddr = this->GetBlock()->GetFunc()->GetGlobalDefAddr(UseOp, UseSSANum);
	}

	if ((UseDefAddr == (FirstFuncAddr - 1)) || AboveStackFrame
		|| (UseDefAddr == BADADDR) || IndirectMemAccess) {
		// Cannot search for general memory DEFs; must be stack or register.
		//  FirstFuncAddr - 1 signifies the pseudo-inst to hold DEFs of regs
		//  that are LiveIn to the function; pseudo-inst is not a bitwise not.
		//  First block addr - 1 is pseudo-location that indicates live-in, UpExposed, 
		//   and LocalName means we will not find a DEF anywhere besides this block.
		//   AboveStackFrame means an incoming arg, whose DEF will not be seen.
		FoundMoveZXCC = false; 
	}
	else if (UseDefAddr < this->GetBlock()->GetFunc()->GetNumBlocks()) {
		// A block number was returned. That means the DEF is in a Phi Function.
		//  We could trace all Phi USEs and see if all of them come from zero-extended
		//  moves into the UseOp register, but we only need one of the Phi USEs to come from
		//  a zero-extended move to potentially lead to a false positive numeric error. We
		//  will recurse on all Phi USEs, declaring success if we find a single one of them
		//  to come from a zero-extended move.
		size_t BlockNum = (size_t) UseDefAddr;
		assert(!LocalName);
		SMPBasicBlock *PhiDefBlock = this->GetBlock()->GetFunc()->GetBlockByNum(BlockNum);
		assert(NULL != PhiDefBlock);
		if (!PhiDefBlock->IsProcessed()) { // Prevent infinite recursion
			set<SMPPhiFunction, LessPhi>::iterator DefPhiIter = PhiDefBlock->FindPhi(UseOp);
			assert(DefPhiIter != PhiDefBlock->GetLastPhi());
			size_t PhiListSize = DefPhiIter->GetPhiListSize();
			PhiDefBlock->SetProcessed(true); // Prevent infinite recursion
			for (size_t UseIndex = 0; UseIndex < PhiListSize; ++UseIndex) {
				int PhiUseSSANum = DefPhiIter->GetUseSSANum(UseIndex);