Skip to content
Snippets Groups Projects
SMPInstr.cpp 620 KiB
Newer Older
		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);
				if (this->IsOpSourceZeroExtendedMoveShiftRightOrConditionCode(UseOp, PhiUseSSANum, TruncationCheck)) {
					FoundMoveZXCC = 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)) {
			FoundMoveZXCC = (FG_MASK_UNSIGNED == SignMask);
		}
		else if (DefInst->MDIsAnySetValue() || DefInst->MDIsShiftRight()) {
			FoundMoveZXCC = 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();
				FoundMoveZXCC = DefInst->IsOpSourceZeroExtendedMoveShiftRightOrConditionCode(MoveUseOp, MoveUseSSANum, TruncationCheck); // recurse
			}
		}
clc5q's avatar
clc5q committed
		else if (TruncationCheck && (DefInst->MDIsNonOverflowingBitManipulation() || DefInst->MDIsSmallAdditionOrSubtraction())) {
			// 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.
clc5q's avatar
clc5q committed
			// NOTE: We combine into this case additions or subtractions of small values, as they only operate on the
			//  lower bits of the register.
			set<DefOrUse, LessDefUse>::iterator BitUseIter = DefInst->FindUse(UseOp);
			if (BitUseIter != DefInst->GetLastUse()) {
				int BitUseSSANum = BitUseIter->GetSSANum();
				FoundMoveZXCC = DefInst->IsOpSourceZeroExtendedMoveShiftRightOrConditionCode(UseOp, BitUseSSANum, true); // recurse up the chain
			}
		}
		else {
			FoundMoveZXCC = false;
		}
	}

	return FoundMoveZXCC;
} // end of SMPInstr::IsOpSourceZeroExtendedMoveShiftRightOrConditionCode()
// Trace through moves to any of the above cases, return source inst
bool SMPInstr::IsOpSourceSpecial(op_t UseOp, int UseSSANum, bool TruncationCheck, ea_t &SourceInstAddr) {
	bool UseFP = this->GetBlock()->GetFunc()->UsesFramePointer();
	if ((UseSSANum == -1) || (!MDIsDataFlowOpnd(UseOp, UseFP))) {
		return false;
	}

	bool FoundMoveNotZXCCSubreg = 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.
		FoundMoveNotZXCCSubreg = 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);
				if (this->IsOpSourceSpecial(UseOp, PhiUseSSANum, TruncationCheck, SourceInstAddr)) {
					FoundMoveNotZXCCSubreg = 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)) {
			FoundMoveNotZXCCSubreg = ((FG_MASK_UNSIGNED == SignMask) || TruncationCheck); // Truncation chain cares if source was reduced width.
			if (FoundMoveNotZXCCSubreg) {
				SourceInstAddr = DefInst->GetAddr();
			}
		}
		else if (DefInst->MDIsAnySetValue() || DefInst->MDIsShiftRight() || DefInst->MDIsBitwiseNotOpcode()) {
			FoundMoveNotZXCCSubreg = true;
			SourceInstAddr = DefInst->GetAddr();
		}
		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();
				FoundMoveNotZXCCSubreg = DefInst->IsOpSourceSpecial(MoveUseOp, MoveUseSSANum, TruncationCheck, SourceInstAddr); // recurse
			}
		}
		else if (TruncationCheck && (DefInst->MDIsNonOverflowingBitManipulation() || DefInst->MDIsSmallAdditionOrSubtraction())) {
			// 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.
			// NOTE: We combine into this case additions or subtractions of small values, as they only operate on the
			//  lower bits of the register.
			set<DefOrUse, LessDefUse>::iterator BitUseIter = DefInst->FindUse(UseOp);
			if (BitUseIter != DefInst->GetLastUse()) {
				int BitUseSSANum = BitUseIter->GetSSANum();
				FoundMoveNotZXCCSubreg = DefInst->IsOpSourceSpecial(UseOp, BitUseSSANum, true, SourceInstAddr); // recurse up the chain
			}
		}
clc5q's avatar
clc5q committed
		else if (TruncationCheck) {
			// Check for reduced-width arithmetic.
			if (DefInst->IsReducedWidthDef()) { // chain like sub cl,3; mov eax,ecx; then "truncating" move of al
				FoundMoveNotZXCCSubreg = true;
				SourceInstAddr = DefInst->GetAddr();
			}
		}
	}

	return FoundMoveNotZXCCSubreg;
} // end of SMPInstr::IsOpSourceSpecial()

// Is opcode a shift or rotate?
// NOTE: We omit MMX/SSE unit shifts that do not use a general purpose
//  register as a shift counter, because right now this method is only
//  used as a helper for IsSubRegUsedAsShiftCount().
bool SMPInstr::MDIsShiftOrRotate(void) const {
	return (((NN_rcl <= SMPcmd.itype) && (NN_ror >= SMPcmd.itype))
		|| ((NN_sal <= SMPcmd.itype) && (NN_shr >= SMPcmd.itype))
		|| (NN_shld == SMPcmd.itype) || (NN_shrd == SMPcmd.itype));
} // end of SMPInstr::MDIsShiftOrRotate()
// Is opcode a shift to the right?
bool SMPInstr::MDIsShiftRight(void) const {
	return ((NN_sar == SMPcmd.itype) || (NN_shr == SMPcmd.itype));
}

