Skip to content
Snippets Groups Projects
SMPInstr.cpp 514 KiB
Newer Older

// Inequality operator for SMPInstr. Key field is address.
int SMPInstr::operator!=(const SMPInstr &rhs) const {
	return (this->address != rhs.GetAddr());
}

// Less than operator for sorting SMPInstr lists. Key field is address.
int SMPInstr::operator<(const SMPInstr &rhs) const {
	return (this->address < rhs.GetAddr());
}

// Less than or equal operator for sorting SMPInstr lists. Key field is address.
int SMPInstr::operator<=(const SMPInstr &rhs) const {
	return (this->address <= rhs.GetAddr());
}

#define MD_FIRST_ENTER_INSTR  NN_enterw
#define MD_LAST_ENTER_INSTR NN_enterq
// Is this instruction one that allocates space on the
//  stack for the local variables?
bool SMPInstr::MDIsFrameAllocInstr(void) {
	// The frame allocating instruction should look like:
	//   sub esp,48   or   add esp,-64   etc.
	ESPOp.type = o_reg;
	ESPOp.reg = R_sp;
	if ((SMPcmd.itype == NN_sub) || (SMPcmd.itype == NN_add)) {
		if (this->GetLastDef() != this->Defs.FindRef(ESPOp)) {
			// We know that an addition or subtraction is being
			//  performed on the stack pointer. This should not be
			//  possible within the prologue except at the stack
			//  frame allocation instruction, so return true. We
			//  could be more robust in this analysis in the future. **!!**
			// CAUTION: If a compiler allocates 64 bytes for locals
			//  and 16 bytes for outgoing arguments in a single
			//  instruction:  sub esp,80
			//  you cannot insist on finding sub esp,LocSize
			// To make this more robust, we are going to insist that
			//  an allocation of stack space is either performed by
			//  adding a negative immediate value, or by subtracting
			//  a positive immediate value. We will throw in, free of
			//  charge, a subtraction of a register, which is how alloca()
			//  usually allocates stack space.
			// PHASE ORDERING: Should we use the Operands[] instead of the USE list? **!!**
			set<DefOrUse, LessDefUse>::iterator CurrUse;
			for (CurrUse = this->GetFirstUse(); CurrUse != this->GetLastUse(); ++CurrUse) {
				if (o_imm == CurrUse->GetOp().type) {
					signed long TempImm = (signed long) CurrUse->GetOp().value;
					if (((0 > TempImm) && (this->SMPcmd.itype == NN_add))
						|| ((0 < TempImm) && (this->SMPcmd.itype == NN_sub))) {
						return true;
					}
				}
				else if ((o_reg == CurrUse->GetOp().type)
						&& (!CurrUse->GetOp().is_reg(R_sp)) // skip the ESP operand
						&& (this->SMPcmd.itype == NN_sub)) { // sub esp,reg: alloca() ?
	else if ((this->SMPcmd.itype >= MD_FIRST_ENTER_INSTR) 
		&& (this->SMPcmd.itype <= MD_LAST_ENTER_INSTR)) {
		return true;
	}
	return false;
} // end of SMPInstr::MDIsFrameAllocInstr()

#define MD_FIRST_LEAVE_INSTR  NN_leavew
#define MD_LAST_LEAVE_INSTR NN_leaveq
// Is this instruction in the epilogue the one that deallocates the local
//  vars region of the stack frame?
bool SMPInstr::MDIsFrameDeallocInstr(bool UseFP, asize_t LocalVarsSize) {
	// The usual compiler idiom for the prologue on x86 is to
	//  deallocate the local var space with:   mov esp,ebp
	//  It could be  add esp,constant.  We can be tricked by
	//  add esp,constant when the constant is just the stack
	//  adjustment after a call. We will have to insist that
	//  the immediate operand have at least the value of
	//  LocalVarsSize for this second form, and that UseFP be true
	//  for the first form.
	set<DefOrUse, LessDefUse>::iterator FirstDef = this->GetFirstDef();
	set<DefOrUse, LessDefUse>::iterator FirstUse = this->GetFirstUse();
	if ((SMPcmd.itype >= MD_FIRST_LEAVE_INSTR) && (SMPcmd.itype <= MD_LAST_LEAVE_INSTR))
		return true;
	else if (this->HasDestMemoryOperand() || this->HasSourceMemoryOperand()) {
		// Don't get fooled by USE or DEF entries of EBP or ESP that come
		//  from memory operands, e.g. mov eax,[ebp-20]
		return false;
	}
	else if (UseFP && (this->SMPcmd.itype == NN_mov)
		&& (FirstDef->GetOp().is_reg(R_sp))
		&& (FirstUse->GetOp().is_reg(R_bp)))
		return true;
	else if ((this->SMPcmd.itype == NN_add)
		&& (FirstDef->GetOp().is_reg(R_sp))) {
		set<DefOrUse, LessDefUse>::iterator SecondUse = ++FirstUse;
		if (SecondUse == this->Uses.GetLastRef())
			return false;  // no more USEs ... strange for ADD instruction
		if (SecondUse->GetOp().is_imm((uval_t) LocalVarsSize))
			return true;
		else if (SecondUse->GetOp().type == o_imm) {
			signed long	TempImm = (signed long) this->SMPcmd.Operands[1].value;
			if (0 > TempImm) // adding a negative to ESP; alloc, not dealloc
				return false;
			else {
				SMP_msg("Used imprecise LocalVarsSize to find dealloc instr.\n");
	}
	else
		return false;
} // end of SMPInstr::MDIsFrameDeallocInstr()

// Is instruction a no-op? There are 1-byte, 2-byte, etc., versions of no-ops.
bool SMPInstr::MDIsNop(void) const {
	bool IsNop = false;
	ushort opcode = this->SMPcmd.itype;

	// NOTE: More examples have arisen, e.g. xchg reg with itself. !!!!!!

	if (NN_nop == opcode)
		IsNop = true;
	else if (NN_mov == opcode) {
		if ((o_reg == this->SMPcmd.Operands[0].type) 
			&& this->SMPcmd.Operands[1].is_reg(this->SMPcmd.Operands[0].reg)) {
			// We have a register to register move with source == destination.
			IsNop = true;
		}
	}
	else if (NN_lea == opcode) {
		if ((o_reg == this->SMPcmd.Operands[0].type)
			&& (o_displ == this->SMPcmd.Operands[1].type)
			&& (0 == this->SMPcmd.Operands[1].addr)) {
			// We are looking for 6-byte no-ops like lea esi,[esi+0]
				ushort destreg = this->SMPcmd.Operands[0].reg;
				if ((this->SMPcmd.Operands[1].hasSIB)
					&& (destreg == (ushort) sib_base(this->SMPcmd.Operands[1]))
					&& (R_sp == sib_index(this->SMPcmd.Operands[1]))) {
					// R_sp signifies no SIB index register. So, we have
					//  lea reg,[reg+0] with reg being the same in both place,
					//  once as Operands[0] and once as the base reg in Operands[1].
					IsNop = true;
				}
				else if (destreg == this->SMPcmd.Operands[1].reg) {
					IsNop = true;
				}
		}
	}
	return IsNop;
} // end of SMPInstr::MDIsNop()

// Opcode always produces an UNSIGNED DEF.
bool SMPInstr::MDAlwaysUnsignedDEF(void) const {
	ushort opcode = this->SMPcmd.itype;
	return ((opcode == NN_bsf) || (opcode == NN_bsr) || (opcode == NN_div)
		|| (opcode == NN_lahf) || (opcode == NN_lar) || (opcode == NN_lgs)
		|| (opcode == NN_lss) || (opcode == NN_lds) || (opcode == NN_les)
		|| (opcode == NN_lfs) || (opcode == NN_lsl) || (opcode == NN_movzx)
		|| (opcode == NN_rcl) || (opcode == NN_rcr) || (opcode == NN_rol)
		|| (opcode == NN_ror) || (opcode == NN_shl) || (opcode == NN_shr)
		|| ((opcode >= NN_seta) && (opcode <= NN_setz)) || (opcode == NN_cpuid)
		|| (opcode == NN_rdtsc) || (opcode == NN_rdpmc) || (opcode == NN_fstsw)
		|| (opcode == NN_setalc) || (opcode == NN_packuswb) || (opcode == NN_paddusb)
		|| (opcode == NN_paddusw) || (opcode == NN_psllw) || (opcode == NN_pslld)
		|| (opcode == NN_psllq) || (opcode == NN_psrlw) || (opcode == NN_psrld)
		|| (opcode == NN_psrlq) || (opcode == NN_psubusb) || (opcode == NN_psubusw)
		|| (opcode == NN_pxor) || (opcode == NN_pavgusb) || (opcode == NN_pavgb)
		|| (opcode == NN_pavgw) || (opcode == NN_pextrw) || (opcode == NN_pmaxub) 
		|| ((opcode >= NN_pminub) && (opcode <= NN_psadbw))
		|| (opcode == NN_movmskpd) || (opcode == NN_pmuludq) || (opcode == NN_pslldq)
		|| (opcode == NN_psrldq) || ((opcode >= NN_pabsb) && (opcode <= NN_pabsd))
		|| (opcode == NN_rdtscp) || (opcode == NN_mpsadbw) || (opcode == NN_packusdw)
		|| ((opcode >= NN_pcmpeqq) && (opcode <= NN_phminposuw)) || (opcode == NN_pmaxud)
		|| (opcode == NN_pmaxuw) || (opcode == NN_pminud) || (opcode == NN_pminuw)
		|| ((opcode >= NN_pmovzxbw) && (opcode <= NN_pmovzxdq)) || ((opcode >= NN_crc32)
		&& (opcode <= NN_pcmpistrm)) || (opcode == NN_popcnt) || (opcode == NN_lzcnt)
		|| ((opcode >= NN_aesenc) && (opcode <= NN_aeskeygenassist)));
} // end of SMPInstr::MDAlwaysUnsignedDEF()

// Opcode always produces a SIGNED DEF.
bool SMPInstr::MDAlwaysSignedDEF(void) const {
	ushort opcode = this->SMPcmd.itype;
	return ((opcode == NN_cbw) || (opcode == NN_cwde) || (opcode == NN_cdqe)
		|| (opcode == NN_cwd) || (opcode == NN_cdq) || (opcode == NN_cqo)
		|| (opcode == NN_idiv) || (opcode == NN_movsx) || (opcode == NN_neg)
		|| (opcode == NN_sal) || (opcode == NN_sar) || (opcode == NN_fist)
		|| (opcode == NN_fistp) || (opcode == NN_fbstp) || (opcode == NN_packsswb)
		|| (opcode == NN_packssdw) || (opcode == NN_paddsb) || (opcode == NN_paddsw)
		|| (opcode == NN_pmaddwd) || (opcode == NN_pmulhw) || (opcode == NN_pmullw)
		|| (opcode == NN_psraw) || (opcode == NN_psrad) || (opcode == NN_psubsb)
		|| (opcode == NN_psubsw) || (opcode == NN_pfadd) || (opcode == NN_pfsub)
		|| (opcode == NN_pfsubr) || (opcode == NN_pfacc) || (opcode == NN_pfmin)
		|| (opcode == NN_pfmax) || (opcode == NN_pf2id) || (opcode == NN_pfrcp)
		|| (opcode == NN_pfadd) || (opcode == NN_pfrsqrt) || (opcode == NN_pfmul)
		|| (opcode == NN_pfrcpit1) || (opcode == NN_pfrsqit1) || (opcode == NN_pfrcpit2)
		|| (opcode == NN_pmulhrw) || ((opcode >= NN_addps) && (opcode <= NN_andps))
		|| ((opcode >= NN_cvtpi2ps)	&& (opcode <= NN_divss)) || ((opcode >= NN_maxps)
		&& (opcode <= NN_movlps)) || ((opcode >= NN_movss) && (opcode <= NN_sqrtss))
		|| (opcode == NN_subps) || (opcode == NN_subss) || (opcode == NN_unpckhps)
		|| (opcode == NN_unpcklps) || (opcode == NN_pmaxsw) || (opcode == NN_pminsw)
		|| (opcode == NN_movntps) || (opcode == NN_pf2iw) || (opcode == NN_pfnacc) 
		|| (opcode == NN_pfpnacc) || (opcode == NN_pi2fw) || ((opcode >= NN_addpd)
		&& (opcode <= NN_andpd)) || ((opcode >= NN_cvtdq2pd) && (opcode <= NN_divsd))
		|| (opcode == NN_maxpd) || (opcode == NN_maxsd) || ((opcode >= NN_minpd)
		&& (opcode <= NN_movapd)) || (opcode == NN_movhpd) || (opcode == NN_movlpd)
		|| (opcode == NN_movntpd) || ((opcode >= NN_movsd) && (opcode <= NN_orpd))
		|| ((opcode >= NN_sqrtpd) && (opcode <= NN_subsd)) && ((opcode >= NN_unpckhpd)
		&& (opcode <= NN_xorpd)) || ((opcode >= NN_movddup) && (opcode <= NN_movsxd))
		|| ((opcode >= NN_addsubpd) && (opcode <= NN_hsubps)) || (opcode == NN_fisttp)
		|| ((opcode >= NN_psignb) && (opcode <= NN_psignd)) || ((opcode >= NN_pmulhrsw)
		&& (opcode <= NN_phsubd)) || (opcode == NN_pfrcpv) || (opcode == NN_pfrsqrtv)
		|| ((opcode >= NN_blendpd) && (opcode <= NN_insertps)) || (opcode == NN_pmaxsb)
		|| (opcode == NN_pmaxsd) || (opcode == NN_pminsb) || (opcode == NN_pminsd)
		|| ((opcode >= NN_pmovsxbw) && (opcode <= NN_pmovsxdq)) || (opcode == NN_pmuldq)
		|| (opcode == NN_pmulld) || ((opcode >= NN_roundpd) && (opcode <= NN_roundss))
		|| (opcode == NN_movntsd) || (opcode == NN_movntss));
} // end of SMPInstr::MDAlwaysSignedDEF()

bool SMPInstr::MDIsAddition(void) const {
	unsigned short opcode = this->SMPcmd.itype;

	return ((NN_adc == opcode) || (NN_add == opcode));
}

// Is non-multiply arithmetic instruction that can possibly overflow?
bool SMPInstr::MDIsOverflowingOpcode(void) const {
	unsigned short opcode = this->SMPcmd.itype;

	return ((NN_adc == opcode) || (NN_add == opcode) || (NN_inc == opcode)
		|| (NN_neg == opcode) || (NN_xadd == opcode));
}

// Is non-multiply arithmetic instruction that can possibly underflow?
bool SMPInstr::MDIsUnderflowingOpcode(void) const {
	unsigned short opcode = this->SMPcmd.itype;

	return ((NN_dec == opcode) || (NN_sbb == opcode) || (NN_sub == opcode));
}

// Is potentially benign overflow instruction?
bool SMPInstr::MDIsMaybeBenignOverflowOpcode(void) const {
	unsigned short opcode = this->SMPcmd.itype;

	return ((NN_adc == opcode) || (NN_add == opcode));
}

// Is potentially benign underflow instruction?
bool SMPInstr::MDIsMaybeBenignUnderflowOpcode(void) const {
	unsigned short opcode = this->SMPcmd.itype;

	return ((NN_neg == opcode) || (NN_sbb == opcode) || (NN_sub == opcode));
}

// Is definitely benign underflow instruction?
//  NOTE: Overlaps with MDIsMaybeBenignUnderflowOpcode(), so call this one first.
bool SMPInstr::MDIsDefiniteBenignUnderflowOpcode(int &IdiomCode) {
	unsigned short opcode = this->SMPcmd.itype;

	// gcc use:  sbb edx,edx as a tricky way to get all zeroes or all ones into edx.
	//  (Some sort of saturation? Often treated as 0 or -1, i.e. it becomes SIGNED
	//   even if it used to be UNSIGNED.)
	//  The "underflow" on the subtraction is irrelevant and benign.
	bool benign = ((NN_sbb == opcode) && (this->SubtractsFromItself()));
	if (benign) {
		IdiomCode = 4;
	}
	return benign;
}

// Does a subtraction operator get applied to same left and right operands?
bool SMPInstr::SubtractsFromItself(void) {
	bool SelfSubtract = false;
	size_t RTLCount = this->RTL.GetCount();
	for (size_t index = 0; index < RTLCount; ++index) {
		SMPRegTransfer *CurrRT = this->RTL.GetRT(index);
		if ((CurrRT != NULL) && (CurrRT->HasRightSubTree())) {
			CurrRT = CurrRT->GetRightTree();
			SMPoperator CurrOp = CurrRT->GetOperator();
			if ((SMP_SUBTRACT_BORROW == CurrOp) || (SMP_SUBTRACT == CurrOp)) {
				if (!(CurrRT->HasRightSubTree())) {
					// NOTE: Must change this code when we build more precise SMP_SUBTRACT_BORROW RTL.
					op_t LeftOp = CurrRT->GetLeftOperand();
					op_t RightOp = CurrRT->GetRightOperand();
					SelfSubtract = IsEqOp(RightOp, LeftOp);
				}
				break;
			}
		}
	}
	return SelfSubtract;
} // end of SMPInstr::SubtractsFromItself()

// Does instruction subtract an immediate value that is often used in ASCII computations,
//  such as the ASCII code for '0', 'a', or 'A' ?
bool SMPInstr::SubtractsImmedASCII(void) {
	return (this->MDIsMaybeBenignUnderflowOpcode() && (o_imm == this->AddSubSourceOp.type)
		&& (('0' == this->AddSubSourceOp.value) || ('a' == this->AddSubSourceOp.value)
		|| ('A' == this->AddSubSourceOp.value)));
}

// Does instruction compare a location to an immediate value that is often used in ASCII computations,
//  such as the ASCII code for '0' or '9', 'a' or 'A', 'z' or 'Z', or carriage return?
#define SMP_ASCII_CARRIAGE_RETURN 13
bool SMPInstr::MDComparesImmedASCII(void) {
	bool ComparesToASCII = false;
	if (this->SMPcmd.itype == NN_cmp) {
		SMPRegTransfer *CurrRT = this->RTL.GetRT(0);
		if ((CurrRT != NULL) && (CurrRT->HasRightSubTree())) {
			CurrRT = CurrRT->GetRightTree();
			if (!(CurrRT->HasRightSubTree())) {
				op_t LeftOp = CurrRT->GetLeftOperand();
				op_t RightOp = CurrRT->GetRightOperand();
				if ((o_imm == RightOp.type) && ((SMP_ASCII_CARRIAGE_RETURN == RightOp.value)	
					|| ('0' == RightOp.value) || ('9' == RightOp.value) 
					|| ('a' == RightOp.value) || ('z' == RightOp.value)
					|| ('A' == RightOp.value) || ('Z' == RightOp.value))) {
					ComparesToASCII = true;
				}
			}
		}
	}
	return ComparesToASCII;
} // end of SMPInstr::MDComparesImmedASCII()

// Multiply by large constant; overflow is probably intentional.
#define STARS_LARGE_UNSIGNED_MUL_CONSTANT_THRESHOLD 0x80000000
#define STARS_LARGE_SIGNED_MUL_CONSTANT_THRESHOLD 0x40000000
#define STARS_SMALL_SIGNED_MUL_CONSTANT_THRESHOLD ((int)(-STARS_LARGE_SIGNED_MUL_CONSTANT_THRESHOLD))
bool SMPInstr::IsMultiplyByLargeConstant(uval_t &ConstValue, unsigned short SignMask) {
	bool LargeConstFound = false;

	if (this->MDIsMultiply() && (SignMask != FG_MASK_INCONSISTENT_SIGN) && (SignMask != 0)) {
		set<DefOrUse, LessDefUse>::iterator UseIter;
		for (UseIter = this->GetFirstUse(); UseIter != this->GetLastUse(); ++UseIter) {
			if (this->FindConstantValue(UseIter, ConstValue)) {
				if (FG_MASK_UNSIGNED == SignMask) {
					if (((uval_t) STARS_LARGE_UNSIGNED_MUL_CONSTANT_THRESHOLD) <= ConstValue) {
						LargeConstFound = true;
						break;
					}
				}
				else if (FG_MASK_SIGNED == SignMask) {
					int SignedConstValue = (int) ConstValue;
					if ( (((int) STARS_LARGE_SIGNED_MUL_CONSTANT_THRESHOLD) <= SignedConstValue)
						|| (((int) STARS_SMALL_SIGNED_MUL_CONSTANT_THRESHOLD) >= SignedConstValue)) {
						LargeConstFound = true;
						break;
					}
				}
			}
		}
	}

	return LargeConstFound;
} // end of SMPInstr::IsMultiplyByLargeConstant()

// Subtraction of large constant; underflow is probably intentional.
#define STARS_LARGE_UNSIGNED_SUB_CONSTANT_THRESHOLD 0x80000000
#define STARS_LARGE_SIGNED_SUB_CONSTANT_THRESHOLD 0x40000000
#define STARS_SMALL_SIGNED_SUB_CONSTANT_THRESHOLD ((int)(-STARS_LARGE_SIGNED_SUB_CONSTANT_THRESHOLD))
bool SMPInstr::IsSubtractionOfLargeConstant(uval_t &ConstValue, unsigned short SignMask) {
	bool LargeConstFound = false;

	if (this->MDIsUnderflowingOpcode() && (SignMask != FG_MASK_INCONSISTENT_SIGN) && (SignMask != 0)) {
		op_t SubtrahendOp = this->AddSubSourceOp;
		if (o_void != SubtrahendOp.type) {
			set<DefOrUse, LessDefUse>::iterator UseIter = this->FindUse(SubtrahendOp);
			if (this->FindConstantValue(UseIter, ConstValue)) {
				if (FG_MASK_UNSIGNED == SignMask) {
					if (((uval_t) STARS_LARGE_UNSIGNED_SUB_CONSTANT_THRESHOLD) <= ConstValue) {
						LargeConstFound = true;
					}
				}
				else if (FG_MASK_SIGNED == SignMask) {
					int SignedConstValue = (int) ConstValue;
					if ( (((int) STARS_LARGE_SIGNED_SUB_CONSTANT_THRESHOLD) <= SignedConstValue)
						|| (((int) STARS_SMALL_SIGNED_SUB_CONSTANT_THRESHOLD) >= SignedConstValue)) {
						LargeConstFound = true;
					}
				}
			}
		}
	}

	return LargeConstFound;
} // end of SMPInstr::IsSubtractionOfLargeConstant()

// Subtraction of large constant; underflow is probably intentional.
#define STARS_LARGE_UNSIGNED_ADD_CONSTANT_THRESHOLD 0x80000000
#define STARS_LARGE_SIGNED_ADD_CONSTANT_THRESHOLD 0x40000000
#define STARS_SMALL_SIGNED_ADD_CONSTANT_THRESHOLD ((int)(-STARS_LARGE_SIGNED_ADD_CONSTANT_THRESHOLD))
bool SMPInstr::IsAdditionOfLargeConstant(uval_t &ConstValue, unsigned short SignMask) {
	bool LargeConstFound = false;

	if (this->MDIsOverflowingOpcode() && (SignMask != FG_MASK_INCONSISTENT_SIGN) && (SignMask != 0)) {
		op_t AddendOp = this->AddSubSourceOp;
		if (o_void != AddendOp.type) {
			set<DefOrUse, LessDefUse>::iterator UseIter = this->FindUse(AddendOp);
			if (this->FindConstantValue(UseIter, ConstValue)) {
				if (FG_MASK_UNSIGNED == SignMask) {
					if (((uval_t) STARS_LARGE_UNSIGNED_ADD_CONSTANT_THRESHOLD) <= ConstValue) {
						LargeConstFound = true;
					}
				}
				else if (FG_MASK_SIGNED == SignMask) {
					int SignedConstValue = (int) ConstValue;
					if ( (((int) STARS_LARGE_SIGNED_ADD_CONSTANT_THRESHOLD) <= SignedConstValue)
						|| (((int) STARS_SMALL_SIGNED_ADD_CONSTANT_THRESHOLD) >= SignedConstValue)) {
						LargeConstFound = true;
					}
				}
			}
		}
	}

	return LargeConstFound;
} // end of SMPInstr::IsAdditionOfLargeConstant()

// MACHINE DEPENDENT: Is instruction a return instruction?
bool SMPInstr::MDIsReturnInstr(void) const {
	return ((this->SMPcmd.itype == NN_retn) || (this->SMPcmd.itype == NN_retf));
}

// MACHINE DEPENDENT: Is instruction a POP instruction?
#define FIRST_POP_INST   NN_pop
#define LAST_POP_INST    NN_popfq
bool SMPInstr::MDIsPopInstr(void) const {
	return ((this->SMPcmd.itype >= FIRST_POP_INST)
			&& (this->SMPcmd.itype <= LAST_POP_INST));
}

// MACHINE DEPENDENT: Is instruction a PUSH instruction?
#define FIRST_PUSH_INST   NN_push
#define LAST_PUSH_INST    NN_pushfq
bool SMPInstr::MDIsPushInstr(void) const {
	return ((this->SMPcmd.itype >= FIRST_PUSH_INST)
			&& (this->SMPcmd.itype <= LAST_PUSH_INST));
}

// MACHINE DEPENDENT: Is instruction an ENTER instruction?
bool SMPInstr::MDIsEnterInstr(void) const {
	return ((this->SMPcmd.itype >= MD_FIRST_ENTER_INSTR)
			&& (this->SMPcmd.itype <= MD_LAST_ENTER_INSTR));
}

// MACHINE DEPENDENT: Is instruction a LEAVE instruction?
bool SMPInstr::MDIsLeaveInstr(void) const {
	return ((this->SMPcmd.itype >= MD_FIRST_LEAVE_INSTR)
			&& (this->SMPcmd.itype <= MD_LAST_LEAVE_INSTR));
// MACHINE DEPENDENT: Is instruction a HALT instruction?
bool SMPInstr::MDIsHaltInstr(void) const {
	return (NN_hlt == this->SMPcmd.itype);
}

#define MD_FIRST_COND_MOVE_INSTR NN_cmova
#define MD_LAST_COND_MOVE_INSTR  NN_fcmovnu
// MACHINE DEPENDENT: Is instruction a conditional move?
bool SMPInstr::MDIsConditionalMoveInstr(void) const {
	return ((this->SMPcmd.itype >= MD_FIRST_COND_MOVE_INSTR)
			&& (this->SMPcmd.itype <= MD_LAST_COND_MOVE_INSTR));
// MACHINE DEPENDENT: Is instruction any kind of move?
bool SMPInstr::MDIsMoveInstr(void) const {
	return ((NN_mov == this->SMPcmd.itype) || (NN_movsx == this->SMPcmd.itype)
		|| (NN_movzx == this->SMPcmd.itype) || this->MDIsConditionalMoveInstr());
}

// MACHINE DEPENDENT: Do opcode/operands definitely indicate signed arithmetic?
//  Generally, this is only true for certain variants of multiplication and division.
bool SMPInstr::MDIsSignedArithmetic(void) const {
	unsigned short opcode = this->SMPcmd.itype;
	if (NN_idiv == opcode)
		return true;
	if (NN_imul == opcode) {
		// If we discard the upper N bits of the multiplication result, then the
		//  lower N bits are the same for signed and unsigned multiplication, and
		//  gcc/g++ often use the IMUL opcode for both signed and unsigned multiplies
		//  when only N bits of result are retained. Therefore, the SIGNED nature of
		//  IMUL operands can only be inferred from the case in which 2N bits are kept.
		return (!(this->AreMultiplicationBitsDiscarded()));
	}
	else { // idiv and imul are only possible signed cases
		return false;
	}
} // end of SMPInstr::MDIsSignedArithmetic()

// MACHINE DEPENDENT: Is instruction a conditional jump based on an unsigned condition?
bool SMPInstr::MDIsUnsignedBranch(void) const {
	unsigned short opcode = this->SMPcmd.itype;
	return ((NN_ja == opcode) || (NN_jae == opcode) || (NN_jb == opcode) || (NN_jbe == opcode)
		|| (NN_jna == opcode) || (NN_jnae == opcode) || (NN_jnb == opcode) || (NN_jnbe == opcode));
}

// MACHINE DEPENDENT: Is instruction a conditional jump based on a signed condition?
bool SMPInstr::MDIsSignedBranch(void) const {
	unsigned short opcode = this->SMPcmd.itype;
	return ((NN_jg == opcode) || (NN_jge == opcode) || (NN_jl == opcode) || (NN_jle == opcode)
		|| (NN_jng == opcode) || (NN_jnge == opcode) || (NN_jnl == opcode) || (NN_jnle == opcode)
		|| (NN_js == opcode) || (NN_jns == opcode));
}

// MACHINE DEPENDENT: Is instruction a boolean set based on an unsigned condition?
bool SMPInstr::MDIsUnsignedSetValue(void) const {
	unsigned short opcode = this->SMPcmd.itype;
	return ((NN_seta == opcode) || (NN_setae == opcode) || (NN_setb == opcode) || (NN_setbe == opcode)
		|| (NN_setna == opcode) || (NN_setnae == opcode) || (NN_setnb == opcode) || (NN_setnbe == opcode));
}

// MACHINE DEPENDENT: Is instruction a boolean set based on a signed condition?
bool SMPInstr::MDIsSignedSetValue(void) const {
	unsigned short opcode = this->SMPcmd.itype;
	return ((NN_setg == opcode) || (NN_setge == opcode) || (NN_setl == opcode) || (NN_setle == opcode)
		|| (NN_setng == opcode) || (NN_setnge == opcode) || (NN_setnl == opcode) || (NN_setnle == opcode)
		|| (NN_sets == opcode) || (NN_setns == opcode));
}

// MACHINE DEPENDENT: Is instruction a boolean set based on any condition?
bool SMPInstr::MDIsAnySetValue(void) const {
	unsigned short opcode = this->SMPcmd.itype;
	return ((NN_seta <= opcode) && (NN_setz >= opcode));
}

// Is kind of shift or rotate that is used in hash functions
#define STARS_HASH_SHIFT_THRESHOLD 4
bool SMPInstr::MDIsHashingArithmetic(void) const {
	bool FoundHashShift = false;
	unsigned short opcode = this->SMPcmd.itype;
	// We are looking for shifts or rotates in the leftward direction.
	if ((opcode == NN_rcl) || (opcode == NN_rol) || (opcode == NN_shl) || (opcode == NN_shld)) {
		SMPRegTransfer *CurrRT = this->RTL.GetRT(0);
		assert(CurrRT->HasRightSubTree());
		CurrRT = CurrRT->GetRightTree();
		op_t ShiftCountOp = CurrRT->GetRightOperand();
		if (o_imm == ShiftCountOp.type) {
			uval_t CountValue = ShiftCountOp.value;
			FoundHashShift = (CountValue >= STARS_HASH_SHIFT_THRESHOLD);
		}
	}
	return FoundHashShift;
} // end of SMPInstr::MDIsHashingArithmetic()

// Detect comparison of non-immediate to immediate. Return the two operands if true.
bool SMPInstr::MDIsCompareToPositiveConstant(op_t &NonConstOperand, uval_t &ConstValue) const {
	bool CompareToConst = false;

	if (NN_cmp == this->SMPcmd.itype) {
		SMPRegTransfer *CurrRT = this->RTL.GetRT(0);
		assert(CurrRT->HasRightSubTree());
		CurrRT = CurrRT->GetRightTree();
		assert(!(CurrRT->HasRightSubTree()));
		op_t LeftOp = CurrRT->GetLeftOperand();
		op_t RightOp = CurrRT->GetRightOperand();
		if (o_imm == RightOp.type) {
			CompareToConst = true;
			ConstValue = RightOp.value;
			NonConstOperand = LeftOp;
		}
		else if (o_imm == LeftOp.type) { // rare to see immediate first
			CompareToConst = true;
			ConstValue = LeftOp.value;
			NonConstOperand = RightOp;
		}
	}

	return CompareToConst;
} // end of SMPInstr::MDIsCompareToPositiveConstant()

bool SMPInstr::MDIsSubtractionOfConstant(op_t &NonConstOperand, uval_t &ConstValue) const {
	bool SubtractOfConst = false;

	SMPRegTransfer *CurrRT = this->RTL.GetRT(0);
	if (CurrRT->HasRightSubTree()) {
		CurrRT = CurrRT->GetRightTree();
		SMPoperator CurrOp = CurrRT->GetOperator();
		if (SMP_SUBTRACT == CurrOp) {
			assert(!(CurrRT->HasRightSubTree()));
			op_t LeftOp = CurrRT->GetLeftOperand();
			op_t RightOp = CurrRT->GetRightOperand();
			if (o_imm == RightOp.type) {
				SubtractOfConst = true;
				ConstValue = RightOp.value;
				NonConstOperand = LeftOp;
			}
		}
		else if (this->MDIsLoadEffectiveAddressInstr() && (SMP_ADD == CurrOp)) {
			// We could have an addition of a negative constant via an lea opcode,
			//  e.g. lea ecx,[eax-48] will look like ecx := eax+(-48) in the RTL.
			if (!(CurrRT->HasRightSubTree())) {
				op_t LeftOp = CurrRT->GetLeftOperand();
				op_t RightOp = CurrRT->GetRightOperand();
				if (o_imm == RightOp.type) {
					ConstValue = RightOp.value;
					int SignedConstValue = (int) ConstValue;
					if (0 > SignedConstValue) {
						SubtractOfConst = true;
						NonConstOperand = LeftOp;
						ConstValue = (uval_t)(-SignedConstValue); // make +(-x) into -(+x)
					}
				}
			}
		}
	}

	return SubtractOfConst;
} // end of SMPInstr::MDIsSubtractionOfConstant()

// is AND operation that masks off lower BytesMasked bytes
bool SMPInstr::MDIsSubregMaskInst(size_t &BytesMasked) {
	bool MaskingFound = false;

	if (this->MDIsBitwiseAndOpcode()) {
		SMPRegTransfer *CurrRT = this->RTL.GetRT(0);
		if (CurrRT->HasRightSubTree()) {
			CurrRT = CurrRT->GetRightTree();
			SMPoperator CurrOp = CurrRT->GetOperator();
			assert(SMP_BITWISE_AND == CurrOp);
			op_t RightOp = CurrRT->GetRightOperand();
			if (o_imm == RightOp.type) {
				uval_t MaskValue = RightOp.value;
				if (0x01000000 > MaskValue) {
					MaskingFound = true;
					if (0x100 > MaskValue) {
						BytesMasked = 1;
					}
					else if (0x10000 > MaskValue) {
						BytesMasked = 2;
					}
					else {
						BytesMasked = 3;
					}
				}
			}
		}
	}

	return MaskingFound;
}

// MACHINE DEPENDENT: Does instruction use a callee-saved register?
bool SMPInstr::MDUsesCalleeSavedReg(void) {
	set<DefOrUse, LessDefUse>::iterator CurrUse;
	for (CurrUse = this->GetFirstUse(); CurrUse != this->GetLastUse(); ++CurrUse) {
		op_t CurrOp = CurrUse->GetOp();
		if (CurrOp.is_reg(R_bp) || CurrOp.is_reg(R_si)
			|| CurrOp.is_reg(R_di) || CurrOp.is_reg(R_bx)) {
			return true;
		}
	}
	return false;
} // end of SMPInstr::MDUsesCalleeSavedReg()

// Is the instruction a register to register copy of a stack pointer or frame pointer
//  into a general purpose register (which mmStrata will now need to track as a stack 
//  relative pointer)?
bool SMPInstr::MDIsStackPointerCopy(bool UseFP) {
	// OptType 3 indicates a move instruction
	// The lea instruction can perform three operand arithmetic, e.g.
	//  lea ebx,[esp+12] is just ebx:=esp+12, so it is a stack pointer copy.
	if (((this->OptType == 3) || (NN_lea == this->SMPcmd.itype))
		&& (this->GetFirstDef()->GetOp().type == o_reg)
		&& (!(this->GetFirstDef()->GetOp().is_reg(R_sp)))
		&& (!(this->HasSourceMemoryOperand()))) { // reg to reg move
			if (this->GetFirstUse()->GetOp().is_reg(R_bp))
				// Move of base pointer EBP into a general register
				return true;
			else if ((this->GetFirstUse()->GetOp().is_reg(R_sp))
				&& !(this->GetFirstDef()->GetOp().is_reg(R_bp)))
				// Move of ESP into something besides a base pointer
				return true;
		}
		else if (this->GetFirstUse()->GetOp().is_reg(R_sp)) {
			// Move of ESP into a register; no base pointer used in this function
			return true;
		}
	}
	return false;
} // end of SMPInstr::MDIsStackPointerCopy()

// Does any RTL fit the alloca() pattern: stack_pointer -= non-immediate-operand
bool SMPInstr::HasAllocaRTL(void) {
	bool FoundAlloca = false;
	size_t RTLCount = this->RTL.GetCount();
	size_t RTLIndex;

	for (RTLIndex = 0; RTLIndex < RTLCount; ++RTLIndex) {
		SMPRegTransfer *CurrRT = this->RTL.GetRT(RTLIndex);
		if (CurrRT->IsAllocaRTL()) {
			FoundAlloca = true;
			break;
		}
	}

	return FoundAlloca;
} // end of SMPInstr::HasAllocaRTL()

// Determine if the instruction saves or restores a pointer into the stack frame.
// If it saves a stack pointer, set Save to true, set the StackDelta saved, and set
//   the operand that received the saved stack pointer into CopyOp. and return true.
// If it restores a stack pointer, set Save to false, set CopyOp to the operand that
//   held the value being restored, set RestoreOp to the stack pointer or frame pointer
//   register (whichever was restored), leave StackDelta alone for later computation
//   based on reaching definitions, and return true.
// For most instructions, no save or restore of a stack pointer, so return false.
bool SMPInstr::MDIsStackPtrSaveOrRestore(bool UseFP, sval_t FPDelta, bool &Save, sval_t &StackDelta, op_t &CopyOp, bool &Error) {
	bool StackPointerSaveOrRestore;
	size_t RTLCount = this->RTL.GetCount();
	size_t RTLIndex;
	int BaseReg, IndexReg, CopyReg;
	ushort Scale;
	ea_t offset;
	SMPoperator CurrOper;
	bool LookUpStackDelta; // Get stack delta from reaching defs for TempOp
	sval_t DeltaAdjust; // add to StackDelta after computing from reaching defs, e.g. lea esp,[ecx-4] get TempOp of ecx
	                        //  and DeltaAdjust of -4

	Error = false;

	for (RTLIndex = 0; RTLIndex < RTLCount; ++RTLIndex) {
		bool FPRestore = false; // frame pointer is restored
		bool SPRestore = false; // stack pointer is restored
		StackPointerSaveOrRestore = false; // default unless we detect a save or restore of the stack or frame pointer
		TempOp = InitOp;
		LookUpStackDelta = false;
		DeltaAdjust = 0;
		Save = false; // default unless we detect a stack pointer save

		// The stack alignment instructions (SP := SP bitwise_and immediate_value)
		//  look like something that needs to be processed here, but we always ignore
		//  these instructions. They have a variable effect on the stack pointer, from zero
		//  to -15 delta, but we assume that the delta is zero. This works for us because
		//  no stack accesses will occur into the padding region.
		// Also, any instruction that definitely does not restore the stack pointer or
		//  frame pointer from an arbitrary register or memory location, e.g. a leave instruction
		//  in x86 CPUs, is already handled in normal stack delta computations and needs
		//  no lookups from reaching defs, etc.
		if (this->IsStackAlignmentInst() || this->MDIsLeaveInstr() || this->MDIsFrameAllocInstr()) {
			break; // exit and return false
		}

		SMPRegTransfer *CurrRT = this->RTL.GetRT(RTLIndex);
		CurrOper = CurrRT->GetOperator();
		if (SMP_ASSIGN != CurrOper) {
			break; // not a regular RTL
		}
		op_t LeftOp = CurrRT->GetLeftOperand();
		if (LeftOp.is_reg(MD_STACK_POINTER_REG)) {
			SPRestore = true; // temporary; might just be a push or pop RTL, etc., in which case we will reset.
		}
		else if (UseFP && LeftOp.is_reg(MD_FRAME_POINTER_REG)) {
			FPRestore = true; // likewise temporary
		}
		if (!(SPRestore || FPRestore)) {
#if 0
			if (LeftOp.is_reg(MD_FLAGS_REG)) {
				break; // No point in looking for a save into the flags register
			}
#endif
			Save = true;  // Maybe; keep looking for save

		// If we are assigning to the stack pointer reg or the frame pointer reg, we need to analyze the right
		//  hand side of the RTL to see if it is a stack/frame pointer value, and not a simple push, pop, etc.
		if (!(CurrRT->HasRightSubTree())) {
			op_t RightOp = CurrRT->GetRightOperand();
			if ((o_reg <= RightOp.type) && (o_displ >= RightOp.type)) { // register or memory
				if (RightOp.is_reg(MD_STACK_POINTER_REG)) {
					// Stack pointer reg is being saved.
					StackDelta = this->GetStackPtrOffset(); // LeftOp := SP, so saved delta is just current delta
					CopyOp = LeftOp;
					StackPointerSaveOrRestore = true;
					FPRestore = false; // treat FP := SP as a save of SP rather than a restoration of FP
				else if (!SPRestore && UseFP && RightOp.is_reg(MD_FRAME_POINTER_REG)) {
					// Frame pointer is being saved
					StackDelta = FPDelta;
					CopyOp = LeftOp;
					StackPointerSaveOrRestore = true;
					break;
				}
				else if (SPRestore || FPRestore) {
					// stack or frame pointer is being restored; leave Save=false and set other outgoing arguments.
					TempOp = RightOp;
					CopyOp = RightOp;
					StackPointerSaveOrRestore = true;
					LookUpStackDelta = true;
				}
				else { // RightOp is register or non-stack-pointer memory expr; either might hold stack delta
					TempOp = RightOp;
					CopyOp = LeftOp;
					LookUpStackDelta = true; // See if RightOp is holding a stack delta
					StackPointerSaveOrRestore = true;  // Maybe; flag tells us to keep looking
				if (SPRestore || FPRestore) {
					SMP_msg("ERROR: Invalid operand type for assignment to stack or frame pointer at %x\n", this->GetAddr());
				}
				StackPointerSaveOrRestore = false;
				break;
			}
		}
		else { // we have a right subtree in the CurrRT
			SMPRegTransfer *RightRT = CurrRT->GetRightTree();
			// In order to have a right subtree, we must have something like:
			//   lea esp,[ecx-4]  which produces the RTL: esp := ecx - 4
			// We should consider any other RTL structure besides a basic addition or
			//  subtraction on the right subtree to be invalid.
			CurrOper = RightRT->GetOperator();
			if ((SMP_ADD == CurrOper) || (SMP_SUBTRACT == CurrOper)) {
				op_t RightLeftOp = RightRT->GetLeftOperand();
				if (o_reg == RightLeftOp.type) {
					if (RightRT->HasRightSubTree()) {
						// Complex RTL such as lea esp,[ebx+ecx*4] ; cannot analyze
						StackPointerSaveOrRestore = false;
					}
					else {
						op_t RightRightOp = RightRT->GetRightOperand();
						if (o_imm != RightRightOp.type) {
							// Complex RTL such as lea esp,[ebx+ecx] ; cannot analyze
							StackPointerSaveOrRestore = false;
						}
						else {
							TempOp = RightLeftOp;
							DeltaAdjust = (sval_t) RightRightOp.value;
							if (SMP_SUBTRACT == CurrOper) {
								// Negate the stack delta adjustment, e.g. lea esp,[ecx-4] needs DeltaAdjust of -4, not 4.
								DeltaAdjust = (0 - DeltaAdjust);
							}
							LookUpStackDelta = true;
							StackPointerSaveOrRestore = true;
							if (SPRestore || FPRestore) {
								CopyOp = RightLeftOp;
							}
							else {
								CopyOp = LeftOp;
							}
						}
					}
				}
				else { // weird RTL; LeftOp := (MemoryOp OPER ???)
					StackPointerSaveOrRestore = false;
				}
			}
			else { // not ADD or SUBTRACT
				StackPointerSaveOrRestore = false;
			}
		}

		if (LookUpStackDelta) {
			bool StackAccess = false;
			// We need to set StackDelta based on the reaching defs for TempOp
			// A reg is probably a general register, but could have lea ebx,[esp+4] so it could be stack or frame pointer.
			if (TempOp.is_reg(MD_STACK_POINTER_REG)) {
				// Weed out RTs that increment or decrement the stack pointer, e.g. SP := SP -4.
				//  These are not the kind of "save" or "restore" RTs that we are tracking.
				if (CopyOp.is_reg(MD_STACK_POINTER_REG)) {
					StackPointerSaveOrRestore = false;
					SPRestore = false;
					FPRestore = false;
					Save = false;
				}
				else {
					StackDelta = this->GetStackPtrOffset();
					StackDelta += DeltaAdjust;
					LookUpStackDelta = false; // just got it; no need for reaching defs
					StackPointerSaveOrRestore = true;
				}
			}
			else if (UseFP && TempOp.is_reg(MD_FRAME_POINTER_REG)) {
				StackDelta = FPDelta;
				StackDelta += DeltaAdjust;
				LookUpStackDelta = false; // just got it; no need for reaching defs
				StackPointerSaveOrRestore = true;
			else if (o_reg == TempOp.type) { // general reg, not frame or stack pointer reg
				CopyReg = TempOp.reg;
				MDExtractAddressFields(TempOp, BaseReg, IndexReg, Scale, offset);
				CopyReg = BaseReg;
				bool IndexedAccess = ((R_none != BaseReg) && (R_none != IndexReg));
				if (IndexedAccess) {
					StackPointerSaveOrRestore = false;  // Cannot analyze indexed accesses into the stack
				}
				else if (MDIsStackPtrReg(BaseReg, UseFP)) {
					StackAccess = true;
				}
				else {
					// memory expr that is not stack or frame pointer
					NonStackMemAccess = true;  // something like [ecx] might actually turn out to be stack access
					DeltaAdjust = (sval_t) TempOp.addr; // get normalized delta from addr field
				}
			if (StackPointerSaveOrRestore && LookUpStackDelta) {
				op_t FindOp = InitOp;
				if (StackAccess) {
					FindOp = TempOp;
				}
				else {
					FindOp.type = o_reg;
					FindOp.reg = CopyReg;
				}
				if (this->GetBlock()->GetFunc()->IsInStackPtrCopySet(FindOp)) {
					// Screened out time wasters that are not in copy set; now,
					//  look up reaching defs.
					// We need to find out which are the reaching definitions for the FindOp at the current InstAddr.
					this->GetBlock()->GetFunc()->ComputeTempReachingDefs(FindOp, this->GetAddr());
					this->GetBlock()->GetFunc()->ComputeTempStackDeltaReachesList(FindOp);
					// See if TempStackDeltaReachesList has a consistent delta value.
					StackPointerSaveOrRestore = this->GetBlock()->GetFunc()->FindReachingStackDelta(StackDelta); // consistent SavedDelta value across entire list
					StackDelta += DeltaAdjust;
					if (StackPointerSaveOrRestore && NonStackMemAccess) {
						// We have something like [ecx] or [ecx+DeltaAdjust]. It turns out that
						//  ECX has a copy of the stack pointer or frame pointer in it, but that
						//  does not mean that the memory location [ecx] has a copy of a stack or
						//  frame pointer. We need to look up the normalized stack address [esp+StackDelta]
						//  in the StackPtrCopySet just like we did for ECX before we conclude that a
						//  stack pointer save or restore is happening.
						FindOp = InitOp;
						FindOp.type = o_displ;
						FindOp.reg = MD_STACK_POINTER_REG;
						FindOp.addr = StackDelta;
						if (this->GetBlock()->GetFunc()->IsInStackPtrCopySet(FindOp)) {
							// Screened out time wasters that are not in copy set; now,
							//  look up reaching defs.
							// We need to find out which are the reaching definitions for the FindOp at the current InstAddr.
							this->GetBlock()->GetFunc()->ComputeTempReachingDefs(FindOp, this->GetAddr());
							this->GetBlock()->GetFunc()->ComputeTempStackDeltaReachesList(FindOp);
							// See if TempStackDeltaReachesList has a consistent delta value.
							StackPointerSaveOrRestore = this->GetBlock()->GetFunc()->FindReachingStackDelta(StackDelta); // consistent SavedDelta value across entire list
							// StackPointerSaveOrRestore will now be true only if [ecx] pointed to a saved stack or frame pointer with consistent delta.
						}
						else {
							// E.g. [ecx] pointed to stack location that was not holding a saved stack or frame pointer.
							StackPointerSaveOrRestore = false;
						}
					}
				}
				else {
					StackPointerSaveOrRestore = false; // reset, not in stack pointer copy set
				}
		} // end if (LookupStackDelta)

		if (!StackPointerSaveOrRestore && !Save && (SPRestore || FPRestore)) {
			// Any restore that could not be analyzed is an error.
			Error = true;
			break; // error exit
		}
		else if (StackPointerSaveOrRestore) {
			if (FPRestore) {
				// If we succeeded in looking up a stack delta that goes into the frame pointer reg,
				//  then we want to consider this instruction to be a save of a stack delta into
				//  a register (which happens to be the frame pointer reg in this case).
				FPRestore = false;
				Save = true;
			break; // assume only one save or restore in an instruction; exit with success
	} // end for all RTs in the RTL

	return StackPointerSaveOrRestore;
} // end of SMPInstr::MDIsStackPtrSaveOrRestore()

// If call instruction is to malloc(), set the DEF register EAX type to
//  HEAPPTR and return true.
bool SMPInstr::MDFindMallocCall(op_t TargetOp) {
	bool changed = false;
	func_t *TargetFunc = get_func(TargetOp.addr);
	if (TargetFunc) {
		char FuncName[MAXSTR];
		get_func_name(TargetFunc->startEA, FuncName, sizeof(FuncName) - 1);
		if (0 == strcmp("malloc", FuncName)) {
			// NOTE: Some compilers might call it __malloc ; make this more robust !!!
#if SMP_VERBOSE_FIND_POINTERS
			SMP_msg("Found call to malloc at %x\n", this->addr);
#endif
			op_t SearchOp = InitOp;
			SearchOp.type = o_reg;
			SearchOp.reg = R_ax;
			set<DefOrUse, LessDefUse>::iterator EAXDEF;
			EAXDEF = this->SetDefType(SearchOp, HEAPPTR);
			int SSANum = EAXDEF->GetSSANum();
			changed = true;