Skip to content
Snippets Groups Projects
SMPInstr.cpp 207 KiB
Newer Older
				}
				else {
					;
#if SMP_VERBOSE_DEBUG_BUILD_RTL
					msg("WARNING: Skipping USE operand: ");
					PrintOperand(TempOp);
					msg(" at %x in %s\n", this->GetAddr(), this->GetDisasm());
#endif
				}
			}

			if (!(this->features & UseMacros[OpNum])) {
				;
#if SMP_VERBOSE_DEBUG_BUILD_RTL_DEF_USE
				msg("WARNING: Operand neither DEF nor USE: ");
				PrintOperand(TempOp);
				msg(" at %x in %s\n", this->GetAddr(), this->GetDisasm());
#endif
			}
		} // end if DEF ... else ...
	} // end for (OpNum = 0; ...)

	if (!DestFound || !SourceFound) {
#if SMP_DEBUG_BUILD_RTL
		if (!DestFound) {
			msg("ERROR: Could not find lea DEF operand at %x for %s\n", this->GetAddr(),
				this->GetDisasm());
		}
		else {
			msg("ERROR: Could not find lea USE operand at %x for %s\n", this->GetAddr(),
				this->GetDisasm());
			this->PrintOperands();
		}
#endif
	}
	else { // Ready to build the RTL
		// We build the RTL down to the right, in reverse order, with any multiplication
		//  of the index register by a scale factor at the bottom of the RTL tree.
		// Note that almost any combination of BaseReg, IndexReg, and offset can be present
		//  or absent.
		AssignRT = new SMPRegTransfer;
		AssignRT->SetLeftOperand(DefOp);
		AssignRT->SetOperator(SMP_ASSIGN);

		ScaledIndexReg = ((ScaleFactor > 0) && (IndexReg != R_none));
		op_t BaseOp, IndexOp, OffsetOp, ScaleOp;
		BaseOp.type = o_reg;
		BaseOp.reg = (ushort) BaseReg;
		IndexOp.type = o_reg;
		IndexOp.reg = (ushort) IndexReg;
		OffsetOp.type = o_imm;
		OffsetOp.value = (uval_t) offset;
		ScaleOp.type = o_imm;
		ScaleOp.value = (uval_t) ScaleFactor;

		if (ScaledIndexReg) {
			// First, build the subtree to scale the IndexReg.
			SMPRegTransfer *MultRT = new SMPRegTransfer;
			MultRT->SetLeftOperand(IndexOp);
			MultRT->SetOperator(SMP_U_LEFT_SHIFT);
			MultRT->SetRightOperand(ScaleOp);
			// Now, case on the possibilities for existence of the other address fields.
			if (0 != offset) {
				// Add the offset to the scaled index subtree.
				SMPRegTransfer *AddOffRT = new SMPRegTransfer;
				AddOffRT->SetLeftOperand(OffsetOp);
				AddOffRT->SetOperator(SMP_ADD);
				AddOffRT->SetRightTree(MultRT);
				// Add a BaseReg, if any.
				if (R_none != BaseReg) {
					SMPRegTransfer *AddBaseRT = new SMPRegTransfer;
					AddBaseRT->SetLeftOperand(BaseOp);
					AddBaseRT->SetOperator(SMP_ADD);
					AddBaseRT->SetRightTree(AddOffRT);
					// Link into assignment root tree.
					AssignRT->SetRightTree(AddBaseRT);
				}
				else { // no BaseReg
					AssignRT->SetRightTree(AddOffRT);
				}
			} // end if nonzero offset
			else { // no offset to add
				// Add a BaseReg, if any.
				if (R_none != BaseReg) {
					SMPRegTransfer *AddBaseRT = new SMPRegTransfer;
					AddBaseRT->SetLeftOperand(BaseOp);
					AddBaseRT->SetOperator(SMP_ADD);
					AddBaseRT->SetRightTree(MultRT);
					// Link into assignment root tree.
					AssignRT->SetRightTree(AddBaseRT);
				}
				else { // no BaseReg
					AssignRT->SetRightTree(MultRT);
				}
			}
		} // end if ScaleIndexReg
		else { // no scaled index register
			if (0 != offset) {
				if (R_none != IndexReg) {
					SMPRegTransfer *AddOffRT = new SMPRegTransfer;
					AddOffRT->SetLeftOperand(OffsetOp);
					AddOffRT->SetOperator(SMP_ADD);
					AddOffRT->SetRightOperand(IndexOp);
					// Add BaseReg, if any.
					if (R_none != BaseReg) {
						SMPRegTransfer *AddBaseRT = new SMPRegTransfer;
						AddBaseRT->SetLeftOperand(BaseOp);
						AddBaseRT->SetOperator(SMP_ADD);
						AddBaseRT->SetRightTree(AddOffRT);
						// Link into assignment root tree.
						AssignRT->SetRightTree(AddBaseRT);
					}
					else { // no BaseReg
						AssignRT->SetRightTree(AddOffRT);
					}
				} // end if valid IndexReg
				else { // no IndexReg
					// Add BaseReg, if any.
					if (R_none != BaseReg) {
						SMPRegTransfer *AddBaseRT = new SMPRegTransfer;
						AddBaseRT->SetLeftOperand(BaseOp);
						AddBaseRT->SetOperator(SMP_ADD);
						AddBaseRT->SetRightOperand(OffsetOp);
						// Link into assignment root tree.
						AssignRT->SetRightTree(AddBaseRT);
					}
					else { // no BaseReg, no IndexReg, just offset?
						msg("ERROR: No BaseReg, no IndexReg at %x for %s\n", this->address,
							this->GetDisasm());
						AssignRT->SetRightOperand(OffsetOp);
					}
				}
			} // end if nonzero offset
			else { // no offset
				if ((R_none == BaseReg) || (R_none == IndexReg)) {
					msg("WARNING: lea used as move at %x for %s\n", this->address,
						this->GetDisasm());
					if (R_none != BaseReg)
						AssignRT->SetRightOperand(BaseOp);
					else {
						assert(R_none != IndexReg);
						AssignRT->SetRightOperand(IndexOp);
					}
				}
				else { // we have a BaseReg and an IndexReg, unscaled, no offset
					SMPRegTransfer *AddBaseRT = new SMPRegTransfer;
					AddBaseRT->SetLeftOperand(BaseOp);
					AddBaseRT->SetOperator(SMP_ADD);
					AddBaseRT->SetRightOperand(IndexOp);
					// Link into assignment root tree.
					AssignRT->SetRightTree(AddBaseRT);
				}
			} // end if nonzero offset ... else ...
		} // end if (ScaledIndexReg) ... else ...
		this->RTL.push_back(AssignRT);
	}
	return (DestFound && SourceFound);
} // end of SMPInstr::BuildLeaRTL()