// Does the shift or rotate RTL move the upper HalfBitWidth bits
//  into the lower half of the register? Or, if MustBeHalfRegWidth is false,
//  do we shift right by HalfBitWidth bits?
bool SMPInstr::ShiftMakesUpperBitsLower(size_t HalfBitWidth, bool MustBeHalfRegWidth) {
	if (!MustBeHalfRegWidth || (MD_NORMAL_MACHINE_BITWIDTH == (HalfBitWidth * 2))) {
		SMPRegTransfer *CurrRT = this->RTL.GetRT(0);
		if ((NULL != CurrRT) && (CurrRT->HasRightSubTree())) {
			CurrRT = CurrRT->GetRightTree();
			SMPoperator CurrOper =  CurrRT->GetOperator();
			bool LeftRotate = (SMP_ROTATE_LEFT == CurrOper);
			if ((SMP_U_RIGHT_SHIFT == CurrOper) || (SMP_S_RIGHT_SHIFT == CurrOper)
				|| LeftRotate || (SMP_ROTATE_RIGHT == CurrOper)) {
				if (CurrRT->HasRightSubTree()) { // double-word shift
					CurrRT = CurrRT->GetRightTree();
				}
				assert(!(CurrRT->HasRightSubTree()));
				op_t ShiftCount = CurrRT->GetRightOperand();
				if (o_imm == ShiftCount.type) {
					uval_t ImmVal = ShiftCount.value;
					// If we rotate left by e.g. 32-HalfBitWidth bits, then we are processing
					//  bytes or halfregs one at a time; if we rotate or shift right by HalfBitWidth,
					//  we are processing the register one HalfBitWidth at a time. We also a
					if (MustBeHalfRegWidth || (!LeftRotate)) {
						FullCircle = (HalfBitWidth == ImmVal);
					}
					else {
						// Left rotate amount plus HalfBitWidth must add up to full register width
						FullCircle = (MD_NORMAL_MACHINE_BITWIDTH == (ImmVal + HalfBitWidth));
					}
				}
			}
		}
	}
	return FullCircle;
} // SMPInstr::ShiftMakesUpperBitsLower()

#if 0
// Find SearchDelta in StackDeltaSet, inserting it if not found. Return whether it was initially found.
bool SMPInstr::FindStackPtrDelta(sval_t SearchDelta) const {
	bool found = (this->StackDeltaSet.find(SearchDelta) != this->StackDeltaSet.end());
	if (!found) {
		this->StackDeltaSet.insert(SearchDelta);
		if (SearchDelta < this->StackPtrOffset) {
			// Mimic IDA Pro, which seems to keep the biggest stack frame possible.
			//  With negative stack deltas, this means the smallest stack delta is kept.
			this->SetStackPtrOffset(SearchDelta);
		}
	}
	return found;
} // end of SMPInstr::FindStackPtrDelta()
#endif

// Set the type of all immediate operands found in the USE set.
// Set all flags and floating point register USEs and DEFs to NUMERIC also,
//  along with easily determined types for special cases.
void SMPInstr::SetImmedTypes(bool UseFP) {
	set<DefOrUse, LessDefUse>::iterator CurrUse;
	set<DefOrUse, LessDefUse>::iterator CurrDef;
	bool DebugFlag = false;
#if SMP_VERBOSE_DEBUG_BUILD_RTL
	DebugFlag = DebugFlag || (this->address == 0x805cd52) || (this->address == 0x805cd56);
	DebugFlag |= (0 == strncmp("__libc_csu_fini", this->BasicBlock->GetFunc()->GetFuncName(), 15));
#endif

	CurrUse = this->GetFirstUse();
	while (CurrUse != this->GetLastUse()) {
		UseOp = CurrUse->GetOp();
		if (DebugFlag) {
			PrintOperand(UseOp);
		if (o_imm == UseOp.type) {
			ImmVal = UseOp.value;
			if (IsImmedGlobalAddress((ea_t) ImmVal)) {
				if (DebugFlag) SMP_msg("Setting to GLOBALPTR\n");
				CurrUse = this->SetUseType(UseOp, GLOBALPTR);
#if 0
			else if (IsDataAddress((ea_t) ImmVal)) {
				// NOTE: We must call IsDataAddress() before we call IsImmedCodeAddress()
				//  to catch the data addresses within the code address range.
				if (DebugFlag) SMP_msg("Setting to POINTER\n");
				CurrUse = this->SetUseType(UseOp, POINTER);
			}
#endif
			else if (this->MDIsInterruptCall() || IsImmedCodeAddress((ea_t) ImmVal)) {
				if (DebugFlag) SMP_msg("Setting to CODEPTR\n");
				CurrUse = this->SetUseType(UseOp, CODEPTR);
				if (DebugFlag) SMP_msg("Setting to NUMERIC\n");
				CurrUse = this->SetUseType(UseOp, NUMERIC);
		else if (o_reg == UseOp.type) {
			if (UseOp.is_reg(X86_FLAGS_REG)) {
				if (DebugFlag) SMP_msg("Setting flags reg to NUMERIC\n");
				CurrUse = this->SetUseType(UseOp, NUMERIC);
			}
#if 1
			else if (MDIsStackOrFramePointerReg(UseOp, UseFP)) {
				if (DebugFlag) SMP_msg("Setting reg to STACKPTR\n");
				CurrUse = this->SetUseType(UseOp, STACKPTR);
			}
#endif
		}
#if 0  // could these registers have pointers in them?
		else if ((o_trreg == UseOp.type) ||(o_dbreg == UseOp.type) || (o_crreg == UseOp.type)) {
			if (DebugFlag) SMP_msg("Setting special reg to NUMERIC\n");
			CurrUse = this->SetUseType(UseOp, NUMERIC);
		}