// Build the RTL for an double-word shift instruction
bool SMPInstr::BuildDoubleShiftRTL(SMPoperator BinaryOp) {
	size_t OpNum;
	bool DestFound = false;
	bool SourceFound = false;
	bool CountFound = false;
	SMPRegTransfer *TempRT = NULL;
	SMPRegTransfer *RightRT = new SMPRegTransfer;
	SMPRegTransfer *LowerRightRT = new SMPRegTransfer;

	op_t VoidOp;
	VoidOp.type = o_void;

	op_t FlagsOp;
	FlagsOp.type = o_reg;
	FlagsOp.reg = X86_FLAGS_REG;

	for (OpNum = 0; !(DestFound && SourceFound && CountFound) && (OpNum < UA_MAXOP); ++OpNum) {
		op_t TempOp = this->SMPcmd.Operands[OpNum];
		if (this->features & DefMacros[OpNum]) { // DEF
			if (MDKnownOperandType(TempOp)) {
				DestFound = true;
				TempRT = new SMPRegTransfer;
				TempRT->SetLeftOperand(TempOp);
				TempRT->SetOperator(SMP_ASSIGN);
				RightRT->SetLeftOperand(TempOp);
				RightRT->SetOperator(BinaryOp);
				TempRT->SetRightTree(RightRT);
				LowerRightRT->SetOperator(BinaryOp);
				RightRT->SetRightTree(LowerRightRT);
			}
		}
		else { // USE
			if (MDKnownOperandType(TempOp)) {
				if (!SourceFound) {
					SourceFound = true;
					LowerRightRT->SetLeftOperand(TempOp);
				}
				else {
					CountFound = true;
					LowerRightRT->SetRightOperand(TempOp);
				}
			}
		}
	} // end for (OpNum = 0; ...)

	if (!DestFound || !SourceFound || !CountFound) {
		if (NULL != TempRT)
			delete TempRT;
#if SMP_DEBUG_BUILD_RTL
		msg("ERROR: Could not find double-shift operand at %x for %s\n", this->GetAddr(), this->GetDisasm());
#endif
	}
	else {
		this->RTL.push_back(TempRT);
		// The carry flag gets the last shifted out bit.
		this->RTL.ExtraKills.push_back(FlagsOp);
	}
	return (DestFound && SourceFound);
} // end of SMPInstr::BuildDoubleShiftRTL()

// Build the RTL for a multiply or divide, which can have implicit EAX and/or EDX operands
bool SMPInstr::BuildMultiplyDivideRTL(SMPoperator BinaryOp) {
	size_t OpNum;
	bool DestFound = false;
	bool SourceFound = false;
	bool HiddenEAXUse = false;
	SMPRegTransfer *TempRT = NULL;
	SMPRegTransfer *RightRT = new SMPRegTransfer;

	op_t VoidOp;
	VoidOp.type = o_void;

	op_t FPRegOp;
	FPRegOp.type = o_fpreg;  // floating point register stack
	FPRegOp.reg = 0;

	op_t Immed1Op;
	Immed1Op.type = o_imm;  // immediate 1 for increment or decrement
	FPRegOp.value = 1;

	// Detect the cases in which EDX:EDX is the destination and EAX is a hidden operand.
	//  See detailed comments on the multiply and divide instructions in MDFixupDefUseLists().
	for (OpNum = 0; !(DestFound && SourceFound) && (OpNum < UA_MAXOP); ++OpNum) {
		op_t TempOp = this->SMPcmd.Operands[OpNum];
		if (!TempOp.showed()) { // hidden operand
			if (TempOp.is_reg(R_ax)) { // not R_al, so it is not 8 bits
				// This for always has a hidden use of EDX:EAX
				HiddenEAXUse = true;
			}
		}
	}

	for (OpNum = 0; !(DestFound && SourceFound) && (OpNum < UA_MAXOP); ++OpNum) {
		op_t TempOp = this->SMPcmd.Operands[OpNum];
		if (this->features & DefMacros[OpNum]) { // DEF
			if (MDKnownOperandType(TempOp)) {
				DestFound = true;
				TempRT = new SMPRegTransfer;
				TempRT->SetLeftOperand(TempOp);
				TempRT->SetOperator(SMP_ASSIGN);
				RightRT->SetLeftOperand(TempOp);
				RightRT->SetOperator(BinaryOp);
				TempRT->SetRightTree(RightRT);
			}
		}
		else { // USE
			if (MDKnownOperandType(TempOp)) {
				SourceFound = true;
				RightRT->SetRightOperand(TempOp);
			}
		}
	} // end for (OpNum = 0; ...)

	if (!DestFound || !SourceFound) {
		assert(NULL != RightRT);
		if (DestFound && (NULL != TempRT))
#if SMP_DEBUG_BUILD_RTL
		msg("ERROR: Could not find mul/div operand at %x for %s\n", this->GetAddr(), this->GetDisasm());
#endif
	}
	else {
		this->RTL.push_back(TempRT);
		if (HiddenEAXUse) {
			// Need another effect for EDX, which was implicit.
			//  Make a deep copy from existing effect and change EAX dest to EDX.
			//  For divisions, we also change EAX source to EDX.
			SMPRegTransfer *EDXRT = new SMPRegTransfer;
			SMPRegTransfer *EDXRightRT = new SMPRegTransfer;
			op_t EDXOp;
			EDXRT->SetOperator(SMP_ASSIGN);
			EDXOp = TempRT->GetLeftOperand();
			assert(EDXOp.is_reg(R_ax));
			EDXOp.reg = R_dx;
			EDXRT->SetLeftOperand(EDXOp);
			op_t SourceOp = RightRT->GetLeftOperand();
			if ((NN_div == this->SMPcmd.itype) || (NN_idiv == this->SMPcmd.itype)) {
				// Need to change left operand of RightRT to EDX. i.e. we are
				//  changing the effect from eax := eax DIV foo to edx := edx DIV foo.
				assert(SourceOp.is_reg(R_ax));
				EDXRightRT->SetLeftOperand(EDXOp);
			}
			else { // just use same source operands for multiplies
				EDXRightRT->SetLeftOperand(SourceOp);
			}
			EDXRightRT->SetOperator(BinaryOp);
			EDXRightRT->SetRightOperand(RightRT->GetRightOperand());
			EDXRT->SetRightTree(EDXRightRT);
			this->RTL.push_back(EDXRT);
		}
	}
	return (DestFound && SourceFound);
} // end of SMPInstr::BuildMultiplyDivideRTL()

// Build the RTL for an instruction with a tertiary arithmetic opcode applied to
//  two operands plus an implied FLAGS operand, e.g. add with carry adds the carry bit
//  and two operands together; rotate through carry, etc.
bool SMPInstr::BuildBinaryPlusFlagsRTL(SMPoperator BinaryOp) {
	size_t OpNum;
	bool DestFound = false;
	bool SourceFound = false;
	SMPRegTransfer *TempRT = NULL;

	op_t FlagsOp;
	FlagsOp.type = o_reg;
	FlagsOp.reg = X86_FLAGS_REG;

	SMPRegTransfer *RightRT = new SMPRegTransfer;
	SMPRegTransfer *FlagsRightRT = new SMPRegTransfer;

	for (OpNum = 0; !(DestFound && SourceFound) && (OpNum < UA_MAXOP); ++OpNum) {
		op_t TempOp = this->SMPcmd.Operands[OpNum];
		if (this->features & DefMacros[OpNum]) { // DEF
			if (MDKnownOperandType(TempOp)) {
				DestFound = true;
				TempRT = new SMPRegTransfer;
				TempRT->SetLeftOperand(TempOp);
				TempRT->SetOperator(SMP_ASSIGN);
				RightRT->SetLeftOperand(TempOp);
				RightRT->SetOperator(BinaryOp);
				TempRT->SetRightTree(RightRT);
			}
		}
		else { // USE
			if (MDKnownOperandType(TempOp)) {
				SourceFound = true;
				FlagsRightRT->SetLeftOperand(TempOp);
				FlagsRightRT->SetOperator(BinaryOp);
				FlagsRightRT->SetRightOperand(FlagsOp);
				RightRT->SetRightTree(FlagsRightRT);
			}
		}
	} // end for (OpNum = 0; ...)

	if (!DestFound || !SourceFound) {
		if (DestFound)
			delete TempRT;   // also deletes linked in RightRT
		else
			delete RightRT;  // will also delete FlagsRightRT if SourceFound is true
		if (!SourceFound) // FlagsRightRT not linked into RightRT yet
			delete FlagsRightRT; // .. so delete FlagsRightRT separately
#if SMP_DEBUG_BUILD_RTL
		msg("ERROR: Could not find binary operand at %x for %s\n", this->GetAddr(), this->GetDisasm());
#endif
	}
	else {
		this->RTL.push_back(TempRT);
	}
	return (DestFound && SourceFound);
} // end of SMPInstr::BuildBinaryPlusFlagsRTL()

#define SMP_FIRST_SET_OPCODE  NN_seta
#define SMP_LAST_SET_OPCODE   NN_setz
// Build the RTL for an instruction of form dest := unary_operator(source), dest != source
bool SMPInstr::BuildUnary2OpndRTL(SMPoperator UnaryOp) {
	size_t OpNum;
	bool DestFound = false;
	bool SourceFound = false;
	SMPRegTransfer *TempRT = NULL;
	SMPRegTransfer *RightRT = new SMPRegTransfer;

	op_t VoidOp;
	VoidOp.type = o_void;

	op_t FlagsOp;
	FlagsOp.type = o_reg;
	FlagsOp.reg = X86_FLAGS_REG;

	// Handle special cases first.
	if ((SMP_FIRST_SET_OPCODE <= this->SMPcmd.itype) && (SMP_LAST_SET_OPCODE >= this->SMPcmd.itype)) {
		// Set instructions implicitly use the flags register.
		SourceFound = true;
		RightRT->SetLeftOperand(FlagsOp);
	}

	for (OpNum = 0; !(DestFound && SourceFound) && (OpNum < UA_MAXOP); ++OpNum) {
		op_t TempOp = this->SMPcmd.Operands[OpNum];
		if (this->features & DefMacros[OpNum]) { // DEF
			if (MDKnownOperandType(TempOp)) {
				DestFound = true;
				TempRT = new SMPRegTransfer;
				TempRT->SetLeftOperand(TempOp);
				TempRT->SetOperator(SMP_ASSIGN);
				RightRT->SetRightOperand(VoidOp);
				RightRT->SetOperator(UnaryOp);
				TempRT->SetRightTree(RightRT);
			}
		}
		else { // USE
			if (MDKnownOperandType(TempOp)) {
				SourceFound = true;
				RightRT->SetLeftOperand(TempOp);
			}
		}
	} // end for (OpNum = 0; ...)

	if (!DestFound || !SourceFound) {
		if (!DestFound)
			delete RightRT; // never linked in to TempRT
		if (NULL != TempRT)
			delete TempRT;
#if SMP_DEBUG_BUILD_RTL
		msg("ERROR: Could not find binary operand at %x for %s\n", this->GetAddr(), this->GetDisasm());
#endif
	}
	else {
		this->RTL.push_back(TempRT);
	}
	return (DestFound && SourceFound);
} // end of SMPInstr::BuildUnary2OpndRTL()

// Build the RTL for an instruction of form dest := source, dest != source
bool SMPInstr::BuildMoveRTL(SMPoperator GuardOp) {
	size_t OpNum;
	bool DestFound = false;
	bool SourceFound = false;
	bool MemSrc = this->HasSourceMemoryOperand();
	bool MemDest = this->HasDestMemoryOperand();
	bool HasRepeatPrefix = (0 != (this->SMPcmd.auxpref & aux_rep)) 
		|| (0 != (this->SMPcmd.auxpref & aux_repne));

	SMPRegTransfer *TempRT = new SMPRegTransfer;

	op_t VoidOp;
	VoidOp.type = o_void;

	op_t EAXOp;
	EAXOp.type = o_reg;
	EAXOp.reg = R_ax;

	op_t ALOp;
	ALOp.type = o_reg;
	ALOp.reg = R_al;

	op_t CountOp;
	CountOp.type = o_reg;
	CountOp.reg = R_cx;

	op_t FlagsOp;
	FlagsOp.type = o_reg;
	FlagsOp.reg = X86_FLAGS_REG;

	op_t FPRegOp;
	FPRegOp.type = o_fpreg;  // floating point register stack
	FPRegOp.reg = 0;

	op_t ZeroOp;
	ZeroOp.type = o_imm;  // immediate zero
	ZeroOp.value = 0;

#if SMP_DEBUG_BUILD_RTL
	if (MemSrc && MemDest && (NN_movs != this->SMPcmd.itype)) {
		if (NN_stos != this->SMPcmd.itype) {
			msg("ERROR: MemDest and MemSrc in move at %x for %s\n", this->GetAddr(),
				this->GetDisasm());
		}
		else {  // IDA incorrectly lists [EDI] as both DEF and USE, because reg EDI
			    //  is both DEF and USE.
			msg("WARNING: MemDest and MemSrc in move at %x for %s\n", this->GetAddr(),
				this->GetDisasm());
		}
		this->PrintOperands();
	}
#endif

	// First, handle special cases with implicit operands
	if (NN_lahf == this->SMPcmd.itype) {  // load AH from flags
		TempRT->SetOperator(SMP_ASSIGN);
		TempRT->SetLeftOperand(EAXOp);
		TempRT->SetRightOperand(FlagsOp);
		this->RTL.push_back(TempRT);
		return true;
	}
	if (NN_sahf == this->SMPcmd.itype) {  // store AH to flags
		TempRT->SetOperator(SMP_ASSIGN);
		TempRT->SetLeftOperand(FlagsOp);
		TempRT->SetRightOperand(EAXOp);
		this->RTL.push_back(TempRT);
		return true;
	}
	if ((NN_movs == this->SMPcmd.itype) || (NN_stos == this->SMPcmd.itype)) {
		// The ESI and EDI registers get incremented or decremented, depending
		//  on the direction flag DF, for MOVS; only EDI for STOS.
		// This is true with or without a repeat prefix.
		op_t ESIOp, EDIOp;
		ESIOp.type = o_reg;
		ESIOp.reg = R_si;
		EDIOp.type = o_reg;
		EDIOp.reg = R_di;
		op_t ESIMemOp, EDIMemOp;  // [esi] and [edi]
		ESIMemOp.type = o_phrase;
		ESIMemOp.reg = R_si;
		ESIMemOp.hasSIB = 0;
		EDIMemOp.type = o_phrase;
		EDIMemOp.reg = R_di;
		EDIMemOp.hasSIB = 0;
		if (NN_movs == this->SMPcmd.itype) {
			this->RTL.ExtraKills.push_back(ESIOp);
			this->RTL.ExtraKills.push_back(EDIOp);
			TempRT->SetOperator(SMP_ASSIGN);
			TempRT->SetLeftOperand(EDIMemOp);
			TempRT->SetRightOperand(ESIMemOp);
			DestFound = true;
			SourceFound = true;
		}
		else { // NN_stos
			this->RTL.ExtraKills.push_back(EDIOp);
			TempRT->SetOperator(SMP_ASSIGN);
			TempRT->SetLeftOperand(EDIMemOp);
			TempRT->SetRightOperand(ALOp); // default in case we don't find source later
			DestFound = true;
		}
	}

	// Some floating point instructions use the floating point register stack top as
	//  an implicit source or destination, but the other operand of the load or store
	//  is explicit, so we set the implicit operand and let control flow pass to the
	//  main processing loop below.
	if ((NN_fld == this->SMPcmd.itype) || (NN_fbld == this->SMPcmd.itype)
		|| (NN_fild == this->SMPcmd.itype)) {
		// Loads implicitly use the floating point stack top as destination.
		TempRT->SetLeftOperand(FPRegOp);
		TempRT->SetOperator(SMP_ASSIGN);
		DestFound =  true;
	}
	else if ((NN_fst == this->SMPcmd.itype) || (NN_fstp == this->SMPcmd.itype)
		|| (NN_fbstp == this->SMPcmd.itype) || (NN_fist == this->SMPcmd.itype)
		|| (NN_fistp == this->SMPcmd.itype)) {
		// Stores implicitly use the floating point stack top as source
		TempRT->SetRightOperand(FPRegOp);
		SourceFound = true;
		// The "p" at the end of the opcode indicates that the floating point
		//  register stack gets popped.
		if ((NN_fstp == this->SMPcmd.itype)
			|| (NN_fbstp == this->SMPcmd.itype)
			|| (NN_fistp == this->SMPcmd.itype)) {
			this->RTL.ExtraKills.push_back(FPRegOp);
		}
	}

	for (OpNum = 0; !(DestFound && SourceFound) && (OpNum < UA_MAXOP); ++OpNum) {
		op_t TempOp = this->SMPcmd.Operands[OpNum];
		if (this->features & DefMacros[OpNum]) { // DEF
			if (!DestFound && MDKnownOperandType(TempOp)) {
				// See comments just below for floating point sources. FP stores
				//  are analogous to FP loads.
				if (!MemDest || ((TempOp.type >= o_mem) && (TempOp.type <= o_displ))) {
					DestFound = true;
					TempRT->SetLeftOperand(TempOp);
					TempRT->SetOperator(SMP_ASSIGN);
				}
			if (!SourceFound && MDKnownOperandType(TempOp)) {
				// If this is a floating point instruction with the fpregs listed as
				//  a USE and a memory operand also listed as a USE, then we want to
				//  ignore the irrelevant USE of the fpreg stack.
				// Note that MemDest AND MemSrc means something like stosb is being
				//  processed, where the memory operand is both DEF and USE to IDA
				//  for mysterious reasons.
				if (!MemSrc || MemDest || ((TempOp.type >= o_mem) && (TempOp.type <= o_displ))) {
					SourceFound = true;
					TempRT->SetRightOperand(TempOp);
				}
			}
			if (this->features & UseMacros[OpNum]) {
				;
#if SMP_VERBOSE_DEBUG_BUILD_RTL_DEF_USE
				msg("WARNING: Operand neither DEF nor USE: ");
				PrintOperand(TempOp);
				msg(" at %x in %s\n", this->GetAddr(), this->GetDisasm());
#endif
			}
		}
	} // end for (OpNum = 0; ...)

	if (!DestFound || !SourceFound) {
		if (NULL != TempRT)
			delete TempRT;
#if SMP_DEBUG_BUILD_RTL
		msg("ERROR: Could not find move operand at %x for %s\n", this->GetAddr(), this->GetDisasm());
#endif
	}
	else {
		// If the move is conditional, set the guard expression.
		if (SMP_NULL_OPERATOR != GuardOp) {
			SMPGuard *Guard1 = new SMPGuard;
			Guard1->SetLeftOperand(FlagsOp);
			Guard1->SetOperator(GuardOp);
			Guard1->SetRightOperand(ZeroOp);
			TempRT->SetGuard(Guard1);
			if (this->MDIsConditionalMoveInstr()) {
				// We need to represent the possibility that the DEF operand will not
				//  be set because the move is conditional. We will add the DEF operand
				//  into the USE set and special case our type inferences so that the
				//  USE and the pseudo-USE (prior SSA value of the DEF operand) must
				//  agree in type before we can be sure of the result type.
				assert(this->Defs.GetSize() == 1);
				this->Uses.SetRef(this->Defs.GetFirstRef()->GetOp());
			}
		}
		this->RTL.push_back(TempRT);
		// Now, create the repeat prefix effects
		if (HasRepeatPrefix) { // Must be MOVS or STOS
			// The repeat causes USE and DEF of ECX as a counter
			SMPRegTransfer *CounterRT = new SMPRegTransfer;
			SMPRegTransfer *RightRT = new SMPRegTransfer;
			CounterRT->SetLeftOperand(CountOp);
			CounterRT->SetOperator(SMP_ASSIGN);
			RightRT->SetLeftOperand(CountOp);
			RightRT->SetOperator(SMP_UNARY_NUMERIC_OPERATION);
			RightRT->SetRightOperand(VoidOp);
			CounterRT->SetRightTree(RightRT);
			this->RTL.push_back(CounterRT);
		}
	}
	return (DestFound && SourceFound);
} // end of SMPInstr::BuildMoveRTL()

// Build the RTL for a compare string instruction, possibly with repeat prefix.
bool SMPInstr::BuildCompareStringRTL(void) {
	size_t OpNum;
	bool Src1Found = false;
	bool Src2Found = false;
	bool HasRepeatPrefix = (0 != (this->SMPcmd.auxpref & aux_rep)) 
		|| (0 != (this->SMPcmd.auxpref & aux_repne));

	op_t FlagsOp;
	FlagsOp.type = o_reg;
	FlagsOp.reg = X86_FLAGS_REG;

	op_t CountOp;
	CountOp.type = o_reg;
	CountOp.reg = R_cx;

	op_t VoidOp;
	VoidOp.type = o_void;

	SMPRegTransfer *TempRT = new SMPRegTransfer;
	SMPRegTransfer *RightRT = new SMPRegTransfer;

	for (OpNum = 0; !(Src1Found && Src2Found) && (OpNum < UA_MAXOP); ++OpNum) {
		op_t TempOp = this->SMPcmd.Operands[OpNum];
		if (MDKnownOperandType(TempOp)) {
			if (!Src1Found) {
				Src1Found = true;
				TempRT->SetLeftOperand(FlagsOp);
				TempRT->SetOperator(SMP_ASSIGN);
				RightRT->SetLeftOperand(TempOp);
				RightRT->SetOperator(SMP_U_COMPARE);
				TempRT->SetRightTree(RightRT);
				if (this->features & DefMacros[OpNum]) // DEF
					msg("CMPS 1st opnd is DEF\n");
				else if (this->features & UseMacros[OpNum]) // USE
					msg("CMPS 1st opnd is USE\n");
				else
					msg("CMPS 1st opnd neither DEF nor USE\n");
			}
			else {
				Src2Found = true;
				RightRT->SetRightOperand(TempOp);
				if (this->features & DefMacros[OpNum]) // DEF
					msg("CMPS 2nd opnd is DEF\n");
				else if (this->features & UseMacros[OpNum]) // USE
					msg("CMPS 2nd opnd is USE\n");
				else
					msg("CMPS 2nd opnd neither DEF nor USE\n");
			}
		}
	} // end for (OpNum = 0; ...)

	if (!Src1Found || !Src2Found) {
		if (NULL != TempRT)
			delete TempRT;
#if SMP_DEBUG_BUILD_RTL
		msg("ERROR: Could not find CMPS operand at %x for %s\n", this->GetAddr(), this->GetDisasm());
#endif
	}
	else {
		this->RTL.push_back(TempRT);
		// Now, create the repeat prefix effects
		if (HasRepeatPrefix) {
			// The repeat causes USE and DEF of ECX as a counter
			SMPRegTransfer *CounterRT = new SMPRegTransfer;
			SMPRegTransfer *RightRT = new SMPRegTransfer;
			CounterRT->SetLeftOperand(CountOp);
			CounterRT->SetOperator(SMP_ASSIGN);
			RightRT->SetLeftOperand(CountOp);
			RightRT->SetOperator(SMP_UNARY_NUMERIC_OPERATION);
			RightRT->SetRightOperand(VoidOp);
			CounterRT->SetRightTree(RightRT);
			this->RTL.push_back(CounterRT);
		}
	}
	return (Src1Found && Src2Found);
} // end of SMPInstr::BuildCompareStringRTL()

// Build the RTL for an instruction of form dest := source, source := dest
bool SMPInstr::BuildExchangeRTL(void) {
	size_t OpNum;
	bool Src1Found = false;
	bool Src2Found = false;
	SMPRegTransfer *TempRT = new SMPRegTransfer;  // second effect, src := dest

	for (OpNum = 0; !(Src1Found && Src2Found) && (OpNum < UA_MAXOP); ++OpNum) {
		op_t TempOp = this->SMPcmd.Operands[OpNum];
		if (MDKnownOperandType(TempOp)) {
			if (!Src1Found) {
				Src1Found = true;
				TempRT->SetRightOperand(TempOp);
				TempRT->SetOperator(SMP_ASSIGN);
				if (this->features & DefMacros[OpNum]) // DEF
					msg("XCHG 1st opnd is DEF\n");
				else if (this->features & UseMacros[OpNum]) // USE
					msg("XCHG 1st opnd is USE\n");
				else
					msg("XCHG 1st opnd neither DEF nor USE\n");
			}
			else {
				Src2Found = true;
				TempRT->SetLeftOperand(TempOp);
				if (this->features & DefMacros[OpNum]) // DEF
					msg("XCHG 2nd opnd is DEF\n");
				else if (this->features & UseMacros[OpNum]) // USE
					msg("XCHG 2nd opnd is USE\n");
				else
					msg("XCHG 2nd opnd neither DEF nor USE\n");
			}
		}
	} // end for (OpNum = 0; ...)

	if (!Src1Found || !Src2Found) {
		if (NULL != TempRT)
			delete TempRT;
#if SMP_DEBUG_BUILD_RTL
		msg("ERROR: Could not find XCHG operand at %x for %s\n", this->GetAddr(), this->GetDisasm());
#endif
	}
	else {
		// Create the first effect, dest := src
		SMPRegTransfer *FirstRT = new SMPRegTransfer;
		FirstRT->SetLeftOperand(TempRT->GetRightOperand());
		FirstRT->SetRightOperand(TempRT->GetLeftOperand());
		FirstRT->SetOperator(SMP_ASSIGN);
		this->RTL.push_back(FirstRT);
		// Push the second effect on the list, src := dest
		this->RTL.push_back(TempRT);
	}
	return (Src1Found && Src2Found);
} // end of SMPInstr::BuildExchangeRTL()

// Build the RTL for an instruction of form dest := dest + source, source := dest
bool SMPInstr::BuildExchangeAddRTL(void) {
	size_t OpNum;
	bool Src1Found = false;
	bool Src2Found = false;

	SMPRegTransfer *TempRT = new SMPRegTransfer;  // second effect, src := dest

	for (OpNum = 0; !(Src1Found && Src2Found) && (OpNum < UA_MAXOP); ++OpNum) {
		op_t TempOp = this->SMPcmd.Operands[OpNum];
		if (MDKnownOperandType(TempOp)) {
			if (!Src1Found) {
				Src1Found = true;
				TempRT->SetRightOperand(TempOp);
				TempRT->SetOperator(SMP_ASSIGN);
				if (this->features & DefMacros[OpNum]) // DEF
					msg("XADD 1st opnd is DEF\n");
				else if (this->features & UseMacros[OpNum]) // USE
					msg("XADD 1st opnd is USE\n");
				else
					msg("XADD 1st opnd neither DEF nor USE\n");
			}
			else {
				Src2Found = true;
				TempRT->SetLeftOperand(TempOp);
				if (this->features & DefMacros[OpNum]) // DEF
					msg("XADD 2nd opnd is DEF\n");
				else if (this->features & UseMacros[OpNum]) // USE
					msg("XADD 2nd opnd is USE\n");
				else
					msg("XADD 2nd opnd neither DEF nor USE\n");
			}
		}
	} // end for (OpNum = 0; ...)

	if (!Src1Found || !Src2Found) {
		if (NULL != TempRT)
			delete TempRT;
#if SMP_DEBUG_BUILD_RTL
		msg("ERROR: Could not find XADD operand at %x for %s\n", this->GetAddr(), this->GetDisasm());
#endif
	}
	else {
		// Create the first effect, dest := dest + src
		SMPRegTransfer *FirstRT = new SMPRegTransfer;
		SMPRegTransfer *AddRT = new SMPRegTransfer;
		AddRT->SetLeftOperand(TempRT->GetRightOperand());
		AddRT->SetOperator(SMP_ADD);
		AddRT->SetRightOperand(TempRT->GetLeftOperand());
		FirstRT->SetLeftOperand(TempRT->GetRightOperand());
		FirstRT->SetRightTree(AddRT);
		FirstRT->SetOperator(SMP_ASSIGN);
		this->RTL.push_back(FirstRT);
		// Push the second effect on the list, src := dest
		this->RTL.push_back(TempRT);
	}
	return (Src1Found && Src2Found);
} // end of SMPInstr::BuildExchangeAddRTL()

// Build the RTL for an instruction of form:
//  if (dest==EAX) dest := source  else  EAX := dest
bool SMPInstr::BuildCompareExchangeRTL(void) {
	size_t OpNum;
	bool DestFound = false;
	bool SourceFound = false;
	op_t DestOp;
	op_t SourceOp;
	SMPRegTransfer *TempRT = new SMPRegTransfer;

	for (OpNum = 0; !(DestFound && SourceFound) && (OpNum < UA_MAXOP); ++OpNum) {
		op_t TempOp = this->SMPcmd.Operands[OpNum];
		if (MDKnownOperandType(TempOp)) {
			if (this->features & DefMacros[OpNum]) { // DEF
				if (!DestFound) {
					DestFound = true;
					DestOp = TempOp;
				}
				else {
					msg("CMPXCHG has two DEF operands.\n");
				}
			}
			else if (this->features & UseMacros[OpNum]) { // USE
				if (!SourceFound) {
					SourceFound = true;
					SourceOp = TempOp;
				}
				else {
					msg("CMPXCHG has two USE operands.\n");
				}
			}
		}
	} // end for (OpNum = 0; ...)

	if (!DestFound || !SourceFound) {
		if (NULL != TempRT)
			delete TempRT;
#if SMP_DEBUG_BUILD_RTL
		msg("ERROR: Could not find CMPXCHG operand at %x for %s\n", this->GetAddr(), this->GetDisasm());
#endif
	}
	else {
		// Create the first effect, if (dest == EAX) dest := src
		SMPGuard *Guard1 = new SMPGuard;
		op_t EAXOp;
		EAXOp.type = o_reg;
		EAXOp.reg =  R_ax;
		Guard1->SetLeftOperand(DestOp);
		Guard1->SetOperator(SMP_EQUAL);
		Guard1->SetRightOperand(EAXOp);
		SMPRegTransfer *FirstRT = new SMPRegTransfer;
		FirstRT->SetLeftOperand(DestOp);
		FirstRT->SetRightOperand(SourceOp);
		FirstRT->SetOperator(SMP_ASSIGN);
		FirstRT->SetGuard(Guard1);
		this->RTL.push_back(FirstRT);
		// Push the second effect on the list, if (dest!=EAX) dest := EAX
		SMPGuard *Guard2 = new SMPGuard;
		Guard2->SetLeftOperand(DestOp);
		Guard2->SetOperator(SMP_EQUAL);
		Guard2->SetRightOperand(EAXOp);
		TempRT->SetLeftOperand(DestOp);
		TempRT->SetRightOperand(EAXOp);
		TempRT->SetOperator(SMP_ASSIGN);
		TempRT->SetGuard(Guard2);
		this->RTL.push_back(TempRT);
	}
	return (DestFound && SourceFound);
} // end of SMPInstr::BuildCompareExchangeRTL()

// Build the RTL for a compare or test instruction with an implicit EFLAGS destination operand
bool SMPInstr::BuildFlagsDestBinaryRTL(SMPoperator BinaryOp) {
	size_t OpNum;
	bool Source1Found = false;
	bool Source2Found = false;
	bool HasRepeatPrefix = (0 != (this->SMPcmd.auxpref & aux_rep)) 
		|| (0 != (this->SMPcmd.auxpref & aux_repne));

	op_t Src1Op, Src2Op;
	SMPRegTransfer *TempRT = new SMPRegTransfer;
	SMPRegTransfer *RightRT = new SMPRegTransfer;

	op_t VoidOp, FlagsOp;
	VoidOp.type = o_void;

	FlagsOp.type = o_reg;
	FlagsOp.reg = X86_FLAGS_REG;

	op_t CountOp;
	CountOp.type = o_reg;
	CountOp.reg = R_cx;

	for (OpNum = 0; !(Source1Found && Source2Found) && (OpNum < UA_MAXOP); ++OpNum) {
		op_t TempOp = this->SMPcmd.Operands[OpNum];
		if (this->features & DefMacros[OpNum]) { // DEF
			if (MDKnownOperandType(TempOp)) {
#if SMP_DEBUG_BUILD_RTL
				msg("ERROR: Found destination for compare or test at %x : %s\n",
					this->GetAddr(), this->GetDisasm());
#endif
			}
		}
		else { // USE
			if (MDKnownOperandType(TempOp)) {
				if (!Source1Found) {
					Source1Found = true;
					Src1Op = TempOp;
					TempRT->SetLeftOperand(FlagsOp);
					TempRT->SetOperator(SMP_ASSIGN);
					RightRT->SetLeftOperand(TempOp);
					RightRT->SetOperator(BinaryOp);
					TempRT->SetRightTree(RightRT);
				}
				else {
					Source2Found = true;
					Src2Op = TempOp;
					RightRT->SetRightOperand(TempOp);
				}
			}
		}
	} // end for (OpNum = 0; ...)

	// The compare string instruction always uses DS:ESI and ES:EDI as its source
	//  operands, regardless of the explicit operands given.
	if (!Source1Found || !Source2Found) {
		if (!Source1Found)
			delete RightRT;
		else
			delete TempRT;
#if SMP_DEBUG_BUILD_RTL
		msg("ERROR: Could not find CMP/TEST/SCAS operand at %x for %s\n", this->GetAddr(), this->GetDisasm());
#endif
	}
	else {
		this->RTL.push_back(TempRT);
		// Now, create the repeat prefix effects
		if (HasRepeatPrefix) { // Must be CMPS or SCAS
			// The repeat causes USE and DEF of ECX as a counter
			SMPRegTransfer *CounterRT = new SMPRegTransfer;
			SMPRegTransfer *RightRT = new SMPRegTransfer;
			CounterRT->SetLeftOperand(CountOp);
			CounterRT->SetOperator(SMP_ASSIGN);
			RightRT->SetLeftOperand(CountOp);
			RightRT->SetOperator(SMP_UNARY_NUMERIC_OPERATION);
			RightRT->SetRightOperand(VoidOp);
			CounterRT->SetRightTree(RightRT);
			this->RTL.push_back(CounterRT);
		}
		if ((NN_cmps == this->SMPcmd.itype) || (NN_scas == this->SMPcmd.itype)) {
			// The ESI and EDI registers get incremented or decremented, depending
			//  on the direction flag DF, for CMPS; only EDI for SCAS.
			// This is true with or without a repeat prefix.
			op_t ESIOp, EDIOp;
			ESIOp.type = o_reg;
			ESIOp.reg = R_si;
			EDIOp.type = o_reg;
			EDIOp.reg = R_di;
			if (NN_cmps == this->SMPcmd.itype) {
				this->RTL.ExtraKills.push_back(ESIOp);
			}
			this->RTL.ExtraKills.push_back(EDIOp);
		}
	}
	return (Source1Found && Source2Found);
} // end of SMPInstr::BuildFlagsDestBinaryRTL()