/*
 * SMPInstr.cpp - <see below>.
 *
 * Copyright (c) 2000, 2001, 2010 - University of Virginia 
 *
 * This file is part of the Memory Error Detection System (MEDS) infrastructure.
 * This file may be used and modified for non-commercial purposes as long as 
 * all copyright, permission, and nonwarranty notices are preserved.  
 * Redistribution is prohibited without prior written consent from the University 
 * of Virginia.
 *
 * Please contact the authors for restrictions applying to commercial use.
 *
 * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * Author: University of Virginia
 * e-mail: jwd@virginia.com
 * URL   : http://www.cs.virginia.edu/
 *
 * Additional copyrights 2010, 2011 by Zephyr Software LLC
 * e-mail: {clc,jwd}@zephyr-software.com
 * URL   : http://www.zephyr-software.com/
 *
 */

//
// SMPInstr.cpp
//
// This module performs the instruction level analyses needed for the
//   SMP project (Software Memory Protection).
//

using namespace std;

#include <string>
#include <cstring>

#include <pro.h>
#include <assert.h>
#include <ua.hpp>
#include <ida.hpp>
#include <idp.hpp>
#include <auto.hpp>
#include <bytes.hpp>
#include <funcs.hpp>
#include <intel.hpp>
#include <loader.hpp>
#include <lines.hpp>
#include <name.hpp>

#include "SMPDBInterface.h"
#include "SMPStaticAnalyzer.h"
#include "SMPDataFlowAnalysis.h"
#include "SMPInstr.h"
#include "SMPProgram.h"
#include "ProfilerInformation.h"

// Set to 1 for debugging output
#define SMP_DEBUG 1
#define SMP_DEBUG2 0   // verbose
#define SMP_DEBUG_XOR 0
#define SMP_DEBUG_BUILD_RTL  1   // should be left on, serious errors!
#define SMP_VERBOSE_DEBUG_BUILD_RTL  0
#define SMP_VERBOSE_DEBUG_BUILD_RTL_DEF_USE 0
#define SMP_VERBOSE_DEBUG_INFER_TYPES 0
#define SMP_VERBOSE_DUMP 0
#define SMP_VERBOSE_FIND_POINTERS 0
#define STARS_DUMP_FG_INFO 1  // show signedness of DEFs and USEs in dump

#define SMP_CALL_TRASHES_REGS 1  // Add DEFs of caller-saved regs to CALL instructions
#define SMP_BASEREG_POINTER_TYPE 1  // Initialize Base Register USEs to type POINTER?
#define SMP_OPTIMIZE_ADD_TO_NUMERIC 0 // optimizing annotation type -5
#define SMP_IDENTIFY_POINTER_ADDRESS_REG 0 // optimizing annotation POINTER
#define SMP_CHILDACCESS_ALL_CODE 0 // CHILDACCESS annotations for all funcs, or just analyzed funcs?
#define SPECIAL_CASE_CARRY_BORROW 0 // Treat sbb/adc different from sub/add annotations?
#define SMP_BUILD_SPECIAL_ADC_SBB_RTL 0 // Explicit RTL subtree for carry flag?
#define SMP_AGGRESSIVE_TYPE_INFERENCE 1  // Shorten iterations by quick propagation in InferOperatorType()
#define SMP_ANNOTATE_ALL_MEMORY_OPERANDS 0 // Info annotation for all memory read and write operands?
#define SMP_AGGRESSIVE_SIGN_TRANSFER 1  // More transfer of signedness across instructions
#define STARS_NO_SHIFT_SIGNEDNESS_IN_SCALEFACTOR 1  // unsigned left shift for scale factors is really unknownsign multiply

// Make the CF_CHG1 .. CF_CHG6 and CF_USE1..CF_USE6 macros more usable
//  by allowing us to pick them up with an array index.
static ulong DefMacros[UA_MAXOP] = {CF_CHG1, CF_CHG2, CF_CHG3, CF_CHG4, CF_CHG5, CF_CHG6};
static ulong UseMacros[UA_MAXOP] = {CF_USE1, CF_USE2, CF_USE3, CF_USE4, CF_USE5, CF_USE6};

// Text to be printed in each optimizing annotation explaining why
//  the annotation was emitted.
static const char *OptExplanation[LAST_TYPE_CATEGORY + 1] =
	{ "NoOpt", "NoMetaUpdate", "AlwaysNUM", "NUMVia2ndSrcIMMEDNUM",
	  "Always1stSrc", "1stSrcVia2ndSrcIMMEDNUM", "AlwaysPtr",
	  "AlwaysNUM", "AlwaysNUM", "NUMViaFPRegDest", "NumericSources",
	  "StackMemoryTracking", "NumericSources", "NumericMemDest",
	  "NeverMemDest", "SafeIfNoIndexing"
	};

static const char *OperatorText[LAST_SMP_OPERATOR + 1] = 
{ 	"SMP_NULL_OPERATOR", "SMP_CALL", "SMP_INPUT", "SMP_OUTPUT", "SMP_ADDRESS_OF",
	"SMP_U_LEFT_SHIFT", "SMP_S_LEFT_SHIFT", "SMP_U_RIGHT_SHIFT", "SMP_S_RIGHT_SHIFT",
	"SMP_ROTATE_LEFT", "SMP_ROTATE_LEFT_CARRY", "SMP_ROTATE_RIGHT", "SMP_ROTATE_RIGHT_CARRY",
	"SMP_DECREMENT", "SMP_INCREMENT",
	"SMP_ADD", "SMP_ADD_CARRY", "SMP_SUBTRACT", "SMP_SUBTRACT_BORROW", "SMP_U_MULTIPLY",
	"SMP_S_MULTIPLY", "SMP_U_DIVIDE", "SMP_S_DIVIDE", "SMP_U_REMAINDER",
	"SMP_SIGN_EXTEND", "SMP_ZERO_EXTEND", "SMP_ASSIGN", "SMP_BITWISE_AND",
	"SMP_BITWISE_OR", "SMP_BITWISE_NOT", "SMP_BITWISE_XOR", "SMP_BITWISE_AND_NOT", "SMP_NEGATE", 
	"SMP_S_COMPARE", "SMP_U_COMPARE", "SMP_GENERAL_COMPARE", "SMP_LESS_THAN", "SMP_GREATER_THAN",
	"SMP_LESS_EQUAL", "SMP_GREATER_EQUAL", "SMP_EQUAL", "SMP_NOT_EQUAL",
	"SMP_LOGICAL_AND", "SMP_LOGICAL_OR", "SMP_UNARY_NUMERIC_OPERATION",
	"SMP_BINARY_NUMERIC_OPERATION", "SMP_SYSTEM_OPERATION",
	"SMP_UNARY_FLOATING_ARITHMETIC", "SMP_BINARY_FLOATING_ARITHMETIC",
	"SMP_REVERSE_SHIFT_U", "SMP_SHUFFLE", "SMP_COMPARE_EQ_AND_SET",
	"SMP_COMPARE_NE_AND_SET", "SMP_COMPARE_GT_AND_SET", 
	"SMP_COMPARE_GE_AND_SET", "SMP_COMPARE_LT_AND_SET", "SMP_COMPARE_LE_AND_SET",
	"SMP_PACK_SIGNED", "SMP_PACK_UNSIGNED",
	"SMP_AVERAGE_UNSIGNED", "SMP_MULTIPLY_AND_ADD", "SMP_SUM_OF_DIFFS",
	"SMP_MAX_S", "SMP_MAX_U", "SMP_MIN_S", "SMP_MIN_U", "SMP_ABS_VALUE",
	"SMP_CONVERT_INT_TO_FP", "SMP_CONVERT_FP_TO_INT", "SMP_CREATE_MASK",
	"SMP_INTERLEAVE", "SMP_CONCATENATE", "SMP_EXTRACT_ZERO_EXTEND", 
	"SMP_ENCRYPTION_OPERATION", "SMP_SIGNAL"
};

#if 0
// Does the CurrOperator definitely indicate a signed or unsigned operation?
bool OperatorHasSignedness(SMPoperator CurrOperator) {
	bool DetectedSignedness;

	switch (CurrOperator) {
		case SMP_NULL_OPERATOR:
			DetectedSignedness = false;
			break;

		case SMP_CALL:  // CALL instruction
			DetectedSignedness = true;
			break;

		case SMP_INPUT:  // input from port
		case SMP_OUTPUT: // output to port
		case SMP_ADDRESS_OF: // take effective address
		case SMP_GENERAL_COMPARE:
			DetectedSignedness = false;
			break;

		case SMP_U_LEFT_SHIFT: // unsigned left shift
		case SMP_U_RIGHT_SHIFT: // unsigned right shift
		case SMP_ROTATE_LEFT:
		case SMP_ROTATE_LEFT_CARRY: // rotate left through carry
		case SMP_ROTATE_RIGHT:
		case SMP_ROTATE_RIGHT_CARRY: // rotate right through carry
		case SMP_U_MULTIPLY:
		case SMP_U_DIVIDE:
		case SMP_U_REMAINDER:
		case SMP_ZERO_EXTEND:
		case SMP_BITWISE_NOT: // unary operator
		case SMP_BITWISE_XOR:
		case SMP_BITWISE_AND_NOT:
		case SMP_U_COMPARE: // unsigned compare (AND-based)
			DetectedSignedness = true;
			break;

		case SMP_S_LEFT_SHIFT: // signed left shift
		case SMP_S_RIGHT_SHIFT: // signed right shift
		case SMP_S_MULTIPLY:
		case SMP_S_DIVIDE:
		case SMP_SIGN_EXTEND:
		case SMP_NEGATE:    // unary negation
		case SMP_S_COMPARE: // signed compare (subtraction-based)
		case SMP_LESS_THAN: // boolean test operators
		case SMP_GREATER_THAN:
		case SMP_LESS_EQUAL:
		case SMP_GREATER_EQUAL:
			DetectedSignedness = true;
			break;

		case SMP_DECREMENT:
		case SMP_INCREMENT:
		case SMP_ADD:
		case SMP_ADD_CARRY:   // add with carry
		case SMP_SUBTRACT:
		case SMP_SUBTRACT_BORROW:  // subtract with borrow
		case SMP_ASSIGN:
		case SMP_BITWISE_AND:
		case SMP_BITWISE_OR:
		case SMP_EQUAL:
		case SMP_NOT_EQUAL:
		case SMP_LOGICAL_AND:
		case SMP_LOGICAL_OR:
		case SMP_UNARY_NUMERIC_OPERATION:  // miscellaneous; produces NUMERIC result
		case SMP_BINARY_NUMERIC_OPERATION:  // miscellaneous; produces NUMERIC result
		case SMP_SYSTEM_OPERATION:   // for instructions such as CPUID, RDTSC, etc.; NUMERIC
		case SMP_SHUFFLE: // Shuffle bytes, words, etc. within destination operation per source mask
		case SMP_SIGNAL: // signal or raise exception
			DetectedSignedness = false;
			break;

		case SMP_UNARY_FLOATING_ARITHMETIC:  // all the same to our type system; all NUMERIC
		case SMP_BINARY_FLOATING_ARITHMETIC:  // all the same to our type system; all NUMERIC
			DetectedSignedness = true;
			break;

		case SMP_REVERSE_SHIFT_U: // Shift right operand by bit count in left operand
		case SMP_COMPARE_EQ_AND_SET: // Compare for equality and set fields to all 1's or all 0's
		case SMP_COMPARE_NE_AND_SET: // Compare for inequality and set fields to all 1's or all 0's
		case SMP_COMPARE_GT_AND_SET: // Compare for greater-than and set fields to all 1's or all 0's
		case SMP_COMPARE_GE_AND_SET: // Compare for greater-than-or-equal and set fields to all 1's or all 0's
		case SMP_COMPARE_LT_AND_SET: // Compare for less-than and set fields to all 1's or all 0's
		case SMP_COMPARE_LE_AND_SET: // Compare for less-than-or-equal and set fields to all 1's or all 0's
		case SMP_PACK_S:  // Pack operands into extended-precision register, signed saturation for loss of precision
		case SMP_PACK_U:  // Pack operands into extended-precision register, unsigned saturation for loss of precision
		case SMP_AVERAGE_U: // Average of unsigned operands
		case SMP_MULTIPLY_AND_ADD: // multiply and add (or multiply and accumulate)
		case SMP_SUM_OF_DIFFS: // sum over two vectors of absolute values of differences of their elements
		case SMP_MAX_S: // dest := signed_max(dest, src)
		case SMP_MAX_U: // dest := unsigned_max(dest, src)
		case SMP_MIN_S: // dest := signed_min(dest, src)
		case SMP_MIN_U: // dest := unsigned_min(dest, src)
		case SMP_ABSOLUTE_VALUE: // take absolute value
		case SMP_CONVERT_INT_TO_FP: // convert integer to floating point
		case SMP_CONVERT_FP_TO_INT: // convert floating point to integer
		case SMP_INTERLEAVE: // extended-precision interleaving of bytes or words or dwords etc.; NUMERIC
		case SMP_CONCATENATE:     // extended-precision concatenation; NUMERIC
			DetectedSignedness = true;
			break;

		default:
			DetectedSignedness = false;
			SMP_msg("ERROR: Unknown operator in OperatorHasSignedness: %d\n", CurrOperator);
			break;
	} // end switch on operator

	return DetectedSignedness;
} // end of OperatorHasSignedness()
#endif

// Print an operand in SPARK-Ada form.
void PrintSPARKAdaOperand(op_t Opnd, FILE *OutFile) {
	op_t BaseOp = InitOp;
	op_t IndexOp = InitOp;
	BaseOp.type = o_reg;
	IndexOp.type = o_reg;

	if (Opnd.type == o_mem) {
		if (Opnd.hasSIB) {
			SMP_fprintf(OutFile, " Memory[%lx + ", (unsigned long) Opnd.addr);
			AnnotPrintSIB(Opnd, false, OutFile);
			SMP_fprintf(OutFile, "] ");
		}
		else {
			SMP_fprintf(OutFile, " Memory[%lx] ", (unsigned long) Opnd.addr);
		}
	}
	else if (Opnd.type == o_phrase) {
		if (Opnd.hasSIB) { // has SIB info
			SMP_fprintf(OutFile, " Memory[");
			AnnotPrintSIB(Opnd, false, OutFile);
			SMP_fprintf(OutFile, "] ");
		}
		else { // no SIB info
			ushort BaseReg = Opnd.phrase;
			BaseOp.reg = BaseReg;
			if (RegSizes[BaseReg] == 1)
				BaseOp.dtyp = dt_byte;
			SMP_fprintf(OutFile, " Memory[%s] ", MDGetRegName(BaseOp));
		}
		if (Opnd.addr != 0) {
			SMP_msg(" \n WARNING: addr for o_phrase type: %lx\n", (unsigned long) Opnd.addr);
		}
	}
	else if (Opnd.type == o_displ) {
		ea_t offset = Opnd.addr;
		int SignedOffset = (int) offset;
		if (Opnd.hasSIB) {
			SMP_fprintf(OutFile, " Memory[");
			AnnotPrintSIB(Opnd, (SignedOffset != 0), OutFile);
			if (SignedOffset > 0) // print plus sign
				SMP_fprintf(OutFile, "+%d] ", SignedOffset);
			else if (SignedOffset < 0) // minus sign will print automatically
				SMP_fprintf(OutFile, "%d] ", SignedOffset);

		}
		else {
			ushort BaseReg = Opnd.reg;
			BaseOp.reg = BaseReg;
			if (RegSizes[BaseReg] == 1)
				BaseOp.dtyp = dt_byte;
			if (SignedOffset >= 0) // print plus sign
				SMP_fprintf(OutFile, " Memory[%s+%d] ", MDGetRegName(BaseOp), SignedOffset);
			else // minus sign will print automatically
				SMP_fprintf(OutFile, " Memory[%s%d] ", MDGetRegName(BaseOp), SignedOffset);
		}
	}
	else if (Opnd.type == o_reg) {
		SMP_fprintf(OutFile, " %s ", MDGetRegName(Opnd));
	}
	else if (Opnd.type == o_imm) {
		SMP_fprintf(OutFile, " %ld ", (long) Opnd.value);
	}
	else if ((Opnd.type == o_far) || (Opnd.type == o_near)) {
		SMP_fprintf(OutFile, " %lx ", (unsigned long) Opnd.addr);
	}
	else {
		SMP_fprintf(OutFile, " ERROROP");
	}
	return;
} // end of PrintSPARKAdaOperand()

// Print an operator in SPARK-Ada form.
void PrintSPARKAdaOperator(SMPoperator Oper, FILE *OutFile) {
	switch (Oper) {
		case SMP_NULL_OPERATOR: 
		case SMP_INPUT:  // input from port
		case SMP_OUTPUT: // output to port
			SMP_msg("ERROR: SPARK: Cannot translate operator: ");
			SMP_msg(" %s \n", OperatorText[Oper]);
			break;

		case SMP_CALL:  // CALL instruction
			break;

		case SMP_ADDRESS_OF: // take effective address
			break;

		case SMP_U_LEFT_SHIFT: // unsigned left shift
			SMP_fprintf(ZST_SPARKSourceFile, " Interfaces.Shift_Left");
			break;

		case SMP_S_LEFT_SHIFT: // signed left shift
		case SMP_U_RIGHT_SHIFT: // unsigned right shift
		case SMP_S_RIGHT_SHIFT: // signed right shift
		case SMP_ROTATE_LEFT:
		case SMP_ROTATE_LEFT_CARRY: // rotate left through carry
		case SMP_ROTATE_RIGHT:
		case SMP_ROTATE_RIGHT_CARRY: // rotate right through carry
		case SMP_DECREMENT:
		case SMP_INCREMENT:
		case SMP_ADD:
		case SMP_ADD_CARRY:   // add with carry
		case SMP_SUBTRACT:
		case SMP_SUBTRACT_BORROW:  // subtract with borrow
		case SMP_U_MULTIPLY:
		case SMP_S_MULTIPLY:
		case SMP_U_DIVIDE:
		case SMP_S_DIVIDE:
		case SMP_U_REMAINDER:
		case SMP_SIGN_EXTEND:
		case SMP_ZERO_EXTEND:
			break;

		case SMP_ASSIGN:
			SMP_fprintf(OutFile, ":= ");
			break;

		case SMP_BITWISE_AND:
		case SMP_BITWISE_OR:
		case SMP_BITWISE_NOT: // unary operator
		case SMP_BITWISE_XOR:
		case SMP_BITWISE_AND_NOT:
		case SMP_NEGATE:    // unary negation
		case SMP_S_COMPARE: // signed compare (subtraction-based)
		case SMP_U_COMPARE: // unsigned compare (AND-based)
		case SMP_GENERAL_COMPARE: // comparisons of packed data, strings, signed, unsigned depending on control words
		case SMP_LESS_THAN: // boolean test operators
		case SMP_GREATER_THAN:
		case SMP_LESS_EQUAL:
		case SMP_GREATER_EQUAL:
		case SMP_EQUAL:
		case SMP_NOT_EQUAL:
		case SMP_LOGICAL_AND:
		case SMP_LOGICAL_OR:
		case SMP_UNARY_NUMERIC_OPERATION:  // miscellaneous; produces NUMERIC result
		case SMP_BINARY_NUMERIC_OPERATION:  // miscellaneous; produces NUMERIC result
		case SMP_SYSTEM_OPERATION:   // for instructions such as CPUID, RDTSC, etc.; NUMERIC
		case SMP_UNARY_FLOATING_ARITHMETIC:  // all the same to our type system; all NUMERIC
		case SMP_BINARY_FLOATING_ARITHMETIC:  // all the same to our type system; all NUMERIC
		case SMP_REVERSE_SHIFT_U: // Shift right operand by bit count in left operand
		case SMP_SHUFFLE: // Shuffle bytes, words, etc. within destination operation per source mask
		case SMP_COMPARE_EQ_AND_SET: // Compare for equality and set fields to all 1's or all 0's
		case SMP_COMPARE_NE_AND_SET: // Compare for not-equal and set fields to all 1's or all 0's
		case SMP_COMPARE_GT_AND_SET: // Compare for greater-than and set fields to all 1's or all 0's
		case SMP_COMPARE_GE_AND_SET: // Compare for greater-than-or-equal and set fields to all 1's or all 0's
		case SMP_COMPARE_LT_AND_SET: // Compare for less-than and set fields to all 1's or all 0's
		case SMP_COMPARE_LE_AND_SET: // Compare for less-than-or-equal and set fields to all 1's or all 0's
		case SMP_PACK_S:  // Pack operands into extended-precision register, signed saturation for loss of precision
		case SMP_PACK_U:  // Pack operands into extended-precision register, unsigned saturation for loss of precision
		case SMP_AVERAGE_U: // Average of unsigned operands
		case SMP_MULTIPLY_AND_ADD: // multiply and add (or multiply and accumulate)
		case SMP_SUM_OF_DIFFS: // sum over two vectors of absolute values of differences of their elements
		case SMP_MAX_S: // dest := signed_max(dest, src)
		case SMP_MAX_U: // dest := unsigned_max(dest, src)
		case SMP_MIN_S: // dest := signed_min(dest, src)
		case SMP_MIN_U: // dest := unsigned_min(dest, src)
		case SMP_ABSOLUTE_VALUE: // take absolute value
		case SMP_CONVERT_INT_TO_FP: // convert integer to floating point
		case SMP_CONVERT_FP_TO_INT: // convert floating point to integer
		case SMP_CREATE_MASK: // Create AND-mask from operand and byte/word/dword position # in immediate
		case SMP_INTERLEAVE: // extended-precision interleaving of bytes or words or dwords etc.; NUMERIC
		case SMP_CONCATENATE:     // extended-precision concatenation; NUMERIC
		case SMP_EXTRACT_ZERO_EXTEND: // Extract sub-reg and zero-extend to reg length
		case SMP_ENCRYPTION_OPERATION: // encryption or decryption bit manipulation operation
		case SMP_SIGNAL:   // signal or raise exception
			break;

		default:
			SMP_msg("ERROR: SPARK: Cannot translate unknown operator: ");
			SMP_msg(" %s \n", OperatorText[Oper]);
			break;
	}
} // end of PrintSPARKAdaOperator()

// *****************************************************************
// Class SMPGuard
// *****************************************************************
// Constructor
SMPGuard::SMPGuard(void) {
	this->LeftOperand.type = o_void;
	this->RightOperand.type = o_void;
	this->GuardOp = SMP_NULL_OPERATOR;
	return;
}

// Debug print
void SMPGuard::Dump(void) const {
	SMP_msg("GUARD: ");
	PrintOperand(this->LeftOperand);
	SMP_msg(" %s ", OperatorText[this->GuardOp]);
	PrintOperand(this->RightOperand);
	SMP_msg(":");
	return;
} // end of SMPGuard::Dump()

// *****************************************************************
// Class SMPRegTransfer
// *****************************************************************
// Constructors
SMPRegTransfer::SMPRegTransfer(void) {
	this->Guard = NULL;
	this->LeftOperand.type = o_void;
	this->RightOperand.type = o_void;
	this->RTop.oper = SMP_NULL_OPERATOR;
	this->RTop.type = UNINIT;
#if SMP_TRACK_NONSPEC_OPER_TYPE
	this->RTop.NonSpeculativeType = UNINIT;
#endif
	this->booleans1 = 0;
	this->RightRT = NULL;
	this->ParentInst = NULL;
	return;
}

// Destructor
SMPRegTransfer::~SMPRegTransfer() {
#if 0
	SMP_msg("Destroying SMPRegTransfer.\n");
#endif
	if (NULL != this->RightRT)
		delete this->RightRT;
	if (NULL != this->Guard)
		delete this->Guard;
	return;
}

// Get the left operand, and normalize it if it is a stack operand.
op_t SMPRegTransfer::GetLeftOperand(void) const {
	op_t TempOp = this->LeftOperand;
	// AreDefsNormalized and AreUsesNormalized should always agree, but we
	//  use Defs for left operands and Uses for right operands, which is not
	//  strictly true, but there is no difference in results.
	if (this->ParentInst->AreDefsNormalized()) {
		ea_t InstAddr = this->ParentInst->GetAddr();
		TempOp = this->ParentInst->GetBlock()->GetFunc()->GetNormalizedOperand(InstAddr, TempOp);
	}
	return TempOp;
} // end of SMPRegTransfer::GetLeftOperand()

// Get the right operand, and normalize it if it is a stack operand.
op_t SMPRegTransfer::GetRightOperand(void) const {
	op_t TempOp = this->RightOperand;
	if (this->ParentInst->AreDefsNormalized()) {
		ea_t InstAddr = this->ParentInst->GetAddr();
		TempOp = this->ParentInst->GetBlock()->GetFunc()->GetNormalizedOperand(InstAddr, TempOp);
	}
	return TempOp;
} // end of SMPRegTransfer::GetRightOperand()

// Does RTL subtract a non-immediate value from the stack pointer?
bool SMPRegTransfer::IsAllocaRTL(void) {
	bool AllocaFound = false;
	// Search for the pattern: stack_pointer := stack_pointer minus non-immediate
	if ((SMP_ASSIGN == this->GetOperator()) && (this->HasRightSubTree())) {
		op_t DefOp = this->GetLeftOperand();
		if (DefOp.is_reg(MD_STACK_POINTER_REG)) {
			// We have the code pattern stack_pointer := ...
			SMPRegTransfer *RightRT = this->GetRightTree();
			SMPoperator RightOperator = RightRT->GetOperator();
			op_t RightDefOp = RightRT->GetLeftOperand();
			if ((RightDefOp.is_reg(MD_STACK_POINTER_REG)) && (SMP_SUBTRACT == RightOperator)) {
				// We have the code pattern stack_pointer := stack_pointer minus ...
				if (RightRT->HasRightSubTree()) {
					AllocaFound = true; // not an immediate rightop, whatever it is
				}
				else {
					op_t RightUseOp = RightRT->GetRightOperand();
					if (o_imm != RightUseOp.type) {
						AllocaFound = true;
					}
				}
			}
		}
	}
	return AllocaFound;
} // end of SMPRegTransfer::IsAllocaRTL()

// If we see add esp,immediate and the immediate value is large, then
//  some stupid hand-coded ASM is probably counting on an overflow, and
//  this is actually a subtraction from the stack pointer (i.e. it is an
//  addition of a negative number). We have to detect the signedness error
//  because IDA Pro treats the immediate operands as unsigned at all times.
#define STARS_ESP_ADDITION_OVERFLOW_THRESHOLD 0xf0000000

// Compute operand-dependent change in stack pointer value.
sval_t SMPRegTransfer::ComputeStackPointerAlteration(bool IsLeaveInstr, sval_t IncomingDelta, sval_t FramePtrDelta) {
	sval_t delta = 0;

	// Search for the pattern: stack_pointer := ...
	if (SMP_ASSIGN == this->GetOperator()) {
		op_t DefOp = this->GetLeftOperand();
		if (DefOp.is_reg(MD_STACK_POINTER_REG)) {
			// We have the code pattern stack_pointer := ...
			// We expect to find an overall RT structure of:
			//   stack_pointer := stack_pointer binaryoperator constant
			//  If the binaryoperator is addition or subtraction, then
			//   we use the constant to determine our return value.
			//  If the binaryoperator is a bitwise AND, then we return
			//   a special code. Delta is unknown but can probably be treated
			//   as zero, assuming that no stack-pointer-relative accesses to
			//   the stack region above the current stack pointer occur later.
			//  If we have a non-constant operand, we return an error code
			//   to indicate that we cannot compute the delta.
			//  If we don't have a binary operator, we return an error code,
			//   unless we find a stack frame deallocation:  esp := ebp
			if (!this->HasRightSubTree()) {
				op_t UseOp = this->GetRightOperand();
				if (UseOp.is_reg(MD_FRAME_POINTER_REG)) { // !!!!****!!!! Should validate that frame pointer reg is used as frame pointer
					// Found esp := ebp (deallocation of stack frame)
					delta = FramePtrDelta - IncomingDelta;
					assert(delta >= 0); // e.g. -4 - -12 => +8 for an 8-byte frame
				}
				else {
					// !!!!****!!!!**** Need to look up deltas for registers that
					//  were used to hold a copy of the stack pointer.
					// For now, just consider it an error.
					delta = (sval_t) SMP_STACK_DELTA_ERROR_CODE;
				}
			}
			else {
				SMPRegTransfer *RightRT = this->GetRightTree();
				SMPoperator RightOperator = RightRT->GetOperator();
				op_t RightDefOp = RightRT->GetLeftOperand();
				if (IsLeaveInstr) {
					// Found the RT esp := ebp + wordsize that adjusts the stack pointer
					//  for an x86 LEAVE instruction. esp := ebp is equivalent
					//  to esp := <esp when frame ptr was set up>, so delta becomes
					//  <esp delta when frame ptr was set up> - IncomingDelta + wordsize.
					assert(SMP_ADD == RightOperator);
					assert(!RightRT->HasRightSubTree());
					assert(RightDefOp.is_reg(X86_FRAME_POINTER_REG));
					delta = STARS_ISA_Bytewidth + FramePtrDelta - IncomingDelta;
				}
				else if (RightRT->HasRightSubTree()) {
					// Not the right code pattern; unknown effect on stack pointer.
					delta = (sval_t) SMP_STACK_DELTA_ERROR_CODE;
				}
				else if (!RightDefOp.is_reg(MD_STACK_POINTER_REG)) {
					// We have stack_pointer := something1 operator something2
					//  where something1 is not the stack_pointer. It might be
					//  the frame pointer, e.g. SP := FP-12. We can compute this
					//  stack delta because we know the delta when the FP was set up.
					op_t RightUseOp = RightRT->GetRightOperand();
					if (RightDefOp.is_reg(MD_FRAME_POINTER_REG) && (o_imm == RightUseOp.type)) {
						// We have SP := FP operator immediate
						delta = FramePtrDelta - IncomingDelta; // partial computation: SP := BP
						assert(delta >= 0); // e.g. -4 - -12 => +8 for an 8-byte frame
						if (SMP_ADD == RightOperator) {
							delta += RightUseOp.value;
						}
						else if (SMP_SUBTRACT == RightOperator) {
							delta -= RightUseOp.value;
						}
						else {
							// Not the right code pattern; unknown effect on stack pointer.
							delta = (sval_t) SMP_STACK_DELTA_ERROR_CODE;
						}
					}
					else {
						// !!!!****!!!!**** Need to look up deltas for registers that
						//  were used to hold a copy of the stack pointer.
						// For now, just consider it an error.
						delta = (sval_t) SMP_STACK_DELTA_ERROR_CODE;
					}
				}
				else {
					// We have stack_pointer := stack_pointer operator ...
					op_t RightUseOp = RightRT->GetRightOperand();
					// Check the operator
					if (SMP_BITWISE_AND == RightOperator) {
						delta = (sval_t) SMP_STACK_POINTER_BITWISE_AND_CODE;
					}
					else {
						if (o_imm != RightUseOp.type) {
							// Don't know how to deal with adding non-constant to stack pointer
							delta = (sval_t) SMP_STACK_DELTA_ERROR_CODE;
						}
						else if (SMP_ADD == RightOperator) {
							delta = (sval_t) RightUseOp.value;
							if (delta > STARS_ESP_ADDITION_OVERFLOW_THRESHOLD) {
								// Really a subtraction via addition of a negative.
								//  E.g. add esp, 0xfffffff0 is sub esp,16
								int32 TempDelta = (int32) (delta & 0xffffffff);
								delta = (sval_t) TempDelta;
							}
						}
						else if (SMP_SUBTRACT == RightOperator) {
							if (RightUseOp.value > STARS_ESP_ADDITION_OVERFLOW_THRESHOLD) {
								// Really a subtraction via addition of a negative.
								//  E.g. add esp, 0xfffffff0 is sub esp,16
								int32 TempDelta = (int32) (RightUseOp.value & 0xffffffff);
								delta = (0 - ((sval_t) TempDelta));
							}
							else {
								delta = (0 - ((sval_t) RightUseOp.value));
							}
						}
						else {
							delta = (sval_t) SMP_STACK_DELTA_ERROR_CODE;
						}
					}
				}
			}
		}
	}
	return delta;
} // end of SMPRegTransfer::ComputeStackPointerAlteration()

// Evaluate constant expressions for SCCP algorithm
struct STARS_SCCP_Const_Struct SMPRegTransfer::SCCPEvaluateRTLConsts(list<pair<int, int> > &SSAWorkList) {
	struct STARS_SCCP_Const_Struct ReturnConstStruct;
	ReturnConstStruct.ConstType = STARS_CONST_TOP; // default value

	SMPoperator CurrOper = this->GetOperator();
	switch (CurrOper) {
		case SMP_ASSIGN:
		{
			op_t LeftOp = this->GetLeftOperand();
			if (o_reg != LeftOp.type) {
				break; // Only looking to update registers now
			}
			bool NewValueAvailable;
			if (this->HasRightSubTree()) {
				ReturnConstStruct = this->GetRightTree()->SCCPEvaluateRTLConsts(SSAWorkList); // recurse into right subtree
			}
			else {
				op_t RightOp = this->GetRightOperand();
				this->ParentInst->SCCPFetchConstUseValue(RightOp, ReturnConstStruct);
			}
			NewValueAvailable = (STARS_CONST_TOP != ReturnConstStruct.ConstType);
			// Update const map entry for DEF
			if (NewValueAvailable) {
				CanonicalizeOpnd(LeftOp);
				struct STARS_SCCP_Const_Struct OldConstStruct;
				OldConstStruct.ConstType = STARS_CONST_TOP;
				set<DefOrUse, LessDefUse>::iterator DefIter = this->ParentInst->FindDef(LeftOp);
				if (DefIter != this->ParentInst->GetLastDef()) {
					int DefSSANum = DefIter->GetSSANum();
					int DefHashValue = HashGlobalNameAndSSA(LeftOp, DefSSANum);
					bool LocalName = this->ParentInst->GetBlock()->IsLocalName(LeftOp);
					this->ParentInst->SCCPFetchConstDefValue(LeftOp, OldConstStruct);
					bool HasOldValue = (STARS_CONST_TOP != OldConstStruct.ConstType);

					if (HasOldValue) { // must perform type lattice meet operation to update ReturnConstStruct
						STARSConstantTypeMeet(OldConstStruct, ReturnConstStruct);
					}
					if (ReturnConstStruct.ConstType != OldConstStruct.ConstType) { // type change
						map<int, struct STARS_SCCP_Const_Struct>::iterator NewConstIter;
						if (LocalName) {
							NewConstIter = this->ParentInst->GetBlock()->InsertLocalConstValue(DefHashValue, ReturnConstStruct);
						}
						else {
							NewConstIter = this->ParentInst->GetBlock()->GetFunc()->InsertGlobalConstValue(DefHashValue, ReturnConstStruct);
						}
						// Propagate along SSA edges.
						int BlockNum = this->ParentInst->GetBlock()->GetNumber();
						pair<int, int> SSAEdge(BlockNum, DefHashValue);
						SSAWorkList.push_back(SSAEdge);
					}
				}
			}
			break; // end case for SMP_ASSIGN
		}

		case SMP_ADD:
		case SMP_SUBTRACT:
		case SMP_U_MULTIPLY:
		case SMP_S_MULTIPLY:
		case SMP_BITWISE_AND:
		case SMP_BITWISE_OR:
		case SMP_BITWISE_XOR:
		case SMP_BITWISE_AND_NOT:
		case SMP_S_COMPARE:
		case SMP_U_COMPARE:
			// binary arithmetic operators
			// We will initially deal with the simple case: The comparison is of a LeftOp register to a RightOp register or immediate.
			//  If the result is definitely zero, we return zero as the const value (presumably to be put into the zero flag).
			if (!(this->HasRightSubTree())) { // simple compare of two operands should always be the case
				op_t LeftOp = this->GetLeftOperand();
				op_t RightOp = this->GetRightOperand();
				if ((LeftOp.type == o_reg) && ((RightOp.type == o_reg) || (RightOp.type == o_imm))) {
					CanonicalizeOpnd(LeftOp);
					CanonicalizeOpnd(RightOp);
					struct STARS_SCCP_Const_Struct LeftValue, RightValue;

					this->ParentInst->SCCPFetchConstUseValue(LeftOp, LeftValue);
					bool LeftValueAvailable = (STARS_CONST_TOP != LeftValue.ConstType);
					if (STARS_CONST_BOTTOM == LeftValue.ConstType) {
						ReturnConstStruct = LeftValue;
						break; // right operand is irrelevant if left is BOTTOM
					}

					bool RightValueAvailable = false;
					if (o_imm == RightOp.type) {
						RightValueAvailable = true;
						RightValue.ConstType = STARS_CONST_HAS_VALUE;
						RightValue.ConstValue = RightOp.value;
					}
					else {
						this->ParentInst->SCCPFetchConstUseValue(RightOp, RightValue);
						RightValueAvailable = (STARS_CONST_TOP != RightValue.ConstType);
						if (STARS_CONST_BOTTOM == RightValue.ConstType) {
							ReturnConstStruct = RightValue;
							break; // left operand is irrelevant if right is BOTTOM
						}
					}

					if (LeftValueAvailable && RightValueAvailable) {
						// Apply the operator to the values.
						ReturnConstStruct.ConstType = STARS_CONST_HAS_VALUE;
						uval_t TestValue;
						bool CompareFlag = ((CurrOper == SMP_S_COMPARE) || (CurrOper == SMP_U_COMPARE));
						if (CurrOper == SMP_ADD) {
							TestValue = (LeftValue.ConstValue + RightValue.ConstValue);
						}
						else if ((CurrOper == SMP_U_MULTIPLY) || (CurrOper == SMP_S_MULTIPLY)) {
							TestValue = (LeftValue.ConstValue * RightValue.ConstValue);
						}
						else if ((CurrOper == SMP_SUBTRACT) || (CurrOper == SMP_S_COMPARE)) {
							// Signed compare is a subtraction operation
							TestValue = (LeftValue.ConstValue - RightValue.ConstValue);
						}
						else if ((CurrOper == SMP_U_COMPARE) || (CurrOper == SMP_BITWISE_AND)) {
							// Unsigned compare is a bitwise AND operation
							TestValue = (LeftValue.ConstValue & RightValue.ConstValue);
						}
						else if (CurrOper == SMP_BITWISE_OR) {
							TestValue = (LeftValue.ConstValue | RightValue.ConstValue);
						}
						else if (CurrOper == SMP_BITWISE_XOR) {
							TestValue = (LeftValue.ConstValue ^ RightValue.ConstValue);
						}
						else if (CurrOper == SMP_BITWISE_AND_NOT) {
							TestValue = (LeftValue.ConstValue & (~(RightValue.ConstValue)));
						}
						else {
							break; // should be unreachable
						}
						if ((0 != TestValue) && CompareFlag) {
							TestValue = 1; // i.e. zero flag will be set to false
						}
						ReturnConstStruct.ConstValue = TestValue;
					}
				} // end if two regs, or one reg and one immediate
			} // end if no right subtree
			break; // end of signed and unsigned compare operators case

		default:
			break; // ignore
	} // end switch(CurrOper)

	return ReturnConstStruct;
} // end of SMPRegTransfer::SCCPEvaluateRTLConsts()

// Debug print
void SMPRegTransfer::Dump(void) const {
	if (NULL != this->Guard)
		this->Guard->Dump();
	// Left operand
	if (o_void != this->LeftOperand.type)
		PrintOperand(this->LeftOperand);
	// Then the operator
	SMP_msg(" %s ", OperatorText[this->GetOperator()]);
	// then the right operand or subtree
	if (this->HasRightSubTree())
		this->GetRightTree()->Dump();
	else if (o_void != this->RightOperand.type)
		PrintOperand(this->RightOperand);
	return;
}

void SMPRegTransfer::EmitSPARKAda(void) const {
	SMPoperator CurrOper = this->GetOperator();
	switch (CurrOper) {
		case SMP_NULL_OPERATOR: 
		case SMP_INPUT:  // input from port
		case SMP_OUTPUT: // output to port
			SMP_msg("ERROR: SPARK: Cannot translate operator: ");
			SMP_msg(" %s \n", OperatorText[this->GetOperator()]);
			break;

		case SMP_CALL:  // CALL instruction
			break;

		case SMP_ADDRESS_OF: // take effective address
			break;

		case SMP_U_LEFT_SHIFT: // unsigned left shift
			// Ada: result := Interfaces.Shift_Left(Value => LeftOperand, Amount => RightOperand);
		case SMP_U_RIGHT_SHIFT: // unsigned right shift
			// Ada: result := Interfaces.Shift_Right(Value => LeftOperand, Amount => RightOperand);
		case SMP_S_RIGHT_SHIFT: // signed right shift
			// Ada: result := Interfaces.Shift_Right_Arithmetic(Value => LeftOperand, Amount => RightOperand);
		case SMP_ROTATE_LEFT:
			// Ada: result := Interfaces.Rotate_Left(Value => LeftOperand, Amount => RightOperand);
		case SMP_ROTATE_RIGHT:
			// Ada: result := Interfaces.Rotate_Right(Value => LeftOperand, Amount => RightOperand);
			PrintSPARKAdaOperator(CurrOper, ZST_SPARKSourceFile);
			SMP_fprintf(ZST_SPARKSourceFile, "(Value => ");
			PrintSPARKAdaOperand(this->GetLeftOperand(), ZST_SPARKSourceFile);
			SMP_fprintf(ZST_SPARKSourceFile, ", Amount => ");
			this->EmitSPARKAdaForRHS();
			SMP_fprintf(ZST_SPARKSourceFile, ");\n");
			break;

		case SMP_S_LEFT_SHIFT: // signed left shift
			// Need to convert to multiplication
			break;

		case SMP_ROTATE_LEFT_CARRY: // rotate left through carry
		case SMP_ROTATE_RIGHT_CARRY: // rotate right through carry
		case SMP_DECREMENT:
		case SMP_INCREMENT:
		case SMP_ADD:
		case SMP_ADD_CARRY:   // add with carry
		case SMP_SUBTRACT:
		case SMP_SUBTRACT_BORROW:  // subtract with borrow
		case SMP_U_MULTIPLY:
		case SMP_S_MULTIPLY:
		case SMP_U_DIVIDE:
		case SMP_S_DIVIDE:
		case SMP_U_REMAINDER:
		case SMP_SIGN_EXTEND:
		case SMP_ZERO_EXTEND:
			break;

		case SMP_ASSIGN:
			PrintSPARKAdaOperand(this->GetLeftOperand(), ZST_SPARKSourceFile);
			SMP_fprintf(ZST_SPARKSourceFile, ":= ");
			this->EmitSPARKAdaForRHS();
			SMP_fprintf(ZST_SPARKSourceFile, ";\n");
			break;

		case SMP_BITWISE_AND:
		case SMP_BITWISE_OR:
		case SMP_BITWISE_NOT: // unary operator
		case SMP_BITWISE_XOR:
		case SMP_BITWISE_AND_NOT:
		case SMP_NEGATE:    // unary negation
		case SMP_S_COMPARE: // signed compare (subtraction-based)
		case SMP_U_COMPARE: // unsigned compare (AND-based)
		case SMP_GENERAL_COMPARE: // comparisons of packed data, strings, signed, unsigned depending on control words
		case SMP_LESS_THAN: // boolean test operators
		case SMP_GREATER_THAN:
		case SMP_LESS_EQUAL:
		case SMP_GREATER_EQUAL:
		case SMP_EQUAL:
		case SMP_NOT_EQUAL:
		case SMP_LOGICAL_AND:
		case SMP_LOGICAL_OR:
		case SMP_UNARY_NUMERIC_OPERATION:  // miscellaneous; produces NUMERIC result
		case SMP_BINARY_NUMERIC_OPERATION:  // miscellaneous; produces NUMERIC result
		case SMP_SYSTEM_OPERATION:   // for instructions such as CPUID, RDTSC, etc.; NUMERIC
		case SMP_UNARY_FLOATING_ARITHMETIC:  // all the same to our type system; all NUMERIC
		case SMP_BINARY_FLOATING_ARITHMETIC:  // all the same to our type system; all NUMERIC
		case SMP_REVERSE_SHIFT_U: // Shift right operand by bit count in left operand
		case SMP_SHUFFLE: // Shuffle bytes, words, etc. within destination operation per source mask
		case SMP_COMPARE_EQ_AND_SET: // Compare for equality and set fields to all 1's or all 0's
		case SMP_COMPARE_NE_AND_SET: // Compare for not-equal and set fields to all 1's or all 0's
		case SMP_COMPARE_GT_AND_SET: // Compare for greater-than and set fields to all 1's or all 0's
		case SMP_COMPARE_GE_AND_SET: // Compare for greater-than-or-equal and set fields to all 1's or all 0's
		case SMP_COMPARE_LT_AND_SET: // Compare for less-than and set fields to all 1's or all 0's
		case SMP_COMPARE_LE_AND_SET: // Compare for less-than-or-equal and set fields to all 1's or all 0's
		case SMP_PACK_S:  // Pack operands into extended-precision register, signed saturation for loss of precision
		case SMP_PACK_U:  // Pack operands into extended-precision register, unsigned saturation for loss of precision
		case SMP_AVERAGE_U: // Average of unsigned operands
		case SMP_MULTIPLY_AND_ADD: // multiply and add (or multiply and accumulate)
		case SMP_SUM_OF_DIFFS: // sum over two vectors of absolute values of differences of their elements
		case SMP_MAX_S: // dest := signed_max(dest, src)
		case SMP_MAX_U: // dest := unsigned_max(dest, src)
		case SMP_MIN_S: // dest := signed_min(dest, src)
		case SMP_MIN_U: // dest := unsigned_min(dest, src)
		case SMP_ABSOLUTE_VALUE: // take absolute value
		case SMP_CONVERT_INT_TO_FP: // convert integer to floating point
		case SMP_CONVERT_FP_TO_INT: // convert floating point to integer
		case SMP_CREATE_MASK: // Create AND-mask from operand and byte/word/dword position # in immediate
		case SMP_INTERLEAVE: // extended-precision interleaving of bytes or words or dwords etc.; NUMERIC
		case SMP_CONCATENATE:     // extended-precision concatenation; NUMERIC
		case SMP_EXTRACT_ZERO_EXTEND: // Extract sub-reg and zero-extend to reg length
		case SMP_ENCRYPTION_OPERATION: // encryption or decryption bit manipulation operation
		case SMP_SIGNAL:   // signal or raise exception
			break;

		default:
			SMP_msg("ERROR: SPARK: Cannot translate unknown operator: ");
			SMP_msg(" %s \n", OperatorText[this->GetOperator()]);
			break;
	}
	return;
} // end of SMPRegTransfer::EmitSPARKAda()

// Helper for right hand side of statements (i.e. RightOperand or RightTree)
void SMPRegTransfer::EmitSPARKAdaForRHS(void) const {
	if (this->HasRightSubTree()) {
		SMP_fprintf(ZST_SPARKSourceFile, "(");
		SMPRegTransfer *RightRT = this->GetRightTree();
		RightRT->EmitSPARKAda();
		SMP_fprintf(ZST_SPARKSourceFile, ")");
	}
	else {
		PrintSPARKAdaOperand(this->GetRightOperand(), ZST_SPARKSourceFile);
	}
	return;
} // end of SMPRegTransfer::EmitSPARKAdaForRHS()

// *****************************************************************
// Class SMPRTL
// *****************************************************************

// Constructor
SMPRTL::SMPRTL() {
	this->ExtraKills.clear();
	this->RTCount = 0;
	return;
}

// Destructor
SMPRTL::~SMPRTL() {
	for (size_t index = 0; index < this->RTCount; ++index) {
		delete (this->RTvector[index]);
	}
	this->ExtraKills.clear();
	return;
}

// Get methods
SMPRegTransfer *SMPRTL::GetRT(size_t index) const {
	if (index > this->RTCount)
		return NULL;
	else
		return this->RTvector[index];
}

// Set methods
void SMPRTL::push_back(SMPRegTransfer *NewEffect) {
	assert(SMP_RT_LIMIT > this->RTCount);
	this->RTvector[this->RTCount] = NewEffect;
	++(this->RTCount);
	return;
}

// Printing methods
void SMPRTL::Dump(void) const {
	size_t index;
	if (0 < this->RTCount) {
		SMP_msg("RTL: ");
		for (index = 0; index < this->RTCount; ++index) {
			this->RTvector[index]->Dump();
		}
		for (index = 0; index < this->ExtraKills.size(); ++index) {
			SMP_msg(" KILL: ");
			PrintOperand(this->ExtraKills.at(index));
		}
		SMP_msg("\n");
	}
	return;
} // end of SMPRTL::Dump()

// Accumulate stack pointer alteration total across all RTs.
sval_t SMPRTL::TotalStackPointerAlteration(bool IsLeaveInstr, sval_t IncomingDelta, sval_t FramePtrDelta) {
	sval_t TotalDelta = 0;
	sval_t IncrementalDelta;

	for (size_t index = 0; index < this->RTCount; ++index) {
		IncrementalDelta = this->RTvector[index]->ComputeStackPointerAlteration(IsLeaveInstr, IncomingDelta, FramePtrDelta);
		if ((SMP_STACK_DELTA_ERROR_CODE == IncrementalDelta) 
			|| (SMP_STACK_POINTER_BITWISE_AND_CODE == IncrementalDelta)) {
			TotalDelta = IncrementalDelta;  // pass code back
			break; // exit loop and return coded value
		}
		else {
			TotalDelta += IncrementalDelta;
		}
	}

	return TotalDelta;
} // end of SMPRTL::TotalStackPointerAlteration()

// *****************************************************************
// Class SMPInstr
// *****************************************************************

// Constructor for instruction.
SMPInstr::SMPInstr(ea_t addr) {
	this->SMPcmd.size = 0;
	this->address = addr;
#if 0
	this->ResetGoodRTL();
	this->ResetJumpTarget();
	this->ResetBlockTerm();
	this->ResetTailCall();
	this->ResetCondTailCall();
	this->ResetCallUsedAsJump();
	this->ResetDirectRecursiveCall();
	this->ResetInterrupt();
#else
	this->booleans1 = 0;
#endif
#if 0
	this->ResetNop();
	this->ResetRegClearIdiom();
	this->ResetDefsFlags();
	this->ResetUsesFlags();
	this->ResetFarBranchComputed();
	this->ResetBranchesToFarChunk();
	this->ResetIndirectMemWrite();
	this->ResetIndirectMemRead();
#else
	this->booleans2 = 0;
#endif
#if 0
	this->ResetLoadFromStack();
	this->ResetMultiplicationBitsDiscarded();
	this->ResetTypeInferenceComplete();
	this->ResetCategoryInferenceComplete();
	this->ResetDEFsTyped();
	this->ResetUSEsTyped();
#else
	this->booleans3 = 0;
#endif
	this->booleans4 = 0;

	this->CallTarget = BADADDR;
	this->FarBranchTarget = BADADDR;
	this->AddSubSourceType = UNINIT;
	this->AddSubDefUseType = UNINIT;
#if 0
	this->AddSubSourceOp = InitOp;
	this->AddSubDefUseOp = InitOp;
#endif
	this->DEFMemOp = InitOp;
	this->USEMemOp = InitOp;
	this->MoveSource = InitOp;
	this->BasicBlock = NULL;
	this->features = 0;
	this->StackPtrOffset = 0;
	this->type = DEFAULT;
	this->OptType = 0;
	this->Defs.clear();
	this->Uses.clear();
	return;
}

// Destructor.
SMPInstr::~SMPInstr() {
	this->Defs.clear();
	this->Uses.clear();
	return;
}

char *SMPInstr::GetDisasm(void) const {
	return DisAsmText.GetDisAsm(this->GetAddr());
}

// Is the instruction the type that terminates a basic block?
bool SMPInstr::IsBasicBlockTerminator() const {
	return ((type == JUMP) || (type == COND_BRANCH)
			|| (type == INDIR_JUMP) || (type == RETURN));
}

// Get non-flags DEF, usually for arithmetic opcode.
set<DefOrUse, LessDefUse>::iterator SMPInstr::GetFirstNonFlagsDef(void) {
	set<DefOrUse, LessDefUse>::iterator DefIter;
	op_t DefOp;

	for (DefIter = this->GetFirstDef(); DefIter != this->GetLastDef(); ++DefIter) {
		DefOp = DefIter->GetOp();
		if (!((o_reg == DefOp.type) && DefOp.is_reg(MD_FLAGS_REG)))
			break; // found a non-flags-reg DEF.
	}
	return DefIter;
}

// Fetch the operands for a shift instruction
void SMPInstr::GetShiftOperands(op_t &ShiftedOp, op_t &ShiftCounterOp) {
	bool success = false;
	if (this->RTL.GetRT(0)->HasRightSubTree()) {
		SMPRegTransfer *RightRT = this->RTL.GetRT(0)->GetRightTree();
		SMPoperator RightOper = RightRT->GetOperator();
		if ((RightOper == SMP_U_LEFT_SHIFT) || (RightOper == SMP_S_LEFT_SHIFT)
			|| (RightOper == SMP_U_RIGHT_SHIFT) || (RightOper == SMP_S_RIGHT_SHIFT)) {
			if (!(RightRT->HasRightSubTree())) {
				success = true;
				ShiftedOp = RightRT->GetLeftOperand();
				ShiftCounterOp = RightRT->GetRightOperand();
			}
		}
	}

	if (!success) {
		ShiftedOp = InitOp;
		ShiftCounterOp = InitOp;
	}
	return;
} // end of SMPInstr::GetShiftOperands()


// Is the destination operand a memory reference?
bool SMPInstr::HasDestMemoryOperand(void) {
	return (o_void != this->DEFMemOp.type);
} // end of SMPInstr::HasDestMemoryOperand()

// Is a source operand a memory reference?
bool SMPInstr::HasSourceMemoryOperand(void) {
	return (o_void != this->USEMemOp.type);
} // end of SMPInstr::HasSourceMemoryOperand()

// Get the first memory operand in the DEF list.
op_t SMPInstr::MDGetMemDefOp(void) const {
	return this->DEFMemOp; // cached value
} // end of SMPInstr::MDGetMemDefOp()

// Get the first memory operand in the USE list.
op_t SMPInstr::MDGetMemUseOp(void) const {
	return this->USEMemOp; // cached value
} // end of SMPInstr::MDGetMemUseOp()

// return original Lea instruction [pseudo-]memory operand.
op_t SMPInstr::GetLeaMemUseOp(void) {
	if (this->BasicBlock == NULL) {
		return InitOp;
	}
	else {
		map<ea_t, op_t>::iterator MapIter = this->GetBlock()->GetFunc()->FindLeaOperand(this->GetAddr());
		return MapIter->second;
	}
}

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

	bool IsAddSubInst = ((NN_adc == opcode) || (NN_add == opcode) || (NN_inc == opcode)
		|| (NN_dec == opcode) || (NN_sbb == opcode) || (NN_sub == opcode));
	if ((this->RTL.GetCount() < 1) || (!IsAddSubInst))
		return InitOp;  // no RTL or not an addition or subtraction

	assert(this->RTL.GetRT(0)->HasRightSubTree());
	SMPRegTransfer *RightTree = this->RTL.GetRT(0)->GetRightTree();
	op_t RightOp;

#if SMP_BUILD_SPECIAL_ADC_SBB_RTL
	if ((NN_adc != this->SMPcmd.itype) && (NN_sbb != this->SMPcmd.itype)) {
		assert(!(RightTree->HasRightSubTree()));
		RightOp = RightTree->GetRightOperand();  // Src (non-DEF) operand
	}
	else {
		// Add with carry and subtract with borrow have an extra level
		//  to the tree RTL, e.g. for add with carry:
		//  opnd1 := (opnd1 + (opnd2 + carryflag))
		assert(RightTree->HasRightSubTree());
		RightTree = RightTree->GetRightTree();
		RightOp = RightTree->GetLeftOperand();
	}
#else
	RightOp = RightTree->GetRightOperand();    // Use (also DEF) operand
#endif

	return RightOp;
}; // end of SMPInstr::GetUseOnlyAddSubOp()

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

	bool IsAddSubInst = ((NN_adc == opcode) || (NN_add == opcode) || (NN_inc == opcode)
		|| (NN_dec == opcode) || (NN_sbb == opcode) || (NN_sub == opcode));
	if ((this->RTL.GetCount() < 1) || (!IsAddSubInst))
		return InitOp;  // no RTL or not an addition or subtraction

	assert(this->RTL.GetRT(0)->HasRightSubTree());
	SMPRegTransfer *RightTree = this->RTL.GetRT(0)->GetRightTree();
	op_t LeftOp;
	LeftOp = RightTree->GetLeftOperand();    // Use (also DEF) operand

	return LeftOp;
}; // end of SMPInstr::GetDefUseAddSubOp()

// return BADADDR if not jump, target addr otherwise.
ea_t SMPInstr::GetJumpTarget(void) const {
	ea_t TargetAddr = BADADDR;
	if (this->HasGoodRTL()) {
		// We want to find an RTL of the form: inst_ptr_reg := code_addr
		SMPRegTransfer *CurrRT = this->RTL.GetRT(0);
		op_t DefOp = CurrRT->GetLeftOperand();
		if (DefOp.is_reg(MD_INSTRUCTION_POINTER_REG)) {
			if ((SMP_ASSIGN == CurrRT->GetOperator()) && (!CurrRT->HasRightSubTree())) {
				op_t UseOp = CurrRT->GetRightOperand();
				if ((o_near == UseOp.type) || (o_far == UseOp.type)) { // address
					TargetAddr = UseOp.addr;
				}
			}
		}
	}
	return TargetAddr;
} // end SMPInstr::GetJumpTarget()

// Does any USE have type NEGATEDPTR?
bool SMPInstr::HasNegatedPtrUSE(void) {
	bool UseFound = false;
	set<DefOrUse, LessDefUse>::iterator UseIter;
	SMPOperandType UseType;

	for (UseIter = this->GetFirstUse(); UseIter != this->GetLastUse(); ++UseIter) {
		UseType = UseIter->GetType();
		if (IsEqType(UseType, NEGATEDPTR)) {
			UseFound = true;
			break;
		}
	}

	return UseFound;
} // end of SMPInstr::HasNegatedPtrUSE()

// Detect indirect memory DEFs or USEs
void SMPInstr::AnalyzeIndirectRefs(bool UseFP) {
	op_t DefMemOp = this->MDGetMemDefOp();
	op_t UseMemOp = this->MDGetMemUseOp();

	if (o_void != DefMemOp.type) {
		// Found a memory DEF. Is it indirect?
		if (MDIsIndirectMemoryOpnd(DefMemOp, UseFP)) {
			this->SetIndirectMemWrite();
		}
	}

	if (o_void != UseMemOp.type) {
		// Found a memory USE. Is it indirect?
		if (MDIsIndirectMemoryOpnd(UseMemOp, UseFP)) {
			this->SetIndirectMemRead();
		}
	}

	return;
} // end of SMPInstr::AnalyzeIndirectRefs()

set<DefOrUse, LessDefUse>::iterator SMPInstr::GetPointerAddressReg(op_t MemOp) {
	int BaseReg;
	int IndexReg;
	ushort ScaleFactor;
	ea_t displacement;
	set<DefOrUse, LessDefUse>::iterator PtrIter;

	if ((NULL == this->BasicBlock) || (NULL == this->BasicBlock->GetFunc())) {
		SMP_msg("ERROR: NULL member pointers in SMPInstr::GetPointerAddressReg() at %lx \n",
			(unsigned long) this->address);
		return this->GetLastUse();
	}
	bool UseFP = this->BasicBlock->GetFunc()->UsesFramePointer();

	MDExtractAddressFields(MemOp, BaseReg, IndexReg, ScaleFactor,
		displacement);

	if ((R_none != BaseReg) && (!MDIsStackPtrReg(BaseReg, UseFP))) {
		op_t BaseOp = InitOp;
		BaseOp.type = o_reg;
		BaseOp.reg = (ushort) BaseReg;
		BaseOp.dtyp = this->GetOperandDtypField();
		PtrIter = this->FindUse(BaseOp);
		assert(PtrIter != this->GetLastUse());
		if (IsDataPtr(PtrIter->GetType())) {
			return PtrIter;
		}
	}
	if ((R_none != IndexReg) && (!MDIsStackPtrReg(IndexReg, UseFP))) {
		op_t IndexOp = InitOp;
		IndexOp.type = o_reg;
		IndexOp.reg = (ushort) IndexReg;
		IndexOp.dtyp = this->GetOperandDtypField();
		PtrIter = this->FindUse(IndexOp);
		assert(PtrIter != this->GetLastUse());
		if (IsDataPtr(PtrIter->GetType())) {
			return PtrIter;
		}
	}
	PtrIter = this->GetLastUse();
	return PtrIter;
} // end of SMPInstr::GetPointerAddressReg()

// Does the instruction whose flags are in F have a numeric type
//   as the second source operand?
// NOTE: We can only analyze immediate values now. When data flow analyses are implemented,
//   we will be able to analyze many non-immediate operands.
#define IMMEDNUM_LOWER -8191
#define IMMEDNUM_UPPER 8191
bool SMPInstr::IsSecondSrcOperandNumeric(flags_t F) const {
	bool SecondOpImm = (this->SMPcmd.Operands[1].type == o_imm);
	uval_t TempImm;

	if (SecondOpImm) {
		TempImm = this->SMPcmd.Operands[1].value;
	}

	return (SecondOpImm && IsImmedNumeric(TempImm));
} // end of SMPInstr::IsSecondSrcOperandNumeric()

// Determine the type of the USE-only operand for add and subtract
//  instructions. If it is NUMERIC or PROF_NUMERIC, an optimizing
//  annotation will result.
// As a byproduct, find the type of the USE/DEF operand as well.
void SMPInstr::SetAddSubSourceType(void) {
	// Walk the RTL and find the operands we care about.
	// The RTL should look like: opnd1 := (opnd1 op opnd2), where op is
	//  and add or subtract operator. Within the parentheses, the type
	//  of opnd1 is our AddSubUseType and opnd1 is our AddSubUseOp, while
	//  the type of opnd2 is our AddSubSourceType.
	if (this->RTL.GetCount() < 1)
		return;  // no RTL, no leave types as UNINIT.

	assert(this->RTL.GetRT(0)->HasRightSubTree());
	SMPRegTransfer *RightTree = this->RTL.GetRT(0)->GetRightTree();
	op_t LeftOp, RightOp;
	LeftOp = RightTree->GetLeftOperand();    // Use (also DEF) operand
#if SMP_BUILD_SPECIAL_ADC_SBB_RTL
	if ((NN_adc != this->SMPcmd.itype) && (NN_sbb != this->SMPcmd.itype)) {
		assert(!(RightTree->HasRightSubTree()));
		RightOp = RightTree->GetRightOperand();  // Src (non-DEF) operand
	}
	else {
		// Add with carry and subtract with borrow have an extra level
		//  to the tree RTL, e.g. for add with carry:
		//  opnd1 := (opnd1 + (opnd2 + carryflag))
		assert(RightTree->HasRightSubTree());
		RightTree = RightTree->GetRightTree();
		RightOp = RightTree->GetLeftOperand();
	}
#else
	assert(!(RightTree->HasRightSubTree()));
	RightOp = RightTree->GetRightOperand();  // Src (non-DEF) operand
#endif

	set<DefOrUse, LessDefUse>::iterator UseIter, SrcIter;

	SrcIter = this->FindUse(RightOp);
	assert(SrcIter != this->GetLastUse());
	this->AddSubSourceType = SrcIter->GetType();
#if 0
	this->AddSubSourceOp = RightOp;
#endif

	UseIter = this->FindUse(LeftOp);
	assert(UseIter != this->GetLastUse());
	this->AddSubDefUseType = UseIter->GetType();
#if 0
	this->AddSubDefUseOp = LeftOp;
#endif

	return;
} // end of SMPInstr::SetAddSubSourceType()

// Are all DEFs in the DEF set NUMERIC type?
bool SMPInstr::AllDefsNumeric(void) 
{
	bool AllNumeric = (this->Defs.GetSize() > 0);  // false if no DEFs, true otherwise
	set<DefOrUse, LessDefUse>::iterator CurrDef;
	for (CurrDef = this->GetFirstDef(); CurrDef != this->GetLastDef(); ++CurrDef) {
		// We ignore the stack pointer for pop instructions and consider only
		//  the register DEF of the pop.
		if (this->MDIsPopInstr() && CurrDef->GetOp().is_reg(R_sp))
			continue;
		AllNumeric = (AllNumeric && IsNumeric(CurrDef->GetType()));
	}
	return AllNumeric;
} // end of SMPInstr::AllDefsNumeric()

// Were the types of any DEFs derived from profiler info?
bool SMPInstr::AnyDefsProfiled(void) 
{
	bool profd = false;
	set<DefOrUse, LessDefUse>::iterator CurrDef;
	for (CurrDef = this->GetFirstDef(); CurrDef != this->GetLastDef(); ++CurrDef) {
		profd = (profd || IsProfDerived(CurrDef->GetType()));
	}
	return profd;
} 

// Do all DEFs have DEF_METADATA_UNUSED status?
bool SMPInstr::AllDefMetadataUnused(void) {
	bool AllUnused = (this->Defs.GetSize() > 0);  // false if no DEFs, true otherwise
	set<DefOrUse, LessDefUse>::iterator CurrDef;
	for (CurrDef = this->GetFirstDef(); CurrDef != this->GetLastDef(); ++CurrDef) {
		AllUnused = (AllUnused 
			&& (DEF_METADATA_UNUSED == CurrDef->GetMetadataStatus()));
	}
	return AllUnused;
} // end of SMPInstr::AllDefMetadataUnused()

// DEBUG print operands for Inst.
void SMPInstr::PrintOperands(void) const {
	op_t Opnd;
	for (int i = 0; i < UA_MAXOP; ++i) {
		Opnd = SMPcmd.Operands[i];
		PrintOneOperand(Opnd, this->features, i);
	}
	SMP_msg(" \n");
	return;
} // end of SMPInstr::PrintOperands()

// Complete DEBUG printing.
void SMPInstr::Dump(void) {
	SMP_msg("%lx %d SMPitype: %d %s\n", (unsigned long) this->address, this->SMPcmd.size, (int) this->type, 
		DisAsmText.GetDisAsm(this->GetAddr()));
#if STARS_DUMP_FG_INFO
	SMP_msg("USEs: ");
	if (NULL == this->GetBlock()) { // during early improvement of disasm
		this->Uses.Dump();
		SMP_msg("DEFs: ");
		this->Defs.Dump();
	}
	else {
		set<DefOrUse, LessDefUse>::iterator UseIter, DefIter;
		op_t UseOp, DefOp;
		int UseHashValue, DefHashValue, UseSSANum, DefSSANum;
		unsigned short SignMiscInfo, SignMask;
		bool LocalName;
		for (UseIter = this->GetFirstUse(); UseIter != this->GetLastUse(); ++UseIter) {
			UseIter->Dump();
			UseOp = UseIter->GetOp();
			if (o_reg == UseOp.type) {
				LocalName = this->GetBlock()->IsLocalName(UseOp);
				UseSSANum = UseIter->GetSSANum();
				UseHashValue = HashGlobalNameAndSSA(UseOp, UseSSANum);
				if (LocalName) {
					SignMiscInfo = this->GetBlock()->GetUseSignMiscInfo(UseHashValue);
				}
				else {
					SignMiscInfo = this->GetBlock()->GetFunc()->GetUseSignMiscInfo(UseHashValue);
				}
				SignMask = SignMiscInfo & FG_MASK_SIGNEDNESS_BITS;
				if (SignMask == FG_MASK_SIGNED) {
					SMP_msg(" Si ");
				}
				else if (SignMask == FG_MASK_UNSIGNED) {
					SMP_msg(" Un ");
				}
				else if (SignMask == FG_MASK_INCONSISTENT_SIGN) {
					SMP_msg(" Xs ");
				}
			}
			SMP_msg("\n");
		}
		SMP_msg("DEFs: ");
		for (DefIter = this->GetFirstDef(); DefIter != this->GetLastDef(); ++DefIter) {
			DefIter->Dump();
			DefOp = DefIter->GetOp();
			if (o_reg == DefOp.type) {
				LocalName = this->GetBlock()->IsLocalName(DefOp);
				DefSSANum = DefIter->GetSSANum();
				DefHashValue = HashGlobalNameAndSSA(DefOp, DefSSANum);
				if (LocalName) {
					SignMiscInfo = this->GetBlock()->GetDefSignMiscInfo(DefHashValue);
				}
				else {
					SignMiscInfo = this->GetBlock()->GetFunc()->GetDefSignMiscInfo(DefHashValue);
				}
				SignMask = SignMiscInfo & FG_MASK_SIGNEDNESS_BITS;
				if (SignMask == FG_MASK_SIGNED) {
					SMP_msg(" Si ");
				}
				else if (SignMask == FG_MASK_UNSIGNED) {
					SMP_msg(" Un ");
				}
				else if (SignMask == FG_MASK_INCONSISTENT_SIGN) {
					SMP_msg(" Xs ");
				}
			}
			SMP_msg("\n");
		}
	}
#else
	SMP_msg("USEs: ");
	this->Uses.Dump();
	SMP_msg("DEFs: ");
	this->Defs.Dump();
#endif
	this->RTL.Dump();
#if SMP_VERBOSE_DUMP
	this->PrintOperands();
#endif
	SMP_msg("\n");
	return;
} // end of SMPInstr::Dump()

// Print out the destination operand list for the instruction, given
//  the OptCategory for the instruction as a hint.
char * SMPInstr::DestString(int OptType) {
	static char DestList[MAXSTR];
	int RegDestCount = 0;
	DestList[0] = 'Z';  // Make sure there are no leftovers from last call
	DestList[1] = 'Z';
	DestList[2] = '\0';
	set<DefOrUse, LessDefUse>::iterator CurrDef;
	for (CurrDef = this->GetFirstDef(); CurrDef != this->GetLastDef(); ++CurrDef) {
		op_t DefOpnd = CurrDef->GetOp();
		if (DefOpnd.is_reg(X86_FLAGS_REG))  // don't print flags as a destination
			continue;
		// We want to ignore the stack pointer DEF for pops and just include
		//  the register DEF for the pop.
		if (DefOpnd.is_reg(R_sp) && this->MDIsPopInstr())
			continue;
		if (o_reg == DefOpnd.type) {
			ushort DestReg = DefOpnd.reg;
			if (0 == RegDestCount) {
				SMP_strncpy(DestList, RegNames[DestReg], 1 + strlen(RegNames[DestReg]));
			}
			else {
				SMP_strncat(DestList, " ", MAXSTR);
				SMP_strncat(DestList, RegNames[DestReg], MAXSTR);
			}
			++RegDestCount;
		}
	}
	if (0 >= RegDestCount) {
		SMP_msg("WARNING: No destination registers: %s\n", DisAsmText.GetDisAsm(this->GetAddr()));
	}
	else {
		SMP_strncat(DestList, " ZZ ", MAXSTR);
	}
	return DestList;
} // end of SMPInstr::DestString()

// print the registers that are dead right before this instruction.
void SMPInstr::PrintDeadRegs(FILE *OutputFile) {
	size_t RegNum = (size_t) MD_FLAGS_REG;
	// Start with the flags register.
	if (this->DeadRegsBitmap[RegNum]) {
		SMP_fprintf(OutputFile, "%s ", RegNames[RegNum]);
	}
	// Do all other registers
	for (RegNum = 0; RegNum < MD_FLAGS_REG; ++RegNum) {
		if (this->DeadRegsBitmap[RegNum]) {
			SMP_fprintf(OutputFile, "%s ", RegNames[RegNum]);
		}
	}
	for (RegNum = 1 + MD_FLAGS_REG; RegNum <= MD_LAST_REG_NO; ++RegNum) {
		if (this->DeadRegsBitmap[RegNum]) {
			SMP_fprintf(OutputFile, "%s ", RegNames[RegNum]);
		}
	}
	// Print sequence terminator.
	SMP_fprintf(OutputFile, "ZZ");

	return;
} // end of SMPInstr::PrintDeadRegs()

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

// 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.
	op_t ESPOp = InitOp;
	ESPOp.type = o_reg;
	ESPOp.reg = R_sp;
	ESPOp.dtyp = this->GetOperandDtypField();
	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() ?
					return true;
				}
			}
		}
	}
	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(MD_STACK_POINTER_REG))
		&& (FirstUse->GetOp().is_reg(MD_FRAME_POINTER_REG)))
		return true;
	else if ((this->SMPcmd.itype == NN_add)
		&& (FirstDef->GetOp().is_reg(MD_STACK_POINTER_REG))) {
		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");
				return true;
			}
		}
		else
			return false;
	}
	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;

	if ((NN_nop == opcode) || (NN_lock == opcode))
		IsNop = true;
	else if ((NN_mov == opcode) || (NN_xchg == 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,
			//  or a register exchanged with itself.
			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) MD_STARS_sib_base(this->SMPcmd.Operands[1]))
					&& (R_sp == MD_STARS_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;
	bool FoundAddition = ((NN_adc == opcode) || (NN_add == opcode));

	if (this->MDIsLoadEffectiveAddressInstr()) {
		SMPRegTransfer *CurrRT = this->RTL.GetRT(0);
		if (CurrRT->HasRightSubTree()) {
			CurrRT = CurrRT->GetRightTree();
			FoundAddition = (SMP_ADD == CurrRT->GetOperator());
		}
	}

	return FoundAddition;
}


// 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) {
	op_t SubtrahendOp = this->GetUseOnlyAddSubOp();
	return (this->MDIsMaybeBenignUnderflowOpcode() && (o_imm == SubtrahendOp.type)
		&& (('0' == SubtrahendOp.value) || ('a' == SubtrahendOp.value)
		|| ('A' == SubtrahendOp.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 0x20000000
#define STARS_LARGE_SIGNED_MUL_CONSTANT_THRESHOLD 0x10000000
#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->GetUseOnlyAddSubOp();
		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->GetUseOnlyAddSubOp();
		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: Opcode indicates 64-bit operands are the default.
bool SMPInstr::MDDefaultsTo64BitOperands(void) const {
	bool Default64;
	switch (this->SMPcmd.itype) {
		// use ss
		case NN_pop:
		case NN_popf:
		case NN_popfq:
		case NN_push:
		case NN_pushf:
		case NN_pushfq:
		case NN_retn:
		case NN_retf:
		case NN_retnq:
		case NN_retfq:
		case NN_call:
		case NN_callfi:
		case NN_callni:
		case NN_enter:
		case NN_enterq:
		case NN_leave:
		case NN_leaveq:

		// near branches
		case NN_ja:
		case NN_jae:
		case NN_jb:
		case NN_jbe:
		case NN_jc:
		case NN_je:
		case NN_jg:
		case NN_jge:
		case NN_jl:
		case NN_jle:
		case NN_jna:
		case NN_jnae:
		case NN_jnb:
		case NN_jnbe:
		case NN_jnc:
		case NN_jne:
		case NN_jng:
		case NN_jnge:
		case NN_jnl:
		case NN_jnle:
		case NN_jno:
		case NN_jnp:
		case NN_jns:
		case NN_jnz:
		case NN_jo:
		case NN_jp:
		case NN_jpe:
		case NN_jpo:
		case NN_js:
		case NN_jz:
		case NN_jcxz:
		case NN_jecxz:
		case NN_jrcxz:
		case NN_jmp:
		case NN_jmpni:
		case NN_jmpshort:
		case NN_loop:
		case NN_loopq:
		case NN_loope:
		case NN_loopqe:
		case NN_loopne:
		case NN_loopqne:
			Default64 = true;
			break;
		default:
			Default64 = false;
			break;
	}
	return Default64;
} // end of SMPInstr::MDDefaultsTo64BitOperands()

// MACHINE DEPENDENT: Inst has 64-bit operands
bool SMPInstr::MDHas64BitOperands(void) const {
#ifdef __EA64__
  return (((this->SMPcmd.auxpref & aux_use64) != 0)
      && ((this->SMPcmd.rex & REX_W) != 0
       || (((cmd.auxpref & aux_natop) != 0) && this->MDDefaultsTo64BitOperands())));
			// 64-bit segment, rex.w or insns-64
#else
  return false;
#endif
}

// Fetch default bit-width op_t.dtyp field for current instruction's operands
char SMPInstr::GetOperandDtypField(void) const {
	if (this->MDHas64BitOperands()) {
		return dt_qword;
	}
	else {
		return dt_dword;
	}
}

// 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));
}

// MACHINE DEPENDENT: Is instruction a left shift instruction?
bool SMPInstr::MDIsLeftShift(void) const {
	unsigned short opcode = this->SMPcmd.itype;
	return ((NN_sal == opcode) || (NN_shl == 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);
		}
		else {
			// PEASOUP bug # 144: left shift count in CL reg, accumulates in checksum loop.
			FoundHashShift = true;
		}
	}
	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(MD_FRAME_POINTER_REG) || 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 (UseFP) {
			if (this->GetFirstUse()->GetOp().is_reg(MD_FRAME_POINTER_REG))
				// Move of base pointer EBP into a general register
				return true;
			else if ((this->GetFirstUse()->GetOp().is_reg(MD_STACK_POINTER_REG))
				&& !(this->GetFirstDef()->GetOp().is_reg(MD_FRAME_POINTER_REG)))
				// Move of ESP into something besides a base pointer
				return true;
		}
		else if (this->GetFirstUse()->GetOp().is_reg(MD_STACK_POINTER_REG)) {
			// 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;
	op_t TempOp;
	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 (4 > GetOpDataSize(LeftOp)) {
			break; // Not tracking copies of less than the full stack or frame pointer
		}
		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())) {
			// Simple assignment.
			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.
					Save = true;
					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
					break;
				}
				else if (!SPRestore && UseFP && RightOp.is_reg(MD_FRAME_POINTER_REG)) {
					// Frame pointer is being saved
					Save = true;
					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
				}
			}
			else {
				if (SPRestore || FPRestore) {
					SMP_msg("ERROR: Invalid operand type for assignment to stack or frame pointer at %lx\n",
						(unsigned long) 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 (DeltaAdjust > STARS_ESP_ADDITION_OVERFLOW_THRESHOLD) {
								// Really a subtraction via addition of a negative,
								//  or addition via subtraction of a negative.
								//  E.g. add esp, 0xfffffff0 is sub esp,16 and sub esp,0xfffffff0 is add esp,16
								int32 TempDelta = (int32) (DeltaAdjust & 0xffffffff);
								DeltaAdjust = (sval_t) TempDelta;
							}
							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;
			bool NonStackMemAccess = 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;
			}
			else {
				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;
					FindOp.dtyp = this->GetOperandDtypField();
				}
				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;
						FindOp.dtyp = this->GetOperandDtypField();
						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;
			SearchOp.dtyp = this->GetOperandDtypField();
			set<DefOrUse, LessDefUse>::iterator EAXDEF;
			EAXDEF = this->SetDefType(SearchOp, HEAPPTR);
			int SSANum = EAXDEF->GetSSANum();
			changed = true;
			if (this->BasicBlock->IsLocalName(SearchOp)) {
				(void) this->BasicBlock->PropagateLocalDefType(SearchOp, HEAPPTR,
						this->GetAddr(), SSANum, false);
			}
			else { // global name
				this->BasicBlock->GetFunc()->ResetProcessedBlocks(); // set Processed to false
				(void) this->BasicBlock->PropagateGlobalDefType(SearchOp, HEAPPTR,
						SSANum, false);
			}
		} // end if "malloc"
	} // end if (TargetFunc)
	return changed;
} // end of SMPInstr::MDFindMallocCall()

// Is instruction a branch (conditional or unconditional) to a
//  code target that is not in the current chunk?
bool SMPInstr::IsBranchToFarChunk(void) {
	if (this->IsFarBranchComputed()) { // answer is cached
		return this->IsBranchesToFarChunk();
	}
	func_t *CurrChunk = get_fchunk(this->address);
	bool FarBranch = false;
	if ((JUMP | COND_BRANCH) & this->GetDataFlowType()) {
		// Instruction is a direct branch, conditional or unconditional
		if (this->NumUses() > 0) {
			set<DefOrUse, LessDefUse>::iterator CurrUse;
			for (CurrUse = this->GetFirstUse(); CurrUse != this->GetLastUse(); ++CurrUse) {
				op_t JumpTarget = CurrUse->GetOp();
				if ((o_near == JumpTarget.type) || (o_far == JumpTarget.type)) {
					// Branches to a code address
					// stdclib sometimes has jumps to zero and calls to zero. These are dead code.
					if (0 != JumpTarget.addr) {
						func_t *TargetChunk = get_fchunk(JumpTarget.addr);
						// Is target address within the same chunk as the branch?
						FarBranch = (NULL == TargetChunk) || (CurrChunk->startEA != TargetChunk->startEA);
						if (FarBranch) {
							this->FarBranchTarget = JumpTarget.addr;
						}
					}
				}
			}
		}
	}
	if (FarBranch) {
		this->SetBranchesToFarChunk();
	}
	this->SetFarBranchComputed();
	return FarBranch;
} // end of SMPInstr::IsBranchToFarChunk()

set<DefOrUse, LessDefUse>::iterator SMPInstr::SetUseSSA(op_t CurrOp, int SSASub) {
	return this->Uses.SetSSANum(CurrOp, SSASub);
};

set<DefOrUse, LessDefUse>::iterator SMPInstr::SetDefSSA(op_t CurrOp, int SSASub) {
	return this->Defs.SetSSANum(CurrOp, SSASub);
};

set<DefOrUse, LessDefUse>::iterator SMPInstr::SetUseType(op_t CurrOp, SMPOperandType CurrType) {
	return this->Uses.SetType(CurrOp, CurrType, this);
};

set<DefOrUse, LessDefUse>::iterator SMPInstr::SetDefType(op_t CurrOp, SMPOperandType CurrType) {
	return this->Defs.SetType(CurrOp, CurrType, this);
};

set<DefOrUse, LessDefUse>::iterator SMPInstr::SetDefMetadata(op_t CurrOp, SMPMetadataType Status) {
	return this->Defs.SetMetadata(CurrOp, Status);
};

set<DefOrUse, LessDefUse>::iterator SMPInstr::SetDefIndWrite(op_t CurrOp, bool IndWriteFlag) {
	return this->Defs.SetIndWrite(CurrOp, IndWriteFlag);
};

set<DefOrUse, LessDefUse>::iterator SMPInstr::SetUseNoTruncate(op_t CurrOp, bool NoTruncFlag) {
	return this->Uses.SetNoTruncation(CurrOp, NoTruncFlag);
};

set<DefOrUse, LessDefUse>::iterator SMPInstr::SetDefNoOverflow(op_t DefOp, bool NoOverflowFlag) {
	return this->Defs.SetNoOverflow(DefOp, NoOverflowFlag);
};

// Set the DeadRegsBitmap entry for Regnum.
void SMPInstr::SetRegDead(size_t RegNum) {
	this->DeadRegsBitmap.set(RegNum);
	return;
}


// Analyze the instruction and its operands.
void SMPInstr::Analyze(void) {
	bool DebugFlag = false;

	if (0x8049b00 == this->address) {
		// Setting up breakpoint line.
		DebugFlag = true;
	}

	// Fill cmd structure with disassembly of instr
	if (!SMPGetCmd(this->address, this->SMPcmd, this->features))
		return;

	unsigned short opcode = this->SMPcmd.itype;

	// Record what type of instruction this is, simplified for the needs
	//  of data flow and type analysis.
	this->type = DFACategory[opcode];
	// Record optimization category.
	this->OptType = OptCategory[opcode];

	if ((NN_int == opcode) || (NN_into == opcode) || (NN_int3 == opcode)) {
		this->SetInterrupt();
	}
	else {
		this->ResetInterrupt();
	}

	// Fix the IDA Pro mistakes in the operand list.
	this->MDFixupIDAProOperandList();

	// See if instruction is an ASM idiom for clearing a register.
	if ((NN_xor == opcode) || (NN_lea == opcode)) {
		ushort FirstReg;
		if (o_reg == this->SMPcmd.Operands[0].type) {
			FirstReg = this->SMPcmd.Operands[0].reg;
			op_t SecondOpnd = this->SMPcmd.Operands[1];
			if (NN_xor == opcode) {
				// Check for xor of reg with itself
				if (SecondOpnd.is_reg(FirstReg)) {
					this->SetRegClearIdiom();
				}
			}
			else { // must be lea
				// check for lea reg,[nobasereg+nonindexreg+0]
				if ((SecondOpnd.type >= o_mem) && (SecondOpnd.type <= o_displ)) {
					int BaseReg, IndexReg;
					ushort ScaleFactor;
					ea_t Offset;
					MDExtractAddressFields(SecondOpnd, BaseReg, IndexReg, ScaleFactor, Offset);
					if ((R_none == BaseReg) && (R_none == IndexReg) && (0 == Offset)) {
						this->SetRegClearIdiom();
					}
				}
			}
		}
	}

	// See if instruction is simple nop or ASM idiom for nop.
	if (this->MDIsNop()) {
		this->SetNop();
	}

	// Build the DEF and USE lists for the instruction.
	this->FindMemOps();
	this->BuildSMPDefUseLists();

	// Determine whether the instruction is a jump target by looking
	//  at its cross references and seeing if it has "TO" code xrefs.
	SMP_xref_t xrefs;
	for (bool ok = xrefs.SMP_first_to(this->address, XREF_FAR); ok; ok = xrefs.SMP_next_to()) {
		if ((xrefs.GetFrom() != 0) && (xrefs.GetIscode())) {
			this->SetJumpTarget();
			break;
		}
	}

	// If instruction is a call or indirect call, see if a call target has been recorded
	//  by IDA Pro.
	if (this->GetDataFlowType() == INDIR_CALL) {
		for (bool ok = xrefs.SMP_first_from(this->address, XREF_ALL);
			ok;
			ok = xrefs.SMP_next_from()) {
			if ((xrefs.GetTo() != 0) && (xrefs.GetIscode())) {
				// Found a code target, with its address in xrefs.to
				if (xrefs.GetTo() == (this->address + this->GetCmd().size)) {
					// A call instruction will have two targets: the fall through to the
					//  next instruction, and the called function. We want to find
					//  the called function.
					continue;
				}
				// We found a target, not the fall-through.
				this->CallTarget = xrefs.GetTo();
				SMP_msg("Found indirect call target %lx at %lx\n",
					(unsigned long) xrefs.GetTo(), (unsigned long) this->address);
				break;
			}
		} // end for all code xrefs
		if (BADADDR == this->CallTarget) {
			SMP_msg("WARNING: Did not find indirect call target at %lx\n",
				(unsigned long) this->address);
		}
	} // end if INDIR_CALL
	else if (this->GetDataFlowType() == CALL) {
		set<DefOrUse, LessDefUse>::iterator CurrUse;
		for (CurrUse = this->GetFirstUse(); CurrUse != this->GetLastUse(); ++CurrUse) {
			optype_t OpType = CurrUse->GetOp().type;
			if ((OpType == o_near) || (OpType == o_far)) {
				this->CallTarget = CurrUse->GetOp().addr;
			}
		}
		if (BADADDR == this->CallTarget) {
			SMP_msg("ERROR: Target not found for direct call at %lx\n", (unsigned long) this->address);
		}
	}

	if (DebugFlag) {
		SMP_msg("Analyzed debug instruction at %lx\n", (unsigned long) this->address);
	}
	return;
} // end of SMPInstr::Analyze()

// Analyze the floating point NOP marker instruction at the top of the function.
void SMPInstr::AnalyzeMarker(void) {
	// Fill member variable SMPcmd structure with disassembly of instr
	(void) memset(&(this->SMPcmd), 0, sizeof(this->SMPcmd));
	this->SMPcmd.itype = NN_fnop;
	this->SMPcmd.size = 1;
	this->SMPcmd.ea = this->address;
	// Set the instr disassembly text.
	DisAsmText.SetMarkerInstText(this->GetAddr());

	// Record what type of instruction this is, simplified for the needs
	//  of data flow and type analysis.
	this->type = DFACategory[this->SMPcmd.itype];
	// Record optimization category.
	this->OptType = OptCategory[this->SMPcmd.itype];

	return;
} // end of SMPInstr::AnalyzeMarker()

// Detect oddities of call instructions, such as pseudo-calls that are
//  actually jumps within a function
void SMPInstr::AnalyzeCallInst(ea_t FirstFuncAddr, ea_t LastFuncAddr) {
	if (BADADDR != this->CallTarget) {
		if (this->CallTarget == FirstFuncAddr) {
			this->SetDirectRecursiveCall();
		}
		else {
			this->ResetDirectRecursiveCall();
			if ((this->CallTarget > FirstFuncAddr)
					&& (this->CallTarget < LastFuncAddr)) {
				this->SetCallUsedAsJump();
				this->type = JUMP;
			}
			else {
				this->ResetCallUsedAsJump();
			}
		}
	}
	return;
} // end of SMPInstr::AnalyzeCallInst()

sval_t SMPInstr::AnalyzeStackPointerDelta(sval_t IncomingDelta, sval_t PreAllocDelta) {
	uint16 InstType = this->SMPcmd.itype;
	sval_t InstDelta = StackAlteration[InstType];
	SMPitype FlowType = this->GetDataFlowType();
	bool TailCall = this->IsTailCall();

	if (this->IsCallUsedAsJump() || this->MDIsInterruptCall() || this->IsCondTailCall()) {
		// Call is used within function as a jump. Happens when setting up
		//  thunk offsets, for example; OR, call is an interrupt call, in which
		//  the interrupt return cleans up the stack, leaving a delta of zero, but
		//  we do not have the system call code to analyze, OR, the call is a conditional
		//  jump to another function (conditional tail call), in which case the current
		//  function must have a return statement to fall into which will clean up the
		//  only thing left on the stack (the return address) and the conditional jump
		//  has no effect on the stack pointer.
		; // leave InstDelta equal to negative or zero value from StackAlterationTable[]
	}
	else if (this->IsRecursiveCall() || TailCall) {
		// We don't have the net stack delta for our own function yet, so we cannot
		//  look it up. We must assume that each call has no net effect on the stack delta.
		// Alternatively, we could call this->GetBlock()->GetFunc()->GetStackDeltaForCallee() as below.
		// Also, a tail call happens when the stack delta is down to zero, and the callee does not
		//  return to the caller, unlike the call cases below, so the callee's net stack delta is
		//  irrelevant to the caller.
		InstDelta = 0;
	}
	else if (this->IsAllocaCall()) {
		InstDelta = STARS_DEFAULT_ALLOCA_SIZE;
	}
	else if ((CALL == FlowType) || (INDIR_CALL == FlowType)) {
		// A real call instruction, which pushes a return address on the stack,
		//  not a call used as a branch within the function. A return instruction
		//  will usually cancel out the stack push that is implicit in the call, which 
		//  means that the function will have a net stack ptr delta of +4, which will
		//  cancel out the -4 value of the call instruction and set the delta to zero.
		//  However, this is not true in all cases, so we get the net stack ptr delta
		//  directly from the called function unless it is an unresolved indirect call,
		//  in which case we assume +4. !!!!****!!!! In the future, we could analyze
		//  the code around an unresolved indirect call to see if it seems to be
		//  removing items left on the stack by the callee.
#if 0
		// SPECIAL CASE: A jump used as a tail call will have a stack ptr effect that is equal
		//  to the net stack ptr effect of its target function, usually +4, whereas a jump
		//  would otherwise have a net stack ptr effect of 0.
#endif
		ea_t CalledFuncAddr = this->GetCallTarget();
		if ((BADADDR == CalledFuncAddr) || (0 == CalledFuncAddr)) {
			InstDelta = 0;
		}
		else { // We have a call target
			SMPFunction *CalleeFunc = this->GetBlock()->GetFunc()->GetProg()->FindFunction(CalledFuncAddr);
			sval_t AdjustmentDelta;
			if (CalleeFunc) {
				if (!CalleeFunc->HasSTARSStackPtrAnalysisCompleted()) {
					// Phase ordering issue in the call graph. A mutually recursive clique of functions has to
					//  be broken by starting processing somewhere, and all callees cannot be processed before
					//  we start. If we got our stack down to zero and then made a tail call, then we have to assume
					//  that the callee will use our return address, so we assume the default stack delta. If not a
					//  tail call, we ask our function to see if the information is available from IDA Pro analyses,
					//  or if it can be inferred from the fact that the call is followed by a stack adjustment.
					if (TailCall) {
						InstDelta = CALLING_CONVENTION_DEFAULT_FUNCTION_STACK_DELTA;
						SMP_msg("WARNING: Callee stack ptr analysis not yet performed at tail call inst %lx ; normal delta assumed\n",
							(unsigned long) this->GetAddr());
					}
					else {
						AdjustmentDelta = this->GetBlock()->GetFunc()->GetStackDeltaForCallee(CalledFuncAddr);
						InstDelta += AdjustmentDelta;
						SMP_msg("WARNING: Callee stack ptr analysis not yet performed at inst %lx ; stack adjustment used\n",
							(unsigned long) this->GetAddr());
					}
				}
				else if (!CalleeFunc->StackPtrAnalysisSucceeded()) {
					// Callee analyses were done, but they failed. In order to proceed, we have to assume
					//  the same situation as we just did in the case where analyses have not been performed.
					SMP_msg("WARNING: Callee stack ptr analysis failed at inst %lx ; normal delta assumed\n",
						(unsigned long) this->GetAddr());
					if (TailCall) {
						InstDelta = CALLING_CONVENTION_DEFAULT_FUNCTION_STACK_DELTA;
					}
					else {
						AdjustmentDelta = this->GetBlock()->GetFunc()->GetStackDeltaForCallee(this->GetAddr());
						InstDelta += AdjustmentDelta;
					}
				}
				else {
					// Callee's analyses have succeeded, so get delta straight from callee.
					InstDelta += CalleeFunc->GetNetStackPtrDelta();
				}
			}
			else {
#if 0
				SMP_msg("ERROR: SMPInstr::AnalyzeStackPointerDelta failed to find func at %lx in inst %lx\n",
					(unsigned long) CalledFuncAddr, (unsigned long) this->GetAddr());
				InstDelta = SMP_STACK_DELTA_ERROR_CODE;
#else
				SMP_msg("ERROR: SMPInstr::AnalyzeStackPointerDelta failed to find func at %lx in inst %lx\n",
					(unsigned long) CalledFuncAddr, (unsigned long) this->GetAddr());
				if (TailCall) {
					InstDelta = CALLING_CONVENTION_DEFAULT_FUNCTION_STACK_DELTA;
				}
				else {
					InstDelta = 0;
				}
#endif
			}
		}
	} // end CALL or INDIR_CALL or TailCall case
	else if (1 == InstDelta) { 
		// value of 1 is trigger to investigate the RTL for the 
		//  true value, which cannot be found simply by table lookup
		// In the special case of an x86 LEAVE instruction, the effect
		//  on the stack pointer is to deallocate the local frame size,
		//  plus pop the saved frame pointer into EBP. Helper functions
		//  need to know whether to look for this special case.
		bool IsLeaveInstr = this->MDIsLeaveInstr();
		InstDelta = this->RTL.TotalStackPointerAlteration(IsLeaveInstr, IncomingDelta, PreAllocDelta);
	}
	return InstDelta;
} // end of SMPInstr::AnalyzeStackPointerDelta()

// Total the stack adjustment bytes, as happens after a call to a function that leaves
//  outgoing args on the stack or swallows incoming args from the stack.
sval_t SMPInstr::FindStackAdjustment(void) {
	uint16 InstType = this->SMPcmd.itype;
	sval_t InstDelta = StackAlteration[InstType];

	if (1 == InstDelta) { 
		// value of 1 is trigger to investigate the RTL for the 
		//  true value, which cannot be found simply by table lookup
		// In the special case of an x86 LEAVE instruction, the effect
		//  on the stack pointer is to deallocate the local frame size,
		//  plus pop the saved frame pointer into EBP. Helper functions
		//  need to know whether to look for this special case.
		bool IsLeaveInstr = this->MDIsLeaveInstr();
		if (!IsLeaveInstr) {
			InstDelta = this->RTL.TotalStackPointerAlteration(IsLeaveInstr, 0, 0);
		}
		else {
			InstDelta = 0; // LEAVE is not the kind of instr we are looking for
		}
	}
	return InstDelta;
} // end of SMPInstr::FindStackAdjustment()

// Normalize stack operands to have a displacement from the stack pointer value on entry to the function,
//  rather than the current stack pointer value.
// UseFP indicates we are using a frame pointer in the function.
// FPDelta holds the stack delta (normalized) for the frame pointer.
// DefOp comes in with the operand to be normalized, and contains the normalized operand upon return.
// Return true if operand is a register or stack location, false otherwise (true => include in data flow analysis sets and SSA.)
bool SMPInstr::MDComputeNormalizedDataFlowOp(bool UseFP, sval_t FPDelta, op_t &DefOp) {
	if (o_reg == DefOp.type) {
		return true;
	}
	else if (MDIsStackAccessOpnd(DefOp, UseFP)) {
		op_t OldOp = DefOp;
		int SignedOffset = (int) DefOp.addr;
		sval_t NormalizedDelta;

		if (DefOp.hasSIB) {
			// We must deal with a potentially indexed memory expression. We want to
			//  normalize two different cases here: e.g. [esp+ebx+4] will become [esp+ebx-24]
			//  and [ebp+ebx-8] will become [esp+ebx-12] after normalization. A wrinkle
			//  on the second case is when the base register and index register are swapped
			//  in the SIB byte, and we make [ebx+ebp-4] into [esp+ebx-12], which involves
			//  correcting the index/base reg order in the SIB, because an index reg of ESP
			//  is the SIB encoding for "no index register" and we cannot leave it like that.
			int BaseReg = MD_STARS_sib_base(DefOp);
			int IndexReg = (int) MD_STARS_sib_index(DefOp);
			if (X86_STACK_POINTER_REG == IndexReg) // signifies no index register
				IndexReg = R_none;
			if (BaseReg == X86_STACK_POINTER_REG) {
				// We probably have an indexed ESP-relative operand.
				//  We leave the sib byte alone and normalize the offset.
				NormalizedDelta = this->GetStackPtrOffset() + (sval_t) SignedOffset;
			}
			else {
				// Must be EBP-relative.
				NormalizedDelta = FPDelta + (sval_t) SignedOffset;
				// Unfortunately, when we are dealing with a SIB byte in the opcode, we cannot
				//  just say DefOp.reg = MD_STACK_POINTER_REG to convert from the frame pointer
				//  to the stack pointer. Instead, we have to get into the nasty machine code
				//  level and change the SIB bits that specify either the base register or the
				//  index register, whichever one is the frame pointer.
				if (BaseReg == X86_FRAME_POINTER_REG) {
					// The three least significant bits of the SIB byte are the base register.
					//  They must contain a 5, which is the x86 value for register EBP, and we
					//  want to convert it to a 4, denoting register ESP. We can just zero out
					//  the least significant bit to accomplish that.
					DefOp.sib &= 0xfe;
				}
				else {
					// We sometimes have an instruction in which the frame pointer is used as
					//  the "index" register in the SIB byte, and the true index register is
					//  in the "base" register position in the SIB byte.
					assert(IndexReg == X86_FRAME_POINTER_REG);
					// The true index reg is in the lowest three bits, while the next three
					//  bits must contain a 5 (register EBP) and we want to make them a 4 (ESP).
					//  We must swap base and index regs as we normalize (see explanation above).
					char SIBtemp = DefOp.sib;
					char SIBindex = SIBtemp & 0x38;
					char SIBbase = SIBtemp & 0x07;
					assert ((SIBindex >> 3) == 5); // must be EBP
					SIBtemp &= 0xa0; // zero out lower 6 bits; upper 2 bits are scale factor - leave them alone
					SIBtemp &= (SIBbase << 3); // make old base reg (e.g. ebx) into a proper index reg
					SIBtemp |= 0x04; // make the new base reg be 4 (reg ESP)
					DefOp.sib = SIBtemp;
				}
				this->SetFPNormalizedToSP();
				// Add the stack pointer to the USE set for the instruction.
				this->MDAddRegUse(X86_STACK_POINTER_REG, false);
			}
		}

		else if (DefOp.reg == MD_FRAME_POINTER_REG) {
			// If FPDelta is -4 and SignedOffset is +8, then we have [ebp+8] as DefOp, and this
			//  is equivalent to [esp+4] where esp has its entry value, i.e. this would be the first incoming
			//  argument. If SignedOffset is -12, we have [ebp-12] as DefOp, and this is [esp-16] when
			//  normalized to the entry point value of the stack pointer. In both cases, we can see that the
			//  normalized stack delta is just FPDelta+SignedOffset.
			NormalizedDelta = FPDelta + (sval_t) SignedOffset;
			// Now, we simply convert the memory operand from EBP to ESP and replace the SignedOffset with the
			//  NormalizedDelta just computed.
			DefOp.reg = MD_STACK_POINTER_REG;
			this->SetFPNormalizedToSP();
			// Add the stack pointer to the USE set for the instruction.
			this->MDAddRegUse(DefOp.reg, false);
		}
		else {
			assert(DefOp.reg == MD_STACK_POINTER_REG);
			// We only need to adjust the offset to reflect the change in the stack pointer since the function
			//  was entered, e.g. [esp+4] is normalized to [esp-28] if the current esp value is 32 less than it
			//  was upon function entry. We get the value "-32" in that case from a member variable.
			NormalizedDelta = this->GetStackPtrOffset() + (sval_t) SignedOffset;
		}
		DefOp.addr = (ea_t) NormalizedDelta; // common to frame and stack pointer cases
		if ((o_phrase == DefOp.type) && (0 != NormalizedDelta)) {
			// mov [esp],eax has an [esp] operand of type o_phrase, because there is no
			//  displacement field. After normalization, it will have a displacement field, so
			//  it has become an operand like [esp-32] and is now type o_displ.
			DefOp.type = o_displ;
		}
		this->GetBlock()->GetFunc()->AddNormalizedStackOperand(OldOp, this->GetAddr(), DefOp);
		return true;
	}
	else {
		return false;
	}
} // end of SMPInstr::MDComputeNormalizedDataFlowOp()

// Normalize stack operands in all DEFs and USEs to have stack deltas relative to the function entry stack pointer.
// Return true if any stack DEFs or USEs were normalized.
bool SMPInstr::MDNormalizeStackOps(bool UseFP, sval_t FPDelta, bool Recomputing, sval_t DeltaIncrement) {
	bool StackOpFound = false;
	bool OpNormalized;
	bool UniqueDEFMemOp = true; // Does DEFMemOp not match any DEFs?
	bool UniqueUSEMemOp = true; // Does USEMemOp not match any USEs?
	bool UniqueLeaUSEMemOp = true; // Does LeaUSEMemOp not match any USEs?
	bool UniqueMoveSource = true; // Does MoveSource not match any USEs?
	set<DefOrUse, LessDefUse>::iterator DefIter, UseIter;
	list<pair<set<DefOrUse, LessDefUse>::iterator, op_t> > DefWorkList, UseWorkList;
	list<pair<set<DefOrUse, LessDefUse>::iterator, op_t> >::iterator WorkIter;
	op_t OldOp, NewOp;
	
	// Find all the DEFs that need changing, and put their iterators into a list.
	// Normalizing stack ops could change their sort order, hence we could skip over
	//  a DEF in the set by erasing a DEF and reinserting a normalized DEF, so we
	//  make all the changes after we iterate through the DEFS set.
	for (DefIter = this->GetFirstDef(); DefIter != this->GetLastDef(); ++DefIter) {
		OldOp = DefIter->GetOp();
		NewOp = OldOp;
		if ((o_reg != NewOp.type) && (o_imm != NewOp.type)) {
			if (Recomputing) {
				OpNormalized = this->MDRecomputeNormalizedDataFlowOp(DeltaIncrement, true, NewOp);
			}
			else {
				OpNormalized = this->MDComputeNormalizedDataFlowOp(UseFP, FPDelta, NewOp);
			}
			if (OpNormalized) {
				StackOpFound = true;
				if (IsEqOp(OldOp, this->DEFMemOp)) {
					UniqueDEFMemOp = false;
				}
				pair<set<DefOrUse, LessDefUse>::iterator, op_t> DefItem(DefIter, NewOp);
				DefWorkList.push_back(DefItem);
			}
		}
	}
	// Now go through the DEF worklist and change stack operands to normalized stack operands.
	for (WorkIter = DefWorkList.begin(); WorkIter != DefWorkList.end(); ++WorkIter) {
		DefIter = WorkIter->first;
		DefIter = this->Defs.SetOp(DefIter, WorkIter->second);
	}
	// Normalize op_t private data member DEFs.
	if (Recomputing) {
		OpNormalized = this->MDRecomputeNormalizedDataFlowOp(DeltaIncrement, UniqueDEFMemOp, this->DEFMemOp);
	}
	else {
		OpNormalized = this->MDComputeNormalizedDataFlowOp(UseFP, FPDelta, this->DEFMemOp);
	}

	// Find all USEs that need changing, and build a second work list.
	for (UseIter = this->GetFirstUse(); UseIter != this->GetLastUse(); ++UseIter) {
		OldOp = UseIter->GetOp();
		NewOp = OldOp;
		if ((o_reg != NewOp.type) && (o_imm != NewOp.type)) {
			if (Recomputing) {
				OpNormalized = this->MDRecomputeNormalizedDataFlowOp(DeltaIncrement, true, NewOp);
			}
			else {
				OpNormalized = this->MDComputeNormalizedDataFlowOp(UseFP, FPDelta, NewOp);
			}
			if (OpNormalized) {
				StackOpFound = true;
				if (IsEqOp(OldOp, this->USEMemOp)) {
					UniqueUSEMemOp = false;
				}
				if (IsEqOp(OldOp, this->GetLeaMemUseOp())) {
					UniqueLeaUSEMemOp = false;
				}
				if (IsEqOp(OldOp, this->MoveSource)) {
					UniqueMoveSource = false;
				}
				pair<set<DefOrUse, LessDefUse>::iterator, op_t> UseItem(UseIter, NewOp);
				UseWorkList.push_back(UseItem);
			}
		}
	}

	// Now go through the USE worklist and change stack operands to normalized stack operands.
	for (WorkIter = UseWorkList.begin(); WorkIter != UseWorkList.end(); ++WorkIter) {
		UseIter = WorkIter->first;
		UseIter = this->Uses.SetOp(UseIter, WorkIter->second);
	}
	// Normalize op_t private data member USEs.
	op_t TempLeaMemOp = this->GetLeaMemUseOp();
	if (Recomputing) {
		OpNormalized = this->MDRecomputeNormalizedDataFlowOp(DeltaIncrement, UniqueUSEMemOp, this->USEMemOp);
		OpNormalized = this->MDRecomputeNormalizedDataFlowOp(DeltaIncrement, UniqueLeaUSEMemOp, TempLeaMemOp);
		if (OpNormalized)
			this->SetLeaMemUseOp(TempLeaMemOp);
		OpNormalized = this->MDRecomputeNormalizedDataFlowOp(DeltaIncrement, UniqueMoveSource, this->MoveSource);
	}
	else {
		OpNormalized = this->MDComputeNormalizedDataFlowOp(UseFP, FPDelta, this->USEMemOp);
		OpNormalized = this->MDComputeNormalizedDataFlowOp(UseFP, FPDelta, TempLeaMemOp);
		if (OpNormalized)
			this->SetLeaMemUseOp(TempLeaMemOp);
		OpNormalized = this->MDComputeNormalizedDataFlowOp(UseFP, FPDelta, this->MoveSource);
	}
	// Declare victory.
	this->SetDefsNormalized();

	return StackOpFound;
} // end of SMPInstr::MDNormalizeStackOps()

// Renormalize SP-relative stack operands in functions that call alloca() by adding DeltaIncrement to their stack displacements.
// DefOp comes in with the operand to be renormalized, and contains the normalized operand upon return.
// Return true if operand is a register or stack location, false otherwise (true => include in data flow analysis sets and SSA.)
bool SMPInstr::MDRecomputeNormalizedDataFlowOp(sval_t DeltaIncrement, bool UpdateMaps, op_t &DefOp) {
	op_t OldOp = DefOp;
	if (o_reg == DefOp.type) {
		return true;
	}
	else if (MDIsStackAccessOpnd(DefOp, this->GetBlock()->GetFunc()->UsesFramePointer())) {
		if (this->HasFPNormalizedToSP()) {
			// FP-relative operands do no change in alloca() functions when the alloca()
			//  causes the SP to change.
			return true;
		}

		// The remaining cases are simple. The ESP-relative displacement is incremented by
		//  DeltaIncrement, regardless of the presence of a SIB byte.
		int SignedOffset = (int) DefOp.addr;
		sval_t NormalizedDelta = DeltaIncrement + (sval_t) SignedOffset;

		DefOp.addr = (ea_t) NormalizedDelta;

		if ((o_phrase == DefOp.type) && (0 != NormalizedDelta)) {
			// mov [esp],eax has an [esp] operand of type o_phrase, because there is no
			//  displacement field. After normalization, it will have a displacement field, so
			//  it has become an operand like [esp-32] and is now type o_displ.
			DefOp.type = o_displ;
		}

		if (UpdateMaps) { // We don't update maps for duplicate entries, e.g. USEMemOp, DEFMemOp, MoveSource
			this->GetBlock()->GetFunc()->AddNormalizedStackOperand(OldOp, this->GetAddr(), DefOp);
		}
		return true;
	}
	else {
		return false;
	}
} // end of SMPInstr::MDRecomputeNormalizedDataFlowOp()

// If NormOp is a normalized stack memory operand, unnormalize it.
void SMPInstr::MDGetUnnormalizedOp(op_t &NormOp) {
	sval_t SignedOffset;
	bool UseFP = this->GetBlock()->GetFunc()->UsesFramePointer();
	if (this->AreDefsNormalized() && MDIsStackAccessOpnd(NormOp, UseFP)) {
		if (this->HasFPNormalizedToSP()) {
			// Need to convert NormOp back to frame-pointer-relative address.
			if (NormOp.hasSIB) {
				// Convert base register from stack pointer back to frame pointer.
				NormOp.sib |= 0x01;
			}
			else {
				NormOp.reg = MD_FRAME_POINTER_REG;
			}
			SignedOffset = (sval_t) NormOp.addr;
			SignedOffset -= this->GetBlock()->GetFunc()->GetFramePtrStackDelta();
		}
		else {
			// NormOp should remain stack-pointer-relative address, but it
			//  should be a positive offset from the current stack pointer instead
			//  of a negative offset from the entry point of the function.
			SignedOffset = (sval_t) NormOp.addr;
			SignedOffset -= this->GetStackPtrOffset();
			assert((0 <= SignedOffset) || this->GetBlock()->GetFunc()->DoesStackFrameExtendPastStackTop());
		}
		NormOp.addr = (ea_t) SignedOffset;
	}
	return;
} // end of SMPInstr::MDGetUnnormalizedOp()

// Find USE-not-DEF operand that is not the flags register.
op_t SMPInstr::GetSourceOnlyOperand(void) {
	size_t OpNum;
	for (OpNum = 0; OpNum < UA_MAXOP; ++OpNum) {
		if (this->features & DefMacros[OpNum]) { // DEF
			;
		}
		else if (this->features & UseMacros[OpNum]) { // USE
			op_t CurrOp = this->SMPcmd.Operands[OpNum];
			if (!(CurrOp.is_reg(X86_FLAGS_REG))) {
				return CurrOp;
			}
		}
	}
	// It is expected that increment, decrement, and floating point stores
	//  will not have a USE-only operand. Increment and decrement have an
	//  operand that is both USEd and DEFed, while the floating point stack
	//  registers are implicit in most floating point opcodes. Also, exchange
	//  and exchange-and-add instructions have multiple DEF-and-USE operands.
	int TypeGroup = SMPTypeCategory[this->SMPcmd.itype];
	if ((TypeGroup != 2) && (TypeGroup != 4) && (TypeGroup != 9) && (TypeGroup != 12)
		&& (TypeGroup != 13)) {
		SMP_msg("ERROR: Could not find source only operand at %lx in %s\n",
			(unsigned long) this->address, DisAsmText.GetDisAsm(this->GetAddr()));
	}
	return InitOp;
} // end of SMPInstr::GetSourceOnlyOperand()

// Should apparent memory operands be ignored? e.g. lea opcode on x86
bool SMPInstr::MDIgnoreMemOps(void) {
	bool leaInst = (NN_lea == this->SMPcmd.itype);
	return leaInst;
}

// Find memory DEFs and USEs, store in DEFMemOp and USEMemOp
void SMPInstr::FindMemOps(void) {
	size_t OpNum;

	if (!(this->MDIgnoreMemOps())) {
		for (OpNum = 0; OpNum < UA_MAXOP; ++OpNum) {
			op_t TempOp = this->SMPcmd.Operands[OpNum];
			if ((TempOp.type >= o_mem) && (TempOp.type <= o_displ)) { // memory
				if (this->features & DefMacros[OpNum]) { // DEF
					if (this->DEFMemOp.type == o_void) { // only save first mem DEF
						this->DEFMemOp = TempOp;
					}
				}
				if (this->features & UseMacros[OpNum]) { // USE
					if (this->USEMemOp.type == o_void) { // only save first mem USE
						this->USEMemOp = TempOp;
					}
				}
			}
		} // end for (OpNum = 0; ...)
	}
	this->SetMemOpsFound();
	return;
} // end of SMPInstr::FindMemOps()

// Fix problems with the operands list in SMPcmd.
void SMPInstr::MDFixupIDAProOperandList(void) {
	// IDA Pro often takes the instruction imul eax,0x80 and creates the following operands and features bits:
	//  Opnd[0] = EAX, both DEF and USE
	//  Opnd[1] = EAX, just USE
	//  Opnd[2] = immediate, neither DEF nor USE
	//  Our RTL building keys in on the DEF/USE bits in features, so this looks like imul eax,eax to us.
	//  We want it to look like:
	//  Opnd[0] = EAX, both DEF and USE
	//  Opnd[1] = immediate, just USE
	if (NN_imul == this->SMPcmd.itype) {
		op_t Opnd2 = this->SMPcmd.Operands[2];
		if ((!(this->features & DefMacros[2]))
			&& (!(this->features & UseMacros[2]))) {
			if (o_void != Opnd2.type) {
				// We have a third operand that is neither DEF nor USE.
				SMP_msg("INFO: Fixing IMUL operand list at %lx\n", (unsigned long) this->GetAddr());
				this->Dump();
				// Two cases: Operands[0] == Operands[1], e.g. imul eax,Opnd2
				//  or else three-operand form: e.g. imul eax,ecx,Opnd2
				// For the three-operand form, make sure Opnd0 is DEF only, others
				//  are USE only. For the two-operand form, make sure Opnd0 is DEF and USE,
				//  Opnd1 is current Opnd2 and is USE only.
				op_t Opnd0 = this->SMPcmd.Operands[0];
				op_t Opnd1 = this->SMPcmd.Operands[1];
				if (IsEqOp(Opnd0, Opnd1)) {
					// No need for three-operand form.
					this->features |= DefMacros[0];
					this->features |= UseMacros[0];
					this->SMPcmd.Operands[1] = Opnd2;
					this->SMPcmd.Operands[2] = InitOp;
				}
				else { // Must have three-operand form.
					this->features |= UseMacros[2]; // set missing USE bit.
					this->features &= (~UseMacros[0]); // Ensure no USE of Opnd0.
				}
				this->Dump();
			}		
		}
	}
	return;
} // SMPInstr::MDFixupIDAProOperandList()

// Fill the Defs and Uses private data members.
void SMPInstr::BuildSMPDefUseLists(void) {
	size_t OpNum;
	bool DebugFlag = (0x8049b00 == this->GetAddr());
	bool WidthDoubler = this->MDDoublesWidth();

	this->Defs.clear();
	this->Uses.clear();

	// Start with the Defs.
	for (OpNum = 0; OpNum < UA_MAXOP; ++OpNum) {
		if (this->features & DefMacros[OpNum]) { // DEF
			op_t TempOp = this->SMPcmd.Operands[OpNum];
			if (WidthDoubler) {
				// Opcodes that sign-extend a byte to a word, or a word to a dword, 
				//  have only one operand. It is implicit, and it is the shorter USE.
				//  That means the DEF will have the same width as the USE, e.g. if
				//  we are sign-extending AX to EAX, the USE and DEF both be AX without
				//  a special fix. We fix this problem with the DEF operand now.
				if (TempOp.dtyp == dt_byte) {
					TempOp.dtyp = dt_word;
					TempOp.reg = MDCanonicalizeSubReg(TempOp.reg);
				}
				else if (TempOp.dtyp == dt_word) {
					TempOp.dtyp = dt_dword;
					TempOp.reg = MDCanonicalizeSubReg(TempOp.reg);
				}
				else if (TempOp.dtyp == dt_dword) {
					TempOp.dtyp = dt_qword;
				}
				else {
					SMP_msg("ERROR: Instruction operand %zu not 1,2, or 4 bytes at %lx dtyp: %d\n", 
						OpNum, (unsigned long) this->address, TempOp.dtyp);
				}
			}
			if (MDKnownOperandType(TempOp)) {
				if (DebugFlag) {
					SMP_msg("DEBUG: Setting DEF for: ");
					PrintOperand(TempOp);
					SMP_msg("\n");
				}
				this->Defs.SetRef(TempOp);
			}
		}
	} // end for (OpNum = 0; ...)

	if (this->IsRegClearIdiom()) {
		// Something like xor eax,eax clears eax but does not really
		//  use eax. It is the same as mov eax,0 and we don't want to
		//  extend the prior def-use chain for eax to this instruction
		//  by treating the instruction as xor eax,eax. Instead, we
		//  build the DEF and USE lists and RTL as if it were mov eax,0.
		op_t ImmOp = InitOp;
		ImmOp.type = o_imm;
		ImmOp.value = 0;
		ImmOp.dtyp = this->GetOperandDtypField();
		this->Uses.SetRef(ImmOp, NUMERIC);
		return;
	}

	// Now, do the Uses. Uses have special case operations, because
	//  any memory operand could have register uses in the addressing
	//  expression, and we must create Uses for those registers. For
	//  example:  mov eax,[ebx + esi*2 + 044Ch]
	//  This is a two-operand instruction with one def: eax. But
	//  there are three uses: [ebx + esi*2 + 044Ch], ebx, and esi.
	//  The first use is an op_t of type o_phrase (memory phrase),
	//  which can be copied from cmd.Operands[1]. Likewise, we just
	//  copy cmd.Operands[0] into the defs list. However, we must create
	//  op_t types for register ebx and register esi and append them
	//  to the Uses list. This is handled by the machine dependent
	//  method MDFixupDefUseLists().
	for (OpNum = 0; OpNum < UA_MAXOP; ++OpNum) {
		if (this->features & UseMacros[OpNum]) { // USE
			op_t TempOp = this->SMPcmd.Operands[OpNum];
			if (MDKnownOperandType(TempOp)) {
				if (DebugFlag) {
					SMP_msg("DEBUG: Setting USE for: ");
					PrintOperand(TempOp);
					SMP_msg("\n");
				}
				this->Uses.SetRef(TempOp);
			}
		}
	} // end for (OpNum = 0; ...)

	return;
} // end of SMPInstr::BuildSMPDefUseLists()

// Declare a branch/jump to be a tail call, clean up def/use lists.
void SMPInstr::SetTailCall(void) { 
	this->booleans1 |= INSTR_SET_TAIL_CALL;
	if (this->type == COND_BRANCH) {
		this->SetCondTailCall();
	}
	else {
		this->ResetCondTailCall();
	}
	this->CallTarget = this->FarBranchTarget;
	this->type = RETURN;
	this->GetBlock()->SetReturns(true);

	// We want to add the caller-saved registers to the USEs and DEFs lists
	this->MDAddRegDef(R_ax, false);
	this->MDAddRegDef(R_cx, false);
	this->MDAddRegDef(R_dx, false);
	this->MDAddRegUse(R_ax, false);
	this->MDAddRegUse(R_cx, false);
	this->MDAddRegUse(R_dx, false);
} // end of SMPInstr::SetTailCall()

// record original Lea instruction [pseudo-]memory operand.
void SMPInstr::SetLeaMemUseOp(op_t NewLeaOperand) {
	if (NULL != this->BasicBlock) {
		this->GetBlock()->GetFunc()->AddLeaOperand(this->GetAddr(), NewLeaOperand);
	}
	return;
}

// If DefReg is not already in the DEF list, add a DEF for it.
void SMPInstr::MDAddRegDef(ushort DefReg, bool Shown, SMPOperandType Type) {
	op_t TempDef = InitOp;
	TempDef.type = o_reg;
	TempDef.reg = DefReg;
	TempDef.dtyp = this->GetOperandDtypField();
	if (Shown)
		TempDef.set_showed();
	else
		TempDef.clr_showed();
	this->Defs.SetRef(TempDef, Type);
	return;
} // end of SMPInstr::MDAddRegDef()

// If UseReg is not already in the USE list, add a USE for it.
void SMPInstr::MDAddRegUse(ushort UseReg, bool Shown, SMPOperandType Type) {
	op_t TempUse = InitOp;
	TempUse.type = o_reg;
	TempUse.reg = UseReg;
	TempUse.dtyp = this->GetOperandDtypField();
	if (Shown)
		TempUse.set_showed();
	else
		TempUse.clr_showed();
	this->Uses.SetRef(TempUse, Type);
	return;
} // end of SMPInstr::MDAddRegUse()

// Perform machine dependent ad hoc fixes to the def and use lists.
//  For example, some multiply and divide instructions in x86 implicitly
//  use and/or define register EDX. For memory phrase examples, see comment
//  in BuildSMPDefUseLists().
void SMPInstr::MDFixupDefUseLists(void) {
	// First, handle the uses hidden in memory addressing modes. Note that we do not
	//  care whether we are dealing with a memory destination operand or source
	//  operand, because register USEs, not DEFs, happen within the addressing expressions.
	size_t OpNum;
	SMPOperandType RefType;
	unsigned short opcode = this->SMPcmd.itype;
	int BaseReg;
	int IndexReg;
	ushort ScaleFactor;
	ea_t displacement;
	bool UseFP = true;
	bool HasIndexReg = false;
	bool SingleAddressReg = false;
	bool leaInst = (NN_lea == opcode);
	bool DebugFlag = (this->GetAddr() == 0x8086177);
	if (DebugFlag) {
		SMP_msg("DEBUG: Fixing up DEF-USE lists for debug location\n");
		this->Dump();
	}

#if SMP_BASEREG_POINTER_TYPE
	// Some instructions are analyzed outside of any function or block when fixing up
	//  the IDB, so we have to assume the block and func pointers might be NULL.
	if ((NULL != this->BasicBlock) && (NULL != this->BasicBlock->GetFunc()))
		UseFP = this->BasicBlock->GetFunc()->UsesFramePointer();
#endif

	if (DebugFlag) {
		SMP_msg("DEBUG: UseFP = %d\n", UseFP);
	}

	for (OpNum = 0; OpNum < UA_MAXOP; ++OpNum) {
		op_t Opnd = SMPcmd.Operands[OpNum];
		if ((Opnd.type == o_phrase) || (Opnd.type == o_displ) || (Opnd.type == o_mem)) {
			MDExtractAddressFields(Opnd, BaseReg, IndexReg, ScaleFactor, displacement);
			SingleAddressReg = ((0 == displacement) 
				&& ((R_none == BaseReg) || (R_none == IndexReg)));
			if (R_none != IndexReg) { 
				op_t IndexOpnd = Opnd; // Init to current operand field values
				IndexOpnd.type = o_reg; // Change type and reg fields
				IndexOpnd.reg = (ushort) IndexReg;
				IndexOpnd.hasSIB = 0;
				IndexOpnd.set_showed();
				if (0 == ScaleFactor)
					this->Uses.SetRef(IndexOpnd);
				else { // scaling == shift ==> NUMERIC
					HasIndexReg = true;
					this->Uses.SetRef(IndexOpnd, NUMERIC);
				}
			}
			if (R_none != BaseReg) {
				op_t BaseOpnd = Opnd; // Init to current operand field values
				BaseOpnd.type = o_reg; // Change type and reg fields
				BaseOpnd.reg = (ushort) BaseReg;
				BaseOpnd.hasSIB = 0;
				BaseOpnd.set_showed();
				RefType = UNINIT;
#if SMP_BASEREG_POINTER_TYPE
				// R_sp and R_bp will get type STACKPTR in SMPInstr::SetImmedTypes().
				//  Other registers used as base registers should get their USEs as
				//  base registers typed as POINTER, which might get refined later
				//  to STACKPTR, GLOBALPTR, HEAPPTR, etc.
				// NOTE: the NN_lea opcode is often used without a true base register.
				//  E.g. lea eax,[eax+eax+5] is an x86 idiom for eax:=eax*2+5, which
				//  could not be done in one instruction without using the addressing
				//  modes of the machine to do the arithmetic. We don't want to set the
				//  USE of EAX to POINTER in this case, so we will conservatively skip
				//  all lea instructions here.
				// We cannot be sure that a register is truly a base register unless
				//  there is also an index register. E.g. with reg+displacement, we
				//  could have memaddr+indexreg or basereg+offset, depending on what
				//  the displacement is. The exception is if there is no offset and only
				//  one addressing register, e.g. mov eax,[ebx].
				if (BaseOpnd.is_reg(MD_STACK_POINTER_REG) || (UseFP && BaseOpnd.is_reg(MD_FRAME_POINTER_REG))
					|| leaInst || (!HasIndexReg && !SingleAddressReg)) {
					;
				}
				else {
					RefType = POINTER;
				}
#endif
				this->Uses.SetRef(BaseOpnd, RefType);
			} // end if R_none != BaseReg
		} // end if (o_phrase or o_displ operand)
	} // end for (all operands)

	// The lea (load effective address) instruction looks as if it has
	//  a memory USE:  lea ebx,[edx+esi]
	//  However, this instruction is really just: ebx := edx+esi
	//  Now that the above code has inserted the "addressing" registers
	//  into the USE list, we should remove the "memory USE".
	if (leaInst) {
		set<DefOrUse, LessDefUse>::iterator CurrUse;
		for (CurrUse = this->GetFirstUse(); CurrUse != this->GetLastUse(); ++CurrUse) {
			op_t UseOp = CurrUse->GetOp();
			if ((o_mem <= UseOp.type) && (o_displ >= UseOp.type)) {
				this->SetLeaMemUseOp(UseOp);
				this->EraseUse(CurrUse);
				this->USEMemOp = InitOp;
				break;
			}
		}
	}

	// Next, handle repeat prefices in the instructions. The Intel REPE/REPZ prefix
	//  is just the text printed for SCAS/CMPS instructions that have a REP prefix.
	//  Only two distinct prefix codes are actually defined: REP and REPNE/REPNZ, and
	//  REPNE/REPNZ only applies to SCAS and CMPS instructions.
	bool HasRepPrefix = (0 != (this->SMPcmd.auxpref & aux_rep));
	bool HasRepnePrefix = (0 != (this->SMPcmd.auxpref & aux_repne));
	if (HasRepPrefix && HasRepnePrefix)
		SMP_msg("REP and REPNE both present at %lx %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
	if (HasRepPrefix || HasRepnePrefix) {
		// All repeating instructions use ECX as the countdown register.
		op_t BaseOpnd = InitOp;
		BaseOpnd.type = o_reg; // Change type and reg fields
		BaseOpnd.reg = R_cx;
		BaseOpnd.clr_showed();
		BaseOpnd.dtyp = this->GetOperandDtypField();
		this->Defs.SetRef(BaseOpnd, NUMERIC);
		this->Uses.SetRef(BaseOpnd, NUMERIC);
	}
	if ((opcode == NN_cmps) || (opcode == NN_scas) || (opcode == NN_movs) || (opcode == NN_stos)) {
		// ESI and EDI are USEd and DEFed to point to source and dest strings for CMPS/MOVS.
		//  Only EDI is involved with SCAS/STOS.
		op_t BaseOpnd = InitOp;
		BaseOpnd.type = o_reg; // Change type and reg fields
		BaseOpnd.clr_showed();
		BaseOpnd.dtyp = this->GetOperandDtypField();
		if ((opcode == NN_cmps) || (opcode == NN_movs)) {
			BaseOpnd.reg = R_si;
			this->Defs.SetRef(BaseOpnd, POINTER);
			this->Uses.SetRef(BaseOpnd, POINTER);
		}
		BaseOpnd.reg = R_di;
		this->Defs.SetRef(BaseOpnd, POINTER);
		this->Uses.SetRef(BaseOpnd, POINTER);
	}
	else if ((NN_loopw <= opcode) && (NN_loopqne >= opcode)) {
		op_t LoopCounterOp = InitOp;
		LoopCounterOp.type = o_reg;
		LoopCounterOp.reg = R_cx;
		LoopCounterOp.dtyp = this->GetOperandDtypField();
		this->Defs.SetRef(LoopCounterOp, NUMERIC);
		this->Uses.SetRef(LoopCounterOp, NUMERIC);
	}

	// Now, handle special instruction categories that have implicit operands.
	if (NN_cmpxchg == opcode) {
		// x86 Compare and Exchange conditionally sets EAX. We must keep data flow analysis
		//  sound by declaring that EAX is always a DEF.
		this->MDAddRegDef(R_ax, false);
	} // end if NN_cmpxchg
	else if (this->MDIsPopInstr() || this->MDIsPushInstr() || this->MDIsReturnInstr()) {
		// IDA does not include the stack pointer in the DEFs or USEs.
		this->MDAddRegDef(R_sp, false);
		this->MDAddRegUse(R_sp, false);
		if (!this->MDIsReturnInstr()) {
			// We always reference [esp+0] or [esp-4], so add it to the DEF or USE list.
			op_t StackOp = InitOp;
			StackOp.type = o_displ;
			StackOp.reg = R_sp;
			StackOp.dtyp = this->GetOperandDtypField();

			if (this->MDIsPopInstr()) {
				StackOp.addr = 0;  // [ESP+0]
				this->Uses.SetRef(StackOp);  // USE
			}
			else {
				StackOp.addr = (- ((ea_t) STARS_ISA_Bytewidth));  // [ESP-4]
				this->Defs.SetRef(StackOp); // DEF
			}
		}
	}
#if SMP_CALL_TRASHES_REGS
	else if ((this->type == CALL) || (this->type == INDIR_CALL) || this->IsTailCall()) {
		// We want to add the caller-saved registers to the USEs and DEFs lists
		this->MDAddRegDef(R_ax, false);
		this->MDAddRegDef(R_cx, false);
		this->MDAddRegDef(R_dx, false);
		this->MDAddRegUse(R_ax, false);
		this->MDAddRegUse(R_cx, false);
		this->MDAddRegUse(R_dx, false);
#if 1
		if (this->MDIsInterruptCall()) {
#endif
			this->MDAddRegDef(R_bx, false);
			this->MDAddRegUse(R_bx, false);
			this->MDAddRegDef(R_si, false);
			this->MDAddRegUse(R_si, false);
#if 1
		}
#endif
	}
#endif
	else if (this->MDIsEnterInstr() || this->MDIsLeaveInstr()) {
		// Entire function prologue or epilogue microcoded.
		this->MDAddRegDef(MD_STACK_POINTER_REG, false);
		this->MDAddRegUse(MD_STACK_POINTER_REG, false);
		this->MDAddRegDef(MD_FRAME_POINTER_REG, false);
		this->MDAddRegUse(MD_FRAME_POINTER_REG, false);
	}
	else if ((opcode == NN_maskmovq) || (opcode == NN_maskmovdqu)) {
		this->MDAddRegUse(R_di, false, POINTER);
	}
	else if (8 == this->GetOptType()) {
		// This category implicitly writes to EDX:EAX.
		this->MDAddRegDef(R_dx, false);
		this->MDAddRegDef(R_ax, false);
	} // end else if (8 == GetOptType)
	else if (7 == this->GetOptType()) {
		// Category 7 instructions sometimes write implicitly to EDX:EAX or DX:AX.
		//  DX is the same as EDX to IDA Pro (and SMP); ditto for EAX and AX.
		// DIV, IDIV, and MUL all have hidden EAX or AX operands (hidden in the IDA Pro
		//  sense, because they are not displayed in the disassembly text). For example:
		//  mul ebx means EDX:EAX <-- EAX*EBX, and mul bx means DX:AX <-- AX*BX. If the
		//  source operand is only 8 bits wide, there is room to hold the result in AX
		//  without using DX:  mul bl means AX <-- AL*BL.
		// IMUL has forms with a hidden EAX or AX operand and forms with no implicit
		//  operands:  imul ebx means EDX:EAX <-- EAX*EBX, but imul ebx,edx means that
		//  EBX*EDX gets truncated and the result placed in EBX (no hidden operands).
		for (OpNum = 0; OpNum < UA_MAXOP; ++OpNum) {
			op_t TempUse = this->SMPcmd.Operands[OpNum];
			if (!TempUse.showed()) { // hidden operand
				if (TempUse.is_reg(R_ax)) { // not R_al, so it is not 8 bits
					if ((NN_div == this->SMPcmd.itype) || (NN_idiv == this->SMPcmd.itype)) {
						this->MDAddRegUse(R_dx, false);
					}
					this->MDAddRegDef(R_ax, false);
					this->MDAddRegDef(R_dx, false);
				}
			}
		}
	} // end else if (7 == OptType)

#if 0
	// The floating point instructions in type categories 14 and 15 often USE and DEF
	//  the floating point register stack, e.g. pushing a value onto that stack is a
	//  massive copy downward of stack locations. We don't really care about the USE of
	//  the stack if the value being pushed came from elsewhere than the stack. For example,
	//  an "fld" opcode pushes its source onto the stack. We build RTLs with a simple
	//  move structure, but the RTL building can be fooled by seeing two "source" operands
	//  in the USE list.
	if ((14 == SMPTypeCategory[this->SMPcmd.itype])
		|| (15 == SMPTypeCategory[this->SMPcmd.itype])) {
	}
#endif

#if 0  // Not true for LOOP instructions that use only the ECX counter register.
	if (this->type == COND_BRANCH) {
		assert(SMPUsesFlags[opcode]);
	}
#endif
	// The return value register EAX is not quite like a caller-save or callee-save
	//  register (technically, it is caller-save). Within a callee, it might appear
	//  that EAX has become dead by the time a return instruction is reached, but
	//  the USE that would make it not dead is in the caller. To prevent type inference
	//  from mistakenly thinking that all USEs of EAX have been seen in the callee,
	//  we add EAX to the USE list for all return instructions, as well as for all
	//  tail calls, which are essentially returns in terms of data flow analysis.
	// This USE of EAX will always be of type UNINIT unless its DEF has a known type
	//  that propagates to it. Thus, it will prevent an invalid back inference of the
	//  DEF type from "all" USE types that are visible in the callee; even if they
	//  were all NUMERIC, this return USE will be UNINIT and inhibit the invalid
	//  type inference. EAX could be loaded with a pointer from memory, for example,
	//  and USEd only in a comparison instruction, making it falsely appear to be
	//  a NUMERIC, without this extra USE at the return instruction.
	// Because some of the library functions pass values around in EBX, EDI, etc.,
	//  we will add these general purpose registers to the USE list for returns
	//  in order to prevent erroneous analyses of dead registers or unused
	//  metadata.
	if ((this->type == RETURN) || this->IsTailCall()) {
		this->MDAddRegUse(R_ax, false);
		this->MDAddRegUse(R_bx, false);
		this->MDAddRegUse(R_cx, false);
		this->MDAddRegUse(R_dx, false);
		if (!UseFP)
			this->MDAddRegUse(MD_FRAME_POINTER_REG, false);
		this->MDAddRegUse(R_si, false);
		this->MDAddRegUse(R_di, false);
	}

	// Next, add the flags register to the DEFs and USEs for those instructions that
	//  are marked as defining or using flags.
	if (!this->IsDefsFlags() && SMPDefsFlags[opcode]) {
		this->MDAddRegDef(X86_FLAGS_REG, false);
		this->SetDefsFlags();
	}
	if (!this->IsUsesFlags() && SMPUsesFlags[opcode]) {
		this->MDAddRegUse(X86_FLAGS_REG, false);
		this->SetUsesFlags();
	}

#if 1
	if (this->IsNop()) {
		// Clear the DEFs and USEs for no-ops.
		//  These include machine idioms for no-ops, e.g. mov esi,esi
		//  or xchg ax,ax or lea esi,[esi].
		this->Defs.clear();
		this->Uses.clear();
		this->MoveSource = InitOp;
		this->DEFMemOp = InitOp;
		this->USEMemOp = InitOp;
		this->SetLeaMemUseOp(InitOp);
		this->OptType = 1;
	}
#endif

	if (DebugFlag) {
		SMP_msg("DEBUG after MDFixupDefUseLists:\n");
		this->Dump();
	}
	return;
} // end of SMPInstr::MDFixupDefUseLists()

// If we can definitely identify which part of the addressing expression
//  used in MemOp is the POINTER type, and it is not a STACKPTR or GLOBALPTR
//  immediate, set the USE type for that register to POINTER and return true.
//  If we can find definite NUMERIC addressing registers that are not already
//  typed as NUMERIC, set their USE types to NUMERIC and return true.
bool SMPInstr::MDFindPointerUse(op_t MemOp, bool UseFP) {
	bool changed = false;
	int BaseReg;
	int IndexReg;
	op_t BaseOp = InitOp;
	op_t IndexOp = InitOp;
	SMPOperandType BaseType = UNKNOWN;
	SMPOperandType IndexType = UNKNOWN;
	ushort ScaleFactor;
	ea_t offset;
	set<DefOrUse, LessDefUse>::iterator BaseIter;
	set<DefOrUse, LessDefUse>::iterator IndexIter;

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

	MDExtractAddressFields(MemOp, BaseReg, IndexReg, ScaleFactor, offset);
	if (R_none != IndexReg) {
		IndexOp.type = o_reg;
		IndexOp.reg = MDCanonicalizeSubReg((ushort) IndexReg);
		IndexOp.dtyp = this->GetOperandDtypField(); // Canonical reg width
		IndexIter = this->FindUse(IndexOp);
		assert(IndexIter != this->GetLastUse());
		IndexType = IndexIter->GetType();
	}
	if (R_none != BaseReg) {
		BaseOp.type = o_reg;
		BaseOp.reg = MDCanonicalizeSubReg((ushort) BaseReg);
		BaseOp.dtyp = this->GetOperandDtypField(); // Canonical reg width
		BaseIter = this->FindUse(BaseOp);
		assert(BaseIter != this->GetLastUse());
		BaseType = BaseIter->GetType();
	}
	if (MDIsStackPtrReg(BaseReg, UseFP)) {
		if ((R_none != IndexReg) && (!IsNumeric(IndexType))) {
			// We have an indexed access into the stack frame.
			//  Set IndexReg USE type to NUMERIC.
			changed = true;
			IndexIter = this->SetUseType(IndexOp, NUMERIC);
			assert(IndexIter != this->GetLastUse());
		}
		return changed; // stack accesses will get STACKPTR type in SetImmedTypes()
	}
	if (MDIsStackPtrReg(IndexReg, UseFP)) {
		if ((R_none != BaseReg) && (!IsNumeric(BaseType))) {
			// We have an indexed access into the stack frame.
			//  Set BaseReg USE type to NUMERIC.
			// Note that BaseReg is really an IndexReg and vice versa.
			changed = true;
			BaseIter = this->SetUseType(BaseOp, NUMERIC);
			assert(BaseIter != this->GetLastUse());
			SMP_msg("WARNING: BaseReg is index, IndexReg is base: %s\n",
				DisAsmText.GetDisAsm(this->GetAddr()));
		}
		return changed; // stack accesses will get STACKPTR type in SetImmedTypes()
	}
	if (IsImmedGlobalAddress(offset)) {
		if ((R_none != IndexReg) && (!IsNumeric(IndexType))) {
			// We have an indexed access into a global.
			//  Set IndexReg USE type to NUMERIC.
			changed = true;
			IndexIter = this->SetUseType(IndexOp, NUMERIC);
			assert(IndexIter != this->GetLastUse());
		}
		if ((R_none != BaseReg) && (!IsNumeric(BaseType))) {
			// We have an indexed access into a global.
			//  Set BaseReg USE type to NUMERIC.
			// Note that BaseReg is really an index register.
			changed = true;
			BaseIter = this->SetUseType(BaseOp, NUMERIC);
			assert(BaseIter != this->GetLastUse());
#if SMP_VERBOSE_FIND_POINTERS
			SMP_msg("WARNING: BaseReg used as index: %s\n", DisAsmText.GetDisAsm(this->GetAddr()));
#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()) {
				changed = true;
				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) {
				changed = true;
				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()));
			}
		}
		else { // BaseReg was not NUMERIC
			if (UNINIT == BaseType) { // BaseReg is UNINIT
				if (IsNumeric(IndexType)) {
					changed = true;
					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()

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()

// 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()

// 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))) {
		return false;
	}

	bool FoundSmallConst = 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.
		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;
				}
			}
		}
	}
	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);
			}
		}
	}

	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
		//  to come from a bitwise not.
		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))) {
		return false;
	}

	bool FoundConditionalSetInst = 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.
		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.
		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?
bool SMPInstr::IsOpSourceZeroExtendedMove(op_t UseOp, int UseSSANum, bool TruncationCheck) {
	bool UseFP = this->GetBlock()->GetFunc()->UsesFramePointer();
	if ((UseSSANum == -1) || (!MDIsDataFlowOpnd(UseOp, UseFP))) {
		return false;
	}

	bool FoundMoveZX = 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.
		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.
		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();
				FoundMoveZX = DefInst->IsOpSourceZeroExtendedMove(MoveUseOp, MoveUseSSANum, TruncationCheck); // recurse
			}
		}
		else if (TruncationCheck && DefInst->MDIsNonOverflowingBitManipulation()) {
			// 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
			}
		}
		else {
			FoundMoveZX = false;
		}
	}

	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))) {
		return false;
	}

	bool FoundMoveZXCC = 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.
		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
			}
		}
		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();
				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
			}
		}
		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) {
	bool FullCircle = false;

	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;
	op_t UseOp;
	op_t DefOp;
	uval_t ImmVal;
	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) {
			SMP_msg("SetImmedTypes USE: ");
			PrintOperand(UseOp);
			SMP_msg("\n");
		}
		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);
			}
			else { // NUMERIC
				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);
		}
#endif
		else if ((o_fpreg == UseOp.type) || (o_mmxreg == UseOp.type) || (o_xmmreg == UseOp.type)) {
			if (DebugFlag) SMP_msg("Setting floating point reg to NUMERIC\n");
			CurrUse = this->SetUseType(UseOp, NUMERIC);
		}
		else if ((o_mem == UseOp.type) || (o_phrase == UseOp.type) || (o_displ == UseOp.type)) {
			// For memory operands, we need to identify the POINTER value that
			//  is used in the addressing mode, if possible.
			(void) this->MDFindPointerUse(UseOp, UseFP);
		}
		++CurrUse;
	} // end while all USEs via CurrUse

	CurrDef = this->GetFirstDef();
	while (CurrDef != this->GetLastDef()) {
		DefOp = CurrDef->GetOp();
		if (DebugFlag) {
			SMP_msg("SetImmedTypes DEF: ");
			PrintOperand(DefOp);
			SMP_msg("\n");
		}
		if (DebugFlag) SMP_msg("FuncName: %s\n", this->BasicBlock->GetFunc()->GetFuncName());
		if (o_reg == DefOp.type) {
			if (DefOp.is_reg(X86_FLAGS_REG)) {
				if (DebugFlag) SMP_msg("Setting flags reg DEF to NUMERIC\n");
				CurrDef = this->SetDefType(DefOp, NUMERIC);
				// No need to propagate this DEF type, as all flags will become NUMERIC.
			}
#if 1
			else if (MDIsStackOrFramePointerReg(DefOp, UseFP)) {
				if (DebugFlag) SMP_msg("Setting reg DEF to STACKPTR\n");
				CurrDef = this->SetDefType(DefOp, STACKPTR);
				assert(CurrDef != this->Defs.GetLastRef());
				// No need to propagate; all stack and frame pointers will become STACKPTR.
			}
#endif
		}
		else if ((o_fpreg == DefOp.type) || (o_mmxreg == DefOp.type) || (o_xmmreg == DefOp.type)) {
			if (DebugFlag) SMP_msg("Setting floating point reg DEF to NUMERIC\n");
			CurrDef = this->SetDefType(DefOp, NUMERIC);
			// No need to propagate; all FP reg uses will become NUMERIC anyway.
		}
#if 0  // could these registers have pointers in them?
		else if ((o_trreg == DefOp.type) || (o_dbreg == DefOp.type) || (o_crreg == DefOp.type)) {
			if (DebugFlag) SMP_msg("Setting special reg DEF to NUMERIC\n");
			CurrDef = this->SetDefType(DefOp, NUMERIC);
		}
#endif	
		else if ((o_mem == DefOp.type) || (o_phrase == DefOp.type) || (o_displ == DefOp.type)) {
			// For memory operands, we need to identify the POINTER value that
			//  is used in the addressing mode, if possible.
			(void) this->MDFindPointerUse(DefOp, UseFP);
		}
		++CurrDef;
	} // end while all DEFs via CurrDef
	return;
} // end of SMPInstr::SetImmedTypes()

// Is the instruction a load from the stack?
void SMPInstr::MDFindLoadFromStack(bool UseFP) {
	set<DefOrUse, LessDefUse>::iterator UseIter;
	op_t UseOp;

	if ((3 == this->OptType) && (this->HasSourceMemoryOperand())) {
		// Loads and stores are OptCategory 3. We want only loads from the stack.
		for (UseIter = this->GetFirstUse(); UseIter != this->GetLastUse(); ++UseIter) {
			UseOp = UseIter->GetOp();
			if (MDIsStackAccessOpnd(UseOp, UseFP)) {
				this->SetLoadFromStack();
				break;
			}
		}
	}
	return;
} // end of SMPInstr::MDFindLoadFromStack()

// Determine if instr is inherently signed load instruction.
//  True if sign or zero-extended; pass out mask bits if true.
bool SMPInstr::MDIsSignedLoad(unsigned short &SignMask) {
	unsigned short opcode = this->SMPcmd.itype;
	if (NN_movzx == opcode) {
		SignMask = FG_MASK_UNSIGNED;
	}
	else if (NN_movsx == opcode) {
		SignMask = FG_MASK_SIGNED;
	}
	else {
		return false;
	}
	return true;
}

// true if increment or addition of small positive immediate value
#define STARS_SMALL_POS_VALUE_LIMIT 255
bool SMPInstr::MDIsSmallPositiveAddition(void) {
	unsigned short opcode = this->SMPcmd.itype;
	bool found = (NN_inc == opcode);
	uval_t ImmVal;

	if (!found && ((NN_add == opcode) || (NN_adc == opcode))) {
		set<DefOrUse, LessDefUse>::iterator UseIter;
		for (UseIter = this->GetFirstUse(); UseIter != this->GetLastUse(); ++UseIter) {
			op_t UseOp = UseIter->GetOp();
			if (o_imm == UseOp.type) {
				ImmVal = UseOp.value;
				if ((ImmVal <= STARS_SMALL_POS_VALUE_LIMIT) && (0 < ImmVal)) {
					found = true;
					break;
				}
			}
		}
	}
	else if (this->MDIsLoadEffectiveAddressInstr()) {
		// See if we have the form: lea reg1,[reg2+const]
		SMPRegTransfer *CurrRT = this->RTL.GetRT(0);
		if (CurrRT->HasRightSubTree()) {
			CurrRT = CurrRT->GetRightTree();
			SMPoperator CurrOp = CurrRT->GetOperator();
			if ((SMP_ADD == CurrOp) && (!CurrRT->HasRightSubTree())) {
				op_t RightOp = CurrRT->GetRightOperand();
				if (o_imm == RightOp.type) {
					ImmVal = RightOp.value;
					if ((ImmVal <= STARS_SMALL_POS_VALUE_LIMIT) && (0 < ImmVal)) {
						found = true;
					}
				}
			}
		}
	}

	return found;
} // end of SMPInstr::MDIsSmallPositiveAddition()

// true if increment, decrement, or addition or subtraction of small immediate value
bool SMPInstr::MDIsSmallAdditionOrSubtraction(void) {
	unsigned short opcode = this->SMPcmd.itype;
	bool found = ((NN_inc == opcode) || (NN_dec == opcode));

	if ((NN_add == opcode) || (NN_adc == opcode) || (NN_sub == opcode) || (NN_sbb == opcode)) {
		set<DefOrUse, LessDefUse>::iterator UseIter;
		for (UseIter = this->GetFirstUse(); !found && (UseIter != this->GetLastUse()); ++UseIter) {
			op_t UseOp = UseIter->GetOp();
			if (o_imm == UseOp.type) {
				uval_t ImmVal = UseOp.value;
				int SignedImmVal = (int) ImmVal;
				found = ((SignedImmVal >= (-STARS_SMALL_POS_VALUE_LIMIT)) && (SignedImmVal <= STARS_SMALL_POS_VALUE_LIMIT));
			}
		}
	}

	return found;
} // end of SMPInstr::MDIsSmallAdditionOrSubtraction()

// Inst is move or register clear.
bool SMPInstr::MDIsSimpleAssignment(bool &ValueFound, uval_t &ConstValue) {
	bool Simple = false;
	ValueFound = false;

	if (this->IsRegClearIdiom()) {
		Simple = true;
		ValueFound = true;
		ConstValue = 0;
	}
	else if (this->MDIsMoveInstr()) {
		Simple = true;
		if (o_imm == this->MoveSource.type) {
			ValueFound = true;
			ConstValue = this->MoveSource.value;
		}
	}

	return Simple;
} // end of SMPInstr::MDIsSimpleAssignment()

// Inst clears register or adds or subtracts small immediate value, as is done with counter variables.
bool SMPInstr::IsCounterOperation(void) {
	bool CounterOperation = false;
	bool ImmedValueFound = false;
	uval_t ConstValue = 1;
	if (this->MDIsSimpleAssignment(ImmedValueFound, ConstValue)) {
		CounterOperation = (ImmedValueFound && (0 == ConstValue));
	}
	else {
		CounterOperation = this->MDIsSmallAdditionOrSubtraction();
	}

	return CounterOperation;
} // end of SMPInstr::IsCounterOperation()

// Inst does an AND, OR, XOR operation; does not do add, subtract, etc.
bool SMPInstr::MDIsNonOverflowingBitManipulation(void) const {
	unsigned short opcode = this->SMPcmd.itype;
	return ((NN_and == opcode) || (NN_not == opcode) || (NN_or == opcode) || (NN_shl == opcode)
		|| ((NN_xor == opcode) && !this->IsRegClearIdiom()));
} // end of SMPInstr::MDIsNonOverflowingBitManipulation()

// return true if traced USE to a constant value
bool SMPInstr::FindConstantValue(set<DefOrUse, LessDefUse>::iterator UseIter, uval_t &ConstValue) {
	bool FoundConst = false;
	assert(UseIter != this->GetLastUse());
	op_t UseOp = UseIter->GetOp();
	if (UseOp.type == o_imm) {
		ConstValue = UseOp.value;
		FoundConst = true;
	}
	else {
		bool UseFP = this->GetBlock()->GetFunc()->UsesFramePointer();
		if ((o_reg == UseOp.type) || MDIsDirectStackAccessOpnd(UseOp, UseFP)) {
			// We can trace registers and stack locations through SSA chains, if the stack location is directly accessed.
			int UseSSANum = UseIter->GetSSANum();
			bool LocalName = this->GetBlock()->IsLocalName(UseOp);
			ea_t UseAddr = this->GetAddr();
			ea_t UseDefAddr = this->GetBlock()->GetDefAddrFromUseAddr(UseOp, UseAddr, UseSSANum, LocalName);
			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 a single 
				//  constant value, but this is highly unlikely. Terminate search.
				;
			}
			else if ((UseDefAddr == (this->GetBlock()->GetFirstAddr() - 1)) || (BADADDR == UseDefAddr)) {
				// The DEF is in a Phi function in the current block, or is BADADDR. Terminate search.
				;
			}
			else {
				SMPInstr *DefInst = this->GetBlock()->GetFunc()->GetInstFromAddr(UseDefAddr);
				bool ValueFound = false;
				if (DefInst->MDIsSimpleAssignment(ValueFound, ConstValue)) {
					if (ValueFound) {
						FoundConst = true; // ConstValue holds the value that was found.
					}
					else {
						set<DefOrUse, LessDefUse>::iterator NewUseIter = DefInst->GetFirstUse();
						// A simple assignment should have only one USE. Recurse on that USE.
						FoundConst = DefInst->FindConstantValue(NewUseIter, ConstValue);
					}
				}
			}
		}
	}

	return FoundConst;
} // end of SMPInstr::FindConstantValue()


// Infer sign, bit width, other type info for simple cases where all the info needed is
//  within the instruction or can be read from the FineGrainedStackTable in the SMPFunction.
// NOTE: Must be called after SSA analysis is complete.
void SMPInstr::MDSetWidthSignInfo(bool UseFP) {
	set<DefOrUse, LessDefUse>::iterator UseIter;
	set<DefOrUse, LessDefUse>::iterator DefIter;
	op_t UseOp, DefOp;
	struct FineGrainedInfo FGEntry;
	unsigned short SignMask, TempSign, WidthMask;
	int DefHashValue, UseHashValue;
	ea_t DefAddr;  // for flags USE in conditional set
	int SSANum;    // for flags USE in conditional set
	bool LocalFlags;  // is flags register a local name?
	bool case1, case2, case3, case4, case5, case6, case7, case8;
	bool SignedSetOpcode = this->MDIsSignedSetValue();
	bool UnsignedSetOpcode = this->MDIsUnsignedSetValue();

	case1 = this->IsLoadFromStack();
	case2 = this->MDIsSignedLoad(SignMask); // sets value of SignMask if it returns true
	case3 = (7 == this->OptType);  // Multiplies and divides
	case4 = ((CALL == this->GetDataFlowType()) || (INDIR_CALL == this->GetDataFlowType()));
	case5 = (SignedSetOpcode || UnsignedSetOpcode); // set boolean based on flag condition
	case6 = this->MDDoublesWidth(); // convert byte to word, word to dword, etc.
	case7 = this->MDAlwaysUnsignedDEF();
	case8 = this->MDAlwaysSignedDEF();

	// Case 1: Load from stack location.
	if (case1) {
		bool success = false;
		for (UseIter = this->GetFirstUse(); UseIter != this->GetLastUse(); ++UseIter) {
			UseOp = UseIter->GetOp();
			if (MDIsStackAccessOpnd(UseOp, UseFP)) {
				// Found the stack location being loaded into a register. Now we need
				//  to get the sign and width info from the fine grained stack frame
				//  analysis.
				success = this->GetBlock()->GetFunc()->MDGetFGStackLocInfo(this->address, UseOp, FGEntry);
				assert(success);
				// Now we have signedness info in FGEntry. We need to OR it into the register target of the load.
				if (FGEntry.SignMiscInfo == 0) 
					break; // nothing to OR in; save time
				for (DefIter = this->GetFirstDef(); DefIter != this->GetLastDef(); ++DefIter) {
					DefOp = DefIter->GetOp();
					if (o_reg == DefOp.type) {
						CanonicalizeOpnd(DefOp);
						TempSign = FGEntry.SignMiscInfo & FG_MASK_SIGNEDNESS_BITS; // Get both sign bit flags
						DefHashValue = HashGlobalNameAndSSA(DefOp, DefIter->GetSSANum());
						if (this->BasicBlock->IsLocalName(DefOp)) {
							this->BasicBlock->UpdateDefSignMiscInfo(DefHashValue, TempSign);
						}
						else {
							this->BasicBlock->GetFunc()->UpdateDefSignMiscInfo(DefHashValue, TempSign);
						}
						break;  // Should be only one register target for stack load, and no flags are set.
					}
				}
				break; // Only concerned with the stack operand
			}
		}
		assert(success);
	} // end if this->IsLoadFromStack()

	// Case 2: Loads that are sign-extended or zero-extended imply signed and unsigned, respectively.
	//  NOTE: If from the stack, they were handled in Case 1, and the signedness of the stack location
	//  was recorded a long time ago in SMPFunction::FindOutgoingArgsSize();
	else if (case2) {
		DefIter = this->GetFirstDef();
		while (DefIter != this->GetLastDef()) {
			// All non-memory DEFs besides the flags register should get the new SignMask ORed in.
			// On x86, there should only be one DEF for this move, and no flags, but we will generalize
			//  in case other architectures are odd.
			DefOp = DefIter->GetOp();
			if (!(IsMemOperand(DefOp) || MDIsFlagsReg(DefOp))) {
				CanonicalizeOpnd(DefOp);
				DefHashValue = HashGlobalNameAndSSA(DefOp, DefIter->GetSSANum());
				if (this->BasicBlock->IsLocalName(DefOp)) {
					this->BasicBlock->UpdateDefSignMiscInfo(DefHashValue, SignMask);
				}
				else {
					this->BasicBlock->GetFunc()->UpdateDefSignMiscInfo(DefHashValue, SignMask);
				}
			}
			++DefIter;
		}

		// If the signed load is from memory, the only USEs are the memory
		//  operand and addressing registers. We do not want to claim that
		//  EBX is signed in the instruction movsx eax,[ebx]. Only the DEF
		//  register EAX and the memory location [EBX] are signed, and we
		//  have no idea where [EBX] is, so we punt on all USEs if we have
		//  a memory source operand.
		if (!(this->HasSourceMemoryOperand())) {
			UseIter = this->GetFirstUse();
			while (UseIter != this->GetLastUse()) {
				// All non-memory USEs besides the flags register should get the new SignMask ORed in.
				UseOp = UseIter->GetOp();
				if (!(IsMemOperand(UseOp) || MDIsFlagsReg(UseOp))) {
					CanonicalizeOpnd(UseOp);
					UseHashValue = HashGlobalNameAndSSA(UseOp, UseIter->GetSSANum());
					if (this->BasicBlock->IsLocalName(UseOp)) {
						this->BasicBlock->UpdateUseSignMiscInfo(UseHashValue, SignMask);
					}
					else {
						this->BasicBlock->GetFunc()->UpdateUseSignMiscInfo(UseHashValue, SignMask);
					}
				}
				++UseIter;
			}
		}
	} // end of case 2

	// Case 3: multiplies and divides can be signed or unsigned.
	else if (case3) { // Multiplies and divides are type 7.
		if (this->MDIsSignedArithmetic()) {
			SignMask = FG_MASK_SIGNED;
		}
		else if (this->MDIsUnsignedArithmetic()) {
			SignMask = FG_MASK_UNSIGNED;
		}
		else {
			SignMask = 0; // unknown, uninitialized
		}
		if (0 != SignMask) {
			DefIter = this->GetFirstDef();
			while (DefIter != this->GetLastDef()) {
				// All DEFs besides the flags register should get the new SignMask ORed in.
				DefOp = DefIter->GetOp();
				if ((DefOp.type == o_reg) && (!(DefOp.is_reg(X86_FLAGS_REG)))) {
					CanonicalizeOpnd(DefOp);
					DefHashValue = HashGlobalNameAndSSA(DefOp, DefIter->GetSSANum());
					if (this->BasicBlock->IsLocalName(DefOp)) {
						this->BasicBlock->UpdateDefSignMiscInfo(DefHashValue, SignMask);
					}
					else {
						this->BasicBlock->GetFunc()->UpdateDefSignMiscInfo(DefHashValue, SignMask);
					}
				}
				++DefIter;
			}

			UseIter = this->GetFirstUse();
			while (UseIter != this->GetLastUse()) {
				// All USEs besides the flags register should get the new SignMask ORed in.
				UseOp = UseIter->GetOp();
				if ((UseOp.type == o_reg) && (!(UseOp.is_reg(X86_FLAGS_REG)))) {
					CanonicalizeOpnd(UseOp);
					UseHashValue = HashGlobalNameAndSSA(UseOp, UseIter->GetSSANum());
					if (this->BasicBlock->IsLocalName(UseOp)) {
						this->BasicBlock->UpdateUseSignMiscInfo(UseHashValue, SignMask);
					}
					else {
						this->BasicBlock->GetFunc()->UpdateUseSignMiscInfo(UseHashValue, SignMask);
					}
				}
				++UseIter;
			}
		} // end if (0 != SignMask)
	} // end of case 3 (multiplies and divides)

	// Case 4: Calls to library functions can reveal the type of the return register.
	else if (case4) {
		// Get name of function called.
		string FuncName = this->GetTrimmedCalledFunctionName();

		// Get FG info, if any, for called function.
		GetLibFuncFGInfo(FuncName, FGEntry);

		// See if anything was returned in FGEntry.
		if ((FGEntry.SignMiscInfo != 0) || (FGEntry.SizeInfo != 0)) {
			// Need to update the FG info for the DEF of the return register.
			DefOp = InitOp;
			DefOp.type = o_reg;
			DefOp.reg = MD_RETURN_VALUE_REG;
			DefOp.dtyp = this->GetOperandDtypField();
			DefIter = this->FindDef(DefOp);
			assert(DefIter != this->GetLastDef());
			DefHashValue = HashGlobalNameAndSSA(DefOp, DefIter->GetSSANum());
			if (this->BasicBlock->IsLocalName(DefOp)) {
				this->BasicBlock->UpdateDefFGInfo(DefHashValue, FGEntry);
			}
			else {
				this->BasicBlock->GetFunc()->UpdateDefFGInfo(DefHashValue, FGEntry);
			}
		}
		// See if we make a call to a library function that needs signedness checks on
		//  unsigned incoming args.
		unsigned int ArgPosBits = 0;
		GetUnsignedArgPositionsForCallName(FuncName, ArgPosBits);
		if (0 < ArgPosBits) {
			// Mark our basic block as containing this type of call, so signedness checks
			//  can be done later.
			this->GetBlock()->SetCallsUnsignedArgFunc();
			// Find the argument assignments and mark them, to trigger later signedness checks.
			this->GetBlock()->MarkUnsignedArgs(this->GetAddr(), ArgPosBits);
		}
	} // end of case4 (function calls)
	else if (case5) { // signed or unsigned conditional set opcode
		if (UnsignedSetOpcode) {
			SignMask = FG_MASK_UNSIGNED;
		}
		else {
			assert(SignedSetOpcode);
			SignMask = FG_MASK_SIGNED;
		}
		// Find the flags USE.
		UseOp.type = o_reg; // set up a dummy op for searching
		UseOp.reg = X86_FLAGS_REG;
		UseIter = this->FindUse(UseOp);
		assert(UseIter != this->GetLastUse());
		UseOp = UseIter->GetOp(); // get full info in all fields of UseOp
		SSANum = UseIter->GetSSANum();
		LocalFlags = this->GetBlock()->IsLocalName(UseOp);

		DefAddr = this->GetBlock()->GetDefAddrFromUseAddr(UseOp, this->GetAddr(), SSANum, LocalFlags);
		// Pass DefAddr to recursive helper function to propagate signedness of the set opcode.
		this->GetBlock()->PropagateBranchSignedness(DefAddr, UseOp, SignMask);
	}
	else if (case6) { // sign extend to double the width of USE operand into DEF operand
		DefIter = this->GetFirstNonFlagsDef();
		assert(DefIter != this->GetLastDef());
		DefOp = DefIter->GetOp();
		assert(o_reg == DefOp.type);
		SSANum = DefIter->GetSSANum();
		DefHashValue = HashGlobalNameAndSSA(DefOp, SSANum);
		UseIter = this->GetFirstUse();
		assert(UseIter != this->GetLastUse());
		UseOp = UseIter->GetOp();
		assert(o_reg == UseOp.type);
		assert(UseOp.reg == DefOp.reg);
		UseHashValue = HashGlobalNameAndSSA(UseOp, UseIter->GetSSANum()); 
		SignMask = FG_MASK_SIGNED;  // opcodes do sign extension => signed
		// Mark DEF and USE as signed.
		if (this->GetBlock()->IsLocalName(DefOp)) {
			this->GetBlock()->UpdateDefSignMiscInfo(DefHashValue, SignMask);
			this->GetBlock()->UpdateUseSignMiscInfo(UseHashValue, SignMask);
		}
		else {
			this->GetBlock()->GetFunc()->UpdateDefSignMiscInfo(DefHashValue, SignMask);
			this->GetBlock()->GetFunc()->UpdateUseSignMiscInfo(UseHashValue, SignMask);
		}
	}
	else if (case7 || case8) { // always unsigned DEF or always signed DEF.
		DefIter = this->GetFirstNonFlagsDef();
		if (DefIter != this->GetLastDef()) {
			DefOp = DefIter->GetOp();
			if (o_reg == DefOp.type) {
				SSANum = DefIter->GetSSANum();
				DefHashValue = HashGlobalNameAndSSA(DefOp, SSANum);
				if (case7)
					SignMask = FG_MASK_UNSIGNED;
				else
					SignMask = FG_MASK_SIGNED;
				// Mark DEF as signed or unsigned.
				if (this->GetBlock()->IsLocalName(DefOp)) {
					this->GetBlock()->UpdateDefSignMiscInfo(DefHashValue, SignMask);
				}
				else {
					this->GetBlock()->GetFunc()->UpdateDefSignMiscInfo(DefHashValue, SignMask);
				}
			}
		}
	}

	// For all register DEFs and USEs, we should get the obvious register width info
	//  updated. Need to use the RTL operands to get accurate widths.
	SMPRegTransfer *CurrRT;
	for (size_t index = 0; index < this->RTL.GetCount(); ++index) {
		CurrRT = this->RTL.GetRT(index);
		DefOp = CurrRT->GetLeftOperand();
		// Avoid setting def width for case 2; we leave it as zero so that
		//  later uses can determine whether the zero-extension or sign-extension
		//  bits ever got used. See more discussion in EmitIntegerErrorAnnotations()
		//  for the CHECK TRUNCATION case.
		// NOTE: case2 can be set to true even in the case1/case2 overlap case that
		//  only passes through the case1 code above. This is intentional. We want
		//  to leave the DEF width set to 0 for all of case2 including the case1 overlap.
		if (!case2) {
			if (MDIsGeneralPurposeReg(DefOp)) {
				WidthMask = ComputeOperandBitWidthMask(DefOp, 0);
				CanonicalizeOpnd(DefOp);
				DefIter = this->FindDef(DefOp);
				assert(DefIter != this->GetLastDef());
				DefHashValue = HashGlobalNameAndSSA(DefOp, DefIter->GetSSANum());
				if (this->BasicBlock->IsLocalName(DefOp)) {
					this->BasicBlock->UpdateDefWidthTypeInfo(DefHashValue, WidthMask);
				}
				else {
					this->BasicBlock->GetFunc()->UpdateDefWidthTypeInfo(DefHashValue, WidthMask);
				}
			}
		}
		if (CurrRT->HasRightSubTree()) {
			this->MDSetRTLRegWidthInfo(CurrRT->GetRightTree());
		}
		else {
			UseOp = CurrRT->GetRightOperand();
			this->SetRTLUseOpRegWidthInfo(UseOp);
		}
	}  // end for all RTLs 

	return;
} // end of SMPInstr::MDSetWidthSignInfo()

// Infer sign from the SMP types for USEs and DEFs.
void SMPInstr::InferSignednessFromSMPTypes(bool UseFP) {
	// Start with registers only, infer that all kids of pointers are UNSIGNED.
	set<DefOrUse, LessDefUse>::iterator DefIter, UseIter;
	op_t DefOp, UseOp;
	int SSANum;
	int DefHashValue, UseHashValue;
	SMPOperandType DefType, UseType;
	unsigned short DefSignMiscInfo = FG_MASK_UNSIGNED, UseSignMiscInfo = FG_MASK_UNSIGNED;
	bool GlobalName;

	for (DefIter = this->GetFirstDef(); DefIter != this->GetLastDef(); ++DefIter) {
		DefOp = DefIter->GetOp();
		if (MDIsGeneralPurposeReg(DefOp)) {
			DefType = DefIter->GetType();
			if (IsDataPtr(DefType) || (CODEPTR == DefType)) {
				GlobalName = this->BasicBlock->GetFunc()->IsGlobalName(DefOp);
				SSANum = DefIter->GetSSANum();
				DefHashValue = HashGlobalNameAndSSA(DefOp, SSANum);
				if (GlobalName) {
					this->BasicBlock->GetFunc()->UpdateDefSignMiscInfo(DefHashValue, DefSignMiscInfo);
				}
				else {
					this->BasicBlock->UpdateDefSignMiscInfo(DefHashValue, DefSignMiscInfo);
				}
			}
		}
	}

	for (UseIter = this->GetFirstUse(); UseIter != this->GetLastUse(); ++UseIter) {
		UseOp = UseIter->GetOp();
		if (MDIsGeneralPurposeReg(UseOp)) {
			UseType = UseIter->GetType();
			if (IsDataPtr(UseType) || (CODEPTR == UseType)) {
				GlobalName = this->BasicBlock->GetFunc()->IsGlobalName(UseOp);
				SSANum = UseIter->GetSSANum();
				UseHashValue = HashGlobalNameAndSSA(UseOp, SSANum);
				if (GlobalName) {
					this->BasicBlock->GetFunc()->UpdateUseSignMiscInfo(UseHashValue, UseSignMiscInfo);
				}
				else {
					this->BasicBlock->UpdateUseSignMiscInfo(UseHashValue, UseSignMiscInfo);
				}
			}
		}
	}

	return;
} // end of SMPInstr::InferSignednessFromSMPTypes()


// Helper to set width info for a UseOp from an RTL
void SMPInstr::SetRTLUseOpRegWidthInfo(op_t UseOp) {
	unsigned short WidthMask;
	set<DefOrUse, LessDefUse>::iterator UseIter;
	unsigned int UseHashValue;

	if (MDIsGeneralPurposeReg(UseOp)) {
		WidthMask = ComputeOperandBitWidthMask(UseOp, 0);
		CanonicalizeOpnd(UseOp);
		UseIter = this->FindUse(UseOp);
		assert(UseIter != this->GetLastUse());
		UseHashValue = HashGlobalNameAndSSA(UseOp, UseIter->GetSSANum());
		if (this->BasicBlock->IsLocalName(UseOp)) {
			this->BasicBlock->UpdateUseWidthTypeInfo(UseHashValue, WidthMask);
		}
		else {
			this->BasicBlock->GetFunc()->UpdateUseWidthTypeInfo(UseHashValue, WidthMask);
		}
	}

	return;
} // end of SMPInstr::SetRTLUseOpRegWidthInfo()

// Walk the RTL and update the register USE operands' width info.
void SMPInstr::MDSetRTLRegWidthInfo(SMPRegTransfer *CurrRT) {
	op_t UseOp;

	UseOp = CurrRT->GetLeftOperand();
	this->SetRTLUseOpRegWidthInfo(UseOp);
	if (CurrRT->HasRightSubTree()) {
		this->MDSetRTLRegWidthInfo(CurrRT->GetRightTree());
	}
	else {
		UseOp = CurrRT->GetRightOperand();
		this->SetRTLUseOpRegWidthInfo(UseOp);
	}

	return;
} // end of SMPInstr::MDSetRTLRegWidthInfo()

// Do we not consider truncation on this type of instruction to be an error?
bool SMPInstr::IsBenignTruncation(int &IdiomCode) {
	bool benign = false;
	unsigned short SignMask;
	op_t UseOp, SearchOp;

	if (3 == this->GetOptType()) { // Move instruction
		bool ExtendedLoad = this->MDIsSignedLoad(SignMask);
		if (ExtendedLoad && (SignMask & FG_MASK_UNSIGNED)) {
			// We have a zero-extended load. Compilers zero-extend both
			//  signed (unfortunately) and unsigned sub-regs when they know
			//  from the source language types that only the lower bits matter,
			//  e.g. when a char has been stored in the lower bits and regardless
			//  of whether that char was sign-extended or zero-extended previously,
			//  only the char itself is useful info. Otherwise, the compiler could
			//  move the whole register, e.g. instead of edi := zero-extend(cx), the
			//  compiler could have generated edi := ecx. The zero-extension loads
			//  are therefore not good candidates for truncation checks, as they lead
			//  to lots of false positives.
			benign = true;
			IdiomCode = 5;
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
			++BenignTruncationCount;
#endif
		}
		else { // Move, and not extended load, which was handled above.
			// Next case: A move instruction whose USE falsely appears to be a truncation,
			//  but in fact the apparently unused portion of the register is used later, e.g.:
			//   mov [ebp-12],ax  ; looks like EAX is being truncated to AX and stored
			//   shr eax,16       ; gets upper 16 bits into lower 16 bits
			//   mov [ebp-14],ax  ; store what used to be the upper 16 bits of EAX
			// The first instruction will trigger a CHECK TRUNCATION annotation that
			//  causes false positives. We need to analyze the context of the instruction
			//  to see that the whole register EAX was used, so no truncation occurred.
			//  The context analysis in the basic block will mark the second move as
			//  a "truncation" that should be ignored, so we check the flag here to short
			//  circuit redundant analysis.
			UseOp = this->GetMoveSource();
			assert(o_void != UseOp.type);
			SearchOp = UseOp;
			if (o_reg == UseOp.type) {
				CanonicalizeOpnd(SearchOp);
			}
			set<DefOrUse, LessDefUse>::iterator UseIter = this->FindUse(SearchOp);
			assert(UseIter != this->GetLastUse());
			if (UseIter->DoesNotTruncate()) {
				benign = true;
				IdiomCode = 2;
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
				++SuppressTruncationRegPiecesAllUsed;
#endif
			}
			else {
				set<DefOrUse, LessDefUse>::iterator DefIter = this->GetFirstNonFlagsDef();
				assert(DefIter != this->GetLastDef());
				int DefSSANum = DefIter->GetSSANum();
				benign = this->GetBlock()->IsBenignTruncationDEF(DefIter->GetOp(), DefSSANum, this->GetAddr(), IdiomCode);
				if (!benign) {
					// Third case: value gets zero-extended, AND/OR instructions manipulate it, then
					//  the lower bits get written. No adds, subtracts, etc. in the chain of operations.
					//  This is just the typical unwillingness of compiler to do less than 32-bit arithmetic,
					//  not an actual truncation.
					int UseSSANum = UseIter->GetSSANum();
					// Prepare for possible recursive traversals through the function blocks.
					this->GetBlock()->GetFunc()->ResetProcessedBlocks();
					if (this->IsOpSourceZeroExtendedMoveShiftRightOrConditionCode(SearchOp, UseSSANum, true)) {
						IdiomCode = 14;
						benign = true;
					}
				}
				if (!benign) {
					// Fourth case: bits within a byte are copied and shifted (some left, some right) and written
					//  out to different byte addresses. The left and right shifts of two copies of the same byte
					//  are the kind of bit-twiddling done when disassembling some network packets.
					int UseSSANum = UseIter->GetSSANum();
					// Prepare for possible recursive traversals through the function blocks.
					this->GetBlock()->GetFunc()->ResetProcessedBlocks();
					ea_t ShiftInstAddr;
					op_t ShiftedOperand;
					op_t ShiftCounterOperand;
					if (this->IsOpSourceLeftShift(SearchOp, UseSSANum, ShiftCounterOperand, ShiftedOperand, ShiftInstAddr)) {
						if ((o_imm == ShiftCounterOperand.type) && (8 > ShiftCounterOperand.value)) {
							SMPInstr *ShiftInst = this->GetBlock()->GetFunc()->GetInstFromAddr(ShiftInstAddr);
							if (ShiftInst->GetBlock()->IsUseCopiedAndShiftedRight(ShiftedOperand, ShiftInstAddr)) {
								IdiomCode = 25;
								benign = true;
							}
						}
					}
				}
			}
		}
	}
	return benign;
} // end of SMPInstr::IsBenignTruncation()

// Do we not consider overflow or underflow on this type of instruction to be an error?
bool SMPInstr::IsBenignOverflow(int &IdiomCode) {
	bool benign = false;
	set<DefOrUse, LessDefUse>::iterator DefIter, UseIter;
	SMPOperandType DefType, UseType;
	int DefSSANum;
	ea_t DefAddr;
	op_t DefOp;

	if (this->MDIsDefiniteBenignUnderflowOpcode(IdiomCode)) {
		// No further analysis at block or function scope is needed.
		benign = true;
	}
	else if (this->MDIsMaybeBenignUnderflowOpcode()) { // might have the subtract instruction in tricky sequence
		// We are looking to suppress overflow and underflow warnings on the following
		//  code sequence: PTR1-PTR2+1 gets a loop invariant code motion optimization
		//  that pulls  temp := 1-PTR2 out of the loop, and leaves temp2 := PTR1+temp
		//  inside the loop. The hoisted subtraction could underflow, and the addition
		//  that is not hoisted could overflow. The net effect of these two instructions
		//  is benign, however, so we want to suppress underflow and overflow checks on
		//  both of them, but only if we can match the pair of instructions.
		DefIter = this->GetFirstNonFlagsDef();
		assert(DefIter != this->GetLastDef());
		if (DefIter->DoesNotOverflow()) {
			benign = true; // short circuit; already analyzed
		}
		else {
			DefType = DefIter->GetType();
			if (IsEqType(DefType, NEGATEDPTR)) { // We have candidate subtract instruction
				DefOp = DefIter->GetOp();
				DefSSANum = DefIter->GetSSANum();
				DefAddr = this->GetAddr();
				benign = this->GetBlock()->GetFunc()->IsBenignUnderflowDEF(DefOp, DefSSANum, DefAddr, IdiomCode);
				if (!benign) {
					// If we did not find the complicated sequence, we still don't want to have a false positive
					//  on any instruction that is producing a NEGATEDPTR.
					benign = true;
					IdiomCode = 13;
				}
			}
		}
	}
	else if (this->MDIsMaybeBenignOverflowOpcode()) { // might have the add instruction in tricky sequence
		DefIter = this->GetFirstNonFlagsDef();
		assert(DefIter != this->GetLastDef());
		if (DefIter->DoesNotOverflow()) {
			benign = true; // short circuit; already analyzed
			IdiomCode = 6;
		}
		else { // Bad luck to encounter addition first. See what types tell us.
			if (this->HasNegatedPtrUSE()) { // We have candidate for addition.
				DefType = DefIter->GetType();
				if (IsEqType(DefType, PTROFFSET)) {
					// Current instruction is definitely the addition instruction of some
					//  benignly underflowing and overflowing pair of instructions. It does
					//  not really matter that we have not found the subtraction yet; we will
					//  get to it eventually. We should suppress overflow checks on this inst.
					DefOp = DefIter->GetOp();
					this->Defs.SetNoOverflow(DefOp, true);
					benign = true;
					IdiomCode = 6;
				}
				else {
					// A bit of a quandary. Ideally, we would have successful SMP type inference
					//  and always have PTROFFSET := POINTER + NEGATEDPTR. However, sometimes we
					//  might have ?? := ?? + NEGATEDPTR. The instruction could be of the type
					//  NEGATEDPTR := NUMERIC + NEGATEDPTR, so we cannot just assume here that 
					//  we have detected the benign case. However, these instructions are likely
					//  to cause false positives and unlikely to be a source of false negatives,
					//  so we will err on the side of false positive suppression based on experience
					//  (even though we usually do the opposite).
					benign = true;
					IdiomCode = 13;
				}
			}
		}
	}

	if (!benign) {
		// Any overflow or underflow producing a PTROFFSET type should be suppressed.
		for (DefIter = this->GetFirstDef(); DefIter != this->GetLastDef(); ++DefIter) {
			DefType = DefIter->GetType();
			if (IsEqType(DefType, PTROFFSET)) {
				benign = true;
				IdiomCode = 19;
			}
		}
	}
	if (!benign) {
		// Any overflow or underflow using a PTROFFSET type should be suppressed.
		for (UseIter = this->GetFirstUse(); UseIter != this->GetLastUse(); ++UseIter) {
			UseType = UseIter->GetType();
			if (IsEqType(UseType, PTROFFSET)) {
				benign = true;
				IdiomCode = 19;
			}
		}
	}

	return benign;
} // end of SMPInstr::IsBenignOverflow()

// Do we detect a situation in which it is safe to check for signedness errors on
//  the stack write (return false), or not (return true to be safe).
bool SMPInstr::SkipSignednessCheckOnStackWrite(int DefSSANum) {
	bool SkipCheck = (!(this->IsUnsignedArg()));
	op_t StackDefOp = this->DEFMemOp;
	size_t DefBitWidth = 8 * GetOpDataSize(StackDefOp);
	if (DefBitWidth < MD_NORMAL_MACHINE_BITWIDTH) {
		// If we are not dealing with a shortened bit width, then
		//  the next load from the stack will not be sign-extended
		//  or zero-extended.
		if (this->GetBlock()->IsStackOpNextUsedWithSignedness(StackDefOp, this->GetAddr(), DefSSANum)) {
			SkipCheck = false;
		}
	}
	return SkipCheck;
} // end of SMPInstr::SkipSignednessCheckOnStackWrite()

// Does inst pass an outgoing argument? If so, pass back argument position #, starting at zero for [esp], 1 for [esp+4], etc.
bool SMPInstr::MDIsArgumentPass(size_t &ArgumentNumber) {
	bool OutArgPass = false;

	// Current model is writing outargs to stack. For other compiler targets in the
	//  future, we would also include pushes onto the stack.
	if (this->HasDestMemoryOperand() && (this->GetOptType() == 3)) { // move to memory
		if (this->GetBlock()->GetFunc()->OutArgsRegionComputed()) {
			op_t DefOp = this->DEFMemOp;
			OutArgPass = this->GetBlock()->GetFunc()->IsInOutgoingArgsRegion(DefOp);
			if (OutArgPass) {
				op_t UnnormalizedDefOp = DefOp;
				this->MDGetUnnormalizedOp(UnnormalizedDefOp);
				size_t StandardByteSize = (MD_NORMAL_MACHINE_BITWIDTH / 8);
				ArgumentNumber = (UnnormalizedDefOp.addr / StandardByteSize);
			}
		}
	}
	return OutArgPass;
}

// Does UseOp arithmetically affect the value of the NonFlagsDef for this inst?
bool SMPInstr::OperandTransfersValueToDef(op_t UseOp) {
	bool FoundTransfer = false;
	for (size_t index = 0; index < this->RTL.GetCount(); ++index) {
		SMPRegTransfer *CurrRT = this->RTL.GetRT(index);
		if (CurrRT->OperandTransfersValueToDef(UseOp)) {
			FoundTransfer = true;
			break;
		}
	}
	return FoundTransfer;
} // end of SMPInstr::OperandTransfersValueToDef()

// Evaluate constants in assignment statement for SCCP algorithm
void SMPInstr::SCCPEvaluateAssignment(list<pair<int, int> > &SSAWorkList) {
	for (size_t index = 0; index < this->RTL.GetCount(); ++index) {
		SMPRegTransfer *CurrRT = this->RTL.GetRT(index);
		STARS_SCCP_Const_Struct ConstResult = CurrRT->SCCPEvaluateRTLConsts(SSAWorkList);
		if (ConstResult.ConstType == STARS_CONST_HAS_VALUE) {
			++ConstantDEFCount;
		}
	}
	return;
} // end of SMPInstr::SCCPEvaluateAssignment()

// Evaluate conditional branch using constant values from SCCP
void SMPInstr::SCCPEvaluateCondBranch(enum STARSBranchConst &BranchEval) {
	// The conditional branch RTL is just a jump with a Guard RT.
	//  We evaluate the Guard RT to see if it is always true or always false.
	SMPRegTransfer *CurrRT = this->RTL.GetRT(0);
	SMPGuard *BranchCondition = CurrRT->GetGuard();
	assert(NULL != BranchCondition);
	op_t LeftOp = BranchCondition->GetLeftOperand();
	CanonicalizeOpnd(LeftOp);
	op_t RightOp = BranchCondition->GetRightOperand();
	CanonicalizeOpnd(RightOp);
	STARS_SCCP_Const_Struct LeftValue, RightValue;
	this->SCCPFetchConstUseValue(LeftOp, LeftValue);
	this->SCCPFetchConstUseValue(RightOp, RightValue);
	if ((LeftValue.ConstType == STARS_CONST_HAS_VALUE) && (RightValue.ConstType == STARS_CONST_HAS_VALUE)) {
		SMPoperator GuardOper = BranchCondition->GetOperator();
		if (GuardOper == SMP_EQUAL) {
			if (LeftValue.ConstValue == RightValue.ConstValue) {
				BranchEval = STARS_BRANCH_ALWAYS_TAKEN;
				++AlwaysTakenBranchCount;
#if 0
				SMP_msg("INFO: SCCP found always taken conditional branch at %x\n", this->GetAddr());
#endif
			}
			else {
				BranchEval = STARS_BRANCH_NEVER_TAKEN;
				++NeverTakenBranchCount;
#if 0
				SMP_msg("INFO: SCCP found never taken conditional branch at %x\n", this->GetAddr());
#endif
			}
		}
		else if (GuardOper == SMP_NOT_EQUAL) {
			if (LeftValue.ConstValue != RightValue.ConstValue) {
				BranchEval = STARS_BRANCH_ALWAYS_TAKEN;
				++AlwaysTakenBranchCount;
#if 0
				SMP_msg("INFO: SCCP found always taken conditional branch at %x\n", this->GetAddr());
#endif
			}
			else {
				BranchEval = STARS_BRANCH_NEVER_TAKEN;
				++NeverTakenBranchCount;
#if 0
				SMP_msg("INFO: SCCP found never taken conditional branch at %x\n", this->GetAddr());
#endif
			}
		}
	}
	else {
		BranchEval = STARS_BRANCH_UNKNOWN;
	}

	return;
} // end of SMPInstr::SCCPEvaluateCondBranch()

// Fetch constant value, if any, for a USE operand.
void SMPInstr::SCCPFetchConstUseValue(op_t UseOp, STARS_SCCP_Const_Struct &ConstStruct) {
	ConstStruct.ConstType = STARS_CONST_TOP; // default
	if (o_imm == UseOp.type) {
		ConstStruct.ConstType = STARS_CONST_HAS_VALUE;
		ConstStruct.ConstValue = UseOp.value;
	}
	else if (o_reg == UseOp.type) {
		// Look up reg DEF value in local or global map
		op_t SearchOp = UseOp;
		CanonicalizeOpnd(SearchOp);
		set<DefOrUse, LessDefUse>::iterator UseIter = this->FindUse(SearchOp);
		if (UseIter != this->GetLastUse()) {
			int UseSSANum = UseIter->GetSSANum();
			int UseHashValue = HashGlobalNameAndSSA(SearchOp, UseSSANum);
			if (this->GetBlock()->IsLocalName(SearchOp)) { // local name
				map<int, struct STARS_SCCP_Const_Struct>::iterator ConstValIter = this->GetBlock()->FindLocalConstValue(UseHashValue);
				if (ConstValIter != this->GetBlock()->GetLastLocalConstValueIter()) { // Has current const val entry
					ConstStruct = ConstValIter->second;
				}
			}
			else { // global name
				map<int, struct STARS_SCCP_Const_Struct>::iterator ConstValIter = this->GetBlock()->GetFunc()->FindConstValue(UseHashValue);
				if (ConstValIter != this->GetBlock()->GetFunc()->GetLastConstValueIter()) { // Has current const val entry
					ConstStruct = ConstValIter->second;
				}
			}
		}
	}
	return;
} // end of SMPInstr::SCCPFetchConstUseValue()

// Fetch constant value, if any, for a DEF operand.
void SMPInstr::SCCPFetchConstDefValue(op_t DefOp, STARS_SCCP_Const_Struct &ConstStruct) {
	ConstStruct.ConstType = STARS_CONST_TOP; // default
	if (o_imm == DefOp.type) {
		ConstStruct.ConstType = STARS_CONST_HAS_VALUE;
		ConstStruct.ConstValue = DefOp.value;
	}
	else if (o_reg == DefOp.type) {
		// Look up reg DEF value in local or global map
		op_t SearchOp = DefOp;
		CanonicalizeOpnd(SearchOp);
		set<DefOrUse, LessDefUse>::iterator DefIter = this->FindDef(SearchOp);
		if (DefIter != this->GetLastDef()) {
			int DefSSANum = DefIter->GetSSANum();
			int DefHashValue = HashGlobalNameAndSSA(SearchOp, DefSSANum);
			if (this->GetBlock()->IsLocalName(SearchOp)) { // local name
				map<int, struct STARS_SCCP_Const_Struct>::iterator ConstValIter = this->GetBlock()->FindLocalConstValue(DefHashValue);
				if (ConstValIter != this->GetBlock()->GetLastLocalConstValueIter()) { // Has current const val entry
					ConstStruct = ConstValIter->second;
				}
			}
			else { // global name
				map<int, struct STARS_SCCP_Const_Struct>::iterator ConstValIter = this->GetBlock()->GetFunc()->FindConstValue(DefHashValue);
				if (ConstValIter != this->GetBlock()->GetFunc()->GetLastConstValueIter()) { // Has current const val entry
					ConstStruct = ConstValIter->second;
				}
			}
		}
	}
	return;
} // end of SMPInstr::SCCPFetchConstDefValue()

// Trace UseOp through register moves back to its stack location or immediate value source.
//  Return true if we are passing an immediate or stack location back in UltSource.
bool SMPInstr::TraceUltimateMoveSource(op_t UseOp, int UseSSANum, op_t &UltSource, bool &FPRelative) {
	// If we hit an immediate value or a stack location, we are done.
	bool UseFP = this->GetBlock()->GetFunc()->UsesFramePointer();
	op_t NewUseOp; // next UseOp up the move chain
	op_t DefOp, ImmOp;
	int NewUseSSANum;
	set<DefOrUse,LessDefUse>::iterator UseIter;
	bool LocalName;
	ea_t DefAddr;
	SMPInstr *DefInst;

	UltSource = InitOp;
	bool StackOp = MDIsDirectStackAccessOpnd(UseOp, UseFP);
	bool RegisterOp = (UseOp.type == o_reg);

	if (this->GetOptType() == 3) { // move instruction
		if (UseOp.type == o_imm) {
			UltSource = UseOp;
			return true;
		}
		else if ((!RegisterOp) && (!StackOp)) {
			// We only trace the move chain through registers or stack locations to an ultimate 
			//  load-effective-address of a stack location, or a move of an immediate value.
			return false;
		}
	} 
	else if (!this->MDIsLoadEffectiveAddressInstr()) {
		return false;
	}
	else { // Load effective address instruction.
		// If it is a stack location being loaded, trace succeeded, else it failed.
		if (StackOp) {
			UltSource = UseOp;
			FPRelative = this->HasFPNormalizedToSP();
			return true;
		}
		else {
			return false;
		}
	}

	// If we reach this point, we have a move instruction but did not return true or false above.

	// Recursion case. Going back up the move chain has just produced a register or
	//  a stack location, and we still need to find the stack address or immediate value
	//  that was stored in the register or stack location. The stack location could hold
	//  a pointer to a stack object, produced by an earlier LEA instruction, or it
	//  could hold an immediate value (e.g. constant size argument passed to memset() or
	//  similar function).
	LocalName = this->GetBlock()->IsLocalName(UseOp);
	DefAddr = this->GetBlock()->GetDefAddrFromUseAddr(UseOp, this->GetAddr(), UseSSANum, LocalName);
	if ((BADADDR == DefAddr) || (DefAddr < (this->GetBlock()->GetFunc()->GetStartAddr() - 1))) {
		// Def was not found, or was found in Phi function (DefAddr was block number, not instruction addr).
		return false;
	}

	if (DefAddr < (this->GetBlock()->GetFirstAddr())) {
		// If DefAddr is 1 byte less than the first addr in the block, then
		//  it is a pseudo-def in the global DU chains, signifying that the
		//  value was LiveIn and the true DEF is in another block. We could
		//  handle this in the future, but right now we will only deal with
		//  the simpler case in which the move source can be traced
		//  within the basic block.
		return false;
	}

	// Everything is OK so far; time to recurse up the move chain.
	DefInst = this->GetBlock()->GetFunc()->GetInstFromAddr(DefAddr);
	if (DefInst->GetOptType() == 3) {
		NewUseOp = DefInst->GetMoveSource();
	}
	else if (DefInst->MDIsLoadEffectiveAddressInstr()) {
		NewUseOp = DefInst->GetLeaMemUseOp();
		if (MDIsDirectStackAccessOpnd(NewUseOp, UseFP)) {
			UltSource = NewUseOp;
			FPRelative = DefInst->HasFPNormalizedToSP();
			return true;
		}
		else {
			return false;
		}
	}
	// We don't have a move instruction or a load effective address instruction, which
	//  can be used to move a stack address into a register. We don't try to trace through
	//  arithmetic except for two easy cases.
	// Case 1: A register is cleared. Same as assigning immediate value zero to the reg.
	else if (DefInst->IsRegClearIdiom()) {
		UltSource.type = o_imm;
		UltSource.value = 0;  // why would we memset a zero byte region?
		return true;
	}
	// Easy arithmetic Case 2: we have reg += ImmediateValue, and reg was DEFed by reg := LEA(StackLoc).
	else if (DefInst->MDIsAddImmediateToReg(DefOp, ImmOp)) {
		SMPInstr *NewDefInst;
		UseIter = DefInst->FindUse(DefOp);
		assert(UseIter != DefInst->GetLastUse());
		NewUseSSANum = UseIter->GetSSANum();
		LocalName = DefInst->GetBlock()->IsLocalName(DefOp);
		DefAddr = DefInst->GetBlock()->GetDefAddrFromUseAddr(DefOp, DefInst->GetAddr(), NewUseSSANum, LocalName);
		if ((BADADDR == DefAddr) || (DefAddr < (DefInst->GetBlock()->GetFunc()->GetStartAddr() - 1))) {
			// Def was not found, or was found in Phi function (DefAddr was block number, not instruction addr).
			return false;
		}
		NewDefInst = DefInst->GetBlock()->GetFunc()->GetInstFromAddr(DefAddr);
		if (NewDefInst->MDIsLoadEffectiveAddressInstr()) {
			NewUseOp = NewDefInst->GetLeaMemUseOp();
			if (MDIsDirectStackAccessOpnd(NewUseOp, UseFP)) {
				// We have the code sequence we were searching for when we first saw the
				//  addition of an immediate value to a register, e.g.:
				//   lea ebx,[ebp-2000]
				//   add ebx,1000
				//
				// We are essentially making this sequence into a single instruction:
				//   lea ebx,[ebp-1000]
				//  by adding the immediate value to the address offset. With a stack that grows
				//  downward, it does not matter if we add 1000 to [esp+500] to produce [esp+1500],
				//  or we add 1000 to [ebp-2000] to make [ebp-1000]. Either way, we are simulating the
				//  addition of 1000 as we move up in the stack frame.
				NewUseOp.addr += ImmOp.value; // perform the address arithmetic addition
				UltSource = NewUseOp;
				FPRelative = NewDefInst->HasFPNormalizedToSP();
				return true;
			}
			else {
				return false;
			}
		}
		else {
			return false;
		}
	}
	else {
		// Not the kind of instruction we need; cut short the recursion.
		return false;
	}

	// NewUseOp is the move source operand that we seek.
	UseIter = DefInst->FindUse(NewUseOp);
	assert(UseIter != DefInst->GetLastUse());
	NewUseSSANum = UseIter->GetSSANum();  // unused for immediates, used for regs and stack
	// Recurse
	return DefInst->TraceUltimateMoveSource(NewUseOp, NewUseSSANum, UltSource, FPRelative);

} // end of SMPInstr::TraceUltimateMoveSource()

// inst has no code xrefs?
bool SMPInstr::HasNoCodeXrefs(void) {
	SMP_xref_t CurrXrefs;
	bool FoundCodeXref = false;

	for (bool ok = CurrXrefs.SMP_first_to(this->GetAddr(), XREF_ALL); ok; ok = CurrXrefs.SMP_next_to()) {
		ea_t FromAddr = CurrXrefs.GetFrom();
		if ((FromAddr != 0) && (CurrXrefs.GetIscode())) {
			FoundCodeXref = true;
			break;
		}
	}

	return (!FoundCodeXref);
} // end of SMPInstr::HasNoCodeXrefs()

// Infer DEF, USE, and RTL SMPoperator types within the instruction based on the type
//  of operator, the type category of the instruction, and the previously known types 
//  of the operands.
bool SMPInstr::InferTypes(void) {
	bool changed = false;  // return value
	int SSANum;
	int TypeCategory = SMPTypeCategory[this->SMPcmd.itype];
	set<DefOrUse, LessDefUse>::iterator CurrDef;
	set<DefOrUse, LessDefUse>::iterator CurrUse;
	op_t DefOp = InitOp, UseOp = InitOp;
	bool DebugFlag = false;
	bool UseFP = this->BasicBlock->GetFunc()->UsesFramePointer();
	bool SafeFunc = this->BasicBlock->GetFunc()->IsSafe();
	bool IsMemOp;
#if SMP_VERBOSE_DEBUG_INFER_TYPES
	DebugFlag |= (0 == strcmp("InputMove", this->BasicBlock->GetFunc()->GetFuncName()));
#endif

	if (DebugFlag) {
		SMP_msg("opcode: %d TypeCategory: %d\n", this->SMPcmd.itype, TypeCategory);
	}

	// If we are already finished with all types, return false.
	if (this->IsTypeInferenceComplete())
		return false;

	if (this->AllDEFsTyped() && this->AllUSEsTyped()) {
		this->SetTypeInferenceComplete();
		return false;
	}

	if (this->HasDestMemoryOperand()) {
		changed |= this->MDFindPointerUse(this->MDGetMemDefOp(), UseFP);
	}
	if (this->HasSourceMemoryOperand()) {
		changed |= this->MDFindPointerUse(this->MDGetMemUseOp(), UseFP);
	}

	// The control flow instructions can be handled simply based on their type
	//  and do not need an RTL walk.
	SMPitype DFAType = this->GetDataFlowType();
	bool CallInst = ((DFAType == CALL) || (DFAType == INDIR_CALL) || this->IsTailCall());
	ushort IndirCallReg = R_none;
	if (DebugFlag) {
		SMP_msg("DFAType: %d  CategoryInferenceComplete: %d\n",
			DFAType, this->IsCategoryInferenceComplete());
	}

	if (DFAType == INDIR_CALL) {
		op_t TargetOp = this->SMPcmd.Operands[0];
		if (TargetOp.type == o_reg)
			IndirCallReg = TargetOp.reg;
	}

	if (((DFAType >= JUMP) && (DFAType <= INDIR_CALL)) || this->IsTailCall()) {
		// All USEs are either the flags (NUMERIC) or the target address (CODEPTR).
		//  The exceptions are the USE list for interrupt calls, which includes
		//  the caller-saved regs, and indirect calls through a memory
		//  operand, such as call [ebx+esi+20h], where the memory operand
		//  is a CODEPTR but the addressing registers are a BaseReg and
		//  IndexReg as in any other memory addressing, and the saved
		//  regs on any call.
		CurrUse = this->GetFirstUse();
		while (CurrUse != this->GetLastUse()) {
			UseOp = CurrUse->GetOp();
			if (UseOp.is_reg(X86_FLAGS_REG))
				CurrUse = this->SetUseType(UseOp, NUMERIC);
			else if ((CurrUse->GetType() != CODEPTR)
				&& (!(this->MDIsInterruptCall() && (o_reg == UseOp.type)))
				&& (!(CallInst && (o_reg == UseOp.type)))
				&& (!(this->HasSourceMemoryOperand() 
					&& (INDIR_CALL == this->GetDataFlowType())
					&& (o_reg == UseOp.type)))) {
				CurrUse = this->SetUseType(UseOp, CODEPTR);
				if (CallInst && (DFAType != INDIR_CALL)) {
					// If the call is to malloc(), then the DEF of the return
					//  register is of type HEAPPTR.
					//  ****!!!!**** Could have INDIR_CALL resolved to malloc.
					changed |= this->MDFindMallocCall(UseOp);
				}
			}
			else if ((CurrUse->GetType() != CODEPTR) && CallInst
				&& UseOp.is_reg(IndirCallReg)) {

				CurrUse = this->SetUseType(UseOp, CODEPTR);
			}
			++CurrUse;
		}
		this->SetTypeInferenceComplete();
		return true;
	}

	// First, see if we can infer something about DEFs and USEs just from the 
	//  type category of the instruction.
	if (!this->IsCategoryInferenceComplete()) {
		bool MemPropagate = false;
		switch (TypeCategory) {
			case 0: // no inference possible just from type category
			case 1: // no inference possible just from type category
			case 3:  // MOV instructions; inference will come from source to dest in RTL walk.
			case 5:  // binary arithmetic; inference will come in RTL walk.
			case 10:  // binary arithmetic; inference will come in RTL walk.
			case 11:  // push and pop instructions; inference will come in RTL walk.
			case 12:  // exchange instructions; inference will come in RTL walk.
				this->SetCategoryInferenceComplete();
				break;

			case 2: // Result type is always NUMERIC.
			case 7: // Result type is always NUMERIC.
			case 8: // Result type is always NUMERIC.
			case 9: // Result type is always NUMERIC.
			case 13: // Result type is always NUMERIC.
			case 14: // Result type is always NUMERIC.  !!!!****!!!! scas should not be here, or don't reset POINTERs to NUMERICs
			case 15: // Result type is always NUMERIC.
				CurrDef = this->GetFirstDef();
				while (CurrDef != this->GetLastDef()) {
					if (!IsEqType(NUMERIC, CurrDef->GetType())) {
						DefOp = CurrDef->GetOp();
						SSANum = CurrDef->GetSSANum();
						CurrDef = this->SetDefType(DefOp, NUMERIC);
						changed = true;
						// Be conservative and only propagate register DEFs and SAFE stack locs. We
						//  can improve this in the future. **!!**
						bool IsMemOp = (o_reg != DefOp.type);
						bool MemPropagate = MDIsDirectStackAccessOpnd(DefOp, UseFP);
#if SMP_PROPAGATE_MEM_TYPES
						;
#else
						// Be conservative and only propagate register DEFs and SAFE stack locs.
						//  We can improve this in the future. **!!**
						MemPropagate = MemPropagate && SafeFunc;
#endif
						if ((o_reg == DefOp.type) || MemPropagate) {
							if (this->BasicBlock->IsLocalName(DefOp)) {
								(void) this->BasicBlock->PropagateLocalDefType(DefOp, NUMERIC,
									this->GetAddr(), SSANum, IsMemOp);
							}
							else { // global name
								this->BasicBlock->GetFunc()->ResetProcessedBlocks(); // set Processed to false
								(void) this->BasicBlock->PropagateGlobalDefType(DefOp, NUMERIC,
									SSANum, IsMemOp);
							}
						}
					}
					++CurrDef;
				}
				this->SetCategoryInferenceComplete();
				break;

			case 4: // Unary INC, DEC, etc.: dest=source, so type remains the same
				assert(1 == this->RTL.GetCount());
				assert(this->RTL.GetRT(0)->HasRightSubTree());
				UseOp = this->RTL.GetRT(0)->GetLeftOperand(); // USE == DEF
				CurrUse = this->Uses.FindRef(UseOp);
				assert(CurrUse != this->GetLastUse());
				if (UNINIT != CurrUse->GetType()) {
					// Only one USE, and it has a type assigned, so assign that type
					// to the DEF.
					CurrDef = this->GetFirstDef();
					while (CurrDef != this->GetLastDef()) {
						// Two DEFs: EFLAGS is NUMERIC, dest==source
						DefOp = CurrDef->GetOp();
						SSANum = CurrDef->GetSSANum();
						if (DefOp.is_reg(X86_FLAGS_REG)) {
							; // SetImmedTypes already made it NUMERIC
						}
						else {
							CurrDef = this->SetDefType(DefOp, CurrUse->GetType());
							// Be conservative and only propagate register DEFs and SAFE stack locs. We
							//  can improve this in the future. **!!**
							bool IsMemOp = (o_reg != DefOp.type);
							MemPropagate = MDIsDirectStackAccessOpnd(DefOp, UseFP);
#if SMP_PROPAGATE_MEM_TYPES
							;
#else
							// Be conservative and only propagate register DEFs and SAFE stack locs.
							//  We can improve this in the future. **!!**
							MemPropagate = MemPropagate && SafeFunc;
#endif
							if ((o_reg == DefOp.type) || MemPropagate) {
								if (this->BasicBlock->IsLocalName(DefOp)) {
									(void) this->BasicBlock->PropagateLocalDefType(DefOp, CurrUse->GetType(),
										this->GetAddr(), SSANum, IsMemOp);
								}
								else { // global name
									this->BasicBlock->GetFunc()->ResetProcessedBlocks(); // set Processed to false
									(void) this->BasicBlock->PropagateGlobalDefType(DefOp, CurrUse->GetType(),
										SSANum, IsMemOp);
								}
							}
						}
						++CurrDef;
					}
					this->SetCategoryInferenceComplete();
					changed = true;
					this->SetTypeInferenceComplete();
				}
				break;

			case 6: // Result is always POINTER
				DefOp = this->GetFirstDef()->GetOp();
				SSANum = this->GetFirstDef()->GetSSANum();
				CurrDef = this->SetDefType(DefOp, POINTER);
				this->SetCategoryInferenceComplete();
				changed = true;
				// Be conservative and only propagate register DEFs and SAFE stack locs. We
				//  can improve this in the future. **!!**
				IsMemOp = (o_reg != DefOp.type);
				MemPropagate = MDIsDirectStackAccessOpnd(DefOp, UseFP);
#if SMP_PROPAGATE_MEM_TYPES
				;
#else
				// Be conservative and only propagate register DEFs and SAFE stack locs.
				//  We can improve this in the future. **!!**
				MemPropagate = MemPropagate && SafeFunc;
#endif
				if ((o_reg == DefOp.type) || MemPropagate)  {
					if (this->BasicBlock->IsLocalName(DefOp)) {
						(void) this->BasicBlock->PropagateLocalDefType(DefOp, POINTER,
							this->GetAddr(), SSANum, IsMemOp);
					}
					else { // global name
						this->BasicBlock->GetFunc()->ResetProcessedBlocks(); // set Processed to false
						(void) this->BasicBlock->PropagateGlobalDefType(DefOp, POINTER,
							SSANum, IsMemOp);
					}
				}
				break;

			default:
				SMP_msg("ERROR: Unknown type category for %s\n", DisAsmText.GetDisAsm(this->GetAddr()));
				this->SetCategoryInferenceComplete();
				break;
		} // end switch on TypeCategory
	} // end if (!CategoryInference)

	// Walk the RTL and infer types based on operators and operands.
	if (DebugFlag) {
		SMP_msg("RTcount: %zu\n", this->RTL.GetCount());
	}
	for (size_t index = 0; index < this->RTL.GetCount(); ++index) {
		SMPRegTransfer *CurrRT = this->RTL.GetRT(index);
		if (SMP_NULL_OPERATOR == CurrRT->GetOperator()) // nothing to infer
			continue;
		if (!(CurrRT->IsTypeInferenceComplete())) {
			changed |= this->InferOperatorType(CurrRT);
		}
		if (DebugFlag) {
			SMP_msg("returned from InferOperatorType\n");
		}
	} // end for all RTs in the RTL
	return changed;
} // end of SMPInstr::InferTypes()

// Infer the type of an operator within an RT based on the types of its operands and
//  based on the operator itself. Recurse down the tree if necessary.
// Return true if the operator type of the RT is updated.
bool SMPInstr::InferOperatorType(SMPRegTransfer *CurrRT) {
	bool updated = false;
	bool LeftNumeric, RightNumeric, OperNumeric;
	bool LeftPointer, RightPointer, OperPointer;
	bool UseFP = this->BasicBlock->GetFunc()->UsesFramePointer();
	bool SafeFunc = this->BasicBlock->GetFunc()->IsSafe();
	set<DefOrUse, LessDefUse>::iterator CurrDef;
	set<DefOrUse, LessDefUse>::iterator CurrUse;
	set<DefOrUse, LessDefUse>::iterator LeftUse;
	set<DefOrUse, LessDefUse>::iterator RightUse;
	SMPOperandType LeftType = UNINIT;
	SMPOperandType RightType = UNINIT;
	SMPOperandType OperType = UNINIT;
	op_t UseOp = InitOp, DefOp = InitOp, LeftOp = InitOp, RightOp = InitOp;
	SMPoperator CurrOp = CurrRT->GetOperator();
	bool TypeInferenceFinished = false;
#if SMP_VERBOSE_DEBUG_INFER_TYPES
	bool DebugFlag = false;
#if 1
	DebugFlag |= (0 == strcmp("InputMove", this->BasicBlock->GetFunc()->GetFuncName()));
#endif
	DebugFlag = DebugFlag || ((this->address == 0x806453b) || (this->address == 0x806453e));
#endif

#if SMP_VERBOSE_DEBUG_INFER_TYPES
	if (DebugFlag) {
		SMP_msg("Entered InferOperatorType for CurrOp: %d at %x\n", CurrOp, this->GetAddr());
	}
#endif

	if (CurrRT->IsTypeInferenceComplete()) {
		return updated;
	}

	switch (CurrOp) {
		case SMP_NULL_OPERATOR:
		case SMP_SIGNAL: // signal or raise exception
			TypeInferenceFinished = true;
			break;

		case SMP_CALL:  // CALL instruction
			if (UNINIT == CurrRT->GetOperatorType()) {
				CurrRT->SetOperatorType(CODEPTR, this);
				updated = true;
				UseOp = CurrRT->GetRightOperand();
				CurrUse = this->Uses.FindRef(UseOp);
				assert(CurrUse != this->GetLastUse());
				if (UNINIT == CurrUse->GetType()) {
					CurrUse = this->SetUseType(UseOp, CODEPTR);
				}
				else if (CODEPTR != CurrUse->GetType()) {
					SMP_msg("WARNING: call target is type %d, setting to CODEPTR at %lx in %s\n",
						CurrUse->GetType(), (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
					CurrUse = this->SetUseType(UseOp, CODEPTR);
				}
			}
			TypeInferenceFinished = true;
			break;

		case SMP_INPUT:  // input from port
			if (UNINIT == CurrRT->GetOperatorType()) {
				CurrRT->SetOperatorType(NUMERIC, this);
				updated = true;
			}
			break;

		case SMP_OUTPUT: // output to port
			if (UNINIT == CurrRT->GetOperatorType()) {
				CurrRT->SetOperatorType(NUMERIC, this);
				updated = true;
			}
			break;

#if 0
		case SMP_SIGN_EXTEND:
		case SMP_ZERO_EXTEND:
			// Should we infer that all operands are NUMERIC?  !!!???!!!!
			if (UNINIT == CurrRT->GetOperatorType()) {
				CurrRT->SetOperatorType(NUMERIC, this);
				updated = true;
			}
			break;
#endif

		case SMP_ADDRESS_OF: // take effective address
			if (UNINIT == CurrRT->GetOperatorType()) {
				CurrRT->SetOperatorType(POINTER, this);
				// Left operand is having its address taken, but we cannot infer what its
				//  type is.
				updated = true;
			}
			break;

		case SMP_SIGN_EXTEND:
		case SMP_ZERO_EXTEND:
		case SMP_U_LEFT_SHIFT: // unsigned left shift
		case SMP_S_LEFT_SHIFT: // signed left shift
		case SMP_U_RIGHT_SHIFT: // unsigned right shift
		case SMP_S_RIGHT_SHIFT: // signed right shift
		case SMP_ROTATE_LEFT:
		case SMP_ROTATE_LEFT_CARRY: // rotate left through carry
		case SMP_ROTATE_RIGHT:
		case SMP_ROTATE_RIGHT_CARRY: // rotate right through carry
		case SMP_U_MULTIPLY:
		case SMP_S_MULTIPLY:
		case SMP_U_DIVIDE:
		case SMP_S_DIVIDE:
		case SMP_U_REMAINDER:
		case SMP_BITWISE_XOR:
		case SMP_BITWISE_AND_NOT:
		case SMP_S_COMPARE: // signed compare (subtraction-based)
		case SMP_U_COMPARE: // unsigned compare (AND-based)
		case SMP_GENERAL_COMPARE:
		case SMP_LESS_THAN: // boolean test operators
		case SMP_GREATER_THAN:
		case SMP_LESS_EQUAL:
		case SMP_GREATER_EQUAL:
		case SMP_EQUAL:
		case SMP_NOT_EQUAL:
		case SMP_LOGICAL_AND:
		case SMP_LOGICAL_OR:
		case SMP_UNARY_NUMERIC_OPERATION:  // miscellaneous; produces NUMERIC result
		case SMP_BINARY_NUMERIC_OPERATION:  // miscellaneous; produces NUMERIC result
		case SMP_SYSTEM_OPERATION:   // for instructions such as CPUID, RDTSC, etc.; NUMERIC
		case SMP_UNARY_FLOATING_ARITHMETIC:  // all the same to our type system; all NUMERIC
		case SMP_BINARY_FLOATING_ARITHMETIC:  // all the same to our type system; all NUMERIC
		case SMP_REVERSE_SHIFT_U:   // all the same to our type system; all NUMERIC
		case SMP_SHUFFLE:   // all the same to our type system; all NUMERIC
		case SMP_COMPARE_EQ_AND_SET: // Compare for equality and set fields to all 1's or all 0's
		case SMP_COMPARE_NE_AND_SET: // Compare for inequality and set fields to all 1's or all 0's
		case SMP_COMPARE_GT_AND_SET: // Compare for greater-than and set fields to all 1's or all 0's
		case SMP_COMPARE_GE_AND_SET: // Compare for greater-than-or-equal and set fields to all 1's or all 0's
		case SMP_COMPARE_LT_AND_SET: // Compare for less-than and set fields to all 1's or all 0's
		case SMP_COMPARE_LE_AND_SET: // Compare for less-than-or-equal and set fields to all 1's or all 0's
		case SMP_PACK_S:  // Pack operands into extended-precision register, signed saturation for loss of precision
		case SMP_PACK_U:  // Pack operands into extended-precision register, unsigned saturation for loss of precision
		case SMP_AVERAGE_U: // Average of unsigned operands
		case SMP_MULTIPLY_AND_ADD: // multiply and add (or multiply and accumulate)
		case SMP_SUM_OF_DIFFS: // sum over two vectors of absolute values of differences of their elements
		case SMP_MAX_S: // dest := signed_max(dest, src)
		case SMP_MAX_U: // dest := unsigned_max(dest, src)
		case SMP_MIN_S: // dest := signed_min(dest, src)
		case SMP_MIN_U: // dest := unsigned_min(dest, src)
		case SMP_ABSOLUTE_VALUE: // take absolute value
		case SMP_CONVERT_INT_TO_FP: // convert integer to floating point
		case SMP_CONVERT_FP_TO_INT: // convert floating point to integer
		case SMP_CREATE_MASK:  // Create AND-mask from operand and byte/word/dword position # in immediate
		case SMP_INTERLEAVE:  // interleave fields from two packed operands; NUMERIC
		case SMP_CONCATENATE:   // all the same to our type system; all NUMERIC
		case SMP_ENCRYPTION_OPERATION: // encryption or decryption bit manipulation operation
		case SMP_EXTRACT_ZERO_EXTEND: // Extract sub-reg and zero-extend to reg length
			if (UNINIT == CurrRT->GetOperatorType()) {
				CurrRT->SetOperatorType(NUMERIC, this);
				updated = true;
			}
			// Left operand should be NUMERIC if it exists.
			UseOp = CurrRT->GetLeftOperand();
			if (UseOp.type != o_void) {
				CurrUse = this->Uses.FindRef(UseOp);
				if (CurrUse == this->GetLastUse()) {
					SMP_msg("SERIOUS WARNING: Adding missing USE of ");
					PrintOperand(UseOp);
					SMP_msg(" at %lx in %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
					this->Uses.SetRef(UseOp, NUMERIC, -1);
					updated = true;
				}
				else if (UNINIT == CurrUse->GetType()) {
					CurrUse = this->SetUseType(UseOp, NUMERIC);
					updated = true;
				}
			}
			// Right operand should be NUMERIC if it exists.
			if (CurrRT->HasRightSubTree()) {
				// Recurse into subtree
#if SMP_AGGRESSIVE_TYPE_INFERENCE
				if (UNINIT == CurrRT->GetRightTree()->GetOperatorType()) {
					CurrRT->GetRightTree()->SetOperatorType(NUMERIC, this);
					updated = true;
				}
#endif
				updated |= this->InferOperatorType(CurrRT->GetRightTree());
			}
			else {
				UseOp = CurrRT->GetRightOperand();
				if (UseOp.type != o_void) {
					CurrUse = this->Uses.FindRef(UseOp);
					if (CurrUse == this->GetLastUse()) {
						SMP_msg("SERIOUS WARNING: Adding missing USE of ");
						PrintOperand(UseOp);
						SMP_msg(" at %lx in %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
						this->Uses.SetRef(UseOp, NUMERIC, -1);
						updated = true;
					}
					else if (UNINIT == CurrUse->GetType()) {
						CurrUse = this->SetUseType(UseOp, NUMERIC);
						updated = true;
					}
				}
			}
			break;

		case SMP_BITWISE_NOT: // unary operator
		case SMP_NEGATE:    // unary negation
			UseOp = CurrRT->GetLeftOperand();
			assert(o_void != UseOp.type);
			CurrUse = this->Uses.FindRef(UseOp);
			if (CurrUse == this->GetLastUse()) {
				SMP_msg("SERIOUS WARNING: Adding missing USE of ");
				PrintOperand(UseOp);
				SMP_msg(" at %lx in %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
				updated = true;
			}
			else {
				OperType = CurrRT->GetOperatorType();
				LeftType = CurrUse->GetType();
				// Only tricky cases are the negation of a POINTER or PTROFFSET.
				//  Negation of PTROFFSET could be inefficient code that computed
				//  PTR1 - PTR2 and later corrected it to PTR2 - PTR1 by negation.
				//  The type remains PTROFFSET. Negating a POINTER could be an unusual
				//  case similar to subtracting a POINTER from a NUMERIC. See comments
				//  in the SMP_ADD case below, and also the SMP_SUBTRACT case.
				if (LeftType == PTROFFSET) {
					// Override any prior operator type, in case PTROFFSET was inferred late
					//  in our analysis and the operator was set to NUMERIC.
					CurrRT->SetOperatorType(PTROFFSET, this);
					updated = true;
					if (CurrOp == SMP_BITWISE_NOT)
						SMP_msg("INFO: NOT of PTROFFSET at %lx %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
				}
				else if (IsDataPtr(LeftType)) {
					// Override any prior operator type, in case POINTER was inferred late
					//  in our analysis and the operator was set to NUMERIC.
					CurrRT->SetOperatorType(NEGATEDPTR, this);
					SMP_msg("INFO: Pointer negated at %lx %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
					updated = true;
				}
				else if (OperType == UNINIT) {
					// Default to NUMERIC for most negations.
					CurrRT->SetOperatorType(NUMERIC, this);
					// But, leave left operand type alone, in case an UNINIT operand
					//  might be determined later to be PTROFFSET or NEGATEDPTR.
					//  Leaving it alone causes us not to set TypeInferenceFinished to true
					//  at the end of this function in the UNINIT case.
					updated = true;
				}
			}
			break;

		case SMP_INCREMENT:
		case SMP_DECREMENT:
			// The type of the left operand is propagated to the operator, or vice
			//  versa, whichever receives a type first.
			assert(!CurrRT->HasRightSubTree());
			UseOp = CurrRT->GetLeftOperand();
			assert(o_void != UseOp.type);
			CurrUse = this->Uses.FindRef(UseOp);
			if (CurrUse == this->GetLastUse()) {
				SMP_msg("SERIOUS WARNING: Adding missing USE of ");
				PrintOperand(UseOp);
				SMP_msg(" at %lx in %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
				this->Uses.SetRef(UseOp);
				updated = true;
				break;
			}
			if (UNINIT == CurrRT->GetOperatorType()) {
				if (UNINIT != CurrUse->GetType()) {
					// Propagate operand type up to the operator.
					CurrRT->SetOperatorType(CurrUse->GetType(), this);
					updated = true;
				}
			}
			else if (UNINIT == CurrUse->GetType()) {
				// Propagate operator type to operand.
				CurrUse = this->SetUseType(UseOp, CurrRT->GetOperatorType());
				updated = true;
			}
			break;

		case SMP_ADD:
		case SMP_ADD_CARRY:   // add with carry
		case SMP_BITWISE_AND:
		case SMP_BITWISE_OR:
			// Extract the current types of right and left operands and the operator.
			OperType = CurrRT->GetOperatorType();
			LeftOp = CurrRT->GetLeftOperand();
			CurrUse = this->Uses.FindRef(LeftOp);
			assert(CurrUse != this->GetLastUse()); // found it
			LeftType = CurrUse->GetType();
			if (CurrRT->HasRightSubTree()) {
				updated |= this->InferOperatorType(CurrRT->GetRightTree());
				RightType = CurrRT->GetRightTree()->GetOperatorType();
			}
			else {
				RightOp = CurrRT->GetRightOperand();
				if (o_void == RightOp.type) {
					SMP_msg("ERROR: void operand at %lx in %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
					return updated;
				}
				else {
					CurrUse = this->Uses.FindRef(RightOp);
					if (CurrUse == this->GetLastUse()) {
						SMP_msg("SERIOUS WARNING: Adding missing USE of ");
						PrintOperand(RightOp);
						SMP_msg(" at %lx in %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
						this->Uses.SetRef(RightOp);
						updated = true;
						break;
					}
					else {
						RightType = CurrUse->GetType();
					}
				}
			}

			// We have to know both operand types to infer the operator, or know the
			//  operator type and one operand type to infer the other operand type.
			if ((UNINIT == OperType) 
				&& ((UNINIT == LeftType) || (UNINIT == RightType)))
				break;

			// If both operands are NUMERIC, operator and result are NUMERIC.
			// If one operand is NUMERIC and the other is a pointer type,
			//  then the ADD operator and the result will inherit this second type,
			//  while AND and OR operators will remain UNINIT (we don't know what
			//  type "ptr AND 0xfffffff8" has until we see how it is used).
			LeftNumeric = IsEqType(NUMERIC, LeftType);
			RightNumeric = IsEqType(NUMERIC, RightType);
			LeftPointer = IsDataPtr(LeftType);
			RightPointer = IsDataPtr(RightType);
			if (UNINIT == OperType) {
				// Infer operator type from left and right operands.
				if (LeftNumeric && RightNumeric) {
					CurrRT->SetOperatorType(NUMERIC, this);
					updated = true;
					break;
				}
				else if (LeftNumeric || RightNumeric) {
					// ADD of NUMERIC to non-NUMERIC preserves non-NUMERIC type.
					// AND and OR operations should leave the operator UNINIT for now.
					if (LeftNumeric && (UNINIT != RightType) 
						&& ((SMP_ADD == CurrOp) || (SMP_ADD_CARRY == CurrOp))) {
						CurrRT->SetOperatorType(RightType, this);
						updated = true;
						break;
					}
					else if (RightNumeric && (UNINIT != LeftType) 
						&& ((SMP_ADD == CurrOp) || (SMP_ADD_CARRY == CurrOp))) {
						CurrRT->SetOperatorType(LeftType, this);
						updated = true;
						break;
					}
				}
				else if (LeftPointer && RightPointer) {
					// Arithmetic on two pointers
					if ((SMP_ADD == CurrOp) || (SMP_ADD_CARRY == CurrOp)) {
						CurrRT->SetOperatorType(UNKNOWN, this);
						updated = true;
					}
					else { // bitwise AND or OR of two pointers
						SMP_msg("WARNING: hash of two pointers at %lx in %s\n",
							(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
						// hash operation? leave operator as UNINIT
					}
					break;
				}
				else if ((LeftPointer && IsEqType(RightType, PTROFFSET))
					|| (RightPointer && IsEqType(LeftType, PTROFFSET))) {
					// Arithmetic on PTR and PTROFFSET
					if ((SMP_ADD == CurrOp) || (SMP_ADD_CARRY == CurrOp)) {
						// We assume (A-B) is being added to B or vice versa **!!**
						CurrRT->SetOperatorType(POINTER, this);
						updated = true;
					}
					else { // bitwise AND or OR of pointer and pointer difference
						SMP_msg("WARNING: hash of PTROFFSET and POINTER at %lx in %s\n",
							(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
						// hash operation? leave operator as UNINIT
					}
					break;
				}
				else if ((LeftPointer && IsEqType(RightType, NEGATEDPTR))
					|| (RightPointer && IsEqType(LeftType, NEGATEDPTR))) {
					// Compiler optimizations can take a ptr expression such as:
					//  PTR1 - PTR2 + 1
					//  and hoist the loop-invariant subexpression " - PTR2 + 1"
					//  out of the loop as "1 - PTR2", which produces a NEGATEDPTR type.
					//  When PTR1 gets its value determined inside the loop, then the
					//  addition of PTR1 finally happens, producing a PTROFFSET type,
					//  which is what the whole expression is.
					if ((SMP_ADD == CurrOp) || (SMP_ADD_CARRY == CurrOp)) {
						CurrRT->SetOperatorType(PTROFFSET, this);
						updated = true;
					}
					else { // bitwise AND or OR of pointer and pointer difference
						SMP_msg("WARNING: hash of NEGATEDPTR and POINTER at %lx in %s\n",
							(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
						// hash operation? leave operator as UNINIT
					}
					break;
				}
			} // end if UNINIT operator type
			else { // operator has type other than UNINIT
				// We make add-with-carry and subtract-with-borrow exceptions
				//  to the type propagation. LeftOp could have POINTER type
				//  inferred later; these instructions can change the type of
				//  the register from POINTER to NUMERIC, unlike regular
				//  add and subtract opcodes.
				OperNumeric = IsEqType(NUMERIC, OperType);
				OperPointer = IsDataPtr(OperType);
				if (OperNumeric) {
					if ((UNINIT == LeftType)
						&& (SMP_ADD_CARRY != CurrOp)) {
						CurrUse = this->SetUseType(LeftOp, CurrRT->GetOperatorType());
						updated = true;
						assert(CurrUse != this->GetLastUse());
						break;
					}
					if (CurrRT->HasRightSubTree()) {
						// Must need to iterate through the right tree again, as the operator
						//  has been typed.
						if (UNINIT == RightType) {
							CurrRT->GetRightTree()->SetOperatorType(CurrRT->GetOperatorType(), this);
							updated = true;
							updated |= this->InferOperatorType(CurrRT->GetRightTree());
						}
						break;
					}
					else { // right operand; propagate operator type if needed
						if (UNINIT == RightType) {
							CurrUse = this->SetUseType(RightOp, CurrRT->GetOperatorType());
							updated = true;
							assert(CurrUse != this->GetLastUse());
							break;
						}
					}
				}
			}
			break;

		case SMP_SUBTRACT:
		case SMP_SUBTRACT_BORROW:  // subtract with borrow
			// Extract the current types of right and left operands and the operator.
			OperType = CurrRT->GetOperatorType();
			LeftOp = CurrRT->GetLeftOperand();
			LeftUse = this->Uses.FindRef(LeftOp);
			assert(LeftUse != this->GetLastUse()); // found it
			LeftType = LeftUse->GetType();
			if (CurrRT->HasRightSubTree()) {
				updated |= this->InferOperatorType(CurrRT->GetRightTree());
				RightType = CurrRT->GetRightTree()->GetOperatorType();
			}
			else {
				RightOp = CurrRT->GetRightOperand();
				if (o_void == RightOp.type) {
					SMP_msg("ERROR: void operand in %s\n", DisAsmText.GetDisAsm(this->GetAddr()));
					return false;
				}
				else {
					RightUse = this->Uses.FindRef(RightOp);
					if (RightUse == this->GetLastUse()) {
						SMP_msg("WARNING: Adding missing USE of ");
						PrintOperand(RightOp);
						SMP_msg(" in %s\n", DisAsmText.GetDisAsm(this->GetAddr()));
						this->Uses.SetRef(RightOp);
						updated = true;
						break;
					}
					else {
						RightType = RightUse->GetType();
					}
				}
			}
			// If left operand is NUMERIC, operator is NUMERIC.
			LeftNumeric = IsEqType(NUMERIC, LeftType);
			RightNumeric = IsEqType(NUMERIC, RightType);
			LeftPointer = IsDataPtr(LeftType);
			RightPointer = IsDataPtr(RightType);
			if (LeftNumeric) {
				// Subtracting anything from a NUMERIC leaves it NUMERIC or NEGATEDPTR,
				//  in the special case in which a POINTER is subtracted from a NUMERIC.
				//  See NEGATEDPTR comments in the ADD/AND operators case above.
				if (RightPointer) {
					CurrRT->SetOperatorType(NEGATEDPTR, this);
					updated = true;
				}
				else if (UNINIT == OperType) {
					CurrRT->SetOperatorType(NUMERIC, this);
					updated = true;
				}
				else if (IsNotEqType(NUMERIC, OperType) && IsNotEqType(NEGATEDPTR, OperType)) {
					SMP_msg("ERROR: SMP_SUBTRACT from NUMERIC should be NUMERIC or NEGATEDPTR operator.");
					SMP_msg(" Operator type is %d in: %s\n", OperType, DisAsmText.GetDisAsm(this->GetAddr()));
				}
#if 0
				if (!RightNumeric) {
					// Right operand is being used as a NUMERIC, so propagate NUMERIC to it.
					if (CurrRT->HasRightSubTree()) {
						CurrRT->GetRightTree()->SetOperatorType(NUMERIC, this);
					}
					else {
						RightUse = this->SetUseType(RightOp, NUMERIC);
					}
					updated = true;
				}
#endif
			} // end if LeftNumeric
			else if (LeftPointer) {
				if (UNINIT == OperType) {
					// If we subtract another pointer type, we produce PTROFFSET.
					if (RightPointer) {
						CurrRT->SetOperatorType(PTROFFSET, this);
						updated = true;
					}
					else if (RightType == PTROFFSET) {
						// We assume B - (B - A) == A    **!!**
						CurrRT->SetOperatorType(POINTER, this);
						SMP_msg("WARNING: PTR - PTROFFSET produces PTR at %lx in %s\n", 
							(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
						updated = true;
					}
					else if (RightNumeric) {
						// pointer minus NUMERIC keeps same pointer type
						CurrRT->SetOperatorType(LeftType, this);
						updated = true;
					}
				}
				else { // we have an operator type for the SMP_SUBTRACT
					OperNumeric = IsEqType(NUMERIC, OperType);
					OperPointer = IsDataPtr(OperType);
					if (CurrRT->HasRightSubTree()) {
						// Might need to iterate through the right tree again, if its operator
						//  can be typed.
						if (UNINIT == RightType) {
							if (OperPointer) {
								// PTR := PTR - ?? ==> ?? is NUMERIC  Why? ?? could be PTROFFSET
								CurrRT->GetRightTree()->SetOperatorType(NUMERIC, this);
								updated = true;
								updated |= this->InferOperatorType(CurrRT->GetRightTree());
							}
							else if (OperType == PTROFFSET) {
								// PTROFFSET := PTR - ?? ==> ?? is PTR
								CurrRT->GetRightTree()->SetOperatorType(LeftType, this);
								updated = true;
								updated |= this->InferOperatorType(CurrRT->GetRightTree());
							}
							else if (OperNumeric) {
								SMP_msg("WARNING: PTR - ?? produces NUMERIC at %lx in %s\n", 
									(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
							}
						}
						break;
					}
					else { // right operand; propagate operator type if needed
						if (UNINIT == RightType) {
							if (OperPointer) {
								// PTR := PTR - ?? ==> ?? is NUMERIC  Why? ?? could be PTROFFSET
								RightUse = this->SetUseType(RightOp, NUMERIC);
								updated = true;
								assert(RightUse != this->GetLastUse());
							}
							else if (OperType == PTROFFSET) {
								// PTROFFSET := PTR - ?? ==> ?? is PTR
								RightUse = this->SetUseType(RightOp, LeftType);
								updated = true;
							}
							else if (OperNumeric) {
								SMP_msg("WARNING: PTR - ?? produces NUMERIC at %lx in %s\n", 
									(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
							}
							break;
						}
					}
				} // end if OperType is UNINIT ... else ...
			} // end if LeftNumeric ... else if LeftPointer ...
			else if (UNINIT == LeftType) {
				// We make add-with-carry and subtract-with-borrow exceptions
				//  to the type propagation. LeftOp could have POINTER type
				//  inferred later; these instructions can change the type of
				//  the register from POINTER to NUMERIC, unlike regular
				//  add and subtract opcodes.
				if ((UNINIT != OperType)
					&& (SMP_SUBTRACT_BORROW != CurrOp)) {
					LeftUse = this->SetUseType(LeftOp, OperType);
					assert(LeftUse != this->GetLastUse());
					updated = true;
				}
			}
			break;

		case SMP_ASSIGN:
			// Extract the current types of right and left operands and SMP_ASSIGN operator.
			OperType = CurrRT->GetOperatorType();
			DefOp = CurrRT->GetLeftOperand();
			CurrDef = this->Defs.FindRef(DefOp);
			assert(CurrDef != this->GetLastDef()); // found it
			LeftType = CurrDef->GetType();
			if (CurrRT->HasRightSubTree()) {
				updated |= this->InferOperatorType(CurrRT->GetRightTree());
				RightType = CurrRT->GetRightTree()->GetOperatorType();
			}
			else {
				UseOp = CurrRT->GetRightOperand();
				if (o_void == UseOp.type) {
					SMP_msg("ERROR: void operand for SMP_ASSIGN in %s\n", DisAsmText.GetDisAsm(this->GetAddr()));
					return false;
				}
				else {
					CurrUse = this->Uses.FindRef(UseOp);
					if (CurrUse == this->GetLastUse()) {
						SMP_msg("WARNING: Adding missing USE of ");
						PrintOperand(UseOp);
						SMP_msg(" in %s\n", DisAsmText.GetDisAsm(this->GetAddr()));
						this->Uses.SetRef(UseOp);
						updated = true;
						break;
					}
					else {
						RightType = CurrUse->GetType();
					}
				}
			}

#if SMP_VERBOSE_DEBUG_INFER_TYPES
			if (DebugFlag) {
				SMP_msg("%x LeftType: %d OperatorType: %d RightType: %d\n", this->address, LeftType,
					OperType, RightType);
			}
#endif
			if ((UNINIT == RightType) && (UNINIT == LeftType)) {
				unsigned short TempSignMask;
				if (this->MDIsReducedWidthMove() && (!this->MDIsSignedLoad(TempSignMask))) {
					CurrDef = this->SetDefType(DefOp, NUMERIC); // e.g. mov al,cl cannot be a POINTER
					updated = true;
					if (!CurrRT->HasRightSubTree()) {
						CurrUse = this->SetUseType(UseOp, NUMERIC);
					}
					assert(UNINIT == OperType);
					CurrRT->SetOperatorType(NUMERIC, this);
				}
				break;
			}
			else if (UNINIT == OperType) {
				// UNINIT SMP_ASSIGN operator, but either LeftType or RightType is not UNINIT.
				bool UpdatedOperType = false;
				if (UNINIT != RightType) {
					// We have to special case conditional moves. Only if both operands
					//  (the source and the prior value of the potential destination,
					//  which was added to the USE set by BuildMoveRTL()) agree in type
					//  can we propagate their common type to the operator and ultimately
					//  to the DEF.
					if ((!this->MDIsConditionalMoveInstr()) || this->Uses.TypesAgreeNoFlags()) {
						CurrRT->SetOperatorType(RightType, this);
						updated = true;
						OperType = RightType;
						UpdatedOperType = true;
					}
				}
				else { // LeftType must not be UNINIT
					CurrRT->SetOperatorType(LeftType, this);
					updated = true;
					UpdatedOperType = true;
					OperType = LeftType;
				}
				// Speed up type propagation by passing the RightType/OperType to the Def
				//  on this iteration.
				if (UpdatedOperType) {
					// Propagate the new DEF type unless it is an indirect memory access.
					//  Future: Propagate until re-DEF of addressing register terminates
					//  the propagation. **!!**
					CurrDef = this->SetDefType(DefOp, OperType);
					LeftType = OperType;
					if (!MDIsIndirectMemoryOpnd(DefOp, this->BasicBlock->GetFunc()->UsesFramePointer())) {
						bool IsMemOp = (o_reg != DefOp.type);
						bool MemPropagate = MDIsStackAccessOpnd(DefOp, UseFP);
#if SMP_PROPAGATE_MEM_TYPES
						;
#else
						// Be conservative and only propagate register DEFs and SAFE stack locs.
						//  We can improve this in the future. **!!**
						MemPropagate = MemPropagate && SafeFunc;
#endif
						if ((o_reg == DefOp.type) || MemPropagate) {
							int SSANum = CurrDef->GetSSANum();
							if (this->BasicBlock->IsLocalName(DefOp)) {
								(void) this->BasicBlock->PropagateLocalDefType(DefOp, LeftType,
									this->GetAddr(), SSANum, IsMemOp);
							}
							else { // global name
								this->BasicBlock->GetFunc()->ResetProcessedBlocks(); // set Processed to false
								(void) this->BasicBlock->PropagateGlobalDefType(DefOp, LeftType,
									SSANum, IsMemOp);
							}
						}
					}
				}
				break;
			}
			else if (UNINIT == LeftType) {
				// SMP_ASSIGN operator has type, so propagate it.
				CurrDef = this->SetDefType(DefOp, OperType);
				LeftType = OperType;
				updated = true;
				// Propagate the new DEF type unless it is an indirect memory access.
				//  Future: Propagate until re-DEF of addressing register terminates
				//  the propagation. **!!**
				if (!MDIsIndirectMemoryOpnd(DefOp, this->BasicBlock->GetFunc()->UsesFramePointer())) {
					bool IsMemOp = (o_reg != DefOp.type);
					bool MemPropagate = MDIsStackAccessOpnd(DefOp, UseFP);
#if SMP_PROPAGATE_MEM_TYPES
					;
#else
					// Be conservative and only propagate register DEFs and SAFE stack locs.
					//  We can improve this in the future. **!!**
					MemPropagate = MemPropagate && SafeFunc;
#endif
					if ((o_reg == DefOp.type) || MemPropagate) {
						int SSANum = CurrDef->GetSSANum();
						if (this->BasicBlock->IsLocalName(DefOp)) {
							(void) this->BasicBlock->PropagateLocalDefType(DefOp, LeftType,
								this->GetAddr(), SSANum, IsMemOp);
						}
						else { // global name
							this->BasicBlock->GetFunc()->ResetProcessedBlocks(); // set Processed to false
							(void) this->BasicBlock->PropagateGlobalDefType(DefOp, LeftType,
								SSANum, IsMemOp);
						}
					}
				}
				break;
			}
			else if (UNINIT == RightType) {
				// SMP_ASSIGN operator has type, so propagate it.
				if (CurrRT->HasRightSubTree()) {
					CurrRT->GetRightTree()->SetOperatorType(OperType, this);
					updated = true;
					updated |= this->InferOperatorType(CurrRT->GetRightTree());
				}
				else {
					// For conditional moves, propagate to the pseudo-USE of the
					//  destination register as well as the source operand.
					if (this->MDIsConditionalMoveInstr()) {
						CurrUse = this->FindUse(DefOp);
						assert(CurrUse != this->GetLastUse());
						if (UNINIT == CurrUse->GetType())
							CurrUse = this->SetUseType(DefOp, OperType);
						else if (OperType != CurrUse->GetType()) {
							SMP_msg("WARNING: Avoiding lattice oscillation from type %d to %d at %lx for: ",
								CurrUse->GetType(), OperType, (unsigned long) this->address);
							PrintOperand(CurrUse->GetOp());
							SMP_msg("\n");
						}
					}
					CurrUse = this->SetUseType(UseOp, OperType);
					updated = true;
					RightType = OperType;
				}
				break;
			}
			break;

		default:
			SMP_msg("ERROR: Unknown operator %d at %lx in %s\n", 
				CurrOp, (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
			break;
	} // end switch on operator

	// Determine if type inference is finished for this register transfer.
	if (updated && (!TypeInferenceFinished)) {
		bool FinishedRight = false;
		bool FinishedLeft = false;
		bool FinishedOperator = (CurrRT->GetOperatorType() != UNINIT);
		if (FinishedOperator) {
			switch (CurrOp) {
				case SMP_INPUT:  // input from port
				case SMP_OUTPUT: // output to port
				case SMP_SIGN_EXTEND:
				case SMP_ZERO_EXTEND:
				case SMP_ADDRESS_OF: // take effective address
				case SMP_SYSTEM_OPERATION:   // for instructions such as CPUID, RDTSC, etc.; NUMERIC
				case SMP_BITWISE_NOT: // unary operator
				case SMP_NEGATE:    // unary negation
				case SMP_DECREMENT:
				case SMP_INCREMENT:
				case SMP_UNARY_NUMERIC_OPERATION:  // miscellaneous; produces NUMERIC result
				case SMP_UNARY_FLOATING_ARITHMETIC:  // all the same to our type system; all NUMERIC
					// Unary operators have no right operand.
					FinishedRight = true;
					break;

				default: // All binary operators come here
					if (CurrRT->HasRightSubTree()) {
						FinishedRight = CurrRT->GetRightTree()->IsTypeInferenceComplete();
					}
					else {
						UseOp = CurrRT->GetRightOperand();
						if (UseOp.type != o_void) {
							CurrUse = this->Uses.FindRef(UseOp);
							assert(CurrUse != this->GetLastUse());
							FinishedRight = (CurrUse->GetType() != UNINIT);
						}
						else { // if o_void, no further type inference on it is possible.
							FinishedRight = true;
						}
					}
					break;
			} // end switch on CurrOp
			if (FinishedRight) { // no point checking left op if right op is not finished
				DefOp = CurrRT->GetLeftOperand();
				if (DefOp.type != o_void) {
					if (SMP_ASSIGN == CurrOp) {
						CurrDef = this->Defs.FindRef(DefOp);
						assert(CurrDef != this->GetLastDef());
						FinishedLeft = (CurrDef->GetType() != UNINIT);
					}
					else { // not ASSIGN, so really a UseOp not DefOp
						CurrUse = this->Uses.FindRef(DefOp);
						assert(CurrUse != this->GetLastUse());
						FinishedLeft = (CurrUse->GetType() != UNINIT);
					}
				}
				else { // if o_void, no further type inference on it is possible.
					FinishedLeft = true;
				}
			}
			TypeInferenceFinished = (FinishedLeft && FinishedRight);
		} // end if (FinishedOperator)
	} // end if (updated && (!TypeInferenceFinished))
	if (TypeInferenceFinished) {
		CurrRT->SetTypeInferenceComplete();
	}
	return updated;
} // end of SMPInstr::InferOperatorType()

// Transfer function: Does operator propagate signedness of its operands to its result?
bool SMPInstr::DoesOperatorTransferSign(SMPoperator CurrOp) {
	bool transfer = false;

	switch (CurrOp) {
		case SMP_NULL_OPERATOR:
		case SMP_CALL:  // CALL instruction
		case SMP_INPUT:  // input from port
		case SMP_OUTPUT: // output to port
		case SMP_SYSTEM_OPERATION:   // for instructions such as CPUID, RDTSC, etc.; NUMERIC
		case SMP_SIGNAL: // signal or raise exception
			// No concept of signedness for some operators
			break;

		case SMP_ADDRESS_OF: // take effective address
		case SMP_U_LEFT_SHIFT: // unsigned left shift
		case SMP_U_RIGHT_SHIFT: // unsigned right shift
		case SMP_ROTATE_LEFT:
		case SMP_ROTATE_LEFT_CARRY: // rotate left through carry
		case SMP_ROTATE_RIGHT:
		case SMP_ROTATE_RIGHT_CARRY: // rotate right through carry
		case SMP_U_MULTIPLY:
		case SMP_U_DIVIDE:
		case SMP_U_REMAINDER:
		case SMP_ZERO_EXTEND:
		case SMP_BITWISE_NOT: // unary operator
		case SMP_BITWISE_XOR:
		case SMP_BITWISE_AND_NOT:
		case SMP_S_COMPARE: // signed compare (subtraction-based)
		case SMP_U_COMPARE: // unsigned compare (AND-based)
		case SMP_GENERAL_COMPARE:
		case SMP_S_LEFT_SHIFT: // signed left shift
		case SMP_S_RIGHT_SHIFT: // signed right shift
		case SMP_S_MULTIPLY:
		case SMP_S_DIVIDE:
		case SMP_SIGN_EXTEND:
		case SMP_NEGATE:    // unary negation
		case SMP_LESS_THAN: // boolean test operators
		case SMP_GREATER_THAN:
		case SMP_LESS_EQUAL:
		case SMP_GREATER_EQUAL:
		case SMP_ENCRYPTION_OPERATION: // encryption or decryption bit manipulation operation
		case SMP_EXTRACT_ZERO_EXTEND: // Extract sub-reg and zero-extend to reg length
			// Inherently unsigned and signed operators force the signedness
			//  of their results, rather than propagating the signedness of
			//  their operands.
			break;

		case SMP_DECREMENT:
		case SMP_INCREMENT:
		case SMP_ADD:
		case SMP_ADD_CARRY:   // add with carry
		case SMP_SUBTRACT:
		case SMP_SUBTRACT_BORROW:  // subtract with borrow
		case SMP_ASSIGN:
		case SMP_BITWISE_AND:
		case SMP_BITWISE_OR:
		case SMP_EQUAL:
		case SMP_NOT_EQUAL:
		case SMP_LOGICAL_AND:
		case SMP_LOGICAL_OR:
		case SMP_UNARY_NUMERIC_OPERATION:  // miscellaneous; produces NUMERIC result
		case SMP_BINARY_NUMERIC_OPERATION:  // miscellaneous; produces NUMERIC result
			transfer = true;
			break;

		case SMP_UNARY_FLOATING_ARITHMETIC:  // all the same to our type system; all NUMERIC
		case SMP_BINARY_FLOATING_ARITHMETIC:  // all the same to our type system; all NUMERIC
		case SMP_REVERSE_SHIFT_U: // Shift right operand by bit count in left operand
		case SMP_SHUFFLE: // Shuffle bytes, words, etc. within destination operation per source mask
		case SMP_COMPARE_EQ_AND_SET: // Compare for equality and set fields to all 1's or all 0's
		case SMP_COMPARE_NE_AND_SET: // Compare for inequality and set fields to all 1's or all 0's
		case SMP_COMPARE_GT_AND_SET: // Compare for greater-than and set fields to all 1's or all 0's
		case SMP_COMPARE_GE_AND_SET: // Compare for greater-than-or-equal and set fields to all 1's or all 0's
		case SMP_COMPARE_LT_AND_SET: // Compare for less-than and set fields to all 1's or all 0's
		case SMP_COMPARE_LE_AND_SET: // Compare for less-than-or-equal and set fields to all 1's or all 0's
		case SMP_PACK_S:  // Pack operands into extended-precision register, signed saturation for loss of precision
		case SMP_PACK_U:  // Pack operands into extended-precision register, unsigned saturation for loss of precision
		case SMP_AVERAGE_U: // Average of unsigned operands
		case SMP_MULTIPLY_AND_ADD: // multiply and add (or multiply and accumulate)
		case SMP_SUM_OF_DIFFS: // sum over two vectors of absolute values of differences of their elements
		case SMP_MAX_S: // dest := signed_max(dest, src)
		case SMP_MAX_U: // dest := unsigned_max(dest, src)
		case SMP_MIN_S: // dest := signed_min(dest, src)
		case SMP_MIN_U: // dest := unsigned_min(dest, src)
		case SMP_ABSOLUTE_VALUE: // take absolute value
		case SMP_CONVERT_INT_TO_FP: // convert integer to floating point
		case SMP_CONVERT_FP_TO_INT: // convert floating point to integer
		case SMP_CREATE_MASK: // Create AND-mask from operand and byte/word/dword position # in immediate
		case SMP_INTERLEAVE: // extended-precision interleaving of bytes or words or dwords etc.; NUMERIC
		case SMP_CONCATENATE:     // extended-precision concatenation; NUMERIC
			transfer = true;
			break;

		default:
			SMP_msg("ERROR: Unknown operator in %s\n", DisAsmText.GetDisAsm(this->GetAddr()));
			break;
	} // end switch on operator

	return transfer;
} // end of SMPInstr::DoesOperatorTransferSign()

// Adjust signedness based on SSA def-use info.
void SMPInstr::MDFixupSignedness(void) {
	set<DefOrUse, LessDefUse>::iterator DefIter = this->GetFirstNonFlagsDef();
	set<DefOrUse, LessDefUse>::iterator UseIter;
	unsigned short SignMask;
	op_t DefOp = InitOp;
	int DefSSANum;
	int IdiomCode;
	bool UnderflowOpcode = this->MDIsUnderflowingOpcode();
	bool UseFP = this->GetBlock()->GetFunc()->UsesFramePointer();

	if (DefIter != this->GetLastDef()) {
		DefOp = DefIter->GetOp();
		DefSSANum = DefIter->GetSSANum();
	}

	int TypeGroup = SMPTypeCategory[this->SMPcmd.itype];
	if (this->IsNop())
		TypeGroup = 1; // no-op idioms need their category reset
	if (5 == TypeGroup) {
		this->SetAddSubSourceType();
	}

	if (this->MDIsSignedLoad(SignMask)) {
		// Compilers can generate zero-extensions just to clear unused bits in a register.
		//  We can wrongly infer UNSIGNED for the DEF as a result. The problem can be detected
		//  by seeing whether the zeroed-out bits are ever used. If all USEs of this register DEF
		//  only use the same number of bits as the source operand for the move, then the
		//  zero-extension bits do not mean anything, so we reset the signedness to unknown.
		//  This will hopefully not conflict with other sources of an UNSIGNED inference that
		//  could also have occurred (e.g. a MEDS type of POINTER is unlikely to occur with a 
		//  zero-extended operand).
		if (SignMask == FG_MASK_UNSIGNED) {
			op_t MoveSource = this->GetMoveSource();
			size_t SourceBitWidth = 8 * GetOpDataSize(MoveSource);
			assert(DefIter != this->GetLastDef());
			if (!(IsMemOperand(DefOp) || MDIsFlagsReg(DefOp))) {
				CanonicalizeOpnd(DefOp);
				int DefHashValue = HashGlobalNameAndSSA(DefOp, DefSSANum);
				struct FineGrainedInfo DefUseFGInfo;
				bool LocalName = this->BasicBlock->IsLocalName(DefOp);
				if (LocalName) {
					DefUseFGInfo = this->BasicBlock->GetUseFGInfo(DefHashValue);
				}
				else {
					DefUseFGInfo = this->BasicBlock->GetFunc()->GetUseFGInfo(DefHashValue);
				}
				size_t DefUseMaxBitWidth = LargestBitWidthFromMask(DefUseFGInfo.SizeInfo);
				if ((DefUseMaxBitWidth <= SourceBitWidth) && (0 != DefUseMaxBitWidth)) {
					// We never use more bits than the original source had before it was zero-extended.
					//  We exclude the bitwidth==0 special case that signals that it was only used in
					//  a zero-extension or sign-extension move.
					if (LocalName) {
						this->BasicBlock->ClearDefSignedness(DefHashValue);
					}
					else {
						this->BasicBlock->GetFunc()->ClearDefSignedness(DefHashValue);
					}
				}
			}
		}
	}

	// Second case: Subtraction of two values, each of which is just a condition code.
	//  This can happen in optimized code that tests for which of two condition codes
	//  has been set, e.g.:
	//  [arithmetic operation or comparison]
	//  seta al  ; if "above" flag then al := 1 else al := 0
	//  setb bl  ; if "below" flag then bl := 1 else bl := 0
	//  mov ecx,eax  ; make copy of eax (including al) into ecx
	//  sub al,bl ; al := al - bl
	//  The resulting value in al will be 1 if the above flag was set, -1 if below, 0 if neither.
	//  We see the seta/setb as implying unsigned values, which is true, but if al becomes -1
	//   we do not want to consider this to be an underflow.
	//  The same logic applies to overflow opcodes: lea edx,[eax+eax-1] is hard to classify as
	//   potential underflow or overflow. If eax comes from a condition code (seta eax), the values
	//   will be small and no overflow check is needed.
	int UseSSANum;
	bool BenignUnderflow = false;
	if (UnderflowOpcode && MDIsDataFlowOpnd(DefOp, UseFP)) {
		UseIter = this->FindUse(DefOp); // DEF is also USE in subtraction
		assert(UseIter != this->GetLastUse());
		UseSSANum = UseIter->GetSSANum();
		if (this->IsOpSourceConditionCode(DefOp, UseSSANum)) {
			// If we had a decrement opcode, we are done, and underflow is benign.
			if (this->MDIsDecrement()) {
				BenignUnderflow = true;
			}
			else { // For subtraction, need to see if BOTH operands came from condition codes (flags).
				op_t UseOp = this->GetUseOnlyAddSubOp();
				if (MDIsDataFlowOpnd(UseOp, UseFP)) {
					CanonicalizeOpnd(UseOp);
					UseIter = this->FindUse(UseOp);
					assert(UseIter != this->GetLastUse());
					UseSSANum = UseIter->GetSSANum();
					BenignUnderflow = this->IsOpSourceConditionCode(UseOp, UseSSANum);
				}
			}
		}
		if (BenignUnderflow) {
			// We detected a subtraction or decrement that is permitted to produce a negative
			//  result. This means that the DEF is really SIGNED. We don't want to emit
			//  any underflow checks on this instruction, and we also want to propagate SIGNED
			//  as the type of DEF.
			this->SetSuppressNumericAnnotation();
			SignMask = FG_MASK_SIGNED;
			struct FineGrainedInfo NewFG;
			NewFG.SignMiscInfo = SignMask;
			NewFG.SizeInfo = 0;
			// Note that old FG info should be null at this point in FG inference,
			//  so we only have to pass in the SIGNED bits.
			bool MapsChanged = this->UpdateDefOpFGInfo(DefOp, NewFG);
		}
	} // end if Underflow on register

	if (this->MDIsDefiniteBenignUnderflowOpcode(IdiomCode) || this->MDIsSignBitFill()) {
		// We have a pattern that changes sign, e.g. sbb edx,edx puts
		//  0 or -1 in edx; likewise for sar edx,31. This needs no annotation.
		this->SetSuppressNumericAnnotation();
		// Furthermore, if we find add edx,positive_immediate_value
		//  in the SSA chain for this instruction, then we don't want
		//  to get false positives from the addition, which often changes
		//  the temporarily SIGNED value back to its original UNSIGNED:
		//   sbb edx,edx ; if edx is UNSIGNED, false positive when we produce -1.
		//   add edx,2   ; another false positive when we convert (0 or -1) to (1 or 2).
		this->GetBlock()->SuppressAnnotOnSignChangingAddition(DefOp, DefSSANum, this->GetAddr());
	}

	return;
} // end of SMPInstr::MDFixupSignedness()

// Initial inferences (if any) about FG info of operand based solely on the RTL operator type above it in RTL.
bool SMPInstr::InitFGInfoFromOperator(SMPoperator CurrOp, struct FineGrainedInfo &InitFG) {
	bool changed = false;

	switch (CurrOp) {
		case SMP_NULL_OPERATOR:
			break;

		case SMP_CALL:  // CALL instruction
			InitFG.SignMiscInfo |= FG_MASK_UNSIGNED; // target address is unsigned 32-bit
			InitFG.SizeInfo |= (MD_NORMAL_BITWIDTH_MASK | FG_MASK_CODEPOINTER);
			changed = true;
			break;

		case SMP_INPUT:  // input from port
		case SMP_OUTPUT: // output to port
		case SMP_ADDRESS_OF: // take effective address
		case SMP_U_COMPARE: // unsigned compare (AND-based)
		case SMP_S_COMPARE: // signed compare (subtraction-based)
		case SMP_GENERAL_COMPARE:
			// NOTE: The AND-based and subtraction-based comparisons are used
			//  on lots of operands of all types, and the conditional jump that
			//  follows determines signedness, not the operator.
			break;

		case SMP_U_LEFT_SHIFT: // unsigned left shift
#if STARS_NO_SHIFT_SIGNEDNESS_IN_SCALEFACTOR
			if (!this->MDIsLoadEffectiveAddressInstr()) {
				// The left shift in the RTL for lea edx,[ebx+eax*4]
				//  does not imply that EAX is UNSIGNED. For other
				//  unsigned left shift RTLs, UNSIGNED is fine.
				InitFG.SignMiscInfo |= FG_MASK_UNSIGNED;
				changed = true;
			}
			break;
#endif
		case SMP_U_RIGHT_SHIFT: // unsigned right shift
		case SMP_ROTATE_LEFT:
		case SMP_ROTATE_LEFT_CARRY: // rotate left through carry
		case SMP_ROTATE_RIGHT:
		case SMP_ROTATE_RIGHT_CARRY: // rotate right through carry
		case SMP_U_MULTIPLY:
		case SMP_U_DIVIDE:
		case SMP_U_REMAINDER:
		case SMP_ZERO_EXTEND:
		case SMP_BITWISE_NOT: // unary operator
		case SMP_BITWISE_XOR:
		case SMP_BITWISE_AND_NOT:
			InitFG.SignMiscInfo |= FG_MASK_UNSIGNED;
			changed = true;
			break;

		case SMP_S_LEFT_SHIFT: // signed left shift
		case SMP_S_RIGHT_SHIFT: // signed right shift
		case SMP_S_MULTIPLY:
		case SMP_S_DIVIDE:
		case SMP_SIGN_EXTEND:
		case SMP_NEGATE:    // unary negation
		case SMP_LESS_THAN: // boolean test operators
		case SMP_GREATER_THAN:
		case SMP_LESS_EQUAL:
		case SMP_GREATER_EQUAL:
			// Special case: If signed multiply operator, it might sometimes
			//  be used for unsigned operands when upper bits of the result
			//  are discarded, because there is no difference in the result bits
			//  between unsigned and signed multiplication when only the lower
			//  N bits are retained and the upper N bits are discarded.
			if ((SMP_S_MULTIPLY == CurrOp) && (!(this->MDIsSignedArithmetic()))) {
				break;
			}
			InitFG.SignMiscInfo |= FG_MASK_SIGNED;
			changed = true;
			break;

		case SMP_DECREMENT:
		case SMP_INCREMENT:
		case SMP_ADD:
		case SMP_ADD_CARRY:   // add with carry
		case SMP_SUBTRACT:
		case SMP_SUBTRACT_BORROW:  // subtract with borrow
		case SMP_ASSIGN:
		case SMP_BITWISE_AND:
		case SMP_BITWISE_OR:
		case SMP_EQUAL:
		case SMP_NOT_EQUAL:
		case SMP_LOGICAL_AND:
		case SMP_LOGICAL_OR:
		case SMP_UNARY_NUMERIC_OPERATION:  // miscellaneous; produces NUMERIC result
		case SMP_BINARY_NUMERIC_OPERATION:  // miscellaneous; produces NUMERIC result
		case SMP_SYSTEM_OPERATION:   // for instructions such as CPUID, RDTSC, etc.; NUMERIC
		case SMP_SHUFFLE: // Shuffle bytes, words, etc. within destination operation per source mask
		case SMP_CREATE_MASK: // Create AND-mask from operand and byte/word/dword position # in immediate
		case SMP_SIGNAL:  // signal or raise exception
			break;

		case SMP_UNARY_FLOATING_ARITHMETIC:  // all the same to our type system; all NUMERIC
		case SMP_BINARY_FLOATING_ARITHMETIC:  // all the same to our type system; all NUMERIC
			InitFG.SignMiscInfo |= FG_MASK_SIGNED;
			InitFG.SizeInfo |= FG_MASK_FLOAT_MMX;
			changed = true;
			break;

		case SMP_REVERSE_SHIFT_U: // Shift right operand by bit count in left operand
		case SMP_COMPARE_EQ_AND_SET: // Compare for equality and set fields to all 1's or all 0's
		case SMP_COMPARE_NE_AND_SET: // Compare for inequality and set fields to all 1's or all 0's
		case SMP_COMPARE_GT_AND_SET: // Compare for greater-than and set fields to all 1's or all 0's
		case SMP_COMPARE_GE_AND_SET: // Compare for greater-than-or-equal and set fields to all 1's or all 0's
		case SMP_COMPARE_LT_AND_SET: // Compare for less-than and set fields to all 1's or all 0's
		case SMP_COMPARE_LE_AND_SET: // Compare for less-than-or-equal and set fields to all 1's or all 0's
		case SMP_PACK_S:  // Pack operands into extended-precision register, signed saturation for loss of precision
		case SMP_MAX_S: // dest := signed_max(dest, src)
		case SMP_MIN_S: // dest := signed_min(dest, src)
		case SMP_ABSOLUTE_VALUE: // take absolute value
		case SMP_CONVERT_INT_TO_FP: // convert integer to floating point
		case SMP_CONVERT_FP_TO_INT: // convert floating point to integer
			InitFG.SignMiscInfo |= FG_MASK_SIGNED;
			InitFG.SizeInfo |= (FG_MASK_FLOAT_MMX | FG_MASK_BITWIDTH_128);
			changed = true;
			break;

		case SMP_PACK_U:  // Pack operands into extended-precision register, unsigned saturation for loss of precision
		case SMP_AVERAGE_U: // Average of unsigned operands
		case SMP_MULTIPLY_AND_ADD: // multiply and add (or multiply and accumulate)
		case SMP_SUM_OF_DIFFS: // sum over two vectors of absolute values of differences of their elements
		case SMP_MAX_U: // dest := unsigned_max(dest, src)
		case SMP_MIN_U: // dest := unsigned_min(dest, src)
		case SMP_ENCRYPTION_OPERATION: // encryption or decryption bit manipulation operation
		case SMP_EXTRACT_ZERO_EXTEND: // Extract sub-reg and zero-extend to reg length
			InitFG.SignMiscInfo |= FG_MASK_UNSIGNED;
			InitFG.SizeInfo |= (FG_MASK_FLOAT_MMX | FG_MASK_BITWIDTH_128);
			changed = true;
			break;

		case SMP_INTERLEAVE: // extended-precision interleaving of bytes or words or dwords etc.; NUMERIC
		case SMP_CONCATENATE:     // extended-precision concatenation; NUMERIC
			InitFG.SignMiscInfo |= FG_MASK_SIGNED;
			InitFG.SizeInfo |= (FG_MASK_FLOAT_MMX | FG_MASK_BITWIDTH_128);
			changed = true;
			break;

		default:
			SMP_msg("ERROR: Unknown operator in %s\n", DisAsmText.GetDisAsm(this->GetAddr()));
			break;
	} // end switch on operator

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

// Helper to take USE operand, find its SSANum, and return its UseHashValue.
int SMPInstr::GetUseOpHashAndSSA(op_t UseOp, int &SSANum) {
	op_t SearchOp = UseOp;
	CanonicalizeOpnd(SearchOp);
	set<DefOrUse, LessDefUse>::iterator UseIter = this->FindUse(SearchOp);
	assert(UseIter != this->GetLastUse());
	SSANum = UseIter->GetSSANum();
	int UseHashValue = HashGlobalNameAndSSA(SearchOp, SSANum);
	return UseHashValue;
} // end of SMPInstr::GetUseOpHashAndSSA()

// Helper to take DEF operand, find its SSANum, and return its DefHashValue.
int SMPInstr::GetDefOpHashAndSSA(op_t DefOp, int &SSANum) {
	op_t SearchOp = DefOp;
	CanonicalizeOpnd(SearchOp);
	set<DefOrUse, LessDefUse>::iterator DefIter = this->FindDef(SearchOp);
	assert(DefIter != this->GetLastDef());
	SSANum = DefIter->GetSSANum();
	int DefHashValue = HashGlobalNameAndSSA(SearchOp, SSANum);
	return DefHashValue;
} // end of SMPInstr::GetDefOpHashAndSSA()

// helper for InferOperatorFGInfo() to update DEF maps, return true if changed maps
bool SMPInstr::UpdateDefOpFGInfo(op_t DefOp, struct FineGrainedInfo NewFG) {
	bool MapsChanged = false; // Changes to maps of name/SSA to FG info?
	set<DefOrUse, LessDefUse>::iterator DefIter;
	int SSANum;
	int DefHashValue;
	op_t SearchOp;
	bool LocalName;
	struct FineGrainedInfo OldFG, UnionFG;

	if (o_reg == DefOp.type) {
		// If operator is inherently signed, then we will have 
		//  a sign bit set in NewFG from InitFGInfoFromOperator().
		DefHashValue = this->GetDefOpHashAndSSA(DefOp, SSANum);
		LocalName = this->BasicBlock->IsLocalName(DefOp);
		if (LocalName) {
			// Get old FG info from block level.
			OldFG = this->BasicBlock->GetDefFGInfo(DefHashValue);
		}
		else { // global name
			// Get old FG info from function level.
			OldFG = this->BasicBlock->GetFunc()->GetDefFGInfo(DefHashValue);
		}

		// Get rid of stack access bits being passed around in InferOperatorFGInfo()
		//  for register operands in RTLs.
		NewFG.SignMiscInfo &= FG_MASK_SIGNEDNESS_BITS;

		UnionFG.SignMiscInfo = OldFG.SignMiscInfo | NewFG.SignMiscInfo;
		UnionFG.SizeInfo = OldFG.SizeInfo | NewFG.SizeInfo;
		if ((OldFG.SignMiscInfo != UnionFG.SignMiscInfo) || (OldFG.SizeInfo != UnionFG.SizeInfo)) {
			// The signs they are a-changin' (or the sizes).
			MapsChanged = true;
			if (LocalName)
				this->BasicBlock->UpdateDefFGInfo(DefHashValue, UnionFG);
			else
				this->BasicBlock->GetFunc()->UpdateDefFGInfo(DefHashValue, UnionFG);
		}
	}
	else if (MDIsDirectStackAccessOpnd(DefOp, this->GetBlock()->GetFunc()->UsesFramePointer())) {
		ea_t InstAddr = this->GetAddr();
		MapsChanged = this->GetBlock()->GetFunc()->MDUpdateFGStackLocInfo(InstAddr, DefOp, NewFG);
	}

	return MapsChanged;
} // end of SMPInstr::UpdateDefOpFGInfo()

// helper for InferOperatorFGInfo() to update USE maps, return true if changed maps
bool SMPInstr::UpdateUseOpFGInfo(op_t UseOp, struct FineGrainedInfo NewFG) {
	bool MapsChanged = false; // Changes to maps of name/SSA to FG info?
	int SSANum;
	int UseHashValue;
	bool LocalName;
	struct FineGrainedInfo OldFG, UnionFG;

	if (o_reg == UseOp.type) {
		// If operator is inherently signed, then we will have 
		//  a sign bit set in NewFG from InitFGInfoFromOperator().
		UseHashValue = this->GetUseOpHashAndSSA(UseOp, SSANum);
		LocalName = this->BasicBlock->IsLocalName(UseOp);
		if (LocalName) {
			// Get old FG info from block level.
			OldFG = this->BasicBlock->GetUseFGInfo(UseHashValue);
		}
		else { // global name
			// Get old FG info from function level.
			OldFG = this->BasicBlock->GetFunc()->GetUseFGInfo(UseHashValue);
		}

		// Get rid of stack access bits being passed around in InferOperatorFGInfo()
		//  for register operands in RTLs.
		NewFG.SignMiscInfo &= FG_MASK_SIGNEDNESS_BITS;

		UnionFG.SignMiscInfo = OldFG.SignMiscInfo | NewFG.SignMiscInfo;
		UnionFG.SizeInfo = OldFG.SizeInfo | NewFG.SizeInfo;
		if ((OldFG.SignMiscInfo != UnionFG.SignMiscInfo) || (OldFG.SizeInfo != UnionFG.SizeInfo)) {
			// The signs they are a-changin'.
			MapsChanged = true;
			if (LocalName)
				this->BasicBlock->UpdateUseFGInfo(UseHashValue, UnionFG);
			else
				this->BasicBlock->GetFunc()->UpdateUseFGInfo(UseHashValue, UnionFG);
		}
	}
	else if (MDIsDirectStackAccessOpnd(UseOp, this->GetBlock()->GetFunc()->UsesFramePointer())) {
		ea_t InstAddr = this->GetAddr();
		MapsChanged = this->GetBlock()->GetFunc()->MDUpdateFGStackLocInfo(InstAddr, UseOp, NewFG);
	}

	return MapsChanged;
} // end of SMPInstr::UpdateUseOpFGInfo()

// Helper to fetch DEF signedness info for UseOp that has none.
unsigned short SMPInstr::GetDefSignInfoFromUseOp(op_t UseOp) {
	int SSANum, UseHashValue;
	bool LocalName;

	UseHashValue = this->GetUseOpHashAndSSA(UseOp, SSANum);
	LocalName = this->BasicBlock->IsLocalName(UseOp);
	if (LocalName) {
		// Get old sign info from block level.
		return this->BasicBlock->GetDefSignMiscInfo(UseHashValue);
	}
	else { // global name
		// Get old sign info from function level.
		return this->BasicBlock->GetFunc()->GetDefSignMiscInfo(UseHashValue);
	}
} // end of SMPInstr::GetDefSignInfoFromUseOp()

// infer FG info, + width on FirstIter; pass out FG info for op subtree, return true if change made to any FG info map.
bool SMPInstr::InferOperatorFGInfo(SMPRegTransfer *CurrRT, bool FirstIter, struct FineGrainedInfo &OpFG) {
	bool MapsChanged = false; // Changes to maps of name/SSA to FG info?
	bool NewChange = false;  // Bit changes from InitFGInfoFromOperator() ?
	SMPoperator CurrOp = CurrRT->GetOperator();
	struct FineGrainedInfo LeftFG, OldLeftFG;
	struct FineGrainedInfo RightFG, OldRightFG;
	op_t LeftOp, RightOp;
	unsigned short WidthMask, SignMask;
	bool CurrOpTransfersSign = this->DoesOperatorTransferSign(CurrOp);
	bool SpecialTransferCase = false;
	bool UseFP = this->BasicBlock->GetFunc()->UsesFramePointer();
	bool success;
	int DefHashValue, UseHashValue, SSANum;

#if SMP_AGGRESSIVE_SIGN_TRANSFER
	// Special case: If signed multiply operator, it might sometimes
	//  be used for unsigned operands when upper bits of the result
	//  are discarded, because there is no difference in the result bits
	//  between unsigned and signed multiplication when only the lower
	//  N bits are retained and the upper N bits are discarded.
	// As a result, InitFGInfoFromOperator() did not set FG_MASK_SIGNED
	//  for the result of the multiplication. If we now detect that two
	//  unsigned operands are being multiplied together using the "signed"
	//  multiply operator, we need to transfer UNSIGNED to the result.
	if ((SMP_S_MULTIPLY == CurrOp) && (!(this->MDIsSignedArithmetic()))) {
		SpecialTransferCase = true;
	}
#endif

	// Recurse to the right first, so we can do a depth-first accumulation of FG info.
	RightFG.SignMiscInfo = 0;
	RightFG.SizeInfo = 0;
	if (CurrRT->HasRightSubTree()) {
		if (FirstIter) { // Get width as well as signedness
			NewChange = this->InitFGInfoFromOperator(CurrOp, RightFG);
		} // end if (FirstIter)
		MapsChanged |= this->InferOperatorFGInfo(CurrRT->GetRightTree(), FirstIter, RightFG);
	}
	else {
		RightOp = CurrRT->GetRightOperand();
		if (RightOp.type == o_imm) {
			// If immediate operand is a data address or code address, we can infer that it is unsigned.
			uval_t ImmVal = RightOp.value;
			if (IsImmedGlobalAddress((ea_t) ImmVal)) {
				// Data address (type GLOBALPTR)
				RightFG.SignMiscInfo |= FG_MASK_UNSIGNED;
			}
			else if (this->MDIsInterruptCall() || IsImmedCodeAddress((ea_t) ImmVal)) {
				// Code address (type GLOBALPTR)
				RightFG.SignMiscInfo |= FG_MASK_UNSIGNED;
			}
		}
		else if ((RightOp.type == o_reg) && !RightOp.is_reg(MD_INSTRUCTION_POINTER_REG)) {
			if (FirstIter) { // Get width as well as signedness
				NewChange = this->InitFGInfoFromOperator(CurrOp, RightFG);
				WidthMask = ComputeOperandBitWidthMask(RightOp, 0);
				RightFG.SizeInfo |= WidthMask;
			} // end if (FirstIter)
#if SMP_AGGRESSIVE_SIGN_TRANSFER
			else {
				// On all iterations other than 1st, see if USE has FG info.
				UseHashValue = this->GetUseOpHashAndSSA(RightOp, SSANum);
				if (this->BasicBlock->IsLocalName(RightOp)) {
					// Get FG info from block.
					RightFG = this->BasicBlock->GetUseFGInfo(UseHashValue);
				}
				else {
					// Get FG info from function level.
					RightFG = this->BasicBlock->GetFunc()->GetUseFGInfo(UseHashValue);
				}
			}
#endif
			// Propagate signedness on all iterations.
			// If operator is inherently signed, then we will have 
			//  a sign bit set in RightFG from InitFGInfoFromOperator().
			if ((RightFG.SignMiscInfo == 0) && (CurrOpTransfersSign || SpecialTransferCase)) {
				// We have a USE with no sign info. See if we
				//  can get sign info from the DEF of this USE so we can
				//  transfer it up the RTL tree. 
				RightFG.SignMiscInfo = 
					(FG_MASK_SIGNEDNESS_BITS & (this->GetDefSignInfoFromUseOp(RightOp)));
			}
			if ((RightFG.SignMiscInfo != 0) || (RightFG.SizeInfo != 0))
				MapsChanged |= this->UpdateUseOpFGInfo(RightOp, RightFG);
		} // end if (RightOP is o_reg)
		else if (MDIsDirectStackAccessOpnd(RightOp, UseFP)) {
			// We used to assume that all FG info transfers from stack locations to
			//  the target registers of stack loads happened in SMPInstr::MDSetWidthSignInfo(),
			//  in an early pass that needed no iteration. The FG info was loaded from the
			//  StackFGInfo that was computed in SMPFunction::FindOutgoingArgsSize() based solely
			//  on whether the load was sign-extended or zero-extended. Of course, many stack
			//  locations have neither kind of signed/unsigned load. So, if we see a store to
			//  a stack location with no signedness, we transfer the signedness of the RightFG
			//  to the stack location FGInfo in the code below that processes the LeftOp.
			//  As a result, we now have a need to examine regular loads from the stack to
			//  see if there is signedness info for the stack location.
			success = this->BasicBlock->GetFunc()->MDGetFGStackLocInfo(this->address, RightOp, RightFG);
			if (success) {
				SignMask = (RightFG.SignMiscInfo & FG_MASK_SIGNEDNESS_BITS);
				RightFG.SizeInfo = 0; // only want to transfer signedness
			}
		}
	} // end if (right subtree) else right operand

	LeftFG.SignMiscInfo = 0;
	LeftFG.SizeInfo = 0;
	LeftOp = CurrRT->GetLeftOperand();
	bool OpIsDEF = (SMP_ASSIGN == CurrOp);
	// Skip control-flow assignments to the instruction pointer register.
	if ((LeftOp.type == o_reg) && !LeftOp.is_reg(MD_INSTRUCTION_POINTER_REG)) {
		if (FirstIter) { // Get width as well as signedness
			NewChange = this->InitFGInfoFromOperator(CurrOp, LeftFG);
			// Special case: For sign-extended and zero-extended loads,
			//  we don't know whether the DEF will always be USEd as
			//  the smaller or larger size. For example, we could
			//  zero-extend a 16-bit stack location into a 32-bit register
			//  just because the compiler always loads unsigned shorts
			//  that way, but we might never use it as a 32-bit value.
			//  So there is no truncation if we store only 16 bits later.
			//  By setting the target of an extended load to zero width,
			//  we signal that we want the maximum USE width to determine
			//  whether the store is truncated (see EmitIntegerErrorAnnotations).
			WidthMask = ComputeOperandBitWidthMask(LeftOp, 0);
			if (OpIsDEF) {
				if (this->MDIsSignedLoad(SignMask)) {
					WidthMask = 0;
				}
				// DEF inherits sign from right hand side.
				LeftFG.SignMiscInfo |= RightFG.SignMiscInfo; 
			}
			else if ((LeftFG.SignMiscInfo == 0) && (CurrOpTransfersSign || SpecialTransferCase)) {
				// We have a USE, not a DEF, with no sign info. See if we
				//  can get sign info from the DEF of this USE so we can
				//  transfer it up the RTL tree. 
				LeftFG.SignMiscInfo = 
					(FG_MASK_SIGNEDNESS_BITS & (this->GetDefSignInfoFromUseOp(LeftOp)));
			}

			LeftFG.SizeInfo |= WidthMask;
			if ((LeftFG.SignMiscInfo != 0) || (LeftFG.SizeInfo != 0)) {
				// Either NewChanged or CurrOpTransfersSign or SpecialTransferCase is true or we set WidthMask above.
				//  See if we would change the FG map entry.
				if (OpIsDEF) { // Need DEF map info
					MapsChanged |= this->UpdateDefOpFGInfo(LeftOp, LeftFG);
				}
				else { // need USE map info
					MapsChanged |= this->UpdateUseOpFGInfo(LeftOp, LeftFG);
				}
			} // end if non-zero LeftFG info
		} // end if (FirstIter)
#if SMP_AGGRESSIVE_SIGN_TRANSFER
		else {
			// On all iterations other than 1st, see if LeftOp has FG info.
			if (!OpIsDEF) { // LeftOp is a USE
				UseHashValue = this->GetUseOpHashAndSSA(LeftOp, SSANum);
				if (this->BasicBlock->IsLocalName(LeftOp)) {
					// Get FG info from block.
					LeftFG = this->BasicBlock->GetUseFGInfo(UseHashValue);
				}
				else {
					// Get FG info from function level.
					LeftFG = this->BasicBlock->GetFunc()->GetUseFGInfo(UseHashValue);
				}
			}
			else { // LeftOp is a DEF
				DefHashValue = this->GetDefOpHashAndSSA(LeftOp, SSANum);
				if (this->BasicBlock->IsLocalName(LeftOp)) {
					// Get FG info from block.
					LeftFG = this->BasicBlock->GetDefFGInfo(DefHashValue);
				}
				else {
					// Get FG info from function level.
					LeftFG = this->BasicBlock->GetFunc()->GetDefFGInfo(DefHashValue);
				}
				// See if RightFG has sign info to transfer to LeftFG.
				SignMask = (RightFG.SignMiscInfo & FG_MASK_SIGNEDNESS_BITS);
				unsigned short LeftSignMask = (LeftFG.SignMiscInfo & FG_MASK_SIGNEDNESS_BITS);
				bool UpdateLeftSignMask = ((SignMask != 0) && (SignMask != LeftSignMask));
#if 1
				if (OpIsDEF && (0 != LeftSignMask)) {
					// We have a signedness value for the DEF operand. These values are
					//  highly reliable, e.g. MEDS type inference detects that the DEF is
					//  a POINTER and therefore it must be UNSIGNED, or the opcode always
					//  produces a SIGNED result, etc. We do not want to produce a mixed
					//  signedness DEF in these cases, regardless of what happens when
					//  we examine operands in the RTLs, because compiler code generation
					//  can produce screwy results that are less reliable than our early
					//  determinations of DEF signedness (e.g. compilers can zero-extend
					//  bytes even though they are signed, and hand-code assembly authors
					//  can sign-extend bytes that are unsigned and get away with it 
					//  because the values are always very small and have a sign bit of zero.)
					UpdateLeftSignMask = false;
				}
#endif
				if (UpdateLeftSignMask) {
					// SignMask from RightFG has bits that will change LeftFG.SignMiscInfo.
					LeftFG.SignMiscInfo |= SignMask;
					MapsChanged |= this->UpdateDefOpFGInfo(LeftOp, LeftFG);
				}
			}
		}
#endif
	} // end of register case for LeftOp
	else if (OpIsDEF && MDIsDirectStackAccessOpnd(LeftOp, UseFP) 
		&& (!this->BasicBlock->GetFunc()->IsInOutgoingArgsRegion(LeftOp))) {
		// For stores into the stack, if the operand being stored has signedness
		//  and the stack location has no signedness, then we have a case where
		//  none of the loads from the stack location were signed, so it is
		//  safe to infer signedness of the stack location based on what is being
		//  stored into it, as no store signedness will conflict with load signedness.
		success = this->BasicBlock->GetFunc()->MDGetFGStackLocInfo(this->address, LeftOp, LeftFG);
		assert(success);
		if (0 == (LeftFG.SignMiscInfo & FG_MASK_SIGNEDNESS_BITS)) {
			// No previous signedness info for the stack location.
			//  Get signedness info from RightFG.
			SignMask = (RightFG.SignMiscInfo & FG_MASK_SIGNEDNESS_BITS);
			if ((0 != SignMask) && (FG_MASK_INCONSISTENT_SIGN != SignMask)) {
				// Operand being stored has signedness.
				//  Transfer the signedness to the stack location.
				struct FineGrainedInfo TempFG;
				TempFG.SignMiscInfo = SignMask;
				TempFG.SizeInfo = 0; // just update signedness
				success = this->BasicBlock->GetFunc()->MDUpdateFGStackLocInfo(this->address, LeftOp, TempFG);
				MapsChanged |= success;
			}
		}
	}

	// Prepare to return FG info for operator. First, OR the left and right FG infos.
	if (NewChange || MapsChanged || CurrOpTransfersSign || SpecialTransferCase) {
		OpFG.SignMiscInfo |= LeftFG.SignMiscInfo;
		OpFG.SizeInfo |= LeftFG.SizeInfo;
		OpFG.SignMiscInfo |= RightFG.SignMiscInfo;
		OpFG.SizeInfo |= RightFG.SizeInfo;
	}
	// An operator could override the width or signedness info of its operands.
	if (CurrOp == SMP_ADDRESS_OF) {
		// Result is 32-bit data pointer.
		OpFG.SizeInfo &= (~FG_MASK_BITWIDTH_FIELDS); // clear all width bits
		OpFG.SizeInfo |= (FG_MASK_BITWIDTH_32 | FG_MASK_DATAPOINTER);
		OpFG.SignMiscInfo &= (~FG_MASK_SIGNED);
		OpFG.SignMiscInfo |= FG_MASK_UNSIGNED;
	}

	return MapsChanged;
} // end of SMPInstr::InferOperatorFGInfo()


// infer width on first pass, signedness on all passes
bool SMPInstr::InferFGInfo(unsigned short IterCount) {
	bool MapsChanged = false; // Changes to maps of name/SSA to FG info?
	struct FineGrainedInfo OpFG;
	SMPitype DFType = this->GetDataFlowType();

	assert(0 < IterCount); // start IterCount at 1, not 0.


	if (DFType != DEFAULT) {
		// We have a control flow instruction, e.g. call, return, branch, jump
		//  No data operands unless these instructions are indirect through a register,
		//  and the indirect operand is a memory operand in that case, e.g. [eax].
		return MapsChanged;
	}

	if (1 == IterCount) {
		// Fix signedness info now that complete SSA chains have been analyzed.
		this->MDFixupSignedness();
	}

	for (size_t index = 0; index < this->RTL.GetCount(); ++index) {
		SMPRegTransfer *CurrRT = this->RTL.GetRT(index);
		if (SMP_NULL_OPERATOR == CurrRT->GetOperator()) // nothing to infer
			continue;
		OpFG.SignMiscInfo = 0;
		OpFG.SizeInfo = 0;

		MapsChanged |= this->InferOperatorFGInfo(CurrRT, (1 == IterCount), OpFG);
		if (SMP_CALL == CurrRT->GetOperator()) // no LeftOp DEF
			continue;
	} // end for all RTs in the RTL

	return MapsChanged;
} // end of SMPInstr::InferFGInfo()

// Get the meet of the metadata types of all non-flags DEFs.
SMPMetadataType SMPInstr::GetDefMetadataType(void) {
	SMPMetadataType MeetType = DEF_METADATA_UNANALYZED;
	set<DefOrUse, LessDefUse>::iterator CurrDef;

	for (CurrDef = this->GetFirstDef(); CurrDef != this->GetLastDef(); ++CurrDef) {
		SMPMetadataType CurrType;
		op_t DefOp = CurrDef->GetOp();
		if (DefOp.is_reg(X86_FLAGS_REG))
			continue; // flags are always unused metadata; irrelevant
		CurrType = CurrDef->GetMetadataStatus();
		if (MeetType == CurrType)
			continue; // no meet operation to perform
		// Any time we find USED metadata, that overrides all other types.
		if (CurrType == DEF_METADATA_USED)
			return CurrType;
		if (MeetType == DEF_METADATA_UNANALYZED)
			MeetType = CurrType;
		else if (MeetType < DEF_METADATA_REDUNDANT) {
			// Conflict between types of different DEFs. It could be that
			//  a multiply or divide instruction DEFs EAX and EDX, and one
			//  of them is used in a store and the other is unused. In that
			//  case, the final MeetType is USED and we can return. Or, if
			//  one type is UNUSED and the other is REDUNDANT, we can set
			//  the final type to the REDUNDANT type and return. The USED case
			//  is handled above, so we must have the UNUSED vs. REDUNDANT case.
			assert(CurrType >= DEF_METADATA_REDUNDANT);
			MeetType = CurrType;
		}
		else { // MeetType REDUNDANT, not equal to CurrType.
			if (CurrType >= DEF_METADATA_REDUNDANT) {
				// One type is profile derived, both are REDUNDANT.
				MeetType = DEF_METADATA_PROF_REDUNDANT;
			}
			else {
				assert(DEF_METADATA_UNUSED == CurrType);
				// leave MeetType as REDUNDANT
			}
		}
	} // end for all DEFs

	return MeetType;
} // end of SMPInstr::GetDefMetadataType()

// Are numeric values from a system call trusted input, so that all numeric errors
//  derived from the returned values shouold be treated as benign?
bool SMPInstr::IsNumericTrustedSystemCall(void) {
	bool TrustedCall = false;
	if ((BADADDR != this->CallTarget) && (!this->IsCallUsedAsJump())) {
		// We have a resolved call target address, either via direct or indirect call.
		string FuncName = this->GetTrimmedCalledFunctionName();
		TrustedCall = IsNumericSafeSystemCall(FuncName);
	}

	return TrustedCall;
} // end of SMPInstr::IsNumericTrustedSystemCall()

// Handle x86 opcode SIB byte annotations.
void SMPInstr::MDAnnotateSIBStackConstants(FILE *AnnotFile, op_t Opnd, ea_t offset, bool UseFP) {
	int BaseReg;
	int IndexReg;
	ea_t displacement;
	ushort ScaleFactor;
	char *disasm = DisAsmText.GetDisAsm(this->GetAddr());
	int SignedOffset = (int) offset;

	MDExtractAddressFields(Opnd, BaseReg, IndexReg, ScaleFactor, displacement);

	if (BaseReg == MD_STACK_POINTER_REG) { // ESP cannot be IndexReg
		// ESP-relative constant offset
		SMP_fprintf(AnnotFile,
				"%10lx %6d PTRIMMEDESP STACK %d displ %s\n",
				(unsigned long) this->SMPcmd.ea, this->SMPcmd.size, SignedOffset, disasm);
	}
	else if (UseFP && ((IndexReg == MD_FRAME_POINTER_REG) || (BaseReg == MD_FRAME_POINTER_REG))) {
		// EBP-relative constant offset
		SMP_fprintf(AnnotFile,
				"%10lx %6d PTRIMMEDEBP STACK %d displ %s\n",
				(unsigned long) this->SMPcmd.ea, this->SMPcmd.size, SignedOffset, disasm);
	}

	return;
} // end of MDAnnotateSIBStackConstants

// Emit annotations for constants used as ptr offsets from EBP or
//  ESP into the stack frame. Only pay attention to EBP-relative
//  offsets if EBP is being used as a frame pointer (UseFP == true).
void SMPInstr::AnnotateStackConstants(bool UseFP, FILE *AnnotFile) {
	op_t Opnd;
	ea_t offset;
	int BaseReg;
	int IndexReg;
	ushort ScaleFactor;
	char *disasm = DisAsmText.GetDisAsm(this->GetAddr());
	int SignedOffset;

#if 0
	if (this->address == 0x80925f4) {
		SMP_msg("PROBLEM INSTRUCTION: \n");
		this->PrintOperands();
	}
#endif
	for (int i = 0; i < UA_MAXOP; ++i) {
		Opnd = this->SMPcmd.Operands[i];
		if ((Opnd.type == o_displ) || (Opnd.type == o_phrase))
			MDExtractAddressFields(Opnd, BaseReg, IndexReg, ScaleFactor, offset);
		SignedOffset = (int) offset;

		if (Opnd.type == o_displ) {
			if (Opnd.hasSIB) {
				MDAnnotateSIBStackConstants(AnnotFile, Opnd, offset, UseFP);
			}
			else { // no SIB
				if (BaseReg == MD_STACK_POINTER_REG) {
					// ESP-relative constant offset
					SMP_fprintf(AnnotFile,
							"%10lx %6d PTRIMMEDESP STACK %d displ %s\n",
							(unsigned long) this->SMPcmd.ea, this->SMPcmd.size, SignedOffset, disasm);
				}
				else if (UseFP && (BaseReg == MD_FRAME_POINTER_REG)) {
					// EBP-relative constant offset
					SMP_fprintf(AnnotFile,
							"%10lx %6d PTRIMMEDEBP STACK %d displ %s\n",
							(unsigned long) this->SMPcmd.ea, this->SMPcmd.size, SignedOffset, disasm);
				}
			} // end if (Opnd.hasSIB) ... else ...
		} // end if (Opnd.type == o_displ) 
		else if (Opnd.type == o_phrase) {
			offset = 0; // mmStrata thinks [esp] is [esp+0]
			if (Opnd.hasSIB) {
				MDAnnotateSIBStackConstants(AnnotFile, Opnd, offset, UseFP);
			}
			else { // Something like [ecx]; is it [esp] or [ebp] ?
				if (BaseReg == MD_STACK_POINTER_REG) {
					// ESP-relative constant offset
					SMP_fprintf(AnnotFile,
							"%10lx %6d PTRIMMEDESP STACK %d displ %s\n",
							(unsigned long) this->SMPcmd.ea, this->SMPcmd.size, SignedOffset, disasm);
				}
				else if (UseFP && (BaseReg == MD_FRAME_POINTER_REG)) {
					// EBP-relative constant offset
					SMP_fprintf(AnnotFile,
							"%10lx %6d PTRIMMEDEBP STACK %d displ %s\n",
							(unsigned long) this->SMPcmd.ea, this->SMPcmd.size, SignedOffset, disasm);
				}
			} // end if (Opnd.hasSIB) ... else ...
		} // end else if (Opnd.type == o_phrase)
	} // end for all operands

	// If we move a stack pointer or frame pointer into another register, we
	//  need to annotate the implicit zero offset, e.g. mov edi,esp == mov edi,esp+0
	//  and edi is becoming a stack pointer that mmStrata needs to track.
	if (this->MDIsStackPointerCopy(UseFP)) {
		// Two possibilities: a move of the stack pointer, or an "lea"
		//  opcode, e.g. lea eax,[eap+8] ==> eax:=esp+8. In the move
		//  instruction (e.g. mov eax,esp), we have the implicit zero
		//  offset from the stack pointer register, but in the lea case,
		//  we might have zero or some other offset (lea eax,[esp] has
		//  the implicit zero).
		int ESPoffset = 0;
		if (NN_lea == this->SMPcmd.itype) {
			ESPoffset = this->MDGetImmedUse();
		}
		// NOTE: Looks like this next line should be "else" because an lea instruction
		//  looks like it has a memory operand, hence it has already been handled above.
		//  We are getting duplicate annotations for lea instructions.
		else {
			if (UseFP && this->GetFirstUse()->GetOp().is_reg(MD_FRAME_POINTER_REG)) {
				SMP_fprintf(AnnotFile,	"%10lx %6d PTRIMMEDEBP STACK %d displ %s\n",
						(unsigned long) this->SMPcmd.ea, this->SMPcmd.size, ESPoffset, disasm);
			}
			else {
				SMP_fprintf(AnnotFile,	"%10lx %6d PTRIMMEDESP STACK %d displ %s\n",
						(unsigned long) this->SMPcmd.ea, this->SMPcmd.size, ESPoffset, disasm);
			}
		}
	}

	return;
} // end of SMPInstr::AnnotateStackConstants()

// Emit all annotations for the instruction in the absence of RTL type inference.
void SMPInstr::EmitAnnotations(bool UseFP, bool AllocSeen, bool NeedsFrame, FILE *AnnotFile, FILE *InfoAnnotFile) {
	ea_t addr = this->address;
	flags_t InstrFlags = getFlags(addr);
	bool MemDest = this->HasDestMemoryOperand();
	bool MemSrc = this->HasSourceMemoryOperand();
	bool SecondSrcOperandImmNum = this->IsSecondSrcOperandNumeric(InstrFlags); 	// assumes 2nd source is Imm or not-numeric?!
	bool NoWarnFlag = false; // NOWARN annotation emitted?
	char *disasm = DisAsmText.GetDisAsm(this->GetAddr());

#if SMP_CHILDACCESS_ALL_CODE
	bool OrphanCode = (NULL == this->BasicBlock);
	ProfilerInformation *ProfInfo = NULL;
	if (!OrphanCode)
		ProfInfo = this->BasicBlock->GetFunc()->GetProg()->GetProfInfo();
#endif

	++OptCount[OptType]; // keep count for debugging info

#if SMP_ANNOTATE_ALL_MEMORY_OPERANDS
	// Emit informational annotations for memory operands.
	if (MemSrc) {
		op_t MemSrcOp = this->MDGetMemUseOp();
		size_t SrcBitWidth = 8 * GetOpDataSize(MemSrcOp);
		op_t AnnotDefOp = MemSrcOp;
		// Need to unnormalize stack memory DEFs and USEs before printing annotations.
		this->MDGetUnnormalizedOp(AnnotDefOp);
		SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR MEMSRC %d", (unsigned long) addr, this->SMPcmd.size, SrcBitWidth);
		AnnotPrintOperand(AnnotDefOp, InfoAnnotFile);
		SMP_fprintf(InfoAnnotFile, " ZZ %s \n", disasm);
	}
	if (MemDest) {
		op_t MemDestOp = this->MDGetMemDefOp();
		size_t DestBitWidth = 8 * GetOpDataSize(MemDestOp);
		op_t AnnotDefOp = MemDestOp;
		// Need to unnormalize stack memory DEFs and USEs before printing annotations.
		this->MDGetUnnormalizedOp(AnnotDefOp);
		SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR MEMDEF %d", (unsigned long) addr, this->SMPcmd.size, DestBitWidth);
		AnnotPrintOperand(AnnotDefOp, InfoAnnotFile);
		SMP_fprintf(InfoAnnotFile, " ZZ %s \n", disasm);
	}
#endif

	// If the instruction is a CALL (or INDIR_CALL that has been resolved to
	//  a single target address), then we need to see if the call is to a 
	//  function that has been forbidden by a security policy. If so, we
	//  need to output a security alert.
	// In the near future, we will output SPRI instrumentation to prevent
	//  the system/library call from executing.
	if ((BADADDR != this->CallTarget) && (!this->IsCallUsedAsJump())) {
		// We have a resolved call target address, either via direct or indirect call.
		string FuncName = this->GetTrimmedCalledFunctionName();
		ZST_SysCallType FuncCallType = GetCallTypeFromFuncName(FuncName);
		ZST_Policy FuncCallPolicy = GetPolicyFromCallType(FuncCallType);
		if (ZST_DISALLOW == FuncCallPolicy) {
			if ((NULL != this->GetBlock()) && (NULL != this->GetBlock()->GetFunc())) {
				SMP_fprintf(ZST_AlarmFile, "ALARM: Call to %s will be disallowed at %lx in %s\n", 
					FuncName.c_str(), (unsigned long) this->address, this->GetBlock()->GetFunc()->GetFuncName());
			}
			else {
				SMP_fprintf(ZST_AlarmFile, "ALARM: Call to %s will be disallowed at %lx\n",
					FuncName.c_str(), (unsigned long) this->address);
			}
			SMP_fprintf(ZST_AlarmFile, "ALARM REASON: Call policy is DISALLOW for all calls of type %s\n", CallTypeNames[FuncCallType]);
			SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR SECURITYCALL Disallow 1 1 %s \n",
				(unsigned long) addr, this->SMPcmd.size, disasm);
		}
	}


#if SMP_DEBUG_MEM
	if (MemDest || MemSrc) {
		SMP_msg("OptType: %d %s", OptType, disasm);
		this->PrintOperands();
	}
#endif

	// Emit appropriate optimization annotations.
	bool SDTInstrumentation = false;
	switch (OptType) {
		case 0:  // SDT will have to handle these
		{
#if SMP_DEBUG_TYPE0
			SMP_msg("OptType 0: %lx  %s\n", (unsigned long) addr, disasm);
#endif
			// mmStrata wants to suppress warnings on the PUSH
			//  instructions that precede the LocalVarsAllocInstr
			//  (i.e. the PUSHes of callee-saved regs).
			if ((!AllocSeen || !NeedsFrame) && this->MDIsPushInstr()) {
				SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL NoWarn %s \n",
						(unsigned long) addr, -3, disasm);
				NoWarnFlag = true;
			}
			else {
				SDTInstrumentation = true;
			}
			break;
		}

		case 1:  // nothing for SDT to do
		{	SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL %s %s \n",
					(unsigned long) addr, -1, OptExplanation[OptType], disasm);
			++AnnotationCount[OptType];
			break;
		}

		case 4:  // INC, DEC, etc.: no SDT work unless MemDest
		{	if (MemDest || MemSrc) {
				SDTInstrumentation = true;
				break;  // treat as category 0
	 		}
			SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL Always1stSrc %s \n",
					(unsigned long) addr, -1, disasm);
			++AnnotationCount[OptType];
			break;
		}

		case 5: // ADD, etc.: If numeric 2nd src operand, no SDT work.
		{	if (MemDest || MemSrc) {
				SDTInstrumentation = true;
				break;  // treat as category 0
			}
			if (SecondSrcOperandImmNum 
				&& !this->MDIsFrameAllocInstr()
#if SPECIAL_CASE_CARRY_BORROW
				&& (this->SMPcmd.itype != NN_adc)
				&& (this->SMPcmd.itype != NN_sbb)
#endif
				) { // treat as category 1
				SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL %s %s \n",
						(unsigned long) addr, -1, OptExplanation[OptType], disasm);
				++AnnotationCount[OptType];
			}
			else {
				SDTInstrumentation = true;
			}
			break;
		}

		case 6: // Only OS code should include these; problem for SDT
		{	if (MemDest) {
				SDTInstrumentation = true;
				break;  // treat as category 0
			}
			SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL AlwaysPTR %s \n",
					(unsigned long) addr, -OptType, disasm);
			++AnnotationCount[OptType];
			break;
		}

		case 8: // Implicitly writes to EDX:EAX, always numeric.
		{	SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL n EDX EAX ZZ %s %s \n",
					(unsigned long) addr, -2, OptExplanation[OptType], disasm);
			++AnnotationCount[OptType];
			SDTInstrumentation = true;
			break;
		}

		case 9:  // Either writes to FP reg (cat. 1) or memory (cat. 0)
		{	if (MemDest) {
#if SMP_DEBUG2
				// MemDest seems to happen too much.
				SMP_msg("Floating point MemDest: %s \n", disasm);
#endif
				SDTInstrumentation = true;
				break; // treat as category 0
			}
			SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL %s %s \n",
					(unsigned long) addr, -1, OptExplanation[OptType], disasm);
			++AnnotationCount[OptType];
			break;
		}

		case 10: // Implicitly writes to EDX:EAX and ECX, always numeric.
		{	SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL n EDX EAX ECX ZZ %s %s \n",
					(unsigned long) addr, -2, OptExplanation[OptType], disasm);
			++AnnotationCount[OptType];
			SDTInstrumentation = true;
			break;
		}

		default: // 2,3,7: Optimization possibilities depend on operands
		{ 
#if SMP_DEBUG2
			if (OptType ==  3) {  // MOV instr class
				if (MemDest) {
					SMP_msg("MemDest on MOV: %s\n", disasm);
				}
				else if (!SecondSrcOperandNum) {
					SMP_msg("MOV: not 2nd op numeric: %s\n", disasm);
						this->PrintOperands();
				}
			}
#endif
			SDTInstrumentation = true;
			if (MemDest) {
#if SMP_DEBUG_XOR
				if (OptType == 2)
					SMP_msg("MemDest on OptType 2: %s\n", disasm);
#endif
				break;  // treat as category 0
			}
			if ((OptType == 2) || (OptType == 7) || SecondSrcOperandImmNum) {
				SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL n %s %s %s \n",
						(unsigned long) addr, -2, this->DestString(OptType), 
						OptExplanation[OptType], disasm);
				++AnnotationCount[OptType];
			}
			break;
		}
	} // end switch (OptType)

	// always emit stack constant annotations, in case strata is 
	// instrumenting all instructions, or trying to verify speculative annotations. 
	this->AnnotateStackConstants(UseFP, AnnotFile);
	
	// If mmStrata is going to have to deal with the
	//  instruction, then we can annotate EBP and ESP
	//  relative constant offsets. If we have emitted
	//  an annotation of type -1, there is no point
	//  in telling mmStrata about these constants.
	// Likewise, we can tell mmStrata if a MemDest is an
	//  non-directly-accessed child object.
	if (SDTInstrumentation || NoWarnFlag) {
		if (this->DeadRegsBitmap.any()) {
			// Optimize by informing mmStrata of dead registers. It can avoid saving
			//  and restoring dead state. This is particularly important for EFLAGS,
			//  as restoring the flags is a pipeline serializing instruction.
			SMP_fprintf(AnnotFile, "%10lx %6d INSTR DEADREGS  ",
				(unsigned long) addr, this->SMPcmd.size);
			this->PrintDeadRegs(AnnotFile);
			SMP_fprintf(AnnotFile, " %s \n", disasm);
		}
#if SMP_CHILDACCESS_ALL_CODE
		int ChildOffset, ChildSize;
		if (MemDest && !OrphanCode
			&& ProfInfo->GetMemoryAccessInfo()->ComputeNonDirectAccessRegion(addr,
			ChildOffset, ChildSize)) {
			SMP_fprintf(AnnotFile, "%10lx %6d INSTR CHILDACCESS %d %d ZZ %s \n",
				(unsigned long) addr, this->SMPcmd.size, ChildOffset, ChildSize, disasm);
		}
#endif
	}
	return;
} // end of SMPInstr::EmitAnnotations()

/**
 * Emits Safe Returns
 * Mark the type of  the annotation as "-4". Currently  the SDT is ignoring this
 * annotation. 
 */ 
void SMPInstr::EmitSafeReturn(FILE *AnnotFile)
{
	char *disasm = DisAsmText.GetDisAsm(this->GetAddr());
	SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL SafeReturn %s\n",
		(unsigned long) this->address, -4, disasm);
}

// Emit all annotations for the instruction using RTL type inference.
void SMPInstr::EmitTypeAnnotations(bool UseFP, bool AllocSeen, bool NeedsFrame, FILE *AnnotFile, FILE *InfoAnnotFile) {
	ea_t addr = this->address;
	flags_t InstrFlags = getFlags(addr);
	int TypeGroup = SMPTypeCategory[this->SMPcmd.itype];
	bool NumericDEFs = this->AllDefsNumeric();  // all DEFs are NUMERIC or CODEPTR
	bool ProfiledDEFs = this->AnyDefsProfiled();  // Some DEFs come from the profiler
	bool UnusedMetadata = this->AllDefMetadataUnused();
	bool MemDest = this->HasDestMemoryOperand();
	bool MemSrc = this->HasSourceMemoryOperand();
	bool SecondSrcOperandImmNum = this->IsSecondSrcOperandNumeric(InstrFlags); // assumes 2nd source is imm or not-numeric??
	bool NoWarnFlag = false; // NOWARN annotation emitted?
	bool CarryBorrow = ((this->SMPcmd.itype == NN_adc) 
		|| (this->SMPcmd.itype == NN_sbb));
	// Do we have the special case in which a non-NUMERIC comes into
	//  an add with carry or subtract with borrow and the result
	//  has been inferred to be NUMERIC?
	bool TypeChange = CarryBorrow && (!IsNumeric(this->AddSubDefUseType))
				&& NumericDEFs;
	SMPMetadataType DefMetadataType = this->GetDefMetadataType();
	ProfilerInformation *ProfInfo;
	ProfInfo = this->BasicBlock->GetFunc()->GetProg()->GetProfInfo();
	char *disasm = DisAsmText.GetDisAsm(this->GetAddr());

	++OptCount[this->OptType]; // keep count for debugging info

	if (this->IsNop())
		TypeGroup = 1; // no-op idioms need their category reset

	// Emit appropriate optimization annotations.
	bool SDTInstrumentation = false;

	// In case we short circuit this function due to redundant or unused metadata, etc.,
	//  perform analyses that are useful to integer error annotations.

#if SMP_ANNOTATE_ALL_MEMORY_OPERANDS
	// Emit informational annotations for memory operands.
	if (MemSrc) {
		op_t MemSrcOp = this->MDGetMemUseOp();
		size_t SrcBitWidth = 8 * GetOpDataSize(MemSrcOp);
		op_t AnnotDefOp = MemSrcOp;
		// Need to unnormalize stack memory DEFs and USEs before printing annotations.
		this->MDGetUnnormalizedOp(AnnotDefOp);
		SMP_fprintf(InfoAnnotFile, "%10lx %6zu INSTR MEMSRC %zu", (unsigned long) addr, this->SMPcmd.size, SrcBitWidth);
		AnnotPrintOperand(AnnotDefOp, InfoAnnotFile);
		SMP_fprintf(InfoAnnotFile, " ZZ %s \n", disasm);
	}
	if (MemDest) {
		op_t MemDestOp = this->MDGetMemDefOp();
		size_t DestBitWidth = 8 * GetOpDataSize(MemDestOp);
		op_t AnnotDefOp = MemDestOp;
		// Need to unnormalize stack memory DEFs and USEs before printing annotations.
		this->MDGetUnnormalizedOp(AnnotDefOp);
		SMP_fprintf(InfoAnnotFile, "%10lx %6zu INSTR MEMDEF %zu", (unsigned long) addr, this->SMPcmd.size, DestBitWidth);
		AnnotPrintOperand(AnnotDefOp, InfoAnnotFile);
		SMP_fprintf(InfoAnnotFile, " ZZ %s \n", disasm);
	}
#endif

	// If the instruction is a CALL (or INDIR_CALL that has been resolved to
	//  a single target address), then we need to see if the call is to a 
	//  function that has been forbidden by a security policy. If so, we
	//  need to output a security alert.
	// In the near future, we will output SPRI instrumentation to prevent
	//  the system/library call from executing.
	if ((BADADDR != this->CallTarget) && (!this->IsCallUsedAsJump())) {
		// We have a resolved call target address, either via direct or indirect call.
		string FuncName = this->GetTrimmedCalledFunctionName();
		ZST_SysCallType FuncCallType = GetCallTypeFromFuncName(FuncName);
		ZST_Policy FuncCallPolicy = GetPolicyFromCallType(FuncCallType);
		if (ZST_DISALLOW == FuncCallPolicy) {
			SMP_fprintf(ZST_AlarmFile, "ALARM: Call to %s will be disallowed at %lx in %s\n", 
				FuncName.c_str(), (unsigned long) this->address, this->GetBlock()->GetFunc()->GetFuncName());
			SMP_fprintf(ZST_AlarmFile, "ALARM REASON: Call policy is DISALLOW for all calls of type %s\n", CallTypeNames[FuncCallType]);
			SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR SECURITYCALL Disallow 1 1 %s \n",
				(unsigned long) addr, this->SMPcmd.size, disasm);
		}
	}

	// If the DEF metadata is all unused, mmStrata can skip the instruction.
	//  We omit this for groups 1 and 14, so that the metadata analysis
	//  does not get statistical credit for instructions that were already
	//  getting -1 annotations without analysis.
	// We also cannot skip NN_adc and NN_sbb instructions that change the
	//  type of the incoming register.
	if ((1 != TypeGroup) && (14 != TypeGroup) && (!this->MDIsInterruptCall())
		&& !TypeChange) {
		if (UnusedMetadata) {
			SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL MetadataUnused %s \n",
						(unsigned long) addr, -1, disasm);
			++AnnotationCount[this->OptType];
			return;
		}
		else if (DEF_METADATA_REDUNDANT == DefMetadataType) {
			SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL MetadataRedundant %s \n",
						(unsigned long) addr, -1, disasm);
			++AnnotationCount[this->OptType];
			return;
		}
		else if (DEF_METADATA_PROF_REDUNDANT == DefMetadataType) {
			SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL MetadataRedundant %s \n",
						(unsigned long) addr, -257, disasm);
			++AnnotationCount[this->OptType];
			// Profiler annotations could be backed off due to false
			//  positives, in which case we will need stack constant
			//  annotations.
			this->AnnotateStackConstants(UseFP, AnnotFile);
			return;
		}
	}

	switch (TypeGroup) {
		case 0:  // SDT will have to handle these
		case 11: // PUSH/POP  **!!** What if we push/pop NUMERIC type? Optimize?

			// --jdh
			// pop numeric's can be optimized with a numericdef annotation.
			// numeric push's can't immediately be optimized, but if the stack location
			// can be proven as dead metadata, then perhaps optimize.
			// --jdh

			// mmStrata wants to suppress warnings on the PUSH
			//  instructions that precede the LocalVarsAllocInstr
			//  (i.e. the PUSHes of callee-saved regs).
			if ((!AllocSeen || !NeedsFrame) && this->MDIsPushInstr()) {
				SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL NoWarn %s \n",
						(unsigned long) addr, -3, disasm);
				NoWarnFlag = true;
			}
			else if (this->MDIsPopInstr() && NumericDEFs) {
				SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL n %s NumericDEFs %s \n",
						(unsigned long) addr, ProfiledDEFs ? -256-2 : -2, this->DestString(this->OptType),
						disasm);
				++AnnotationCount[this->OptType];
			}
			else {
				SDTInstrumentation = true;
			}
			break;

		case 1:  // nothing for SDT to do
		case 14:
			if (MemDest) {
				SMP_msg("ERROR: MemDest in Type Category 1 or 14: %lx %s\n", (unsigned long) addr, disasm);
				SDTInstrumentation = true;
				break;
			}
			SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL %s %s \n",
					(unsigned long) addr, -1, OptExplanation[this->OptType], disasm);
			++AnnotationCount[this->OptType];
			break;

		case 4:  // INC, DEC, etc.: no SDT work unless MemDest
			if (MemDest || MemSrc) { // pretty conservative here?
						// could be more aggressive if we know there's no overflow. -- jdh
				SDTInstrumentation = true;
				break;  // treat as category 0
	 		}
			SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL Always1stSrc %s \n",
					(unsigned long) addr, -1, disasm);
			++AnnotationCount[this->OptType];
			break;

		case 5: // ADD, etc.: If numeric 2nd src operand, no SDT work.
#if 1
			if (MemDest) {
				SDTInstrumentation = true;
				break;  // treat as category 0
			}
#endif
			if (SecondSrcOperandImmNum 
				&& !this->MDIsFrameAllocInstr()
				&& !TypeChange
#if SPECIAL_CASE_CARRY_BORROW
				&& (!CarryBorrow)
#endif
				) {
				// treat as category 1
				SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL %s %s \n",
						(unsigned long) addr, -1, OptExplanation[this->OptType], disasm);
				++AnnotationCount[this->OptType];
			}
			else if (IsEqType(NUMERIC, this->AddSubSourceType)
				&& !this->MDIsFrameAllocInstr()
				&& !TypeChange
#if SPECIAL_CASE_CARRY_BORROW
				&& (!CarryBorrow)
#endif
				) {
				SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL 2ndSrcNumeric %s \n",
						(unsigned long) addr, -1, disasm);
				++AnnotationCount[this->OptType];
			}
			else if (NumericDEFs) {
				SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL n %s NumericDEFs %s \n",
						(unsigned long) addr, ProfiledDEFs ? -256-2 : -2, this->DestString(this->OptType), disasm);
				++AnnotationCount[this->OptType];
			}
#if SMP_OPTIMIZE_ADD_TO_NUMERIC
			else if ((NN_add == this->SMPcmd.itype) && (!MemSrc)
				&& IsNumeric(this->AddSubDefUseType)) {
				// reg1 := reg1 + reg2, where reg1 comes in as NUMERIC,
				//  means that reg1 will get DEFed to the type of reg2,
				//  whatever it is. If reg2 were known to be NUMERIC,
				//  we would have hit one of the annotation cases above.
				SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL %s := %s ZZ AddToNumeric %s \n",
					(unsigned long) addr, -5, RegNames[this->GetDefUseAddSubOp().reg],
					RegNames[this->GetUseOnlyAddSubOp().reg], disasm);
				++AnnotationCount[this->OptType];
			}
#endif
			else {
				SDTInstrumentation = true;
			}
			break;

		case 6: // Only OS code should include these; problem for SDT
			if (MemDest) {
				SDTInstrumentation = true;
				break;  // treat as category 0
			}
			SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL AlwaysPTR %s \n",
					(unsigned long) addr, -OptType, disasm);
			++AnnotationCount[this->OptType];
			break;

		case 8: // Implicitly writes to EDX:EAX, always numeric.
			if (this->OptType == 10) { // writes to ECX also
				SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL n EDX EAX ECX ZZ %s %s \n",
						(unsigned long) addr, -2, OptExplanation[this->OptType], disasm);
			}
			else {
				SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL n EDX EAX ZZ %s %s \n",
						(unsigned long) addr, -2, OptExplanation[this->OptType], disasm);
			}
			++AnnotationCount[this->OptType];
			SDTInstrumentation = true;
			break;

		case 9:  // Either writes to FP reg (cat. 1) or memory (cat. 0)
			if (MemDest) {
				SDTInstrumentation = true;
#if 0
				if (NumericDEFs) {
					SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL n %s NumericDEFs %s \n",
						(unsigned long) addr, ProfiledDEFs ? -256-2 : -2, this->DestString(this->OptType), disasm);
					++AnnotationCount[this->OptType];
				}
#endif
			}
			else {
				SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL %s %s \n",
						(unsigned long) addr, -1, OptExplanation[this->OptType], disasm);
				++AnnotationCount[this->OptType];
			}
			break;

		case 10: // AND, OR, etc.: If all DEFs have been inferred to be
				 //  NUMERIC, then output optimizing annotation.
			SDTInstrumentation = true;
			if (MemDest) { // **!!** optimize with numeric annotation in future
				break;  // treat as category 0
			}
			else if (NumericDEFs) { // NUMERIC result because of NUMERIC sources
				SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL n %s NumericDEFs %s \n",
						(unsigned long) addr, ProfiledDEFs ? -256-2 : -2, this->DestString(this->OptType), disasm);
				++AnnotationCount[this->OptType];
			}
			break;

		case 12: // Exchange, exchange and add, conditional exchange: All NUMERIC
				 //  sources ==> NUMERIC DEFs, so nothing for mmStrata to do.
			if (MemDest) { // **!!** optimize with numeric annotation in future
				SDTInstrumentation = true;
				break;  // treat as category 0
			}
			else if (NumericDEFs) { // NUMERIC result because of NUMERIC sources
				SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL %s %s \n", (unsigned long) addr,
						ProfiledDEFs ? -256-1 : -1, OptExplanation[TypeGroup], disasm);
				++AnnotationCount[this->OptType];
			}
			else 
				SDTInstrumentation = true;
			break;

		case 13:
		case 15: // Floating point, NUMERIC, possible memory destination.
				 //  If not memory destination, fpreg dest, so nothing for mmStrata to do.
			if (MemDest) { // **!!** optimize with numeric annotation in future
				SDTInstrumentation = true;
				break;  // treat as category 0
			}
			else { // NUMERIC floating register result; these regs are always NUMERIC
				SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL %s %s \n", (unsigned long) addr,
						-1, OptExplanation[TypeGroup], disasm);
				++AnnotationCount[this->OptType];
			}
			break;

		default: // 2,3,7: Optimization possibilities depend on operands 
			SDTInstrumentation = true;
			if (MemDest) {
				break;  // treat as category 0
			}

			if ((OptType == 2) || (OptType == 7) || SecondSrcOperandImmNum) {
				SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL n %s %s %s \n",
						(unsigned long) addr, -2, this->DestString(this->OptType), 
						OptExplanation[this->OptType], disasm);
				++AnnotationCount[this->OptType];
			}
			else if (NumericDEFs) { // NUMERIC move instruction
				SMP_fprintf(AnnotFile, "%10lx %6d INSTR LOCAL n %s NumericDEFs %s \n",
						(unsigned long) addr, ProfiledDEFs ? -256-2 : -2, this->DestString(this->OptType), disasm);
				++AnnotationCount[this->OptType];
			}
			break;
	} // end switch (OptType)
	

	// always annotate stack constants for the profiler, etc.
	this->AnnotateStackConstants(UseFP, AnnotFile);

	// If mmStrata is going to have to deal with the
	//  instruction, then we can annotate EBP and ESP
	//  relative constant offsets. If we have emitted
	//  an annotation of type -1, there is no point
	//  in telling mmStrata about these constants.
	// Likewise, we can tell mmStrata if a MemDest is an
	//  non-directly-accessed child object.
	if (SDTInstrumentation || NoWarnFlag) {
		if (this->DeadRegsBitmap.any()) {
			// Optimize by informing mmStrata of dead registers. It can avoid saving
			//  and restoring dead state. This is particularly important for EFLAGS,
			//  as restoring the flags is a pipeline serializing instruction.
			SMP_fprintf(AnnotFile, "%10lx %6d INSTR DEADREGS  ",
				(unsigned long) addr, this->SMPcmd.size);
			this->PrintDeadRegs(AnnotFile);
			SMP_fprintf(AnnotFile, " %s \n", disasm);
		}
		int ChildOffset, ChildSize;
		if (MemDest && ProfInfo->GetMemoryAccessInfo()->ComputeNonDirectAccessRegion(addr,
			ChildOffset, ChildSize)) {
			SMP_fprintf(AnnotFile, "%10lx %6d INSTR CHILDACCESS %d %d ZZ %s \n",
				(unsigned long) addr, this->SMPcmd.size, ChildOffset, ChildSize, disasm);
		}
#if SMP_IDENTIFY_POINTER_ADDRESS_REG
		// WARNING: This old code was written prior to the normalization of stack operands.
		if (MemDest) {
			assert(this->HasDestMemoryOperand());
			set<DefOrUse, LessDefUse>::iterator PtrUse;
			PtrUse = this->GetPointerAddressReg(this->DEFMemOp);
			if (PtrUse != this->GetLastUse()) { // found POINTER addr reg USE
				if (PtrUse->GetOp().type == o_reg) {
					ushort PtrReg = PtrUse->GetOp().reg;
					SMP_fprintf(AnnotFile, "%10lx %6d INSTR POINTER reg %s ZZ %s \n",
						(unsigned long) addr, this->SMPcmd.size, RegNames[PtrReg], disasm);
				}
			}
		}
#endif
	}
	return;
} // end of SMPInstr::EmitTypeAnnotations()

// union of sign masks from 2 reg USEs for binary arithmetic
unsigned short SMPInstr::SignMaskUnionFromUseRegs(void) {
	unsigned short UnionMask = 0;
	unsigned short UseSignMask, DefSignMask;
	set<DefOrUse, LessDefUse>::iterator UseIter;
	op_t UseOp;
	size_t RegOpCount = 0;
	int UseHashValue;
	struct FineGrainedInfo UseFGInfo, DefFGInfo;
	bool UseFP = this->GetBlock()->GetFunc()->UsesFramePointer();

	if (this->HasSourceMemoryOperand()) {
		// Don't have binary arithmetic on just registers.
		return UnionMask;
	}

	for (UseIter = this->GetFirstUse(); UseIter != this->GetLastUse(); ++UseIter) {
		UseOp = UseIter->GetOp();
		if (MDIsGeneralPurposeReg(UseOp) && (!MDIsStackPtrReg(UseOp.reg, UseFP))) {
			++RegOpCount;
			UseHashValue = HashGlobalNameAndSSA(UseOp, UseIter->GetSSANum());
			bool LocalUseName = this->BasicBlock->IsLocalName(UseOp);

			if (LocalUseName) {
				// Local name, find in basic block maps.
				UseFGInfo = this->BasicBlock->GetUseFGInfo(UseHashValue);
			}
			else { // Global name, find in global maps.
				UseFGInfo = this->BasicBlock->GetFunc()->GetUseFGInfo(UseHashValue);
			}
			UseSignMask = (FG_MASK_SIGNEDNESS_BITS & UseFGInfo.SignMiscInfo);
			if (0 == UseSignMask) {
				// Try to get signedness from DEF.
				if (LocalUseName) {
					// Local name, find in basic block maps.
					DefFGInfo = this->BasicBlock->GetDefFGInfo(UseHashValue);
				}
				else { // Global name, find in global maps.
					DefFGInfo = this->BasicBlock->GetFunc()->GetDefFGInfo(UseHashValue);
				}
				DefSignMask = (FG_MASK_SIGNEDNESS_BITS & DefFGInfo.SignMiscInfo);
				UnionMask |= DefSignMask;
			}
			else {
				UnionMask |= UseSignMask;
			}
		}
	}

	if (2 > RegOpCount) { // only interested in binary arithmetic on two registers
		UnionMask = 0;
	}
	return UnionMask;
} // SMPInstr::SignMaskUnionFromUseRegs()

// emit check annotations for signedness, overflow, truncation, etc.
void SMPInstr::EmitIntegerErrorAnnotations(FILE *InfoAnnotFile, list<size_t> &LoopList) {
	set<DefOrUse, LessDefUse>::iterator UseIter, DefIter;
	op_t UseOp, DefOp;
	unsigned short UseWidthInfo, DefWidthInfo, SourceDefWidthInfo;
	unsigned short DefSignInfo, SourceDefSignInfo;
	unsigned short UseSignMask, DefSignMask, SourceDefSignMask;
	struct FineGrainedInfo UseFGInfo, DefFGInfo, SourceDefFGInfo;
	size_t UseBitWidth, DefBitWidth, UseMaxBitWidth, SourceDefBitWidth, DefMaxBitWidth;
	ea_t DefAddr;
	int UseHashValue, DefHashValue, SSANum, DefSSANum, UseSSANum;
	int IdiomCode = 0; // records code pattern number causing suppression of annotation.
	bool OverflowOpcode = this->MDIsOverflowingOpcode();
	bool UnderflowOpcode = this->MDIsUnderflowingOpcode();
	bool CheckForOverflow;
	bool UseIsSigned, DefIsSigned, UseIsUnsigned, DefIsUnsigned, SourceDefIsSigned, SourceDefIsUnsigned;
	bool UseSignMixed, SourceDefSignMixed; // inconsistent signedness
	bool UseFP = this->BasicBlock->GetFunc()->UsesFramePointer();
	bool SuppressSignednessCheck = false; // If we are not confident in check, set to true.
	bool PartialStore; // Store is fewer bits than is defined for the target, e.g. overwriting last 8 bits
	                   //  of an int or a pointer. Cannot have signedness error in that case, as sign bit
	                   //  is not affected.
	char *disasm = DisAsmText.GetDisAsm(this->GetAddr());
	string SinkString("");

	if (this->IsNumericAnnotationSuppressed()) {
		return; // Cannot figure out IdiomCode; suppressed from earlier instruction's analyses
	}

	// If the instruction is the beginning of an infinite loop, we want no annotations other than
	//  the infinite loop annotation.
	if (this->IsFirstInBlock()) {
		if (this->GetBlock()->IsInfiniteSelfLoop()) {
			SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR INFINITELOOP %s \n",
					(unsigned long) this->address, this->SMPcmd.size, disasm);
			return;
		}
	}

	// Case 1: Overflow on addition.
	// Case 2: Underflow on subtraction.
	if (OverflowOpcode || UnderflowOpcode) {
		// If the flags register DEF is dead, we need a CHECK OVERFLOW/UNDERFLOW annotation.
		DefOp = InitOp;
		DefOp.type = o_reg;
		DefOp.reg = MD_FLAGS_REG;
		DefOp.dtyp = this->GetOperandDtypField();
		DefIter = this->FindDef(DefOp);
		assert(DefIter != this->GetLastDef());
		if (this->BasicBlock->IsDefDead(this->address, DefOp)) {
			DefIter = this->GetFirstNonFlagsDef();
			assert(DefIter != this->GetLastDef());
			DefOp = DefIter->GetOp();
			SSANum = DefIter->GetSSANum();
			SMPOperandType DefType = DefIter->GetType();
			SMPOperandType MemType;
			bool IgnoreOverflow = this->IsBenignOverflow(IdiomCode);
			uval_t ConstValue = 0;
			// NOTE: We no longer suppress the IgnoreOverflow annotations. Instead, we print
			//  them with an IdiomCode so that suppression can happen downstream, along with
			//  customized continuation policies, statistical summarizing, etc.
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
			if (IgnoreOverflow)
				++BenignOverflowInstCount;
#endif
			// Don't worry about stack space allocation instructions. The
			//  program will crash long before the stack pointer underflows
			//  below zero.
			if (!((o_reg == DefOp.type) && DefOp.is_reg(MD_STACK_POINTER_REG))) {
				if (!IgnoreOverflow && (this->GetBlock()->IsBenignOverflowDEF(DefOp, SSANum, this->GetAddr(), UnderflowOpcode, IdiomCode))) {
					IgnoreOverflow = true;
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
					++BenignOverflowDefCount;
#endif
				}
				if (o_reg == DefOp.type) {
					DefHashValue = HashGlobalNameAndSSA(DefOp, SSANum);
					if (this->BasicBlock->IsLocalName(DefOp)) {
						// Local name, find in basic block maps.
						DefFGInfo = this->BasicBlock->GetDefFGInfo(DefHashValue);
					}
					else { // Global name, find in global maps.
						DefFGInfo = this->BasicBlock->GetFunc()->GetDefFGInfo(DefHashValue);
					}
				}
				else if (MDIsDirectStackAccessOpnd(DefOp, UseFP)) {
					bool success = this->BasicBlock->GetFunc()->MDGetFGStackLocInfo(this->address, DefOp, DefFGInfo);
					assert(success);
				}
				else { // non-stack memory address; we know nothing about it.
					DefFGInfo.SignMiscInfo = 0;
					DefFGInfo.SizeInfo = 0;
				}
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
				++NumericAnnotationsCount12;
#endif
				DefSignInfo = DefFGInfo.SignMiscInfo;
				DefSignMask = DefSignInfo & FG_MASK_SIGNEDNESS_BITS;
				DefWidthInfo = DefFGInfo.SizeInfo;
				DefBitWidth = LargestBitWidthFromMask(DefWidthInfo);
				if (0 == DefBitWidth) {
					// Could happen for non-stack memory operands, for example.
					DefBitWidth = MD_NORMAL_MACHINE_BITWIDTH;
				}
				if (DefSignMask == 0) {
					// If no sign info from DEF, see if we can get it from the USE regs.
					DefSignMask = this->SignMaskUnionFromUseRegs();
				}
				if ((0 == IdiomCode) && (DefSignMask == FG_MASK_UNSIGNED)) {
					// UNSIGNED is often reliable because compilers zero-extend values
					//  just so they can avoid having undefined register bits. Later, only
					//  the lower bits get stored. We already detect this pattern as a benign
					//  truncation, but we need to back off on the certainty of our UNSIGNED
					//  inference on overflow/underflow operations along the path.
					UseIter = this->FindUse(DefOp);
					if (UseIter != this->GetLastUse()) {
						UseOp = UseIter->GetOp();
						UseSSANum = UseIter->GetSSANum();
						if ((o_reg == UseOp.type) || MDIsDirectStackAccessOpnd(UseOp, UseFP)) {
							if (this->IsOpSourceZeroExtendedMove(UseOp, UseSSANum, false)) {
								if (this->GetBlock()->IsOpDestTruncatedWrite(DefOp, SSANum, this->GetAddr())) {
									// Operand source was reduced-width, zero-extended; ultimate use is to store
									//  only the lower bits. The zero extension is no longer a reliable source of 
									//  inference for UNSIGNEDness.
									DefSignMask = FG_MASK_INCONSISTENT_SIGN;
								}
							}
							else if (UnderflowOpcode && this->IsOpSourceSmallPositiveConstant(UseOp, UseSSANum)) {
								// subtract from small positive, danger of UNSIGNED UNDERFLOW. Most likely, the
								//  inference of UNSIGNED is unreliable.
								DefSignMask = FG_MASK_INCONSISTENT_SIGN;
							}
						}
					}
				}
				if (OverflowOpcode) {
					if ((17 == IdiomCode) && (FG_MASK_UNSIGNED == DefSignMask)) {
						// An IdiomCode of 17 means not a benign overflow, but an addition that
						//  produces a jump table offset, which can be an addition of mixed signedness
						//  that produces false positives if treated as UNSIGNED. See discussion in
						//  SMPBasicBlock::IsBenignOverflowDEF().
						DefSignMask = FG_MASK_INCONSISTENT_SIGN;
					}
					else if (this->IsAdditionOfLargeConstant(ConstValue, DefSignMask)) {
						IgnoreOverflow = true;
						IdiomCode = 11;
					}

					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW %s %zu ",
						(unsigned long) this->address, this->SMPcmd.size, SignednessStrings[DefSignMask], DefBitWidth);
				}
				else { // must be UnderflowOpcode
					// (1) Two more benign case to exclude: 
					//   movzx eax, byte ptr [esp+37] ; get char, with misleading zero-extension
					//   sub eax,0x65   ; subtract 'A' to see if char is in letter range
					//   cmp eax,25     ; there are 26 capital letters
					//   ja nextcheck   ; not in range of 'A' to 'Z'
					//   return true    ; found an alphanumeric
					// These operations make eax look UNSIGNED. But it is an ASCII char, and the subtraction
					//  will underflow whenever the char is less than 'A'. Similar checks occur for 'a'
					//  and the digit '0' quite often. We do not want false positives on underflow checks.
					//
					// (2) sub eax,[large constant value]
					//  We might have to follow the subtrahend operand back to its origin. A subtraction of a
					//  number that has a very large absolute value tends to indicate that underflow is benign
					//  and is being ignored.
					if (!IgnoreOverflow) {
						if ((DefSignMask == FG_MASK_UNSIGNED) && (this->SubtractsImmedASCII())) {
							IgnoreOverflow = true;
							IdiomCode = 9;
						}
						else if ((DefSignMask == FG_MASK_UNSIGNED) || (DefSignMask == FG_MASK_SIGNED)) {
							if (this->IsSubtractionOfLargeConstant(ConstValue, DefSignMask)) {
								IgnoreOverflow = true;
								IdiomCode = 11;
							}
						}
					}
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK UNDERFLOW %s %zu ",
							(unsigned long) this->address, this->SMPcmd.size, SignednessStrings[DefSignMask], DefBitWidth);
				}
				op_t AnnotDefOp = DefOp;
				if (o_reg != DefOp.type) {
					// Need to unnormalize stack memory DEFs and USEs before printing annotations.
					this->MDGetUnnormalizedOp(AnnotDefOp);
				}
				AnnotPrintOperand(AnnotDefOp, InfoAnnotFile);
				if (!IgnoreOverflow) {
					// See if we made a special detection of an operation involved in a hash function, which can
					//  be expected to overflow benignly.
					if (this->IsHashOperation()) {
						IgnoreOverflow = true;
						IdiomCode = 15;
					}
					else if (IsDataPtr(DefType)) {
						// IDIOM 18 says to let C7 (buffer overflow/underflow) defenses handle the issues if it is a pointer.
						IgnoreOverflow = true;
						IdiomCode = 18;						
					}
					else if (1 <= LoopList.size()) { // Limit search for address-reg-only case to loops for now.
						list<size_t>::iterator LoopIter;
						for (LoopIter = LoopList.begin(); LoopIter != LoopList.end(); ++LoopIter) {
							size_t Counter = 0;
							size_t LoopNum = (*LoopIter);
							MemType = UNINIT;
							this->GetBlock()->GetFunc()->ResetProcessedBlocks();
							bool AddrRegOnly = this->GetBlock()->IsDefOnlyUsedAsAddressReg(this->GetAddr(), DefOp, LoopNum, Counter, MemType);
							if (AddrRegOnly && (0 < Counter)) {
								// Similarly, let C7 (buffer overflow/underflow) defenses handle the issues if it is only an index register.
								DefType = MemType;
								IgnoreOverflow = true;
								IdiomCode = 18;
								break; // Don't need to look at next loop
							}
						}
					}
				}
				if (IgnoreOverflow) {
					if (11 == IdiomCode) {
						SMP_fprintf(InfoAnnotFile, " ZZ IDIOM %d CONST %lu %s \n", IdiomCode, (unsigned long) ConstValue, disasm);
					}
					else if (18 == IdiomCode) {
						// Need a tag field telling what kind of pointer.
						if (IsEqType(DefType, STACKPTR)) {
							SMP_fprintf(InfoAnnotFile, " ZZ IDIOM %d STACKMEMSINK %s \n", IdiomCode, disasm);
						}
						else if (IsEqType(DefType, HEAPPTR)) {
							SMP_fprintf(InfoAnnotFile, " ZZ IDIOM %d HEAPMEMSINK %s \n", IdiomCode, disasm);
						}
						else if (IsEqType(DefType, GLOBALPTR)) {
							SMP_fprintf(InfoAnnotFile, " ZZ IDIOM %d GLOBALMEMSINK %s \n", IdiomCode, disasm);
						}
						else { // must be unrefined POINTER type.
							SMP_fprintf(InfoAnnotFile, " ZZ IDIOM %d MEMORYSINK %s \n", IdiomCode, disasm);
						}
					}
					else {
						SMP_fprintf(InfoAnnotFile, " ZZ IDIOM %d %s \n", IdiomCode, disasm);
					}
				}
				else if (this->GetBlock()->GetFunc()->HasIntErrorCallSink(DefOp, SSANum, this->address, SinkString)) {
					SMP_fprintf(InfoAnnotFile, " ZZ %s %s \n", SinkString.c_str(), disasm);
				}
				else {
					SMP_fprintf(InfoAnnotFile, " ZZ %s \n", disasm);
				}
			} // end if (!(DEF is stack ptr register))
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
			else {
				++SuppressStackPtrOverflowCount;
			}
#endif

		} // end if flags reg is dead
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
		else {
			++SuppressLiveFlagsOverflowCount;
		}
#endif

	} // end cases 1-2

	// Case 3: Overflow on multiplication with upper bits discarded.
	if (this->MDIsMultiply()) {
		// There are four overflow sub-cases for x86: (A) the multiplication result
		//  can go into EDX:EAX for 32x32=>64 bit multiplication; (B) the result
		//  can go into DX:AX for 16x16=>32 bit; (C) the result can be in AX
		//  for 8x8=>16 bit; (D) see below. The latter case (C) will be detected most easily
		//  as a truncation in a later instruction, i.e. if only AL gets stored
		//  later, then we check the AH bits at that time for a truncation
		//  error. Because our SSA numbering lumps AL, AH, AX, and EAX into
		//  a single canonicalized register, we would have a hard time using
		//  SSA-based def-use chains to determine if AH is dead.
		// For the other two sub-cases, the question is whether EDX becomes dead
		//  starting with the DEF of EDX in the multiply instruction.
		// Case (D) is where the multiply instruction discards the upper bits
		//  of the multiply.
		// Sub-cases A&B are detected by checking if EDX is dead, and if so, then
		//  emitting an annotation to check for the overflow flag. The x86 sets
		//  overflow and carry flags on multiplication instructions based on whether
		//  the result carries out of the lower half of the result to the upper half.
		// Sub-case D is also detected using flags, but we don't need to check whether EDX
		//  is dead. We just need to detect that EDX is not in the DEF set in the
		//  first place. We have a private member flag for that case.
		CheckForOverflow = false;
		if (this->AreMultiplicationBitsDiscarded()) { // Sub-case D
			CheckForOverflow = true;
			assert(this->RTL.GetCount() > 0);
			DefOp = this->RTL.GetRT(0)->GetLeftOperand();
			DefIter = this->FindDef(DefOp);
			assert(DefIter != this->GetLastDef());
			DefHashValue = HashGlobalNameAndSSA(DefOp, DefIter->GetSSANum());
		}
		else {
			// If the instruction were EDX:=EDX*foo, then it would be
			//  the multiplication bits discarded case and would not
			//  reach this else clause. Therefore, if we find EDX in
			//  the DEF set, it is holding upper result bits of the
			//  multiplication and we have the potential for sub-cases A&B
			//  but not sub-case C. So, we check to see if the DEF of EDX
			//  is dead.
			DefOp = InitOp;
			DefOp.type = o_reg;
			DefOp.reg = R_dx;
			DefOp.dtyp = this->GetOperandDtypField();
			DefIter = this->FindDef(DefOp);
			if (DefIter != this->GetLastDef()) {
				// We found DEF of EDX, so it is not AX:=AL*op8 sub-case C.
				// Now, is DEF of EDX dead (i.e. no uses?)
				CheckForOverflow = this->BasicBlock->IsDefDead(this->address, DefOp);
				if (CheckForOverflow) {
					DefHashValue = HashGlobalNameAndSSA(DefOp, DefIter->GetSSANum());
				}
			}
		} // end if sub-case D else if sub-case A or B

		if (CheckForOverflow) { // need an annotation
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
			++NumericAnnotationsCount3;
#endif
			if (this->BasicBlock->IsLocalName(DefOp)) {
				// Local name, find in basic block maps.
				DefFGInfo = this->BasicBlock->GetDefFGInfo(DefHashValue);
			}
			else { // Global name, find in global maps.
				DefFGInfo = this->BasicBlock->GetFunc()->GetDefFGInfo(DefHashValue);
			}

			DefWidthInfo = DefFGInfo.SizeInfo;
			DefBitWidth = LargestBitWidthFromMask(DefWidthInfo);

			DefSignMask = (DefFGInfo.SignMiscInfo & FG_MASK_SIGNEDNESS_BITS);
			if (DefSignMask == 0) {
				// If no sign info from DEF, see if we can get it from the USE regs.
				DefSignMask = this->SignMaskUnionFromUseRegs();
			}

			// Next two statements exclude the inconsistent sign case and the no sign info known case.
			DefIsSigned = (FG_MASK_SIGNED == DefSignMask);  // exact, not bit-mask-AND
			DefIsUnsigned = (FG_MASK_UNSIGNED == DefSignMask);  // exact, not bit-mask-AND

			uval_t ConstValue = 0;
			IdiomCode = 0;
			bool UnsignedAnnot = (this->MDIsUnsignedArithmetic() || DefIsUnsigned);
			bool SignedAnnot = (this->MDIsSignedArithmetic() || DefIsSigned);
			if (0 == DefSignMask) {
				// Prepare DefSignMask for use by IsMultiplyByLargeConst(),
				//  as it is of no more use in case3.
				if (UnsignedAnnot)
					DefSignMask = FG_MASK_UNSIGNED;
				else if (SignedAnnot)
					DefSignMask = FG_MASK_SIGNED;
			}
			if (this->IsMultiplyByLargeConstant(ConstValue, DefSignMask)) {
				IdiomCode = 10;
			}

			if (UnsignedAnnot) {
				SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW UNSIGNED %zu %s ZZ",
					(unsigned long) this->address, this->SMPcmd.size, DefBitWidth, RegNames[DefOp.reg]);
			}
			else if (SignedAnnot) {
				SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW SIGNED %zu %s ZZ",
					(unsigned long) this->address, this->SMPcmd.size, DefBitWidth, RegNames[DefOp.reg]);
			}
			else {
				SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW UNKNOWNSIGN %zu %s ZZ",
					(unsigned long) this->address, this->SMPcmd.size, DefBitWidth, RegNames[DefOp.reg]);
			}
			if (0 < IdiomCode) {
				SMP_fprintf(InfoAnnotFile, " IDIOM %d CONST %lu %s \n", IdiomCode, (unsigned long) ConstValue, disasm);
			}
			else {
				SMP_fprintf(InfoAnnotFile, " %s \n", disasm);
			}
		} // end if (CheckForOverflow)
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
		else {
			++LiveMultiplyBitsCount;
		}
#endif
	} // end of case 3

	// Case 4: Signedness error on move.
	// Case 5: Truncation error on move.
	IdiomCode = 0;
	UseOp = this->GetMoveSource();
	if ((3 == this->OptType) && (o_reg == UseOp.type)) {
		int TruncationIdiomCode = 0;
		bool SuppressTruncation = this->IsBenignTruncation(TruncationIdiomCode);
		// Possibilities for a move: reg to reg, mem to reg, or reg to mem. If we load
		//  from memory into a register, we cannot track signedness in memory unless it
		//  is a stack location. In that case, we record the signedness in the stack
		//  map and transfer it to the reg DEF in SMPInstr.MDSetWidthSignInfo(). That
		//  determines the signedness of the reg DEF and it cannot be in conflict with
		//  the stack memory USE. The load from stack to reg also determines width
		//  of the stack operand and we cannot have a truncation. So, we can restrict
		//  our analysis of cases 4-5 to register-source move instructions, as we
		//  have done in the condition above.
		//
		//  Similarly, we cannot detect a signedness conflict if the destination is a 
		//  memory location that is not known to be a particular stack offset location.
		//
		// So, we only concern ourselves with signedness errors
		//  when the USE operand of the move is a register, and the destination is another
		//  register or a stack location.
		//
		// We can have a truncation error and a signedness error on a single instruction, so
		//  we group them into common code. For example, move the lower half of a 32-bit unsigned
		//  into a 16-bit signed destination. Upper bits set to 1 and discarded would be a 
		//  truncation, and setting the sign bit of the 16-bit signed destination would be a
		//  signedness error.
		//
		// NOTE: Signedness errors are different from overflow and truncation errors. We
		//  can have incomplete knowledge about an instruction's operands and still determine
		//  that truncation occurred. For example, if we do not know whether register EAX
		//  is signed or unsigned, we can still say that storing only AX is a truncation error
		//  if the upper half of EAX is a mixture of one and zero bits. If EAX is unsigned,
		//  we could be more specific and insist that the upper half be all zero bits; if EAX
		//  is signed, we could insist that the upper half of EAX be the sign-extension of AX.
		//  We can avoid false positives by only declaring a truncation error when the upper
		//  half of EAX is not all zero bits or all one bits. This approach allows a few
		//  potential false negatives. With signedness, if we don't know the signedness
		//  of one of the operands, we can only avoid false positives by doing no checks at
		//  all.
		UseIter = this->FindUse(UseOp);
		assert(UseIter != this->GetLastUse());
		UseBitWidth = 8 * GetOpDataSize(UseOp);

		// Now, the question is: Are we storing fewer bits than
		//  we were using in our computations in this DEF-USE chain?
		//  E.g. if we computed using 32 bits and then only store 16,
		//  we have potential truncation error. But if we computed
		//  using 16 bits all along, we have already checked for 16-bit
		//  overflows on arithmetic in the DU chain and there can be no
		//  truncation on this store.
		op_t SearchOp = UseOp;
		// Canonicalize sub-regs for searching DEFs and USEs.
		CanonicalizeOpnd(SearchOp);
		UseHashValue = HashGlobalNameAndSSA(SearchOp, UseIter->GetSSANum());

		if (this->BasicBlock->IsLocalName(SearchOp)) {
			// Local name, find in basic block maps.
			SourceDefFGInfo = this->BasicBlock->GetDefFGInfo(UseHashValue);
			UseFGInfo = this->BasicBlock->GetUseFGInfo(UseHashValue);
		}
		else { // Global name, find in global maps.
			SourceDefFGInfo = this->BasicBlock->GetFunc()->GetDefFGInfo(UseHashValue);
			UseFGInfo = this->BasicBlock->GetFunc()->GetUseFGInfo(UseHashValue);
		}

		SourceDefWidthInfo = SourceDefFGInfo.SizeInfo;
		UseWidthInfo = UseFGInfo.SizeInfo;
		SourceDefBitWidth = LargestBitWidthFromMask(SourceDefWidthInfo);
		UseMaxBitWidth = LargestBitWidthFromMask(UseWidthInfo);
		UseSignMask = (UseFGInfo.SignMiscInfo & FG_MASK_SIGNEDNESS_BITS);
		SourceDefSignInfo = SourceDefFGInfo.SignMiscInfo;
		SourceDefSignMask = (SourceDefSignInfo & FG_MASK_SIGNEDNESS_BITS);

#if 1
		// If we have no signedness info at all for the UseSignMask, but
		//  the SourceDefSignMask has info, then we want to use the
		//  SourceDefSignMask as our signedness info. This is because of
		//  simple instruction sequences in which no signedness can be inferred
		//  from the use, e.g.:
		//
		//  imul eax,ebx  ; eax := eax*ebx and eax&ebx are signed
		//  mov [ebp-8],al  ; store al on stack
		//
		//  If we don't know the signedness of stack location [ebp-8],
		//   then we will end up in the S->? case below and we will emit
		//   a CHECK TRUNCATION UNKNOWNSIGN annotation. This discards the
		//   knowledge we have that EAX is signed, from the IMUL opcode.
		if (0 == UseSignMask) {
			UseSignMask = SourceDefSignMask;
		}
#endif

		// Next six statements exclude the inconsistent sign case and the no sign info known case.
		UseIsSigned = (FG_MASK_SIGNED == UseSignMask);  // exact, not bit-mask-AND
		UseIsUnsigned = (FG_MASK_UNSIGNED == UseSignMask);  // exact, not bit-mask-AND
		SourceDefIsSigned = (FG_MASK_SIGNED == SourceDefSignMask);  // exact, not bit-mask-AND
		SourceDefIsUnsigned = (FG_MASK_UNSIGNED == SourceDefSignMask);  // exact, not bit-mask-AND
		UseSignMixed = (FG_MASK_INCONSISTENT_SIGN == UseSignMask); // exclude uninit sign case
		SourceDefSignMixed = (FG_MASK_INCONSISTENT_SIGN == SourceDefSignMask); // exclude uninit sign case

		// Not only the CHECK SIGNEDNESS annotations depend on the signedness of the
		//  source and destination operands. The CHECK TRUNCATION annotations come
		//  in SIGNED, UNSIGNED, and UNKNOWNSIGN variants, so we need to get the
		//  signedness of the destination operand before we proceeed.
		DefOp = this->RTL.GetRT(0)->GetLeftOperand(); // RTL must be dest := rhs
		op_t DestSearchOp = DefOp;
		bool StackDestination = false;
		// Outargs locations are reused for different function calls, so no inference of their
		//  signedness is valid. We maintain a flag to suppress signedness checks on writes to
		//  outargs locations on the stack. We make an exception for the known unsigned args to
		//  certain library functions.
		bool OutArgsWrite = false;
		bool IgnoreOutArgsWrite = false;
		bool NonStackMemDestination = false;
		if (o_reg == DestSearchOp.type) {
			StackDestination = false;
			CanonicalizeOpnd(DestSearchOp);
		}
		else if (!(MDIsDirectStackAccessOpnd(DefOp, UseFP))) {
			// If destination of move is not a register and is not
			//  a stack location, we cannot track its signedness and width.
			NonStackMemDestination = true;
		}
		else {
			StackDestination = true;
		}
		DefIter = this->FindDef(DestSearchOp);
		DefSSANum = DefIter->GetSSANum();

		if (StackDestination) {
			// Fetch FG info from stack map.
			bool success = this->GetBlock()->GetFunc()->MDGetFGStackLocInfo(this->address, DefOp, DefFGInfo);
			assert(success);
			OutArgsWrite = this->GetBlock()->GetFunc()->IsInOutgoingArgsRegion(DefOp);
			IgnoreOutArgsWrite = OutArgsWrite && (!(this->IsUnsignedArg())); // ignore out args write iff not a known unsigned argument
		}
		else if (NonStackMemDestination) {
			// We can check truncation of USE operand, but we know nothing about
			//  the DEF operand.
			DefFGInfo.SignMiscInfo = 0;
			DefFGInfo.SizeInfo = 0;
		}
		else {
			// Fetch FG info from register FG info maps.
			DefHashValue = HashGlobalNameAndSSA(DestSearchOp, DefSSANum);
			if (this->BasicBlock->IsLocalName(DestSearchOp)) {
				// Local name, find in basic block maps.
				DefFGInfo = this->BasicBlock->GetDefFGInfo(DefHashValue);
			}
			else { // Global name, find in global maps.
				DefFGInfo = this->BasicBlock->GetFunc()->GetDefFGInfo(DefHashValue);
			}
		}

		DefSignMask = (DefFGInfo.SignMiscInfo & FG_MASK_SIGNEDNESS_BITS);
		// Next two statements exclude the inconsistent sign case and the no sign info known case.
		DefIsSigned = (FG_MASK_SIGNED == DefSignMask);  // exact, not bit-mask-AND
		DefIsUnsigned = (FG_MASK_UNSIGNED == DefSignMask);  // exact, not bit-mask-AND
		// Get the Def bit width and maximum bit width for special cases.
		DefWidthInfo = DefFGInfo.SizeInfo;
		DefMaxBitWidth = LargestBitWidthFromMask(DefWidthInfo); // max width over all defs
		DefBitWidth = 8 * GetOpDataSize(DefOp); // width of def in current instruction
		PartialStore = (DefBitWidth < DefMaxBitWidth);

		if (StackDestination) {
			// We only do signedness checks in limited, safe analysis cases on stack writes.
			SuppressSignednessCheck = this->SkipSignednessCheckOnStackWrite(DefSSANum);
			if (SuppressSignednessCheck) {
				IdiomCode = 7;
			}
		}
		else {
			// Check signedness on regs, but not on non-stack memory DEFs.
			SuppressSignednessCheck = NonStackMemDestination;
		}

		// If we set the (source) DEF bit width to 0, it means we wanted to have the USEs determine
		//  the width. This happens on sign-extended and zero-extended loads. If we zero-extend
		//  a 16-bit value to 32 bits, then immediately store the lower 16 bits to a 16-bit location,
		//  then the upper bits cannot have any overflow info yet. But if we do 32-bit arithmetic
		//  on the zero-extended value, and then store the lower 16 bits, we need to check for
		//  truncation. So, the key is whether the value ever got used as a 32-bit value. If it
		//  did, check for truncation; if not, there is no need to check.
		if ((SourceDefBitWidth > UseBitWidth) 
			|| ((SourceDefBitWidth == 0) && (UseMaxBitWidth > UseBitWidth))) {
			// Original DEF (or subsequent USE) was wider than what we are storing now.
			if (SourceDefBitWidth == 0) { // Convert for printing annotation.
				SourceDefBitWidth = 8 * GetOpDataSize(SearchOp);
			}

			// OK, we need to check for possible truncation. But, how we check depends on the
			//  signedness combinations of the source and destination operands of the move.
			//  Each operand can be signed, unsigned, or of unknown sign (and we lump the
			//  inconsistent sign case into the unknown sign case). So, we have a set of 3x3=9
			//  possible combinations of signedness. 
			// Now we have the DefSignMask to compare to the UseSignMask. The nine possible
			//  combinations, and the annotations we want to emit for each, are shown below.
			//  S = SIGNED, U = UNSIGNED, and ? = unknown or inconsistent sign.
			//  S => U indicates a SIGNED being stored into an UNSIGNED, for example.
			//  Assume without loss of generality that register EAX is the source of
			//   all the move instructions, and that only subword register AX is being stored.
			//   We can perform all truncation and signedness checks on EAX just prior to
			//   the move instruction, which is cheaper than performing checks on the 
			//   destination if the destination is in memory.
			//
			//  U => U
			//  U => S
			//  S => U
			//  U => ?
			//  ? => U
			//
			//  In these first five cases, EAX must be the zero-extension of AX else there is
			//   a truncation error. In the three cases in which the source (EAX/AX) is UNSIGNED,
			//   discarding upper bits that are not zero is obviously truncation. In the case
			//   of S => U, if the upper bits of EAX are not all zeroes, then we either have
			//   a large positive value of EAX that is being truncated, or EAX is negative and
			//   the lower bits will be misinterpreted in the unsigned destination. Finally,
			//   the ? => U case must be either U => U or S => U, and these two cases already
			//   share the demand that EAX be the zero-extension of AX. So, these five cases
			//   will receive the annotation: CHECK TRUNCATION UNSIGNED 32 EAX 16 AX which
			//   means that EAX is tested against AX to see if it is the 32-bit zero-extension
			//   of 16-bit reg AX.
			//  In the U => S case, we can have a signedness error as well as truncation. Even
			//   if the truncation check passes (all upper half bits of EAX are zero), the top
			//   bit of AX might be 1, and this will be misinterpreted as a sign bit in the
			//   destination. So, this case receives a second annotation: CHECK SIGNEDNESS SIGNED 16 AX.
			//  In the two cases that involve signedness uncertainty, there are possible signedness
			//   errors that we are not checking at tun-time, because we do not have enough information
			//   to perform the checks without generating many more false positives than true positives.
			//   As a result, false negatives on signedness can occur.
			//
			// On to more of the 9 combinations:
			//
			// S => S
			//
			// In this case, EAX must be the sign-extension of AX. Because the destination is also
			//  signed, nothing is lost if the sign-extension bits (all zeroes or all ones) are dropped.
			//  We emit a CHECK TRUNCATION SIGNED 32 EAX 16 AX annotation to test EAX == sign-extended AX.
			//
			// S => ?
			// ? => S
			// ? => ?
			//
			// These final three cases all involve at least one operand of unknown signedness, and no
			//  operands that are known to be unsigned. In each case, there are two possibilities:
			//  either EAX must be the sign-extension of AX, or EAX must be the zero-extension of AX.
			//  Because of the uncertainty that is represented by the question marks, we are not sure
			//  which of these two cases we are dealing with. However, rather than just give up and
			//  perform no run-time checks (to avoid false positives), we can still perform a run-time
			//  check that will catch (perhaps most) true positives while causing no false positives.
			//  We can insist that EAX must be EITHER the sign-extension or the zero-extension of AX.
			//  To be neither type of extension of AX implies that some sort of truncation is happening.
			//  So, we emit a CHECK TRUNCATION UNKNOWNSIGN 32 EAX 16 AX annotation, and the Strata
			//  instrumentation will check for either EAX == sign-extended AX or EAX == zero-extended AX
			//  being true. If neither is true, we raise a true positive alert. False negatives on
			//  signedness errors are the result of the uncertainty, but all truncations are detected
			//  for all nine cases.

			bool HasSinkString = this->GetBlock()->GetFunc()->HasIntErrorCallSink(DestSearchOp, DefSSANum, this->address, SinkString);
			if (DefIsUnsigned || UseIsUnsigned) {
				// First five cases above: any UNSIGNED operand leads to CHECK TRUNCATION UNSIGNED annotation.
				if (!SuppressTruncation) {
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK TRUNCATION UNSIGNED %zu %s %zu %s",
						(unsigned long) this->address, this->SMPcmd.size, SourceDefBitWidth,
						MDGetRegName(SearchOp), UseBitWidth, MDGetRegName(UseOp));
					if (HasSinkString) {
						SMP_fprintf(InfoAnnotFile, " ZZ %s %s \n", SinkString.c_str(), disasm);
					}
					else {
						SMP_fprintf(InfoAnnotFile, " ZZ %s \n", disasm);
					}
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
					++TruncationAnnotationsCount;
#endif
				}
				else {
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK TRUNCATION UNSIGNED %zu %s %zu %s ZZ IDIOM %d %s \n",
						(unsigned long) this->address, this->SMPcmd.size, SourceDefBitWidth,
						MDGetRegName(SearchOp), UseBitWidth, MDGetRegName(UseOp), TruncationIdiomCode, disasm);
				}
				if (UseIsUnsigned && DefIsSigned && !OutArgsWrite && !PartialStore) {
					if (!SuppressSignednessCheck && (0 == IdiomCode)) {
						unsigned short DummySignMask;
						if ((0 != TruncationIdiomCode) && this->MDIsSignedLoad(DummySignMask)) {
							// No truncation, extended load, so signedness check is unreliable.
							IdiomCode = 20;
							SuppressSignednessCheck = true;
						}
					}
					if (SuppressSignednessCheck && (0 == IdiomCode)) {
						;
					}
					else if (!SuppressSignednessCheck && (0 == IdiomCode)) {
						SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK SIGNEDNESS SIGNED %zu %s ZZ %s \n",
							(unsigned long) this->address, this->SMPcmd.size, UseBitWidth, MDGetRegName(UseOp), disasm);
					}
					else {
						SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK SIGNEDNESS SIGNED %zu %s ZZ IDIOM %d %s \n",
							(unsigned long) this->address, this->SMPcmd.size, UseBitWidth, MDGetRegName(UseOp), IdiomCode, disasm);
					}
				}
			}
			else if (DefIsSigned && UseIsSigned) {
				// S => S case above. Emit CHECK TRUNCATION SIGNED annotation.
				if (!SuppressTruncation) {
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK TRUNCATION SIGNED %zu %s %zu %s",
						(unsigned long) this->address, this->SMPcmd.size, SourceDefBitWidth,
						MDGetRegName(SearchOp), UseBitWidth, MDGetRegName(UseOp));
						if (HasSinkString) {
							SMP_fprintf(InfoAnnotFile, " ZZ %s %s \n", SinkString.c_str(), disasm);
						}
						else {
							SMP_fprintf(InfoAnnotFile, " ZZ %s \n", disasm);
						}
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
					++TruncationAnnotationsCount;
#endif
				}
				else {
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK TRUNCATION SIGNED %zu %s %zu %s ZZ IDIOM %d %s \n",
						(unsigned long) this->address, this->SMPcmd.size, SourceDefBitWidth,
						MDGetRegName(SearchOp), UseBitWidth, MDGetRegName(UseOp), TruncationIdiomCode, disasm);
				}
			}
			else {
				// S => ?, ? => S, ? => ? cases above: CHECK TRUNCATION UNKNOWNSIGN annotation.
				if (!SuppressTruncation) {
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK TRUNCATION UNKNOWNSIGN %zu %s %zu %s",
						(unsigned long) this->address, this->SMPcmd.size, SourceDefBitWidth,
						MDGetRegName(SearchOp), UseBitWidth, MDGetRegName(UseOp));
					if (HasSinkString) {
						SMP_fprintf(InfoAnnotFile, " ZZ %s %s \n", SinkString.c_str(), disasm);
					}
					else {
						SMP_fprintf(InfoAnnotFile, " ZZ %s \n", disasm);
					}
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
						++TruncationAnnotationsCount;
#endif
				}
				else {
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK TRUNCATION UNKNOWNSIGN %zu %s %zu %s ZZ IDIOM %d %s \n",
						(unsigned long) this->address, this->SMPcmd.size, SourceDefBitWidth,
						MDGetRegName(SearchOp), UseBitWidth, MDGetRegName(UseOp), TruncationIdiomCode, disasm);
				}
			}
#if 1
			// Now check for signedness conflicts between the UseOp USEs and its DEF.
			if (!OutArgsWrite && !PartialStore) { // Inferred signedness of outargs location is invalid anyway
				if (!SuppressSignednessCheck && (0 == IdiomCode)) {
					unsigned short DummySignMask;
					if ((0 != TruncationIdiomCode) && this->MDIsSignedLoad(DummySignMask)) {
						// No truncation, extended load, so signedness check is unreliable.
						IdiomCode = 20;
						SuppressSignednessCheck = true;
					}
				}
				if (UseIsSigned && SourceDefIsUnsigned) {
					if (SuppressSignednessCheck && (0 == IdiomCode)) {
						;
					}
					else if (!SuppressSignednessCheck && (0 == IdiomCode)) {
						SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK SIGNEDNESS UNSIGNED %zu %s ZZ %s \n",
							(unsigned long) this->address, this->SMPcmd.size, UseBitWidth, MDGetRegName(UseOp), disasm);
					}
					else {
						SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK SIGNEDNESS UNSIGNED %zu %s ZZ IDIOM %d %s \n",
							(unsigned long) this->address, this->SMPcmd.size, UseBitWidth, MDGetRegName(UseOp), IdiomCode, disasm);
					}
				}
				else if (UseIsUnsigned && SourceDefIsSigned) {
					// Currently same annotation, but might differ in the future for better forensics
					//  and more precise diagnostic messages.
					if (SuppressSignednessCheck && (0 == IdiomCode)) {
						;
					}
					else if (!SuppressSignednessCheck && (0 == IdiomCode)) {
						SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK SIGNEDNESS SIGNED %zu %s ZZ %s \n",
							(unsigned long) this->address, this->SMPcmd.size, UseBitWidth, MDGetRegName(UseOp), disasm);
					}
					else {
						SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK SIGNEDNESS UNSIGNED %zu %s ZZ IDIOM %d %s \n",
							(unsigned long) this->address, this->SMPcmd.size, UseBitWidth, MDGetRegName(UseOp), IdiomCode, disasm);
					}
				}
				else if ((!SourceDefSignMixed) && UseSignMixed) {
					// DEF has consistent and known signedness, USE is inconsistent.
					if (SuppressSignednessCheck && (0 == IdiomCode)) {
						;
					}
					else if (!SuppressSignednessCheck && (0 == IdiomCode)) {
						SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK SIGNEDNESS %s %zu %s ZZ %s \n",
							(unsigned long) this->address, this->SMPcmd.size, SignednessStrings[SourceDefSignMask], 
							UseBitWidth, MDGetRegName(UseOp), disasm);
					}
					else {
						SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK SIGNEDNESS %s %zu %s ZZ IDIOM %d %s \n",
							(unsigned long) this->address, this->SMPcmd.size, SignednessStrings[SourceDefSignMask], 
							UseBitWidth, MDGetRegName(UseOp), IdiomCode, disasm);
					}
				}
			}
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
			if (SuppressSignednessCheck || (0 < IdiomCode)) {
				++SuppressSignednessOnTruncation;
			}
#endif
#endif
		} // end if truncation
		else if (!IgnoreOutArgsWrite && !PartialStore) { // still need to check for signedness errors even if no truncation
			if (!SuppressSignednessCheck && (0 == IdiomCode)) {
				unsigned short DummySignMask;
				if (this->MDIsSignedLoad(DummySignMask)) {
					// No truncation, extended load, so signedness check is unreliable.
					IdiomCode = 20;
					SuppressSignednessCheck = true;
				}
			}
			if (this->IsUnsignedArg()) {
				DefIsUnsigned = true;
			}
			if (UseIsSigned && DefIsUnsigned) {
				if (SuppressSignednessCheck && (0 == IdiomCode)) {
					;
				}
				else if (!SuppressSignednessCheck && (0 == IdiomCode)) {
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK SIGNEDNESS UNSIGNED %zu %s ZZ %s \n",
						(unsigned long) this->address, this->SMPcmd.size, UseBitWidth, MDGetRegName(UseOp), disasm);
				}
				else {
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK SIGNEDNESS UNSIGNED %zu %s ZZ IDIOM %d %s \n",
						(unsigned long) this->address, this->SMPcmd.size, UseBitWidth, MDGetRegName(UseOp), IdiomCode, disasm);
				}
			}
			else if (UseIsUnsigned && DefIsSigned) {
				// Currently UNSIGNED and SIGNED annotations for signedness differ only in the
				//  arithmetic saturation value applied as a recovery action. UNSIGNED means
				//  left-hand-side is UNSIGNED so saturate a negative right-hand-side up to 0,
				//  while SIGNED means lhs is SIGNED so saturate large rhs to 0x7fff....
				//  For inconsistent sign cases we default to SIGNED.
				if (SuppressSignednessCheck && (0 == IdiomCode)) {
					;
				}
				else if (!SuppressSignednessCheck && (0 == IdiomCode)) {
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK SIGNEDNESS SIGNED %zu %s ZZ %s \n",
						(unsigned long) this->address, this->SMPcmd.size, UseBitWidth, MDGetRegName(UseOp), disasm);
				}
				else {
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK SIGNEDNESS SIGNED %zu %s ZZ IDIOM %d %s \n",
						(unsigned long) this->address, this->SMPcmd.size, UseBitWidth, MDGetRegName(UseOp), IdiomCode, disasm);
				}
			}
			else if (UseIsSigned && SourceDefIsUnsigned) {
				if (SuppressSignednessCheck && (0 == IdiomCode)) {
					;
				}
				else if (!SuppressSignednessCheck && (0 == IdiomCode)) {
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK SIGNEDNESS UNSIGNED %zu %s ZZ %s \n",
						(unsigned long) this->address, this->SMPcmd.size, UseBitWidth, MDGetRegName(UseOp), disasm);
				}
				else {
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK SIGNEDNESS UNSIGNED %zu %s ZZ IDIOM %d %s \n",
						(unsigned long) this->address, this->SMPcmd.size, UseBitWidth, MDGetRegName(UseOp), IdiomCode, disasm);
				}
			}
			else if (UseIsUnsigned && SourceDefIsSigned) {
				// Currently same annotation, but might differ in the future for better forensics
				//  and more precise diagnostic messages.
				if (SuppressSignednessCheck && (0 == IdiomCode)) {
					;
				}
				else if (!SuppressSignednessCheck && (0 == IdiomCode)) {
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK SIGNEDNESS SIGNED %zu %s ZZ %s \n",
						(unsigned long) this->address, this->SMPcmd.size, UseBitWidth, MDGetRegName(UseOp), disasm);
				}
				else {
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK SIGNEDNESS SIGNED %zu %s ZZ IDIOM %d %s \n",
						(unsigned long) this->address, this->SMPcmd.size, UseBitWidth, MDGetRegName(UseOp), IdiomCode, disasm);
				}
			}
#if 0
			else if ((!SourceDefSignMixed) && UseSignMixed) {
				// source DEF has consistent and known signedness, source USE is inconsistent.
				SMP_fprintf(InfoAnnotFile, "%10x %6d INSTR CHECK SIGNEDNESS SIGNED %u %s ZZ %s \n",
					this->address, this->SMPcmd.size, UseBitWidth, MDGetRegName(UseOp), disasm);
			}
#endif
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
			if (SuppressSignednessCheck && (0 == IdiomCode)) {
				;
			}
			else if (!SuppressSignednessCheck && (0 == IdiomCode)) {
				++SignednessWithoutTruncationCount;
			}
			else {
				++SuppressSignednessOnTruncation;
			}
#endif
		} // end if truncation else check signedness
	} // end of cases 4-5, (3 == OptType) checking for TRUNCATION and SIGNEDNESS errors
	else if ((this->MDIsLoadEffectiveAddressInstr()) && (!(this->IsNop() || this->IsRegClearIdiom()))) {
		// Case 6: Load Effective Address opcodes can do arithmetic that silently overflows.
		this->MDEmitLeaOpcodeOverflowAnnotations(InfoAnnotFile, LoopList);
	} // end of case 6, LoadEffectiveAddress instruction
	else if (this->MDDoublesWidth()) {
		// case 7: half of register is sign-extended into the full register.
		//  Potential truncation error if entire register was DEFed first, because
		//  only the lower half is used. That also makes a potential signedness
		//  error, because the "sign bit" that is being extended is really a data bit,
		//  not a sign bit.
		DefIter = this->GetFirstNonFlagsDef();
		assert(DefIter != this->GetLastDef());
		DefOp = DefIter->GetOp();
		assert(o_reg == DefOp.type);
		SSANum = DefIter->GetSSANum();
		DefHashValue = HashGlobalNameAndSSA(DefOp, SSANum);
		UseIter = this->GetFirstUse();
		assert(UseIter != this->GetLastUse());
		UseOp = UseIter->GetOp();
		assert(o_reg == UseOp.type);
		SSANum = UseIter->GetSSANum();
		UseHashValue = HashGlobalNameAndSSA(UseOp, SSANum);
		if (this->GetBlock()->IsLocalName(DefOp)) {
			DefFGInfo = this->GetBlock()->GetDefFGInfo(DefHashValue);
			SourceDefFGInfo = this->GetBlock()->GetDefFGInfo(UseHashValue);
		}
		else {
			DefFGInfo = this->GetBlock()->GetFunc()->GetDefFGInfo(DefHashValue);
			SourceDefFGInfo = this->GetBlock()->GetFunc()->GetDefFGInfo(UseHashValue);
		}
		DefWidthInfo = DefFGInfo.SizeInfo;
		DefMaxBitWidth = LargestBitWidthFromMask(DefWidthInfo); // max width over all defs
		SourceDefWidthInfo = SourceDefFGInfo.SizeInfo;
		SourceDefBitWidth = LargestBitWidthFromMask(SourceDefWidthInfo); // max width over all defs
		// Was the USE in the width-doubling instruction originally DEFed to have more bits
		//  than are used in the width-doubling instruction? If so, we have truncation and
		//  signedness errors to check at run time.
		UseBitWidth = (DefMaxBitWidth / 2); // USE should have been DEFed with this bit width
		if (SourceDefBitWidth > UseBitWidth) {
			// Make checks signed, because of the implications of sign extension by these opcodes.
			SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK TRUNCATION SIGNED %zu %s %zu %s ZZ %s \n",
				(unsigned long) this->address, this->SMPcmd.size, DefMaxBitWidth,
					MDGetRegName(DefOp), UseBitWidth, MDGetRegName(UseOp), disasm);
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
			++WidthDoublingTruncationCount;
#endif
		}
	} // end of case 7, doubles width inside register
	else if ((BADADDR != this->CallTarget) && (!this->IsCallUsedAsJump())) {
		// PEASOUP wants info on memset() calls.
		string FuncName = this->GetTrimmedCalledFunctionName();
		if (0 == FuncName.compare("memset")) {
			op_t MemSetTarget;
			size_t MemSetSize;
			int StackOffset;
			bool FPRelativeTarget = false; // original target before stack delta normalization
			if (this->GetBlock()->AnalyzeMemSet(this->GetAddr(), MemSetTarget, MemSetSize, StackOffset, FPRelativeTarget)) {
				if (0 < MemSetSize) {
					// Emit annotation.
					// NOTE: We want the unnormalized stack operand, so that Strata and SPRI will get
					//  annotations that match what is seen in the assembly language.
					if (FPRelativeTarget) {
						// Must be negative offset from EBP.
						assert(UseFP);
						StackOffset -= (int) this->GetBlock()->GetFunc()->GetFramePtrStackDelta();
						SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR MEMSET STACKOFFSET_EBP %d SIZE %zu ZZ %s \n",
							(unsigned long) this->address, this->SMPcmd.size, StackOffset, MemSetSize, disasm);
					}
					else {
						// Must be non-negative offset from ESP.
						StackOffset -= this->GetStackPtrOffset();
						SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR MEMSET STACKOFFSET_ESP %d SIZE %zu ZZ %s \n",
							(unsigned long) this->address, this->SMPcmd.size, StackOffset, MemSetSize, disasm);
					}
				}
			}
		}
	} // end of memset() case

	return;
} // end of SMPInstr::EmitIntegerErrorAnnotations()

#define MAX_OFFSET_STR_LEN 40

// Emit overflow annotations for lea opcodes that perform arithmetic that
//  can overflow without affecting the flags.
void SMPInstr::MDEmitLeaOpcodeOverflowAnnotations(FILE *InfoAnnotFile, list<size_t> &LoopList) {
	set<DefOrUse, LessDefUse>::iterator UseIter, DefIter;
	size_t OpNum;
	int BaseReg;
	int IndexReg;
	ushort ScaleFactor;
	ea_t offset;
	int SignedOffset;
	bool ScaledIndexReg;
	bool SourceFound = false;
	bool DataPointer = false;
	int SSANum;
	SMPOperandType DefType, UseType;
	int UseHashValue;
	int IdiomCode = 0;
	struct FineGrainedInfo UseFGInfo, SourceDefFGInfo;
	unsigned short UseSignMask, SourceDefSignMask, BaseRegSignMask, TempSignMask;
	unsigned short BaseRegWidthInfo, UseBitWidthInfo;
	size_t BaseRegMaxWidth, IndexRegMaxWidth, TempMaxWidth;
	char OffsetString[MAX_OFFSET_STR_LEN];
	op_t TempOp, DefOp;

	for (OpNum = 0; OpNum < UA_MAXOP; ++OpNum) {
		TempOp = this->SMPcmd.Operands[OpNum];
		if (this->features & UseMacros[OpNum]) { // USE
			if ((TempOp.type >= o_mem) && (TempOp.type <= o_displ)) {
				MDExtractAddressFields(TempOp, BaseReg, IndexReg, ScaleFactor, offset);
				SignedOffset = (int) offset; // IDA Pro makes offset unsigned for some reason.
				SourceFound = true;
				break;
			}
		}
	}
	assert(SourceFound);
	if (MDIsStackAccessOpnd(TempOp, this->BasicBlock->GetFunc()->UsesFramePointer())) {
		// If the lea operand is something like lea ebx,[esp+4] we do not want to waste
		//  time checking for overflow, because stack pointers and frame pointers
		//  are kept within integer bounds (and if not, something big and terrible will
		//  happen long before integer bounds are overflowed or underflowed).
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
		++SuppressStackPtrOverflowCount;
#endif
		return;
	}
	else { // Check for the benign overflow cases we want to ignore.
		DefIter = this->GetFirstNonFlagsDef();
		assert(DefIter != this->GetLastDef());
		DefOp = DefIter->GetOp();
		SSANum = DefIter->GetSSANum();
		DefType = DefIter->GetType();
		DataPointer = IsDataPtr(DefType);
		if (this->IsHashOperation()) {
			IdiomCode = 15;
		}
		else if (this->GetBlock()->IsBenignOverflowDEF(DefOp, SSANum, this->GetAddr(), this->MDIsUnderflowingOpcode(), IdiomCode)) {
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
			++BenignOverflowDefCount;
#endif
			;
		}
	}

	if (0 == IdiomCode) {
		// Any overflow or underflow producing a PTROFFSET type should be suppressed.
		for (DefIter = this->GetFirstDef(); DefIter != this->GetLastDef(); ++DefIter) {
			DefType = DefIter->GetType();
			if (IsEqType(DefType, PTROFFSET)) {
				IdiomCode = 19;
			}
			else if (IsEqType(DefType, NEGATEDPTR)) {
				IdiomCode = 13;
			}
		}
	}
	if (0 == IdiomCode) {
		// Any overflow or underflow using a PTROFFSET type should be suppressed.
		for (UseIter = this->GetFirstUse(); UseIter != this->GetLastUse(); ++UseIter) {
			UseType = UseIter->GetType();
			if (IsEqType(UseType, PTROFFSET)) {
				IdiomCode = 19;
			}
			else if (IsEqType(UseType, NEGATEDPTR)) {
				IdiomCode = 13;
			}
		}
	}

	char *disasm = DisAsmText.GetDisAsm(this->GetAddr());

	ScaledIndexReg = (0 < ScaleFactor);
	if (0 != SignedOffset) {
		(void) SMP_snprintf(OffsetString, MAX_OFFSET_STR_LEN-2, "%d", SignedOffset);
	}

	// Build up the computational string one operation at a time and emit
	//  CHECK OVERFLOW annotations after each step.
	string CurrString("");
	const char *ScaleStrings[4] = {"", "*2", "*4", "*8"};
	string PtrString("");
	if (IdiomCode == 0) {
		if (!DataPointer && (1 == LoopList.size())) { // Start with simple case of blocks only present in one loop
			SMPOperandType MemType = UNINIT;
			size_t Counter = 0;
			size_t LoopNum = LoopList.front();
			this->GetBlock()->GetFunc()->ResetProcessedBlocks();
			bool AddrRegOnly = this->GetBlock()->IsDefOnlyUsedAsAddressReg(this->GetAddr(), DefOp, LoopNum, Counter, MemType);
			if (AddrRegOnly && (0 < Counter)) {
				// Similarly, let C7 (buffer overflow/underflow) defenses handle the issues if it is only an index register.
				DefType = MemType;					
				DataPointer = true;
			}
		}
		if (DataPointer) {
			if (IsEqType(STACKPTR, DefType))
				PtrString = "STACKMEMSINK";
			else if (IsEqType(HEAPPTR, DefType))
				PtrString = "HEAPMEMSINK";
			else if (IsEqType(GLOBALPTR, DefType))
				PtrString = "GLOBALMEMSINK";
			else
				PtrString = "MEMORYSINK";
			IdiomCode = 18;
		}
	}
	op_t RegOp;
	RegOp.type = o_reg;

	// Gather signedness info about BaseReg, if any, that will be used in multiple cases below.
	if (R_none != BaseReg) {
		RegOp.reg = MDCanonicalizeSubReg(BaseReg);
		RegOp.dtyp = this->GetOperandDtypField();
		UseIter = this->FindUse(RegOp);
		assert(UseIter != this->GetLastUse());
		UseHashValue = HashGlobalNameAndSSA(RegOp, UseIter->GetSSANum());
		if (this->BasicBlock->IsLocalName(RegOp)) {
			// Local name, find in basic block maps.
			SourceDefFGInfo = this->BasicBlock->GetDefFGInfo(UseHashValue);
			UseFGInfo = this->BasicBlock->GetUseFGInfo(UseHashValue);
		}
		else { // Global name, find in global maps.
			SourceDefFGInfo = this->BasicBlock->GetFunc()->GetDefFGInfo(UseHashValue);
			UseFGInfo = this->BasicBlock->GetFunc()->GetUseFGInfo(UseHashValue);
		}
		UseSignMask = (UseFGInfo.SignMiscInfo & FG_MASK_SIGNEDNESS_BITS);
		SourceDefSignMask = (SourceDefFGInfo.SignMiscInfo & FG_MASK_SIGNEDNESS_BITS);
		if (UseSignMask == 0) {
			// Get signedness info wherever it is available.
			UseSignMask = SourceDefSignMask;
		}
		BaseRegSignMask = UseSignMask;
		if ((17 == IdiomCode) && (FG_MASK_UNSIGNED == BaseRegSignMask)) {
			// An IdiomCode of 17 means not a benign overflow, but an addition that
			//  produces a jump table offset, which can be an addition of mixed signedness
			//  that produces false positives if treated as UNSIGNED. See discussion in
			//  SMPBasicBlock::IsBenignOverflowDEF().
			BaseRegSignMask = FG_MASK_INCONSISTENT_SIGN;
		}
		BaseRegWidthInfo = (UseFGInfo.SizeInfo & FG_MASK_BITWIDTH_FIELDS);
		if (0 == BaseRegWidthInfo) {
			BaseRegWidthInfo = (SourceDefFGInfo.SizeInfo & FG_MASK_BITWIDTH_FIELDS);
		}
		BaseRegMaxWidth = LargestBitWidthFromMask(BaseRegWidthInfo);
	}
	else {
		BaseRegMaxWidth = 0;
		BaseRegSignMask = 0;
	}

	if (R_none != IndexReg) {
		// Get signedness info for IndexReg.
		RegOp.reg = MDCanonicalizeSubReg(IndexReg);
		RegOp.dtyp = this->GetOperandDtypField();
		UseIter = this->FindUse(RegOp);
		assert(UseIter != this->GetLastUse());
		UseHashValue = HashGlobalNameAndSSA(RegOp, UseIter->GetSSANum());
		if (this->BasicBlock->IsLocalName(RegOp)) {
			// Local name, find in basic block maps.
			SourceDefFGInfo = this->BasicBlock->GetDefFGInfo(UseHashValue);
			UseFGInfo = this->BasicBlock->GetUseFGInfo(UseHashValue);
		}
		else { // Global name, find in global maps.
			SourceDefFGInfo = this->BasicBlock->GetFunc()->GetDefFGInfo(UseHashValue);
			UseFGInfo = this->BasicBlock->GetFunc()->GetUseFGInfo(UseHashValue);
		}
		UseSignMask = (UseFGInfo.SignMiscInfo & FG_MASK_SIGNEDNESS_BITS);
		SourceDefSignMask = (SourceDefFGInfo.SignMiscInfo & FG_MASK_SIGNEDNESS_BITS);
		if (UseSignMask == 0) {
			// Get signedness info wherever it is available.
			UseSignMask = SourceDefSignMask;
		}
		if ((17 == IdiomCode) && (FG_MASK_UNSIGNED == UseSignMask)) {
			// An IdiomCode of 17 means not a benign overflow, but an addition that
			//  produces a jump table offset, which can be an addition of mixed signedness
			//  that produces false positives if treated as UNSIGNED. See discussion in
			//  SMPBasicBlock::IsBenignOverflowDEF().
			UseSignMask = FG_MASK_INCONSISTENT_SIGN;
			IdiomCode = 0; // reset; not a benign code idiom
		}
		UseBitWidthInfo = (UseFGInfo.SizeInfo & FG_MASK_BITWIDTH_FIELDS);
		IndexRegMaxWidth = LargestBitWidthFromMask(UseBitWidthInfo);
		TempSignMask = (BaseRegSignMask | UseSignMask);
		TempMaxWidth = (BaseRegMaxWidth >= IndexRegMaxWidth) ? BaseRegMaxWidth : IndexRegMaxWidth;

		if (ScaledIndexReg) {
			assert((ScaleFactor >= 1) && (ScaleFactor <= 3));
			assert((IndexReg >= R_ax) && (IndexReg <= R_bh));
			CurrString += RegNames[IndexReg];
			CurrString += ScaleStrings[ScaleFactor];
			if (IdiomCode > 0) {
				if (IdiomCode == 18) {
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW %s %zu %s ZZ IDIOM %d %s %s \n",
						(unsigned long) this->address, this->SMPcmd.size, LeaSignednessStrings[UseSignMask], 
						IndexRegMaxWidth, CurrString.c_str(), IdiomCode, PtrString.c_str(), disasm);
				}
				else {
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW %s %zu %s ZZ IDIOM %d %s \n",
						(unsigned long) this->address, this->SMPcmd.size, LeaSignednessStrings[UseSignMask], 
						IndexRegMaxWidth, CurrString.c_str(), IdiomCode, disasm);
				}
			}
			else {
				SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW %s %zu %s ZZ %s \n",
					(unsigned long) this->address, this->SMPcmd.size, LeaSignednessStrings[UseSignMask], 
					IndexRegMaxWidth, CurrString.c_str(), disasm);
			}
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
			++LeaInstOverflowCount;
#endif
			if (R_none != BaseReg) {
				// Have BaseReg+IndexReg*ScaleFactor
				string TempStr(CurrString);
				CurrString.clear();
				CurrString += RegNames[BaseReg];
				CurrString += "+";
				CurrString += TempStr;
				if (IdiomCode > 0) {
					if (IdiomCode == 18) {
						SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW %s %zu %s ZZ IDIOM %d %s %s \n",
							(unsigned long) this->address, this->SMPcmd.size, LeaSignednessStrings[TempSignMask], 
							TempMaxWidth, CurrString.c_str(), IdiomCode, PtrString.c_str(), disasm);
					}
					else {
						SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW %s %zu %s ZZ IDIOM %d %s \n",
							(unsigned long) this->address, this->SMPcmd.size, LeaSignednessStrings[TempSignMask], 
							TempMaxWidth, CurrString.c_str(), IdiomCode, disasm);
					}
				}
				else {
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW %s %zu %s ZZ %s \n",
						(unsigned long) this->address, this->SMPcmd.size, LeaSignednessStrings[TempSignMask], 
						TempMaxWidth, CurrString.c_str(), disasm);
				}
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
				++LeaInstOverflowCount;
#endif
			}
			if (0 != SignedOffset) {
				// We have  [ BaseReg + ] IndexReg*ScaleFactor+offset [BaseReg or not]
				//  CurrString has everything through the end of the scalefactor in either case.
#if 0 // easier for instrumentation to always use ADD, even for negative offsets
				if (0 < SignedOffset)
#endif
					CurrString += "+";

				CurrString += OffsetString;
				if (IdiomCode > 0) {
					if (IdiomCode == 18) {
						SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW %s %zu %s ZZ IDIOM %d %s %s \n",
							(unsigned long) this->address, this->SMPcmd.size, LeaSignednessStrings[TempSignMask], 
							TempMaxWidth, CurrString.c_str(), IdiomCode, PtrString.c_str(), disasm);
					}
					else {
						SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW %s %zu %s ZZ IDIOM %d %s \n",
							(unsigned long) this->address, this->SMPcmd.size, LeaSignednessStrings[TempSignMask], 
							TempMaxWidth, CurrString.c_str(), IdiomCode, disasm);
					}
				}
				else {
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW %s %zu %s ZZ %s \n",
						(unsigned long) this->address, this->SMPcmd.size, LeaSignednessStrings[TempSignMask], 
						TempMaxWidth, CurrString.c_str(), disasm);
				}
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
				++LeaInstOverflowCount;
#endif
			}
		}
		else if (R_none != BaseReg) {
			// We have BaseReg+IndexReg, unscaled.
			CurrString += RegNames[BaseReg];
			CurrString += "+";
			CurrString += RegNames[IndexReg];
			if (IdiomCode > 0) {
				if (IdiomCode == 18) {
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW %s %zu %s ZZ IDIOM %d %s %s \n",
						(unsigned long) this->address, this->SMPcmd.size, LeaSignednessStrings[TempSignMask], 
						TempMaxWidth, CurrString.c_str(), IdiomCode, PtrString.c_str(), disasm);
				}
				else {
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW %s %zu %s ZZ IDIOM %d %s \n",
						(unsigned long) this->address, this->SMPcmd.size, LeaSignednessStrings[TempSignMask], 
						TempMaxWidth, CurrString.c_str(), IdiomCode, disasm);
				}
			}
			else {
				SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW %s %zu %s ZZ %s \n",
					(unsigned long) this->address, this->SMPcmd.size, LeaSignednessStrings[TempSignMask], 
					TempMaxWidth, CurrString.c_str(), disasm);
			}
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
			++LeaInstOverflowCount;
#endif
			if (0 != SignedOffset) {
				// We have BaseReg + IndexReg + offset
#if 0 // easier for instrumentation to always use ADD, even for negative offsets
				if (0 < SignedOffset)
#endif
					CurrString += "+";

				CurrString += OffsetString;
				if (IdiomCode > 0) {
					if (IdiomCode == 18) {
						SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW %s %zu %s ZZ IDIOM %d %s %s \n",
							(unsigned long) this->address, this->SMPcmd.size, LeaSignednessStrings[TempSignMask], 
							TempMaxWidth, CurrString.c_str(), IdiomCode, PtrString.c_str(), disasm);
					}
					else {
						SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW %s %zu %s ZZ IDIOM %d %s \n",
							(unsigned long) this->address, this->SMPcmd.size, LeaSignednessStrings[TempSignMask], 
							TempMaxWidth, CurrString.c_str(), IdiomCode, disasm);
					}
				}
				else {
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW %s %zu %s ZZ %s \n",
						(unsigned long) this->address, this->SMPcmd.size, LeaSignednessStrings[TempSignMask], 
						TempMaxWidth, CurrString.c_str(), disasm);
				}
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
				++LeaInstOverflowCount;
#endif
			}
		}
		else if (0 != SignedOffset) {
			// We have just IndexReg+offset.
			CurrString += RegNames[IndexReg];
#if 0 // easier for instrumentation to always use ADD, even for negative offsets
			if (0 < SignedOffset)
#endif
				CurrString += "+";

			CurrString += OffsetString;
			if (IdiomCode > 0) {
				if (IdiomCode == 18) {
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW %s %zu %s ZZ IDIOM %d %s %s \n",
						(unsigned long) this->address, this->SMPcmd.size, LeaSignednessStrings[TempSignMask], 
						TempMaxWidth, CurrString.c_str(), IdiomCode, PtrString.c_str(), disasm);
				}
				else {
					SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW %s %zu %s ZZ IDIOM %d %s \n",
						(unsigned long) this->address, this->SMPcmd.size, LeaSignednessStrings[TempSignMask], 
						TempMaxWidth, CurrString.c_str(), IdiomCode, disasm);
				}
			}
			else {
				SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW %s %zu %s ZZ %s \n",
					(unsigned long) this->address, this->SMPcmd.size, LeaSignednessStrings[TempSignMask], 
					TempMaxWidth, CurrString.c_str(), disasm);
			}
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
			++LeaInstOverflowCount;
#endif
		}
		else {
			// Just IndexReg, no BaseReg or offset, so nothing to do.
			;
		}
	}
	else if ((R_none != BaseReg) && (SignedOffset != 0)) {
		// No index reg, scaled or otherwise. Just BaseReg+offset
		CurrString += RegNames[BaseReg];
		if (17 == IdiomCode) {
			IdiomCode = 0; // reset; not a benign code idiom
		}
#if 0 // easier for instrumentation to always use ADD, even for negative offsets
		if (0 < SignedOffset)
#endif
			CurrString += "+";

		CurrString += OffsetString;
		if (IdiomCode > 0) {
			if (IdiomCode == 18) {
				SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW %s %zu %s ZZ IDIOM %d %s %s \n",
					(unsigned long) this->address, this->SMPcmd.size, LeaSignednessStrings[BaseRegSignMask], 
					BaseRegMaxWidth, CurrString.c_str(), IdiomCode, PtrString.c_str(), disasm);
			}
			else {
				SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW %s %zu %s ZZ IDIOM %d %s \n",
					(unsigned long) this->address, this->SMPcmd.size, LeaSignednessStrings[BaseRegSignMask], 
					BaseRegMaxWidth, CurrString.c_str(), IdiomCode, disasm);
			}
		}
		else {
			SMP_fprintf(InfoAnnotFile, "%10lx %6d INSTR CHECK OVERFLOW %s %zu %s ZZ %s \n",
				(unsigned long) this->address, this->SMPcmd.size, LeaSignednessStrings[BaseRegSignMask], 
				BaseRegMaxWidth, CurrString.c_str(), disasm);
		}
#if SMP_MEASURE_NUMERIC_ANNOTATIONS
		++LeaInstOverflowCount;
#endif
	}
	else {
		// Either just a BaseReg, or just an offset. Nothing to do.
		;
	}

	return;
} // end of SMPInstr::MDEmitLeaOpcodeOverflowAnnotations()

// Go through the PUSH RTL and get the operand pushed.
op_t SMPInstr::GetPushedOpnd(void) {
	op_t VoidOp = InitOp;

	if (NN_push == this->SMPcmd.itype) {
		for (size_t OpNum = 0; OpNum < UA_MAXOP; ++OpNum) {
			op_t TempOp = this->SMPcmd.Operands[OpNum];
			if (this->features & UseMacros[OpNum]) { // USE
				return TempOp;
			}
		}
		SMP_msg("ERROR: Could not find PUSH operand at %lx %s\n", (unsigned long) this->address,
			DisAsmText.GetDisAsm(this->GetAddr()));
		return VoidOp;
	}
	else {
		return VoidOp;
	}
} // end of SMPInstr::GetPushedOpnd()

// Get the immediate value used in the instruction. Return zero
//  if no immediate was used.
int SMPInstr::MDGetImmedUse(void) {
	int ImmedVal = 0;
	set<DefOrUse, LessDefUse>::iterator CurrUse;
	for (CurrUse = this->GetFirstUse(); CurrUse != this->GetLastUse(); ++CurrUse) {
		op_t UseOp = CurrUse->GetOp();
		if (o_imm == UseOp.type) {
			ImmedVal = (int) UseOp.value;
			break;
		}
	}
	return ImmedVal;
} // end of SMPInstr::MDGetImmedUse()

// Get funcname from call inst and remove "." and "_" prefices.
//  Asserts if this is not a call instruction.
string SMPInstr::GetTrimmedCalledFunctionName(void) {
	SMPitype DFType = this->GetDataFlowType();
	assert((CALL == DFType) || (INDIR_CALL == DFType) || this->IsTailCall());
	ea_t FuncAddr = this->CallTarget;
	char IDA_func_name[MAXSTR];
	size_t SkipCount;
	char *TempFuncName;

	if (CALL == DFType) {
		// We should have a good call target for direct calls.
		assert(BADADDR != FuncAddr);
		(void) get_func_name(FuncAddr, IDA_func_name, (size_t)(MAXSTR - 1));
		SkipCount = strspn(IDA_func_name, "._");
		TempFuncName = &(IDA_func_name[SkipCount]);
		string FuncName(TempFuncName);
		return FuncName;
	}
	else { // INDIR_CALL
		// We might have a resolved call target for indirect calls.
		if (BADADDR != FuncAddr) {
			// We have a resolved address for the indirect call.
			(void) get_func_name(FuncAddr, IDA_func_name, (size_t)(MAXSTR - 1));
			SkipCount = strspn(IDA_func_name, "._");
			TempFuncName = &(IDA_func_name[SkipCount]);
			string IndirFuncName(TempFuncName);
			return IndirFuncName;
		}
		else { // INDIR_CALL, no resolved target.
			string DummyFuncName("ZST_NEVER_MATCH_THIS_FUNC_NAME");
			return DummyFuncName;
		}
	}
} // end of SMPInstr::GetTrimmedCalledFunctionName()

// Build the RTL for an instruction with a unary opcode
bool SMPInstr::BuildUnaryRTL(SMPoperator UnaryOp) {
	size_t OpNum;
	bool DestFound = false;
	bool WidthDoubler = this->MDDoublesWidth();
	SMPRegTransfer *TempRT = NULL;

	op_t VoidOp = InitOp;

	op_t FPRegOp = InitOp;
	FPRegOp.type = o_fpreg;  // floating point register stack
	FPRegOp.dtyp = dt_tbyte;

	op_t FlagsOp = InitOp;
	FlagsOp.type = o_reg;
	FlagsOp.reg = X86_FLAGS_REG;
	FlagsOp.dtyp = this->GetOperandDtypField();

	// Handle special cases first
	if (SMP_UNARY_FLOATING_ARITHMETIC == UnaryOp) {
		// Use of the floating register stack top is implicit
		DestFound = true;
		TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);
		TempRT->SetLeftOperand(FPRegOp);
		TempRT->SetOperator(SMP_ASSIGN);
		SMPRegTransfer *RightRT = new SMPRegTransfer;
		RightRT->SetParentInst(this);
		RightRT->SetLeftOperand(FPRegOp);
		RightRT->SetOperator(UnaryOp);
		RightRT->SetRightOperand(VoidOp);
		TempRT->SetRightTree(RightRT);
		this->RTL.push_back(TempRT);
	}
	else if ((NN_clc == this->SMPcmd.itype) || (NN_cld == this->SMPcmd.itype)
		|| (NN_cmc == this->SMPcmd.itype) || (NN_stc == this->SMPcmd.itype)
		|| (NN_std == this->SMPcmd.itype)) {
		// Flags register is implicit destination.
		DestFound = true;
		TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);
		TempRT->SetLeftOperand(FlagsOp);
		TempRT->SetOperator(SMP_ASSIGN);
		SMPRegTransfer *RightRT = new SMPRegTransfer;
		RightRT->SetParentInst(this);
		if (NN_cmc == this->SMPcmd.itype) { // complement carry flag USEs old carry flag
			RightRT->SetLeftOperand(FlagsOp);
			RightRT->SetOperator(SMP_BITWISE_NOT);
		}
		else {
			RightRT->SetLeftOperand(VoidOp);
			RightRT->SetOperator(UnaryOp);
		}
		RightRT->SetRightOperand(VoidOp);
		TempRT->SetRightTree(RightRT);
		this->RTL.push_back(TempRT);
	}

	for (OpNum = 0; !DestFound && (OpNum < UA_MAXOP); ++OpNum) {
		op_t TempOp = this->SMPcmd.Operands[OpNum];
		op_t LeftOp;
		if (this->features & DefMacros[OpNum]) { // DEF
			if (MDKnownOperandType(TempOp)) {
				DestFound = true;
				TempRT = new SMPRegTransfer;
				TempRT->SetParentInst(this);
				LeftOp = TempOp;

				if (WidthDoubler) {
					// Opcodes that sign-extend a byte to a word, or a word to a dword, 
					//  have only one operand. It is implicit, and it is the shorter USE.
					//  That means the DEF op will have the same width as the USE op, e.g. if
					//  we are sign-extending AX to EAX, the USE op and DEF op will both be AX
					//  without a special fix. We fix this problem with the DEF operand now.
					if (LeftOp.dtyp == dt_byte) {
						LeftOp.dtyp = dt_word;
						LeftOp.reg = MDCanonicalizeSubReg(LeftOp.reg);
					}
					else if (LeftOp.dtyp == dt_word) {
						LeftOp.dtyp = dt_dword;
						LeftOp.reg = MDCanonicalizeSubReg(LeftOp.reg);
					}
					else if (LeftOp.dtyp == dt_dword) {
						LeftOp.dtyp = dt_qword;
					}
					else {
						SMP_msg("ERROR: Instruction operand %zu not 1,2, or 4 bytes at %lx dtyp: %d\n", 
							OpNum, (unsigned long) this->address, LeftOp.dtyp);
					}
				}

				TempRT->SetLeftOperand(LeftOp);

				TempRT->SetOperator(SMP_ASSIGN);
				SMPRegTransfer *RightRT = new SMPRegTransfer;
				RightRT->SetParentInst(this);
				RightRT->SetLeftOperand(TempOp);
				RightRT->SetOperator(UnaryOp);
				RightRT->SetRightOperand(VoidOp);
				TempRT->SetRightTree(RightRT);
				this->RTL.push_back(TempRT);
			}
		}
	} // end for (OpNum = 0; ...)

#if SMP_DEBUG_BUILD_RTL
	if (!DestFound) {
		SMP_msg("ERROR: Could not find unary operand at %lx for %s\n", 
			(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
	}
#endif
	return DestFound;
} // end of SMPInstr::BuildUnaryRTL()

#if 0
// Cleaner, no special-case version of BuildUnary2OpndRTL()
// Build the RTL for an instruction of the form dest := unary_operator(src), with src != dest
bool SMPInstr::BuildUnaryTwoOperandRTL(SMPoperator UnaryOp) {
	size_t OpNum;
	bool DestFound = false;
	bool SrcFound = false;
	op_t DestOp, SrcOp;
	SMPRegTransfer *TempRT = NULL;

	op_t VoidOp = InitOp;

	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;
				DestOp = TempOp;
			}
		}
		else { // not dest, see if valid source
			if (MDKnownOperandType(TempOp)) {
				SourceFound = true;
			}
		}
	} // end for (OpNum = 0; ...)

	if (DestFound && SourceFound) {
		TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);
		TempRT->SetLeftOperand(DestOp);
		TempRT->SetOperator(SMP_ASSIGN);
		SMPRegTransfer *RightRT = new SMPRegTransfer;
		RightRT->SetParentInst(this);
		RightRT->SetLeftOperand(SrcOp);
		RightRT->SetOperator(UnaryOp);
		RightRT->SetRightOperand(VoidOp);
		TempRT->SetRightTree(RightRT);
		this->RTL.push_back(TempRT);
	}
#if SMP_DEBUG_BUILD_RTL
	else {
		SMP_msg("ERROR: Could not find unary operand at %lx for %s\n", 
			(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
	}
#endif
	return DestFound;
} // end of SMPInstr::BuildUnaryTwoOperandRTL()
#endif

// Build the RTL for an instruction with a binary arithmetic opcode
bool SMPInstr::BuildBinaryRTL(SMPoperator BinaryOp, bool HiddenFPStackOp) {
	size_t OpNum;
	int opcode = this->SMPcmd.itype;
	bool DestFound = false;
	bool SourceFound = false;
	bool MemSrc = this->HasSourceMemoryOperand();
	bool MemDest = this->HasDestMemoryOperand();
	// Work around IDA pro error; they assumed that the pcmpeq/ne/gt/ge/lt/le
	//  families of instructions were just compares, so they do not tag
	//  either operand as a DEF. Actually, the first operand has byte or
	//  word or dword fields set to all 1's or all 0's based on the result
	//  of the comparison.
	bool SrcIsReallyDest = ((SMP_COMPARE_EQ_AND_SET <= BinaryOp) 
		&& (SMP_COMPARE_LE_AND_SET >= BinaryOp));
	bool StackPointerModification = false; // SP := SP SMP_BITWISE_AND operand
	bool NeedsGuard = ((NN_arpl == opcode) || (NN_bound == opcode));
	bool BuildOnlySignalRT = (NN_bound == opcode);
	SMPRegTransfer *TempRT = NULL;
	SMPRegTransfer *RightRT = new SMPRegTransfer;
	SMPGuard *Guard1 = NULL;
	RightRT->SetParentInst(this);

	op_t VoidOp = InitOp;

	op_t FPRegOp = InitOp;
	FPRegOp.type = o_fpreg;  // floating point register stack
	FPRegOp.dtyp = dt_tbyte;

	// Handle special cases first
	if (NeedsGuard) {
		// Need a guard in the RTL.
		Guard1 = new SMPGuard;
		Guard1->SetOperator(SMP_U_COMPARE);
	}
	else if (HiddenFPStackOp) {
		// Use of the floating register stack top is implicit
		DestFound = true;
		TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);
		TempRT->SetLeftOperand(FPRegOp);
		TempRT->SetOperator(SMP_ASSIGN);
		RightRT->SetLeftOperand(FPRegOp);
		RightRT->SetOperator(BinaryOp);
		RightRT->SetRightOperand(VoidOp);
		TempRT->SetRightTree(RightRT);
	}

	for (OpNum = 0; !(DestFound && SourceFound) && (OpNum < UA_MAXOP); ++OpNum) {
		op_t TempOp = this->SMPcmd.Operands[OpNum];
		if ((this->features & DefMacros[OpNum]) 
			|| (SrcIsReallyDest && (0 == 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 = new SMPRegTransfer;
					TempRT->SetParentInst(this);
					if (!BuildOnlySignalRT) {
						TempRT->SetLeftOperand(TempOp);
						TempRT->SetOperator(SMP_ASSIGN);
					}
					if (this->IsRegClearIdiom()) {
						op_t ImmOp = InitOp;
						ImmOp.type = o_imm;
						ImmOp.value = 0;
						TempRT->SetRightOperand(ImmOp);
						SourceFound = true; // cause loop exit
					}
					else {
						if (!BuildOnlySignalRT) {
							RightRT->SetLeftOperand(TempOp);
							RightRT->SetOperator(BinaryOp);
							TempRT->SetRightTree(RightRT);
							if (TempOp.is_reg(MD_STACK_POINTER_REG) && (SMP_BITWISE_AND == BinaryOp)) {
								StackPointerModification = true; // searching for SP := SP AND immediate
							}
						}
						if (NeedsGuard) {
							Guard1->SetLeftOperand(TempOp);
							TempRT->SetGuard(Guard1);
						}
					}
				}
				else {
					;
#if SMP_VERBOSE_DEBUG_BUILD_RTL
					SMP_msg("WARNING: Skipping DEF operand: ");
					PrintOperand(TempOp);
					SMP_msg(" at %lx in %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
				}
			}
			else if (DestFound && (!HiddenFPStackOp)) {
				;
#if SMP_VERBOSE_DEBUG_BUILD_RTL
				SMP_msg("ERROR: Found two DEF operands: ");
				PrintOperand(TempOp);
				SMP_msg(" at %lx in %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
			}
		}
		else { // USE
			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 add mem,reg is being
				//  processed, where the memory operand is both DEF and USE.
				if (!MemSrc || MemDest || ((TempOp.type >= o_mem) && (TempOp.type <= o_displ))) {
					SourceFound = true;
					if (!BuildOnlySignalRT) {
						RightRT->SetRightOperand(TempOp);
						if (StackPointerModification && (o_imm == TempOp.type)) {
							this->SetStackAlignmentInst();
						}
					}
				}
				else {
					SMP_msg("ERROR: Operand not processed as USE: ");
					PrintOperand(TempOp);
					SMP_msg(" at %lx in %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
				}
				if (NeedsGuard) {
					Guard1->SetRightOperand(TempOp);
				}
			}
			if (!(this->features & UseMacros[OpNum])) {
				;
#if SMP_VERBOSE_DEBUG_BUILD_RTL_DEF_USE
				SMP_msg("WARNING: Operand neither DEF nor USE: ");
				PrintOperand(TempOp);
				SMP_msg(" at %lx in %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
			}
		} // end if DEF ... else ...
	} // end for (OpNum = 0; ...)

	if (!DestFound || !SourceFound) {
		assert(NULL != RightRT);
		if (DestFound && (NULL != TempRT))
			delete TempRT;
		else
			delete RightRT;
#if SMP_DEBUG_BUILD_RTL
		if (!DestFound) {
			SMP_msg("ERROR: Could not find binary DEF operand at %lx for %s\n",
				(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
		}
		else {
			SMP_msg("ERROR: Could not find binary operand at %lx for %s\n", 
				(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
			this->PrintOperands();
		}
#endif
	}
	else {
		if (BuildOnlySignalRT) {
			TempRT->SetLeftOperand(VoidOp);
			TempRT->SetRightOperand(VoidOp);
			TempRT->SetOperator(SMP_SIGNAL);
			delete RightRT;
		}
		this->RTL.push_back(TempRT);
		// The "p" at the end of the opcode indicates that the floating point
		//  register stack gets popped.
		if ((NN_fstp == opcode) || (NN_fbstp == opcode) || (NN_fistp == opcode)) {
			this->RTL.ExtraKills.push_back(FPRegOp);
		}
	}
	return (DestFound && SourceFound);
} // end of SMPInstr::BuildBinaryRTL()

// Build the RTL for a signal/exception raised based on a guarded comparison of operands
bool SMPInstr::BuildGuardedSignalRTL(SMPoperator SignalOp) {
	size_t OpNum;
	bool Source1Found = false;
	bool Source2Found = false;
	SMPRegTransfer *TempRT = NULL;
	SMPGuard *Guard1 = new SMPGuard;

	op_t VoidOp = InitOp;

	Guard1->SetOperator(SMP_U_COMPARE);

	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_VERBOSE_DEBUG_BUILD_RTL
				SMP_msg("WARNING: Skipping DEF operand: ");
				PrintOperand(TempOp);
				SMP_msg(" at %lx in %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif

			}
		}
		else { // USE
			if (!Source1Found && MDKnownOperandType(TempOp)) {
				Source1Found = true;
				Guard1->SetLeftOperand(TempOp);
			}
			else if ((!Source2Found) && MDKnownOperandType(TempOp)) {
				Source2Found = true;
				Guard1->SetRightOperand(TempOp);
			}
			if (!(this->features & UseMacros[OpNum])) {
				;
#if SMP_VERBOSE_DEBUG_BUILD_RTL_DEF_USE
				SMP_msg("WARNING: Operand neither DEF nor USE: ");
				PrintOperand(TempOp);
				SMP_msg(" at %lx in %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
			}
		} // end if DEF ... else ...
	} // end for (OpNum = 0; ...)

	if (!Source1Found || !Source2Found) {
		if (NULL != TempRT)
			delete TempRT;
#if SMP_DEBUG_BUILD_RTL
		if (!Source1Found) {
			SMP_msg("ERROR: Could not find first USE operand for BOUND at %lx for %s\n",
				(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
		}
		else {
			SMP_msg("ERROR: Could not find second USE operand for BOUND at %lx for %s\n",
				(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
		}
		this->PrintOperands();
#endif
		delete Guard1;
	}
	else {
		TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);
		TempRT->SetLeftOperand(VoidOp);
		TempRT->SetRightOperand(VoidOp);
		TempRT->SetOperator(SignalOp);
		TempRT->SetGuard(Guard1);
		this->RTL.push_back(TempRT);
	}
	return (Source1Found && Source2Found);
} // end of SMPInstr::BuildGuardedSignalRTL()

// Build the RTL for an instruction with a binary arithmetic opcode plus an operator to apply to
//  the two source-only operands, one of which is an immediate value.
bool SMPInstr::BuildBinaryPlusImmedRTL(SMPoperator BinaryOp, SMPoperator ImmedOp) {
	size_t OpNum;
	bool DestFound = false;
	bool SourceFound = false;
	bool ImmedFound = false;
	bool MemSrc = this->HasSourceMemoryOperand();
	bool MemDest = this->HasDestMemoryOperand();
	SMPRegTransfer *TempRT = NULL;
	SMPRegTransfer *RightRT = new SMPRegTransfer;
	SMPRegTransfer *ImmedRT = new SMPRegTransfer;
	RightRT->SetParentInst(this);
	ImmedRT->SetParentInst(this);

	for (OpNum = 0; !(DestFound && SourceFound && ImmedFound) && (OpNum < UA_MAXOP); ++OpNum) {
		op_t TempOp = this->SMPcmd.Operands[OpNum];
		if (this->features & DefMacros[OpNum]) { // DEF
			if (!DestFound && MDKnownOperandType(TempOp)) {
				if (!MemDest || ((TempOp.type >= o_mem) && (TempOp.type <= o_displ))) {
					DestFound = true;
					TempRT = new SMPRegTransfer;
					TempRT->SetParentInst(this);
					TempRT->SetLeftOperand(TempOp);
					TempRT->SetOperator(SMP_ASSIGN);
					RightRT->SetLeftOperand(TempOp);
					RightRT->SetOperator(BinaryOp);
					TempRT->SetRightTree(RightRT);
				}
				else {
					;
#if SMP_VERBOSE_DEBUG_BUILD_RTL
					SMP_msg("WARNING: Skipping DEF operand: ");
					PrintOperand(TempOp);
					SMP_msg(" at %lx in %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
				}
			}
			else if (DestFound) {
				;
#if SMP_VERBOSE_DEBUG_BUILD_RTL
				SMP_msg("ERROR: Found two DEF operands: ");
				PrintOperand(TempOp);
				SMP_msg(" at %lx in %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
			}
		}
		else { // USE
			if (!SourceFound && MDKnownOperandType(TempOp)) {
				if (!MemSrc || ((TempOp.type >= o_mem) && (TempOp.type <= o_displ))) {
					SourceFound = true;
					ImmedRT->SetLeftOperand(TempOp);
				}
			}
			else if (!ImmedFound && (o_imm == TempOp.type)) {
				ImmedFound = true;
				ImmedRT->SetRightOperand(TempOp);
				ImmedRT->SetOperator(ImmedOp);
				RightRT->SetRightTree(ImmedRT);
			}
			if (!(this->features & UseMacros[OpNum])) {
				;
#if SMP_VERBOSE_DEBUG_BUILD_RTL_DEF_USE
				SMP_msg("WARNING: Operand neither DEF nor USE: ");
				PrintOperand(TempOp);
				SMP_msg(" at %lx in %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
			}
		} // end if DEF ... else ...
	} // end for (OpNum = 0; ...)

	if (!DestFound || !SourceFound || !ImmedFound) {
		assert(NULL != RightRT);
		if (DestFound && (NULL != TempRT))
			delete TempRT;
		else {
			delete RightRT;
			if (!ImmedFound)
				delete ImmedRT;
		}
#if SMP_DEBUG_BUILD_RTL
		if (!DestFound) {
			SMP_msg("ERROR: Could not find binary DEF operand at %lx for %s\n",
				(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
		}
		else if (!ImmedFound) {
			SMP_msg("ERROR: Could not find immediate operand at %lx for %s\n",
				(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
			this->PrintOperands();
		}
		else {
			SMP_msg("ERROR: Could not find binary USE operand at %lx for %s\n",
				(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
			this->PrintOperands();
		}
#endif
	}
	else {
		this->RTL.push_back(TempRT);
	}
	return (DestFound && SourceFound && ImmedFound);
} // end of SMPInstr::BuildBinaryPlusImmedRTL()

// Build the RTL for an instruction with a binary arithmetic opcode, ignoring a third operand
//  which is an immediate value which is a control word for packed operations (e.g. SSE, XMM).
bool SMPInstr::BuildBinaryIgnoreImmedRTL(SMPoperator BinaryOp) {
	size_t OpNum;
	bool DestFound = false;
	bool SourceFound = false;
	bool ImmedFound = false;
	bool MemSrc = this->HasSourceMemoryOperand();
	bool MemDest = this->HasDestMemoryOperand();
	bool ECXDest = ((NN_pcmpestri == this->SMPcmd.itype) || (NN_pcmpistri == this->SMPcmd.itype));
	bool XMM0Dest = ((NN_pcmpestrm == this->SMPcmd.itype) || (NN_pcmpistrm == this->SMPcmd.itype));
	bool SrcIsReallyDest = (ECXDest || XMM0Dest); // Dest is implicit, so ASM only has source operand
	SMPRegTransfer *TempRT = NULL;
	SMPRegTransfer *RightRT = new SMPRegTransfer;
	RightRT->SetParentInst(this);

	for (OpNum = 0; !(DestFound && SourceFound && ImmedFound) && (OpNum < UA_MAXOP); ++OpNum) {
		op_t TempOp = this->SMPcmd.Operands[OpNum];
		if ((this->features & DefMacros[OpNum]) 
			|| (SrcIsReallyDest && (0 == OpNum))) { // DEF
			if (!DestFound && MDKnownOperandType(TempOp)) {
				if (!MemDest || ((TempOp.type >= o_mem) && (TempOp.type <= o_displ))) {
					DestFound = true;
					TempRT = new SMPRegTransfer;
					TempRT->SetParentInst(this);
					if (ECXDest) {
						op_t ECXOp = InitOp;
						ECXOp.type = o_reg;
						ECXOp.reg = R_cx;
						ECXOp.dtyp = STARS_ISA_dtyp;
						TempRT->SetLeftOperand(ECXOp);
					}
					else if (XMM0Dest) {
						op_t XMMOp = InitOp;
						XMMOp.type = o_reg;
						XMMOp.reg = R_xmm0;
						XMMOp.dtyp = dt_byte16;
						TempRT->SetLeftOperand(XMMOp);
					}
					else {
						TempRT->SetLeftOperand(TempOp);
					}
					TempRT->SetOperator(SMP_ASSIGN);
					RightRT->SetLeftOperand(TempOp);
					RightRT->SetOperator(BinaryOp);
					TempRT->SetRightTree(RightRT);
				}
				else {
					;
#if SMP_VERBOSE_DEBUG_BUILD_RTL
					SMP_msg("WARNING: Skipping DEF operand: ");
					PrintOperand(TempOp);
					SMP_msg(" at %lx in %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
				}
			}
			else if (DestFound) {
				;
#if SMP_VERBOSE_DEBUG_BUILD_RTL
				SMP_msg("ERROR: Found two DEF operands: ");
				PrintOperand(TempOp);
				SMP_msg(" at %lx in %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
			}
		}
		else { // USE
			if (!SourceFound && MDKnownOperandType(TempOp)) {
				if (!MemSrc || ((TempOp.type >= o_mem) && (TempOp.type <= o_displ))) {
					SourceFound = true;
					RightRT->SetRightOperand(TempOp);
				}
			}
			else if (!ImmedFound && (o_imm == TempOp.type)) {
				ImmedFound = true;
			}
			if (!(this->features & UseMacros[OpNum])) {
				;
#if SMP_VERBOSE_DEBUG_BUILD_RTL_DEF_USE
				SMP_msg("WARNING: Operand neither DEF nor USE: ");
				PrintOperand(TempOp);
				SMP_msg(" at %lx in %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
			}
		} // end if DEF ... else ...
	} // end for (OpNum = 0; ...)

	if (!DestFound || !SourceFound || !ImmedFound) {
		assert(NULL != RightRT);
		if (DestFound && (NULL != TempRT))
			delete TempRT;
		else
			delete RightRT;
#if SMP_DEBUG_BUILD_RTL
		if (!DestFound) {
			SMP_msg("ERROR: Could not find binary DEF operand at %lx for %s\n",
				(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
		}
		else if (!ImmedFound) {
			SMP_msg("ERROR: Could not find immediate operand at %lx for %s\n",
				(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
			this->PrintOperands();
		}
		else {
			SMP_msg("ERROR: Could not find binary USE operand at %lx for %s\n",
				(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
			this->PrintOperands();
		}
#endif
	}
	else {
		this->RTL.push_back(TempRT);
	}
	return (DestFound && SourceFound && ImmedFound);
} // end of SMPInstr::BuildBinaryIgnoreImmedRTL()

// Build the RTL for a load-effective-address instruction.
bool SMPInstr::BuildLeaRTL(void) {
	size_t OpNum;
	bool DestFound = false;
	bool SourceFound = false;
	op_t DefOp = InitOp;
	op_t UseOp = InitOp;
	char Temp_dtyp = this->GetOperandDtypField();
	DefOp.dtyp = UseOp.dtyp = Temp_dtyp;
	SMPRegTransfer *AssignRT = NULL;
	int BaseReg;
	int IndexReg;
	ushort ScaleFactor;
	ea_t offset;
	bool ScaledIndexReg;

	for (OpNum = 0; !(DestFound && SourceFound) && (OpNum < UA_MAXOP); ++OpNum) {
		op_t TempOp = this->SMPcmd.Operands[OpNum];
		if (this->features & DefMacros[OpNum]) { // DEF
			DefOp = TempOp;
			DestFound = true;
			assert(o_reg == DefOp.type);
		}
		else { // USE
			if (!SourceFound && MDKnownOperandType(TempOp)) {
				if ((TempOp.type >= o_mem) && (TempOp.type <= o_displ)) {
					SourceFound = true;
					UseOp = TempOp;
					MDExtractAddressFields(TempOp, BaseReg, IndexReg, ScaleFactor, offset);
				}
				else {
					;
#if SMP_VERBOSE_DEBUG_BUILD_RTL
					SMP_msg("WARNING: Skipping USE operand: ");
					PrintOperand(TempOp);
					SMP_msg(" at %lx in %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
				}
			}

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

	if (!DestFound || !SourceFound) {
#if SMP_DEBUG_BUILD_RTL
		if (!DestFound) {
			SMP_msg("ERROR: Could not find lea DEF operand at %lx for %s\n", (unsigned long) this->GetAddr(),
				DisAsmText.GetDisAsm(this->GetAddr()));
		}
		else {
			SMP_msg("ERROR: Could not find lea USE operand at %lx for %s\n", (unsigned long) this->GetAddr(),
				DisAsmText.GetDisAsm(this->GetAddr()));
			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->SetParentInst(this);
		AssignRT->SetLeftOperand(DefOp);
		AssignRT->SetOperator(SMP_ASSIGN);

		ScaledIndexReg = ((ScaleFactor > 0) && (IndexReg != R_none));
		op_t BaseOp = InitOp, IndexOp = InitOp, OffsetOp = InitOp, ScaleOp = InitOp;
		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->SetParentInst(this);
			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->SetParentInst(this);
				AddOffRT->SetLeftOperand(OffsetOp);
				AddOffRT->SetOperator(SMP_ADD);
				AddOffRT->SetRightTree(MultRT);
				// Add a BaseReg, if any.
				if (R_none != BaseReg) {
					SMPRegTransfer *AddBaseRT = new SMPRegTransfer;
					AddBaseRT->SetParentInst(this);
					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->SetParentInst(this);
					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->SetParentInst(this);
					AddOffRT->SetLeftOperand(OffsetOp);
					AddOffRT->SetOperator(SMP_ADD);
					AddOffRT->SetRightOperand(IndexOp);
					// Add BaseReg, if any.
					if (R_none != BaseReg) {
						SMPRegTransfer *AddBaseRT = new SMPRegTransfer;
						AddBaseRT->SetParentInst(this);
						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->SetParentInst(this);
						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?
						if (UseOp.type != o_mem) {
							SMP_msg("WARNING: lea used as move at %lx for %s\n", (unsigned long) this->address,
								DisAsmText.GetDisAsm(this->GetAddr()));
						}
						AssignRT->SetRightOperand(OffsetOp);
					}
				}
			} // end if nonzero offset
			else { // no offset
				if ((R_none == BaseReg) || (R_none == IndexReg)) {
					SMP_msg("WARNING: lea used as move at %lx for %s\n", (unsigned long) this->address,
						DisAsmText.GetDisAsm(this->GetAddr()));
					if (R_none != BaseReg) {
						AssignRT->SetRightOperand(BaseOp);
					}
					else {
						if (R_none == IndexReg) { // Should be RegClearIdiom in this case, no longer Lea RTL
							assert(this->IsRegClearIdiom());
							op_t ImmOp = InitOp;
							ImmOp.type = o_imm;
							ImmOp.value = 0;
							AssignRT->SetRightOperand(ImmOp);
						}
						else {
							AssignRT->SetRightOperand(IndexOp);
						}
					}
				}
				else { // we have a BaseReg and an IndexReg, unscaled, no offset
					SMPRegTransfer *AddBaseRT = new SMPRegTransfer;
					AddBaseRT->SetParentInst(this);
					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;
	RightRT->SetParentInst(this);
	SMPRegTransfer *LowerRightRT = new SMPRegTransfer;
	LowerRightRT->SetParentInst(this);

	// The doubleword shifts operate as follows: shift the DEF register right or left by
	//  the number of bits specified by the count, and shift in bits from the USE register,
	//  but do not change the USE register. This is hard to represent accurately in an RTL,
	//  so we create an RTL as follows:
	//
	//         ASSIGN
	//         /     \
	//        DEF    SHIFT
	//               /    \
	//              DEF   SHIFT
	//                    /    \
	//                   USE   count
	//
	// This records all the operands, but it makes it look like the result of the
	//  lower shift is the counter for the upper shift, which is unintentional and
	//  will have to be special cased. In all single word shifts, the lower shift
	//  subtree would be replaced by a single count operand. The presence of a sub-tree
	//  instead of an operand is the identifying marker for double-word shifts.

	op_t FlagsOp = InitOp;
	FlagsOp.type = o_reg;
	FlagsOp.reg = X86_FLAGS_REG;
	FlagsOp.dtyp = this->GetOperandDtypField();

	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->SetParentInst(this);
				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
		SMP_msg("ERROR: Could not find double-shift operand at %lx for %s\n",
			(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#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 && CountFound);
} // 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;
	bool ImplicitEDXUse = false;
	SMPRegTransfer *TempRT = NULL;
	SMPRegTransfer *RightRT = new SMPRegTransfer;
	RightRT->SetParentInst(this);

	op_t FPRegOp = InitOp;
	FPRegOp.type = o_fpreg;  // floating point register stack
	FPRegOp.dtyp = dt_tbyte;

	op_t Immed1Op = InitOp;
	Immed1Op.type = o_imm;  // immediate 1 for increment or decrement
	Immed1Op.value = 1;
	Immed1Op.dtyp = this->GetOperandDtypField();


	// Detect the cases in which EDX:EAX 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 form always has a hidden use of EDX:EAX
				HiddenEAXUse = true;
				ImplicitEDXUse = true;
			}
			else if (TempOp.is_reg(R_al)) {
				// Use of AX register to hold 16-bit result is hidden,
				//  but EDX is not needed to hold result bits.
				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->SetParentInst(this);
				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))
			delete TempRT;
		else
			delete RightRT;
#if SMP_DEBUG_BUILD_RTL
		SMP_msg("ERROR: Could not find mul/div operand at %lx for %s\n",
			(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
	}
	else {
		this->RTL.push_back(TempRT);
		if (ImplicitEDXUse) {
			// Need another effect for EDX, which was implicit.
			//  Make a deep copy from existing EAX effect and change EAX dest to EDX.
			//  For divisions, we also deep copy EAX effect and change EAX source to EDX.
			SMPRegTransfer *EDXRT = new SMPRegTransfer;
			EDXRT->SetParentInst(this);
			SMPRegTransfer *EDXRightRT = new SMPRegTransfer;
			EDXRightRT->SetParentInst(this);
			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);
			this->ResetMultiplicationBitsDiscarded();
		}
		else { // No implicit EDX effect.
			// If we had 8x8=>16 bit multiply with AL*op8=>AX there
			//  is no discarding of result bits, else there is discarding.
			if (!HiddenEAXUse)
				this->SetMultiplicationBitsDiscarded();
		}
	}
	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 = InitOp;
	FlagsOp.type = o_reg;
	FlagsOp.reg = X86_FLAGS_REG;
	FlagsOp.dtyp = this->GetOperandDtypField();

	SMPRegTransfer *RightRT = new SMPRegTransfer;
	RightRT->SetParentInst(this);
	SMPRegTransfer *FlagsRightRT = new SMPRegTransfer;
	FlagsRightRT->SetParentInst(this);

	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->SetParentInst(this);
				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
		SMP_msg("ERROR: Could not find binary operand at %lx for %s\n",
			(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#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 = new SMPRegTransfer;
	TempRT->SetParentInst(this);
	SMPRegTransfer *RightRT = new SMPRegTransfer;
	RightRT->SetParentInst(this);
	int opcode = this->SMPcmd.itype;
	bool ExtendedMove = ((NN_movsx == opcode) || (NN_movzx == opcode) || (NN_movsxd == opcode));

	op_t VoidOp = InitOp;

	op_t FlagsOp = InitOp;
	FlagsOp.type = o_reg;
	FlagsOp.reg = X86_FLAGS_REG;
	FlagsOp.dtyp = this->GetOperandDtypField();

	op_t PortNumOp = InitOp;
	PortNumOp.type = o_reg;
	PortNumOp.reg = R_dx;
	PortNumOp.dtyp = dt_word; // always DX, 16-bit

	op_t PortDataOp = InitOp;
	PortDataOp.type = o_reg;
	PortDataOp.reg = R_ax;
	PortDataOp.dtyp = this->GetOperandDtypField();

	// Handle special cases first.
	if ((SMP_FIRST_SET_OPCODE <= opcode) && (SMP_LAST_SET_OPCODE >= opcode)) {
		// 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;
				if (NN_in == opcode) {
#if 0
					SMP_msg("ERROR: Explicit DEF for IN from port opcode at %x : ", this->GetAddr());
					PrintOperand(TempOp);
					SMP_msg("\n");
#endif
					TempRT->SetLeftOperand(TempOp);
					TempRT->SetOperator(UnaryOp);
				}
				else if (NN_out == opcode) {
					TempRT->SetLeftOperand(TempOp);
					TempRT->SetOperator(UnaryOp);
				}
				else {
					TempRT->SetLeftOperand(TempOp);
					TempRT->SetOperator(SMP_ASSIGN);
					RightRT->SetRightOperand(VoidOp);
					RightRT->SetOperator(UnaryOp);
					TempRT->SetRightTree(RightRT);
				}
			}
		}
		else { // USE
			if (MDKnownOperandType(TempOp)) {
				SourceFound = true;
				if (NN_in == opcode) {
					TempRT->SetRightOperand(TempOp);
				}
				else if (NN_out == opcode) {
#if 0
					SMP_msg("ERROR: Explicit USE for OUT to port opcode at %x : ", this->GetAddr());
					PrintOperand(TempOp);
					SMP_msg("\n");
#endif
					TempRT->SetRightOperand(TempOp);
				}
				else {
					RightRT->SetLeftOperand(TempOp);
					if (ExtendedMove)
						this->MoveSource = TempOp;
				}
			}
		}
	} // end for (OpNum = 0; ...)

	if (!SourceFound && (NN_in == opcode)) {
		// Input from port is implicitly from port # in DX register if not
		//  specified with an immediate operand.
		SourceFound = true;
		TempRT->SetRightOperand(PortNumOp);
	}
	if (!DestFound && (NN_in == opcode)) {
		// Input from port is implicitly to register AL, AX, or EAX
		//  depending on the opcode and bit width mode.
		// NOTE: Two different machine codes for 8-bit and 32-bit widths.
		//  We should check and set dtyp field accordingly.
		DestFound = true;
		TempRT->SetLeftOperand(PortDataOp);
		TempRT->SetOperator(UnaryOp);
	}
	if (!DestFound && (NN_out == opcode)) {
		// Output to port is implicitly to port # in DX register if not
		//  specified with an immediate operand.
		// NOTE: Two different machine codes for 8-bit and 32-bit widths.
		//  We should check and set dtyp field accordingly.
		DestFound = true;
		TempRT->SetLeftOperand(PortNumOp);
		TempRT->SetOperator(SMP_ASSIGN);
	}
	if (!SourceFound && (NN_out == opcode)) {
		// Output to port is implicitly from register AL, AX, or EAX
		//  depending on the opcode and bit width mode.
		SourceFound = true;
		TempRT->SetRightOperand(PortDataOp);
	}

	if (!DestFound || !SourceFound) {
		if (!DestFound)
			delete RightRT; // never linked in to TempRT
		if (NULL != TempRT)
			delete TempRT;
#if SMP_DEBUG_BUILD_RTL
		SMP_msg("ERROR: Could not find binary operand at %lx for %s\n",
			(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
	}
	else {
		this->RTL.push_back(TempRT);
		if ((NN_in == opcode) || (NN_out == opcode))
			delete RightRT;  // unused for port I/O
	}
	return (DestFound && SourceFound);
} // end of SMPInstr::BuildUnary2OpndRTL()

// Build the RTL for an instruction of form: dec ECX, loop to address with optional condition code guard
bool SMPInstr::BuildLoopRTL(SMPoperator GuardOp) {
	size_t OpNum;
	bool SourceFound = false;
	bool EqFlag = false; // loopeq variants
	bool NeqFlag = false; // loopne variants
	char CounterDtyp; // bitwidth enum for loop counter decrement operation

	SMPRegTransfer *LoopRT = new SMPRegTransfer;
	LoopRT->SetParentInst(this);
	SMPRegTransfer *DecCounterRT = new SMPRegTransfer;
	DecCounterRT->SetParentInst(this);

	op_t VoidOp = InitOp;

	op_t OneOp = InitOp;
	OneOp.type = o_imm;  // immediate one
	OneOp.value = 1;

	op_t CountOp = InitOp;
	CountOp.type = o_reg;
	CountOp.reg = R_cx;
	switch (this->SMPcmd.itype) {
		case NN_loopw:               // Loop while ECX != 0
			CounterDtyp = dt_dword;
			break;

		case NN_loop:                // Loop while CX != 0
			CounterDtyp = this->GetOperandDtypField();
			break;

		case NN_loopd:               // Loop while ECX != 0
			CounterDtyp = dt_dword;
			break;

		case NN_loopq:               // Loop while RCX != 0
			CounterDtyp = dt_qword;
			break;

		case NN_loopwe:              // Loop while CX != 0 and ZF=1
			CounterDtyp = dt_word;
			EqFlag = true;
			break;

		case NN_loope:               // Loop while rCX != 0 and ZF=1
			CounterDtyp = this->GetOperandDtypField();
			EqFlag = true;
			break;

		case NN_loopde:              // Loop while ECX != 0 and ZF=1
			CounterDtyp = dt_dword;
			EqFlag = true;
			break;

		case NN_loopqe:              // Loop while RCX != 0 and ZF=1
			CounterDtyp = dt_qword;
			EqFlag = true;
			break;

		case NN_loopwne:             // Loop while CX != 0 and ZF=0
			CounterDtyp = dt_word;
			NeqFlag = true;
			break;

		case NN_loopne:              // Loop while rCX != 0 and ZF=0
			CounterDtyp = this->GetOperandDtypField();
			NeqFlag = true;
			break;

		case NN_loopdne:             // Loop while ECX != 0 and ZF=0
			CounterDtyp = dt_dword;
			NeqFlag = true;
			break;

		case NN_loopqne:             // Loop while RCX != 0 and ZF=0
			CounterDtyp = dt_qword;
			NeqFlag = true;
			break;

		default:
			SMP_msg("ERROR: Unknown loop instruction opcode at %lx in BuildLoopRTL.\n", (unsigned long) this->GetAddr());
			CounterDtyp = dt_dword;
			break;
	}

	OneOp.dtyp = CounterDtyp;
	CountOp.dtyp = CounterDtyp;

	op_t EIPOp = InitOp;
	EIPOp.type = o_reg;
	EIPOp.reg = MD_INSTRUCTION_POINTER_REG;
	EIPOp.dtyp = this->GetOperandDtypField();

	// All x86 loop instructions behave as follows:
	//  1. Decrement RCX/ECX/CX depending on 64/32/16-bit mode of CPU.
	//  2. If counter decremented to zero, fall through to next instruction.
	//  3. For condition code variants, fall through if zero flag is 1 or 0, depending on variant.
	//  4. Otherwise, loop back by adding a signed 8-bit offset to the instruction counter.
	//
	// So, for LOOP, it is simply decrement ECX and loop back if ECX did not become zero.
	//  For LOOPE a.k.a. LOOPZ, it is decrement ECX and loop back if ECX != 0 and ZF == 1, which means
	//   that ZF (zero flag) was set to 1 by an instruction before the LOOPE instruction, not by the
	//   decrement of ECX within the microcode for LOOPE.
	//  For LOOPNE a.k.a. LOOPNZ, change ZF == 1 to ZF == 0 in above description.
	//
	// For RTLs, this means we need an RTL to decrement ECX, and a guarded RTL to add an immediate to the EIP reg.
	//  The guard can be simple (ECX != 0) or compound ((ECX != 0) AND (ZF is 0 or 1)). However, because RTs in
	//  an RTL happen in parallel, we compare ECX to 1 because the comparison happens before it is decremented by
	//  another RT in the RTL. Note also that IDA Pro has converted the signed 8-bit relative offset to a near address
	//  in the operand list.

	DecCounterRT->SetLeftOperand(CountOp);
	DecCounterRT->SetOperator(SMP_DECREMENT);
	DecCounterRT->SetRightOperand(VoidOp);

	for (OpNum = 0; (!SourceFound && (OpNum < UA_MAXOP)); ++OpNum) {
		op_t TempOp = this->SMPcmd.Operands[OpNum];
		if (this->features & DefMacros[OpNum]) { // DEF
#if SMP_VERBOSE_DEBUG_BUILD_RTL_DEF_USE
			SMP_msg("WARNING: Unexpected DEF Operand in LOOP instruction: ");
			PrintOperand(TempOp);
			SMP_msg(" at %x in %s\n", this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
			;
		}
		if (!SourceFound && (this->features & UseMacros[OpNum]) && MDKnownOperandType(TempOp)) {
			if (o_near == TempOp.type) {
				LoopRT->SetLeftOperand(EIPOp);
				LoopRT->SetOperator(SMP_ASSIGN);
				LoopRT->SetRightOperand(TempOp);
				SourceFound = true;
			}
		}
	} // end for (OpNum = 0; ...)

	if (!SourceFound) {
		if (NULL != LoopRT)
			delete LoopRT;
		if (NULL != DecCounterRT)
			delete DecCounterRT;
#if SMP_DEBUG_BUILD_RTL
		SMP_msg("ERROR: Could not find loop operand at %lx for %s\n", 
			(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
	}
	else {
		// If the move is conditional, set the guard expression.
		// NOTE: We do not want to complicate the SMPGuard class to handle compound expressions yet.
		//  If the need arises, we can do so. For now, just treat all loop instructions as a simple LOOP
		//  even if it is LOOPE or LOOPNE.
		SMPGuard *Guard1 = new SMPGuard;
		Guard1->SetLeftOperand(CountOp);
		Guard1->SetOperator(SMP_EQUAL);
		Guard1->SetRightOperand(OneOp);
		LoopRT->SetGuard(Guard1);
		this->RTL.push_back(LoopRT);
		this->RTL.push_back(DecCounterRT);
	}
	return (SourceFound);
} // end of SMPInstr::BuildLoopRTL()

// Build the RTL for an instruction of form dest := source, where 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));
	int opcode = this->SMPcmd.itype;

#if IDA_SDK_VERSION < 600
	if ((NN_ldmxcsr == opcode) || (NN_stmxcsr == opcode)) {
		// IDA 5.1 does not have the R_mxcsr enumeration value,
		//  so we cannot handle these opcodes.
		return false;
	}
#endif

	SMPRegTransfer *TempRT = new SMPRegTransfer;
	TempRT->SetParentInst(this);

	op_t VoidOp = InitOp;

	op_t EAXOp = InitOp;
	EAXOp.type = o_reg;
	EAXOp.reg = R_ax;
	EAXOp.dtyp = this->GetOperandDtypField();

	op_t ALOp = InitOp;
	ALOp.type = o_reg;
	ALOp.reg = R_al;
	ALOp.dtyp = dt_byte;

	op_t CountOp = InitOp;
	CountOp.type = o_reg;
	CountOp.reg = R_cx;
	CountOp.dtyp = this->GetOperandDtypField();

	op_t FlagsOp = InitOp;
	FlagsOp.type = o_reg;
	FlagsOp.reg = X86_FLAGS_REG;
	FlagsOp.dtyp = this->GetOperandDtypField();

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

	op_t PortNumOp = InitOp;
	PortNumOp.type = o_reg;
	PortNumOp.reg = R_dx;
	PortNumOp.dtyp = dt_word;

	op_t PortDataOp = InitOp;
	PortDataOp.type = o_reg;
	PortDataOp.reg = R_ax;
	PortDataOp.dtyp = this->GetOperandDtypField();

#if IDA_SDK_VERSION > 599
	op_t MXCSROp = InitOp;  // MMX Control & Status Register
	MXCSROp.type = o_reg;
	MXCSROp.reg = R_mxcsr;
	MXCSROp.dtyp = this->GetOperandDtypField();
#endif

	op_t ZeroOp = InitOp;
	ZeroOp.type = o_imm;  // immediate zero
	ZeroOp.value = 0;
	ZeroOp.dtyp = this->GetOperandDtypField();

#if SMP_DEBUG_BUILD_RTL
	if (MemSrc && MemDest && (NN_movs != opcode) && (NN_movss != opcode) && (NN_movsd != opcode)) {
		if ((NN_stos != opcode) && (NN_outs != opcode)) {
			SMP_msg("ERROR: IDA Pro error: MemDest and MemSrc in move at %lx for %s\n",
				(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
			this->PrintOperands();
		}
#if 1
		else {  // IDA incorrectly lists [EDI] as both DEF and USE, because reg EDI
			    //  is both DEF and USE in NN_stos.
			SMP_msg("WARNING: Ignoring IDA Pro error: MemDest and MemSrc in move at %lx for %s\n",
				(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
			this->PrintOperands();
		}
#endif
	}
#endif

	// First, handle special cases with implicit operands
	if (NN_lahf == opcode) {  // load AH from flags
		TempRT->SetOperator(SMP_ASSIGN);
		TempRT->SetLeftOperand(EAXOp);
		TempRT->SetRightOperand(FlagsOp);
		this->RTL.push_back(TempRT);
		return true;
	}
	if (NN_sahf == opcode) {  // store AH to flags
		TempRT->SetOperator(SMP_ASSIGN);
		TempRT->SetLeftOperand(FlagsOp);
		TempRT->SetRightOperand(EAXOp);
		this->RTL.push_back(TempRT);
		return true;
	}
	if ((NN_movs == opcode) || (NN_stos == opcode) || (NN_ins == opcode) || (NN_outs == opcode)) {
		// The ESI and EDI registers get incremented or decremented, depending
		//  on the direction flag DF, for MOVS; only EDI for STOS and INS;
		//  only ESI for OUTS.
		// This is true with or without a repeat prefix.
		op_t ESIOp = InitOp, EDIOp = InitOp;
		char Temp_dtyp = this->GetOperandDtypField();
		ESIOp.type = o_reg;
		ESIOp.reg = R_si;
		ESIOp.dtyp = Temp_dtyp;
		EDIOp.type = o_reg;
		EDIOp.reg = R_di;
		EDIOp.dtyp = Temp_dtyp;
		op_t ESIMemOp = InitOp, EDIMemOp = InitOp;  // [esi] and [edi]
		ESIMemOp.type = o_phrase;
		ESIMemOp.reg = R_si;
		ESIMemOp.dtyp = Temp_dtyp;
		EDIMemOp.type = o_phrase;
		EDIMemOp.reg = R_di;
		EDIMemOp.dtyp = Temp_dtyp;
		if (NN_movs == opcode) {
			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 if (NN_stos == opcode) {
			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;
		}
		else if (NN_ins == opcode) {
			this->RTL.ExtraKills.push_back(EDIOp);
			TempRT->SetOperator(SMP_INPUT);
			TempRT->SetLeftOperand(EDIMemOp);
			TempRT->SetRightOperand(PortNumOp);
			DestFound = true;
			SourceFound = true;
		}
		else if (NN_outs == opcode) {
			this->RTL.ExtraKills.push_back(ESIOp);
			TempRT->SetOperator(SMP_OUTPUT);
			TempRT->SetLeftOperand(ESIMemOp);
			TempRT->SetRightOperand(PortNumOp);
			DestFound = true;
			SourceFound = 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 == opcode) || (NN_fbld == opcode) || (NN_fild == opcode)) {
		// Loads implicitly use the floating point stack top as destination.
		TempRT->SetLeftOperand(FPRegOp);
		TempRT->SetOperator(SMP_ASSIGN);
		DestFound =  true;
	}
	else if ((NN_fst == opcode) || (NN_fstp == opcode) || (NN_fbstp == opcode)
		|| (NN_fist == opcode) || (NN_fistp == opcode)) {
		// 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 == opcode) || (NN_fbstp == opcode) || (NN_fistp == opcode)) {
			this->RTL.ExtraKills.push_back(FPRegOp);
		}
	}
#if IDA_SDK_VERSION > 599
	else if (NN_ldmxcsr == opcode) {
		// The MMX Control & Status Register is used implicitly.
		TempRT->SetLeftOperand(MXCSROp);
		DestFound = true;
	}
	else if (NN_stmxcsr == opcode) {
		// The MMX Control & Status Register is used implicitly.
		TempRT->SetRightOperand(MXCSROp);
		SourceFound = true;
	}
#endif

	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);
				}
			}
		}
		else { // USE
			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);
					this->MoveSource = TempOp;
				}
			}
			if (this->features & UseMacros[OpNum]) {
				;
#if SMP_VERBOSE_DEBUG_BUILD_RTL_DEF_USE
				SMP_msg("WARNING: Operand neither DEF nor USE: ");
				PrintOperand(TempOp);
				SMP_msg(" at %lx in %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
			}
		}
	} // end for (OpNum = 0; ...)

	if (!DestFound || !SourceFound) {
		if (NULL != TempRT)
			delete TempRT;
#if SMP_DEBUG_BUILD_RTL
		SMP_msg("ERROR: Could not find move operand at %lx for %s\n", 
			(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#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 or INS or OUTS
			// The repeat causes USE and DEF of ECX as a counter
			SMPRegTransfer *CounterRT = new SMPRegTransfer;
			CounterRT->SetParentInst(this);
			SMPRegTransfer *RightRT = new SMPRegTransfer;
			RightRT->SetParentInst(this);
			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::BuildLoopRTL()

// Build the RTL for a load string instruction, which loads from DS:ESI into EAX
//  (or into AX or AL) and increments or decrements ESI based on the direction flag DF.
bool SMPInstr::BuildLoadStringRTL(void) {
	bool DestFound = false;
	unsigned short ByteSize = 0;

	op_t DestOp = InitOp;
	DestOp.type = o_reg;
	DestOp.reg = R_al;
	DestOp.dtyp = dt_byte;

	for (size_t OpNum = 0; !DestFound && (OpNum < UA_MAXOP); ++OpNum) {
		op_t TempOp = this->SMPcmd.Operands[OpNum];
		if (MDKnownOperandType(TempOp)) {
			if ((o_reg == TempOp.type) && (this->features & DefMacros[OpNum])) { // DEF
				DestFound = true;
				if (TempOp.is_reg(R_al)) {
					ByteSize = 1;
				}
				else if (TempOp.is_reg(R_ax)) {
					ByteSize = STARS_ISA_Bytewidth;
					DestOp.reg = R_ax;
				}
				else {
					SMP_msg("ERROR: Load string destination operand is neither AL nor EAX at %lx\n", 
						(unsigned long) this->GetAddr());
					ByteSize = 1; // default to AL destination
				}
			}
		}
	} // end for (OpNum = 0; ...)

	// Return false if we did not find a destination
	if (!DestFound) {
		return false;
	}

	op_t ZeroOp = InitOp;
	ZeroOp.type = o_imm;  // immediate zero
	ZeroOp.value = 0;
	ZeroOp.dtyp = this->GetOperandDtypField();

	op_t OneOp = InitOp;
	OneOp.type = o_imm;  // immediate one
	OneOp.value = 1;
	OneOp.dtyp = this->GetOperandDtypField();

	op_t FlagsOp = InitOp;
	FlagsOp.type = o_reg;
	FlagsOp.reg = X86_FLAGS_REG;
	FlagsOp.dtyp = this->GetOperandDtypField();

	op_t ESIOp = InitOp;
	ESIOp.type = o_reg;
	ESIOp.reg = R_si;
	ESIOp.dtyp = this->GetOperandDtypField();

	op_t DerefESIOp = InitOp;
	DerefESIOp.type = o_phrase;
	DerefESIOp.reg = R_si;
	DerefESIOp.dtyp = this->GetOperandDtypField();

	SMPRegTransfer *TempRT = new SMPRegTransfer;
	TempRT->SetParentInst(this);
	SMPRegTransfer *GuardedIncRT = new SMPRegTransfer;
	GuardedIncRT->SetParentInst(this);
	SMPRegTransfer *GuardedDecRT = new SMPRegTransfer;
	GuardedDecRT->SetParentInst(this);
	SMPRegTransfer *RightIncRT = new SMPRegTransfer;
	RightIncRT->SetParentInst(this);
	SMPRegTransfer *RightDecRT = new SMPRegTransfer;
	RightDecRT->SetParentInst(this);

	// Build the load string RTL. Ignore DS segment register for now.
	// Load string is:  AL := [ESI]; if (DF == 0) ESI += 1 else ESI -= 1;
	//  for the 8-bit case, and EAX := [ESI]; if (DF == 0) ESI += 4 else ESI -= 4;
	//  for the 32-bit case.

	// AL := [ESI] or EAX := [ESI]
	TempRT->SetLeftOperand(DestOp);
	TempRT->SetOperator(SMP_ASSIGN);
	TempRT->SetRightOperand(DerefESIOp);

	this->RTL.push_back(TempRT);

	// Guarded increment RTL: If the DF (Direction Flag) in EFLAGS is 0, increment ESI
	//  by ByteSize.
	op_t IncDecOp =  InitOp;
	IncDecOp.type = o_imm;
	IncDecOp.value = ByteSize;
	IncDecOp.dtyp = this->GetOperandDtypField();

	SMPGuard *Guard1 = new SMPGuard;
	Guard1->SetLeftOperand(FlagsOp);
	Guard1->SetOperator(SMP_U_COMPARE);
	Guard1->SetRightOperand(ZeroOp);
	GuardedIncRT->SetGuard(Guard1);
	GuardedIncRT->SetLeftOperand(ESIOp);
	GuardedIncRT->SetOperator(SMP_ASSIGN);
	RightIncRT->SetLeftOperand(ESIOp);
	RightIncRT->SetOperator(SMP_ADD);
	RightIncRT->SetRightOperand(IncDecOp);
	GuardedIncRT->SetRightTree(RightIncRT);

	this->RTL.push_back(GuardedIncRT);

	// Guarded decrement RTL: If the DF (Direction Flag) in EFLAGS is 1, decrement ESI
	//  by ByteSize.
	SMPGuard *Guard2 = new SMPGuard;
	Guard2->SetLeftOperand(FlagsOp);
	Guard2->SetOperator(SMP_U_COMPARE);
	Guard2->SetRightOperand(OneOp);
	GuardedDecRT->SetGuard(Guard2);
	GuardedDecRT->SetLeftOperand(ESIOp);
	GuardedDecRT->SetOperator(SMP_ASSIGN);
	RightDecRT->SetLeftOperand(ESIOp);
	RightDecRT->SetOperator(SMP_SUBTRACT);
	RightDecRT->SetRightOperand(IncDecOp);
	GuardedDecRT->SetRightTree(RightDecRT);

	this->RTL.push_back(GuardedDecRT);

	return true;
} // end of SMPInstr::BuildLoadStringRTL()

// 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 = InitOp;
	FlagsOp.type = o_reg;
	FlagsOp.reg = X86_FLAGS_REG;
	FlagsOp.dtyp = this->GetOperandDtypField();

	op_t CountOp = InitOp;
	CountOp.type = o_reg;
	CountOp.reg = R_cx;
	CountOp.dtyp = this->GetOperandDtypField();

	op_t VoidOp = InitOp;

	SMPRegTransfer *TempRT = new SMPRegTransfer;
	TempRT->SetParentInst(this);
	SMPRegTransfer *RightRT = new SMPRegTransfer;
	RightRT->SetParentInst(this);

	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
					SMP_msg("CMPS 1st opnd is DEF\n");
				else if (this->features & UseMacros[OpNum]) // USE
					SMP_msg("CMPS 1st opnd is USE\n");
				else
					SMP_msg("CMPS 1st opnd neither DEF nor USE\n");
			}
			else {
				Src2Found = true;
				RightRT->SetRightOperand(TempOp);
				if (this->features & DefMacros[OpNum]) // DEF
					SMP_msg("CMPS 2nd opnd is DEF\n");
				else if (this->features & UseMacros[OpNum]) // USE
					SMP_msg("CMPS 2nd opnd is USE\n");
				else
					SMP_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
		SMP_msg("ERROR: Could not find CMPS operand at %lx for %s\n",
			(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#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;
			CounterRT->SetParentInst(this);
			SMPRegTransfer *RightRT = new SMPRegTransfer;
			RightRT->SetParentInst(this);
			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
	TempRT->SetParentInst(this);

	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 SMP_VERBOSE_DEBUG_BUILD_RTL
				if (this->features & DefMacros[OpNum]) // DEF
					SMP_msg("XCHG 1st opnd is DEF\n");
				else if (this->features & UseMacros[OpNum]) // USE
					SMP_msg("XCHG 1st opnd is USE\n");
				else
					SMP_msg("XCHG 1st opnd neither DEF nor USE\n");
#endif
			}
			else {
				Src2Found = true;
				TempRT->SetLeftOperand(TempOp);
				if (this->features & DefMacros[OpNum]) // DEF
					SMP_msg("XCHG 2nd opnd is DEF\n");
				else if (this->features & UseMacros[OpNum]) // USE
					SMP_msg("XCHG 2nd opnd is USE\n");
				else
					SMP_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
		SMP_msg("ERROR: Could not find XCHG operand at %lx for %s\n",
			(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
	}
	else {
		// Create the first effect, dest := src
		SMPRegTransfer *FirstRT = new SMPRegTransfer;
		FirstRT->SetParentInst(this);
		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
	TempRT->SetParentInst(this);

	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
					SMP_msg("XADD 1st opnd is DEF\n"); // should be the case
				else if (this->features & UseMacros[OpNum]) // USE
					SMP_msg("WARNING: XADD 1st opnd is USE\n");
				else
					SMP_msg("WARNING: XADD 1st opnd neither DEF nor USE\n");
			}
			else {
				Src2Found = true;
				TempRT->SetLeftOperand(TempOp);
				if (this->features & DefMacros[OpNum]) // DEF
					SMP_msg("WARNING: XADD 2nd opnd is DEF\n");
				else if (this->features & UseMacros[OpNum]) // USE
					SMP_msg("XADD 2nd opnd is USE\n"); // should be the case
				else
					SMP_msg("WARNING: 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
		SMP_msg("ERROR: Could not find XADD operand at %lx for %s\n",
			(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
	}
	else {
		// Create the first effect, dest := dest + src
		SMPRegTransfer *FirstRT = new SMPRegTransfer;
		FirstRT->SetParentInst(this);
		SMPRegTransfer *AddRT = new SMPRegTransfer;
		AddRT->SetParentInst(this);
		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 = InitOp;
	DestOp.dtyp = this->GetOperandDtypField();
	op_t SourceOp = InitOp;
	SourceOp.dtyp = this->GetOperandDtypField();
	SMPRegTransfer *TempRT = new SMPRegTransfer;
	TempRT->SetParentInst(this);

	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 {
					SMP_msg("CMPXCHG has two DEF operands.\n");
				}
			}
			else if (this->features & UseMacros[OpNum]) { // USE
				if (!SourceFound) {
					SourceFound = true;
					SourceOp = TempOp;
				}
				else {
					SMP_msg("CMPXCHG has two USE operands.\n");
				}
			}
		}
	} // end for (OpNum = 0; ...)

	if (!DestFound || !SourceFound) {
		if (NULL != TempRT)
			delete TempRT;
#if SMP_DEBUG_BUILD_RTL
		SMP_msg("ERROR: Could not find CMPXCHG operand at %lx for %s\n",
			(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
	}
	else {
		// Create the first effect, if (dest == EAX) dest := src
		SMPGuard *Guard1 = new SMPGuard;
		op_t EAXOp = InitOp;
		EAXOp.type = o_reg;
		EAXOp.reg =  R_ax;
		Guard1->SetLeftOperand(DestOp);
		Guard1->SetOperator(SMP_EQUAL);
		Guard1->SetRightOperand(EAXOp);
		SMPRegTransfer *FirstRT = new SMPRegTransfer;
		FirstRT->SetParentInst(this);
		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 an extended FP concatenate and shift instruction
bool SMPInstr::BuildPackShiftRTL(SMPoperator PackOp, SMPoperator ShiftOp) {
	size_t OpNum;
	bool DestFound = false;
	bool SourceFound = false;
	bool CountFound = false;
	SMPRegTransfer *TempRT = NULL;
	SMPRegTransfer *ShiftRT = new SMPRegTransfer;
	ShiftRT->SetParentInst(this);
	SMPRegTransfer *PackRT = new SMPRegTransfer;
	PackRT->SetParentInst(this);

	// RTL structure: top operator is assignment, next right operator is a reverse
	//  shift with the shift count as its left operand, and lowest right operator
	//  is the concatenation operator. Sequence of operations is pack, shift, assign.
	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->SetParentInst(this);
				TempRT->SetLeftOperand(TempOp);
				TempRT->SetOperator(SMP_ASSIGN);
				PackRT->SetLeftOperand(TempOp);
				PackRT->SetOperator(PackOp);
				ShiftRT->SetOperator(ShiftOp);
				ShiftRT->SetRightTree(PackRT);
				TempRT->SetRightTree(ShiftRT);
			}
		}
		else { // USE
			if (MDKnownOperandType(TempOp)) {
				if (!SourceFound) {
					SourceFound = true;
					PackRT->SetRightOperand(TempOp);
				}
				else {
					CountFound = true;
					ShiftRT->SetLeftOperand(TempOp);
				}
			}
		}
	} // end for (OpNum = 0; ...)

	if (!DestFound || !SourceFound || !CountFound) {
		if (NULL != TempRT)
			delete TempRT;
#if SMP_DEBUG_BUILD_RTL
		SMP_msg("ERROR: Could not find MMX/XMM pack and shift operand at %lx for %s\n",
			(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
	}
	else {
		this->RTL.push_back(TempRT);
	}
	return (DestFound && SourceFound && CountFound);
} // end of SMPInstr::BuildPackShiftRTL()

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

	SMPRegTransfer *TempRT = new SMPRegTransfer;
	TempRT->SetParentInst(this);
	SMPRegTransfer *RightRT = new SMPRegTransfer;
	RightRT->SetParentInst(this);

	op_t VoidOp = InitOp, FlagsOp = InitOp;

	FlagsOp.type = o_reg;
	FlagsOp.reg = X86_FLAGS_REG;
	FlagsOp.dtyp = this->GetOperandDtypField();

	op_t CountOp = InitOp;
	CountOp.type = o_reg;
	CountOp.reg = R_cx;
	CountOp.dtyp = this->GetOperandDtypField();

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

	// 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_fcomi == opcode) || (NN_fucomi == opcode) || (NN_fcomip == opcode)
		|| (NN_fucomip == opcode)) {
		// Compares implicitly use the floating point stack top as destination.
		TempRT->SetLeftOperand(FlagsOp);
		TempRT->SetOperator(SMP_ASSIGN);
		RightRT->SetLeftOperand(FPRegOp);
		RightRT->SetOperator(BinaryOp);
		TempRT->SetRightTree(RightRT);
		Source1Found = true;
		// The "p" at the end of the opcode indicates that the floating point
		//  register stack gets popped.
		if ((NN_fcomip == opcode) || (NN_fucomip == opcode)) {
			this->RTL.ExtraKills.push_back(FPRegOp);
		}
	}

	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
				SMP_msg("ERROR: Found destination for compare or test at %lx : %s\n",
					(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
			}
		}
		else { // USE
			if (MDKnownOperandType(TempOp)) {
				if (!Source1Found) {
					Source1Found = true;
					TempRT->SetLeftOperand(FlagsOp);
					TempRT->SetOperator(SMP_ASSIGN);
					RightRT->SetLeftOperand(TempOp);
					RightRT->SetOperator(BinaryOp);
					TempRT->SetRightTree(RightRT);
				}
				else {
					assert(!Source2Found);
					Source2Found = true;
					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, and might not have
	//  explicit operands; explicit operands are just for documentation.
	// The scan string instruction uses EAX/AX/AH/AL and ES:EDI as its source
	//  operands and might not have any explicit operands at all.
	if ((!NoOperandsRequired) && (!Source1Found || !Source2Found)) {
		if (!Source1Found)
			delete RightRT;
		else
			delete TempRT;
#if SMP_DEBUG_BUILD_RTL
		SMP_msg("ERROR: Could not find CMP/TEST operand at %lx for %s\n",
			(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#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;
			CounterRT->SetParentInst(this);
			SMPRegTransfer *RightRT = new SMPRegTransfer;
			RightRT->SetParentInst(this);
			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 == opcode) || (NN_scas == opcode)) {
			// 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 = InitOp, EDIOp = InitOp;
			ESIOp.type = o_reg;
			ESIOp.reg = R_si;
			EDIOp.type = o_reg;
			EDIOp.reg = R_di;
			if (NN_cmps == opcode) {
				this->RTL.ExtraKills.push_back(ESIOp);
			}
			this->RTL.ExtraKills.push_back(EDIOp);
		}
	}
	return (NoOperandsRequired || (Source1Found && Source2Found));
} // end of SMPInstr::BuildFlagsDestBinaryRTL()

// Build the RTL for a direct or indirect call instruction
bool SMPInstr::BuildCallRTL(void) {
	size_t OpNum;
	bool SourceFound = false;
	op_t VoidOp = InitOp;
	SMPRegTransfer *TempRT = NULL;

	for (OpNum = 0; !SourceFound && (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
				SMP_msg("ERROR: Found destination operand for call at %lx : %s\n",
					(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
			}
		}
		else { // USE
			if (MDKnownOperandType(TempOp)) {
				SourceFound = true;
				TempRT = new SMPRegTransfer;
				TempRT->SetParentInst(this);
				TempRT->SetLeftOperand(VoidOp);
				TempRT->SetOperator(SMP_CALL);
				TempRT->SetRightOperand(TempOp);
			}
		}
	} // end for (OpNum = 0; ...)

	if (!SourceFound) {
#if SMP_DEBUG_BUILD_RTL
		SMP_msg("ERROR: Could not find CALL operand at %lx for %s\n", 
			(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
	}
	else {
		this->RTL.push_back(TempRT);
	}
	return SourceFound;
} // end of SMPInstr::BuildCallRTL()

// Build the RTL for a return instruction, with or without extra bytes popped off stack
bool SMPInstr::BuildReturnRTL(void) {
	size_t OpNum;
	uval_t PopBytes = STARS_ISA_Bytewidth;  // default: pop off return address

	switch (this->SMPcmd.itype) {
		// Returns modified by operand size prefixes
		case NN_retnw:               // Return Near from Procedure (use16)
		case NN_retfw:               // Return Far from Procedure (use16)
			PopBytes = 2;
			break;

		case NN_retnd:               // Return Near from Procedure (use32)
		case NN_retfd:               // Return Far from Procedure (use32)
			PopBytes = 4;
			break;

		case NN_retnq:               // Return Near from Procedure (use64)
		case NN_retfq:               // Return Far from Procedure (use64)
			PopBytes = 8;
			break;
	}

	for (OpNum = 0; 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
				SMP_msg("ERROR: Found destination operand for RET at %lx : %s\n",
					(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
			}
		}
		else { // USE
			if (MDKnownOperandType(TempOp)) {
				if (o_imm == TempOp.type) {
					PopBytes += TempOp.value;
				}
				else {
#if SMP_DEBUG_BUILD_RTL
					if (!(this->IsTailCall())) {
						SMP_msg("ERROR: Found unexpected operand for return at %lx : %s\n",
							(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
					}
#endif
				}
			}
		}
	} // end for (OpNum = 0; ...)

	this->AddToStackPointer(PopBytes);
	return true;
} // end of SMPInstr::BuildReturnRTL()

// Build the RTL for an ENTER instruction
bool SMPInstr::BuildEnterRTL(void) {
	// An "ENTER k,0" instruction with allocation k and nesting level 0 does the following:
	//  push ebp
	//  mov ebp,esp
	//  sub esp,k
	// This can be modeled by the parallel effects:
	//  [esp-4] := ebp; ebp := esp - 4; esp := esp - (k + 4)
	// If nesting level is greater than zero, we have a block structure language with
	//  nested procedures, in which additional frame pointers are saved:
	// "ENTER k,n" pushes n additional frame pointers on the stack. We will only model
	//  the change in the stack pointer here, and not attempt to transfer the display
	//  pointers. A warning will be issued to the log file. Parallel effects are:
	//  [esp-4] := ebp; ebp := esp - 4; esp := esp - (((k + n)*4)+4)
	// Note that k and n are immediate values so the final expression can be computed.
	size_t OpNum;
	uval_t NestingLevel = 0;
	uval_t AllocBytes = 0;
	bool AllocFound = false;
	bool NestingLevelFound = false;

	op_t StackPointerOp = InitOp;  // ESP
	StackPointerOp.type = o_reg;
	StackPointerOp.reg = MD_STACK_POINTER_REG;
	StackPointerOp.dtyp = this->GetOperandDtypField();

	op_t FramePointerOp = InitOp;  // EBP
	FramePointerOp.type = o_reg;
	FramePointerOp.reg = MD_FRAME_POINTER_REG;
	FramePointerOp.dtyp = this->GetOperandDtypField();

	op_t Immed4Op = InitOp;        // 4
	Immed4Op.type = o_imm;
	Immed4Op.value = STARS_ISA_Bytewidth;
	Immed4Op.dtyp = this->GetOperandDtypField();

	op_t SavedEBP = InitOp;        // [ESP-4], location of saved EBP
	SavedEBP.type = o_displ;
	SavedEBP.addr = -((ea_t) STARS_ISA_Bytewidth);
	SavedEBP.reg = MD_STACK_POINTER_REG;
	SavedEBP.dtyp = this->GetOperandDtypField();

	for (OpNum = 0; !(AllocFound && NestingLevelFound) && (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
				SMP_msg("ERROR: Found destination operand for ENTER at %lx : %s\n",
					(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
			}
		}
		else { // USE
			if (MDKnownOperandType(TempOp)) {
				if (o_imm == TempOp.type) {
					if (!AllocFound) {
						AllocBytes = TempOp.value;
						AllocFound = true;
					}
					else {
						NestingLevel = TempOp.value;
						NestingLevelFound = true;
					}
				}
				else {
#if SMP_DEBUG_BUILD_RTL
					SMP_msg("ERROR: Found unexpected operand for ENTER at %lx : %s\n",
						(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
				}
			}
		}
	} // end for (OpNum = 0; ...)

	if (!AllocFound) {
#if SMP_DEBUG_BUILD_RTL
		SMP_msg("ERROR: Could not find allocation operand for ENTER at %lx : %s\n",
			(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
#endif
	}
	else {
		SMPRegTransfer *TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);

		// Add first effect: [esp-4] := ebp
		TempRT->SetLeftOperand(SavedEBP);
		TempRT->SetOperator(SMP_ASSIGN);
		TempRT->SetRightOperand(FramePointerOp);
		this->RTL.push_back(TempRT);
		TempRT = NULL;

		// Add second effect: ebp := esp - wordsize
		TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);
		TempRT->SetLeftOperand(FramePointerOp);
		TempRT->SetOperator(SMP_ASSIGN);
		SMPRegTransfer *RightRT = new SMPRegTransfer;
		RightRT->SetParentInst(this);
		RightRT->SetLeftOperand(StackPointerOp);
		RightRT->SetOperator(SMP_SUBTRACT);
		RightRT->SetRightOperand(Immed4Op);
		TempRT->SetRightTree(RightRT);
		this->RTL.push_back(TempRT);
		TempRT = NULL;
		RightRT = NULL;

		// Add final effect on stack pointer
		AllocBytes += (STARS_ISA_Bytewidth * (NestingLevel + 1));
		if (0 != NestingLevel) {
			SMP_msg("WARNING: Nested procedures in ENTER instruction at %lx : %s\n",
				(unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
		}
		this->SubFromStackPointer(AllocBytes);
	}
	return AllocFound;
} // end of SMPInstr::BuildEnterRTL()

// Build the RTL for an LEAVE instruction
bool SMPInstr::BuildLeaveRTL(void) {
	// A LEAVE instruction simulates the following instructions:
	//  mov ebp into esp (deallocates stack frame)
	//  pop saved ebp off stack into ebp
	// We want to model these two instructions with three parallel effects:
	//  esp := ebp; ebp := [ebp+0]; esp = esp + wordsize;
	// There cannot be two definitions of esp in the list of effects, so we do:
	//  esp := ebp + wordsize; ebp := [ebp+0] as our two parallel effects
	op_t StackPointerOp = InitOp;   // ESP
	StackPointerOp.type = o_reg;
	StackPointerOp.reg = MD_STACK_POINTER_REG;
	StackPointerOp.dtyp = this->GetOperandDtypField();

	op_t FramePointerOp = InitOp;   // EBP
	FramePointerOp.type = o_reg;
	FramePointerOp.reg = MD_FRAME_POINTER_REG;
	FramePointerOp.dtyp = this->GetOperandDtypField();

	op_t Immed4Op = InitOp;         // wordsize
	Immed4Op.type = o_imm;
	Immed4Op.value = STARS_ISA_Bytewidth;
	Immed4Op.dtyp = this->GetOperandDtypField();

	op_t SavedEBP = InitOp;         // [EBP+0]
	SavedEBP.type = o_displ;
	SavedEBP.reg = MD_FRAME_POINTER_REG;
	SavedEBP.dtyp = this->GetOperandDtypField();

	// Build first effect:  ESP := EBP + wordsize
	SMPRegTransfer *TempRT = new SMPRegTransfer;
	TempRT->SetParentInst(this);
	TempRT->SetLeftOperand(StackPointerOp);
	TempRT->SetOperator(SMP_ASSIGN);
	SMPRegTransfer *RightRT = new SMPRegTransfer;
	RightRT->SetParentInst(this);
	RightRT->SetOperator(SMP_ADD);
	RightRT->SetLeftOperand(FramePointerOp);
	RightRT->SetRightOperand(Immed4Op);
	TempRT->SetRightTree(RightRT);
	this->RTL.push_back(TempRT);
	TempRT = NULL;
	RightRT = NULL;

	// Build second effect: EBP := [EBP+0]
	TempRT = new SMPRegTransfer;
	TempRT->SetParentInst(this);
	TempRT->SetLeftOperand(FramePointerOp);
	TempRT->SetOperator(SMP_ASSIGN);
	TempRT->SetRightOperand(SavedEBP);
	this->RTL.push_back(TempRT);
	TempRT = NULL;

	return true;
} // end of SMPInstr::BuildLeaveRTL()

// Build OptCategory 8 RTLs, which set system info into EDX:EAX.
bool SMPInstr::BuildOptType8RTL(void) {
	op_t DestOp = InitOp;
	DestOp.type = o_reg;
	DestOp.dtyp = this->GetOperandDtypField();

	op_t VoidOp = InitOp;
	op_t LeftOp = InitOp;
	if (NN_xgetbv == this->SMPcmd.itype) {
		// AMD xgetbc opcode gets control register number to read out of ECX.
		LeftOp.type = o_reg;
		LeftOp.reg = R_cx;
		LeftOp.dtyp = this->GetOperandDtypField();
	}

	// Create the effect on EDX.
	SMPRegTransfer *TempRT = new SMPRegTransfer;
	TempRT->SetParentInst(this);
	DestOp.reg = R_dx;
	TempRT->SetLeftOperand(DestOp);
	TempRT->SetOperator(SMP_ASSIGN);
	SMPRegTransfer *RightRT =  new SMPRegTransfer;
	RightRT->SetParentInst(this);
	RightRT->SetLeftOperand(LeftOp);
	RightRT->SetOperator(SMP_SYSTEM_OPERATION);
	RightRT->SetRightOperand(VoidOp);
	TempRT->SetRightTree(RightRT);
	this->RTL.push_back(TempRT);

	// Create the effect on EAX.
	TempRT = NULL;
	RightRT = NULL;
	TempRT = new SMPRegTransfer;
	TempRT->SetParentInst(this);
	DestOp.reg = R_ax;
	TempRT->SetLeftOperand(DestOp);
	TempRT->SetOperator(SMP_ASSIGN);
	RightRT = new SMPRegTransfer;
	RightRT->SetParentInst(this);
	RightRT->SetLeftOperand(LeftOp);
	RightRT->SetOperator(SMP_SYSTEM_OPERATION);
	RightRT->SetRightOperand(VoidOp);
	TempRT->SetRightTree(RightRT);
	this->RTL.push_back(TempRT);

	return true;
} // end of BuildOptType8RTL()

// Build the RTL for a direct or indirect jump instruction
bool SMPInstr::BuildJumpRTL(SMPoperator CondBranchOp) {
	size_t OpNum;
	bool TargetFound = false;
	SMPRegTransfer *TempRT = NULL;
	op_t EIPOp = InitOp, ZeroOp = InitOp, FlagsOp = InitOp;

	EIPOp.type = o_reg;
	EIPOp.reg = R_ip;
	EIPOp.dtyp = this->GetOperandDtypField();

	ZeroOp.type = o_imm;
	ZeroOp.dtyp = this->GetOperandDtypField();

	FlagsOp.type = o_reg;
	FlagsOp.reg = X86_FLAGS_REG;
	FlagsOp.dtyp = this->GetOperandDtypField();

	op_t CountOp = InitOp;
	CountOp.type = o_reg;
	CountOp.reg = R_cx;
	CountOp.dtyp = this->GetOperandDtypField();

#if 0
	if (this->IsTailCall())
		return this->BuildReturnRTL();
#endif

	for (OpNum = 0; !TargetFound && (OpNum < UA_MAXOP); ++OpNum) {
		op_t TempOp = this->SMPcmd.Operands[OpNum];
		if (this->features & UseMacros[OpNum]) { // USE
			if (MDKnownOperandType(TempOp)) {
				TargetFound = true;
				TempRT = new SMPRegTransfer;
				TempRT->SetParentInst(this);
				TempRT->SetLeftOperand(EIPOp);
				TempRT->SetOperator(SMP_ASSIGN);
				TempRT->SetRightOperand(TempOp);
				if (CondBranchOp != SMP_NULL_OPERATOR) {
					// Set up a guard expression comparing EFLAGS to zero.
					// NOTE: This is imprecise for value-set purposes, but OK for types.
					SMPGuard *BranchCondition = new SMPGuard;
					BranchCondition->SetOperator(CondBranchOp);
					// The conditional jumps on ECX==0 compare to ECX, not EFLAGS.
					if ((NN_jcxz <= this->SMPcmd.itype) && (NN_jrcxz >= this->SMPcmd.itype))
						BranchCondition->SetLeftOperand(CountOp);
					else
						BranchCondition->SetLeftOperand(FlagsOp);
					BranchCondition->SetRightOperand(ZeroOp);
					TempRT->SetGuard(BranchCondition);
				}
				this->RTL.push_back(TempRT);
			}
		}
	} // end for (OpNum = 0; ...)

#if SMP_DEBUG_BUILD_RTL
	if (!TargetFound) {
		SMP_msg("ERROR: Could not find jump target at %lx for %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
	}
#endif
	return TargetFound;
} // end of SMPInstr::BuildJumpRTL()

// Add to the stack pointer to deallocate stack space, e.g. for a pop instruction.
void SMPInstr::AddToStackPointer(uval_t delta) {
	SMPRegTransfer *TempRT = new SMPRegTransfer;
	TempRT->SetParentInst(this);
	SMPRegTransfer *RightRT = new SMPRegTransfer;
	RightRT->SetParentInst(this);
	op_t StackOp = InitOp, DeltaOp = InitOp;

	StackOp.type = o_reg;
	StackOp.reg = R_sp;
	StackOp.dtyp = this->GetOperandDtypField();

	DeltaOp.type = o_imm;
	DeltaOp.value = delta;
	DeltaOp.dtyp = this->GetOperandDtypField();

	TempRT->SetLeftOperand(StackOp);    // ESP := RightRT
	TempRT->SetOperator(SMP_ASSIGN); 
	RightRT->SetLeftOperand(StackOp); // ESP + delta
	RightRT->SetOperator(SMP_ADD);
	RightRT->SetRightOperand(DeltaOp);
	TempRT->SetRightTree(RightRT);
	this->RTL.push_back(TempRT);
	return;
} // end of SMPInstr::AddToStackPointer()

// Subtract from the stack pointer to allocate stack space, e.g. for a push instruction.
void SMPInstr::SubFromStackPointer(uval_t delta) {
	SMPRegTransfer *TempRT = new SMPRegTransfer;
	TempRT->SetParentInst(this);
	SMPRegTransfer *RightRT = new SMPRegTransfer;
	RightRT->SetParentInst(this);
	op_t StackOp = InitOp, DeltaOp = InitOp;

	StackOp.type = o_reg;
	StackOp.reg = R_sp;
	StackOp.dtyp = this->GetOperandDtypField();

	DeltaOp.type = o_imm;
	DeltaOp.value = delta;
	DeltaOp.dtyp = this->GetOperandDtypField();

	TempRT->SetLeftOperand(StackOp);    // ESP := RightRT
	TempRT->SetOperator(SMP_ASSIGN);
	RightRT->SetLeftOperand(StackOp); // ESP - delta
	RightRT->SetOperator(SMP_SUBTRACT);
	RightRT->SetRightOperand(DeltaOp);
	TempRT->SetRightTree(RightRT);
	this->RTL.push_back(TempRT);
	return;
} // end of SMPInstr::SubFromStackPointer()

#define SMP_FIRST_POP_FLAGS  NN_popfw
#define SMP_LAST_POP_FLAGS  NN_popfq
#define SMP_FIRST_POP_ALL  NN_popaw
#define SMP_LAST_POP_ALL  NN_popaq
// Build the RTL for a pop instruction
bool SMPInstr::BuildPopRTL(void) {
	size_t OpNum, OpSize;
	bool DestFound = false;
	SMPRegTransfer *TempRT = NULL;
	op_t StackOp = InitOp, FlagsOp = InitOp;
	StackOp.type = o_displ;
	StackOp.reg = R_sp;
	StackOp.dtyp = this->GetOperandDtypField();
	// StackOp.addr = 0;  // [ESP+0]
	FlagsOp.type = o_reg;
	FlagsOp.reg = X86_FLAGS_REG;
	FlagsOp.dtyp = this->GetOperandDtypField();

	// Handle special cases first.
	if ((SMP_FIRST_POP_FLAGS <= this->SMPcmd.itype) && (SMP_LAST_POP_FLAGS >= this->SMPcmd.itype)) {
		TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);
		TempRT->SetLeftOperand(FlagsOp);
		TempRT->SetOperator(SMP_ASSIGN);
		TempRT->SetRightOperand(StackOp);
		this->RTL.push_back(TempRT);
		TempRT = NULL;
		// Now create the stack pointer increment effect.
		this->AddToStackPointer(STARS_ISA_Bytewidth);
		return true;
	}

	if ((SMP_FIRST_POP_ALL <= this->SMPcmd.itype) && (SMP_LAST_POP_ALL >= this->SMPcmd.itype)) {
		// We pop off 7 registers from the 8 that were pushed on the stack.
		//  The pushed stack pointer is ignored. Instead, the stack pointer value is
		//  adjusted at the end, per the Intel instruction manuals.

		op_t RegOp = InitOp;
		RegOp.type = o_reg;
		RegOp.dtyp = this->GetOperandDtypField();

		// EDI comes from [ESP+0]
		RegOp.reg = R_di;
		StackOp.addr = 0;  // [ESP+0]
		TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);
		TempRT->SetLeftOperand(RegOp);
		TempRT->SetOperator(SMP_ASSIGN);
		TempRT->SetRightOperand(StackOp);
		this->RTL.push_back(TempRT);
		TempRT = NULL;

		// ESI comes from [ESP+4]
		RegOp.reg = R_si;
		StackOp.addr = STARS_ISA_Bytewidth;  // [ESP+4]
		TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);
		TempRT->SetLeftOperand(RegOp);
		TempRT->SetOperator(SMP_ASSIGN);
		TempRT->SetRightOperand(StackOp);
		this->RTL.push_back(TempRT);
		TempRT = NULL;

		// EBP comes from [ESP+8]
		RegOp.reg = MD_FRAME_POINTER_REG;
		StackOp.addr = 2*STARS_ISA_Bytewidth;  // [ESP+8]
		TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);
		TempRT->SetLeftOperand(RegOp);
		TempRT->SetOperator(SMP_ASSIGN);
		TempRT->SetRightOperand(StackOp);
		this->RTL.push_back(TempRT);
		TempRT = NULL;

		// Skip over saved ESP at [ESP+12]

		// EBX comes from [ESP+16]
		RegOp.reg = R_bx;
		StackOp.addr = 4*STARS_ISA_Bytewidth;  // [ESP+16]
		TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);
		TempRT->SetLeftOperand(RegOp);
		TempRT->SetOperator(SMP_ASSIGN);
		TempRT->SetRightOperand(StackOp);
		this->RTL.push_back(TempRT);
		TempRT = NULL;

		// EDX comes from [ESP+20]
		RegOp.reg = R_dx;
		StackOp.addr = 5*STARS_ISA_Bytewidth;  // [ESP+20]
		TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);
		TempRT->SetLeftOperand(RegOp);
		TempRT->SetOperator(SMP_ASSIGN);
		TempRT->SetRightOperand(StackOp);
		this->RTL.push_back(TempRT);
		TempRT = NULL;

		// ECX comes from [ESP+24]
		RegOp.reg = R_cx;
		StackOp.addr = 6*STARS_ISA_Bytewidth;  // [ESP+24]
		TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);
		TempRT->SetLeftOperand(RegOp);
		TempRT->SetOperator(SMP_ASSIGN);
		TempRT->SetRightOperand(StackOp);
		this->RTL.push_back(TempRT);
		TempRT = NULL;

		// EAX comes from [ESP+28]
		RegOp.reg = R_ax;
		StackOp.addr = 7*STARS_ISA_Bytewidth;  // [ESP+28]
		TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);
		TempRT->SetLeftOperand(RegOp);
		TempRT->SetOperator(SMP_ASSIGN);
		TempRT->SetRightOperand(StackOp);
		this->RTL.push_back(TempRT);
		TempRT = NULL;

		// Now create the stack pointer increment effect.
		this->AddToStackPointer(8*STARS_ISA_Bytewidth);
		return true;
	} // end for "pop all" instructions

	// If we reach this point, we have a simple POP instruction.
	for (OpNum = 0; !DestFound && (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->SetParentInst(this);
				TempRT->SetLeftOperand(TempOp);
				TempRT->SetOperator(SMP_ASSIGN);
				StackOp.dtyp = TempOp.dtyp;  // size of transfer
				TempRT->SetRightOperand(StackOp);
				this->RTL.push_back(TempRT);
				// Now create the stack pointer increment effect.
				OpSize = GetOpDataSize(TempOp);
				this->AddToStackPointer((uval_t) OpSize);
			}
		}
	} // end for (OpNum = 0; ...)

#if SMP_DEBUG_BUILD_RTL
	if (!DestFound) {
		SMP_msg("ERROR: Could not find pop operand at %lx for %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
	}
#endif
	return DestFound;
} // end of SMPInstr::BuildPopRTL()

#define SMP_FIRST_PUSH_FLAGS  NN_pushfw
#define SMP_LAST_PUSH_FLAGS  NN_pushfq
#define SMP_FIRST_PUSH_ALL  NN_pushaw
#define SMP_LAST_PUSH_ALL  NN_pushaq
// Build the RTL for a push instruction
bool SMPInstr::BuildPushRTL(void) {
	size_t OpNum, OpSize;
	bool SourceFound = false;
	SMPRegTransfer *TempRT = NULL;
	op_t StackOp = InitOp, FlagsOp = InitOp;
	StackOp.type = o_displ;
	StackOp.reg = R_sp;
	StackOp.addr = -((ea_t) STARS_ISA_Bytewidth);  // [ESP-wordsize]
	StackOp.dtyp = this->GetOperandDtypField();
	FlagsOp.type = o_reg;
	FlagsOp.reg = X86_FLAGS_REG;
	FlagsOp.dtyp = this->GetOperandDtypField();

	// Handle special cases first.
	if ((SMP_FIRST_PUSH_FLAGS <= this->SMPcmd.itype) && (SMP_LAST_PUSH_FLAGS >= this->SMPcmd.itype)) {
		TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);
		TempRT->SetRightOperand(FlagsOp);
		TempRT->SetOperator(SMP_ASSIGN);
		TempRT->SetLeftOperand(StackOp);
		this->RTL.push_back(TempRT);
		// Now create the stack pointer increment effect.
		this->SubFromStackPointer(STARS_ISA_Bytewidth);
		return true;
	}

	if ((SMP_FIRST_PUSH_ALL <= this->SMPcmd.itype) && (SMP_LAST_PUSH_ALL >= this->SMPcmd.itype)) {
		op_t RegOp = InitOp;
		RegOp.type = o_reg;
		RegOp.dtyp = this->GetOperandDtypField();

		// EDI goes to [ESP-32]
		RegOp.reg = R_di;
		StackOp.addr = -((ea_t)(8*STARS_ISA_Bytewidth));  // [ESP-32]
		TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);
		TempRT->SetRightOperand(RegOp);
		TempRT->SetOperator(SMP_ASSIGN);
		TempRT->SetLeftOperand(StackOp);
		this->RTL.push_back(TempRT);
		TempRT = NULL;

		// ESI goes to [ESP-28]
		RegOp.reg = R_si;
		StackOp.addr = -((ea_t)(7*STARS_ISA_Bytewidth));  // [ESP-28]
		TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);
		TempRT->SetRightOperand(RegOp);
		TempRT->SetOperator(SMP_ASSIGN);
		TempRT->SetLeftOperand(StackOp);
		this->RTL.push_back(TempRT);
		TempRT = NULL;

		// EBP goes to [ESP-24]
		RegOp.reg = MD_FRAME_POINTER_REG;
		StackOp.addr = -((ea_t)(6*STARS_ISA_Bytewidth));  // [ESP-24]
		TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);
		TempRT->SetRightOperand(RegOp);
		TempRT->SetOperator(SMP_ASSIGN);
		TempRT->SetLeftOperand(StackOp);
		this->RTL.push_back(TempRT);
		TempRT = NULL;

		// ESP goes to [ESP-20]
		RegOp.reg = MD_STACK_POINTER_REG;
		StackOp.addr = -((ea_t)(5*STARS_ISA_Bytewidth));  // [ESP-20]
		TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);
		TempRT->SetRightOperand(RegOp);
		TempRT->SetOperator(SMP_ASSIGN);
		TempRT->SetLeftOperand(StackOp);
		this->RTL.push_back(TempRT);
		TempRT = NULL;

		// EBX goes to [ESP-16]
		RegOp.reg = R_bx;
		StackOp.addr = -((ea_t)(4*STARS_ISA_Bytewidth));  // [ESP-16]
		TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);
		TempRT->SetRightOperand(RegOp);
		TempRT->SetOperator(SMP_ASSIGN);
		TempRT->SetLeftOperand(StackOp);
		this->RTL.push_back(TempRT);
		TempRT = NULL;

		// EDX goes to [ESP-12]
		RegOp.reg = R_dx;
		StackOp.addr = -((ea_t)(3*STARS_ISA_Bytewidth));  // [ESP-12]
		TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);
		TempRT->SetRightOperand(RegOp);
		TempRT->SetOperator(SMP_ASSIGN);
		TempRT->SetLeftOperand(StackOp);
		this->RTL.push_back(TempRT);
		TempRT = NULL;

		// ECX goes to [ESP-8]
		RegOp.reg = R_cx;
		StackOp.addr = -((ea_t)(2*STARS_ISA_Bytewidth));  // [ESP-8]
		TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);
		TempRT->SetRightOperand(RegOp);
		TempRT->SetOperator(SMP_ASSIGN);
		TempRT->SetLeftOperand(StackOp);
		this->RTL.push_back(TempRT);
		TempRT = NULL;

		// EAX goes to [ESP-4]
		RegOp.reg = R_ax;
		StackOp.addr = -((ea_t)(STARS_ISA_Bytewidth));  // [ESP-4]
		TempRT = new SMPRegTransfer;
		TempRT->SetParentInst(this);
		TempRT->SetRightOperand(RegOp);
		TempRT->SetOperator(SMP_ASSIGN);
		TempRT->SetLeftOperand(StackOp);
		this->RTL.push_back(TempRT);
		TempRT = NULL;

		// Now create the stack pointer increment effect.
		this->SubFromStackPointer((uval_t) 8*STARS_ISA_Bytewidth);
		return true;
	} // end for "pop all" instructions

	// If we reach this point, we have a simple PUSH instruction.
	for (OpNum = 0; !SourceFound && (OpNum < UA_MAXOP); ++OpNum) {
		op_t TempOp = this->SMPcmd.Operands[OpNum];
		if (this->features & UseMacros[OpNum]) { // USE
			if (MDKnownOperandType(TempOp)) {
				SourceFound = true;
				OpSize = GetOpDataSize(TempOp);
				TempRT = new SMPRegTransfer;
				TempRT->SetParentInst(this);
				TempRT->SetRightOperand(TempOp);
				TempRT->SetOperator(SMP_ASSIGN);
				StackOp.dtyp = TempOp.dtyp;  // size of transfer
				StackOp.addr =  (-((ea_t) OpSize));
				TempRT->SetLeftOperand(StackOp);
				this->RTL.push_back(TempRT);
				TempRT = NULL;
				// Now create the stack pointer increment effect.
				this->SubFromStackPointer((uval_t) OpSize);
#if 0
				this->RTL.Dump();
#endif
			}
		}
	} // end for (OpNum = 0; ...)

#if SMP_DEBUG_BUILD_RTL
	if (!SourceFound) {
		SMP_msg("ERROR: Could not find push operand at %lx for %s\n", (unsigned long) this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr()));
	}
#endif
	return SourceFound;
} // end of SMPInstr::BuildPushRTL()

// Build RTL trees from the SMPcmd info.
bool SMPInstr::BuildRTL(void) {
	op_t FlagsOp = InitOp;
	FlagsOp.type = o_reg;
	FlagsOp.reg = X86_FLAGS_REG;
	FlagsOp.dtyp = this->GetOperandDtypField();
	SMPRegTransfer *NopRT = NULL;  // no-op register transfer

	// We don't want to explicitly represent the various no-ops except as NULL operations.
	//  E.g. mov esi,esi should not generate DEF and USE of esi, because esi does not change.
	if (this->IsNop()) {
		NopRT = new SMPRegTransfer;
		NopRT->SetParentInst(this);
		NopRT->SetOperator(SMP_NULL_OPERATOR);
		this->RTL.push_back(NopRT);
		NopRT = NULL;
		return true;
	}

	switch (this->SMPcmd.itype) {
		case NN_aaa:                 // ASCII Adjust after Addition
		case NN_aad:                 // ASCII Adjust AX before Division
		case NN_aam:                 // ASCII Adjust AX after Multiply
		case NN_aas:                 // ASCII Adjust AL after Subtraction
			return this->BuildUnaryRTL(SMP_UNARY_NUMERIC_OPERATION);

		case NN_adc:                 // Add with Carry
#if SMP_BUILD_SPECIAL_ADC_SBB_RTL
			return this->BuildBinaryPlusFlagsRTL(SMP_ADD_CARRY);
#else
			return this->BuildBinaryRTL(SMP_ADD_CARRY);
#endif

		case NN_add:                 // Add
			return this->BuildBinaryRTL(SMP_ADD);

		case NN_and:                 // Logical AND
			return this->BuildBinaryRTL(SMP_BITWISE_AND);

		case NN_arpl:                // Adjust RPL Field of Selector
			return this->BuildBinaryRTL(SMP_BINARY_NUMERIC_OPERATION);

		case NN_bound:               // Check Array Index Against Bounds
			return this->BuildGuardedSignalRTL(SMP_SIGNAL);

		case NN_bsf:                 // Bit Scan Forward
		case NN_bsr:                 // Bit Scan Reverse
			return this->BuildUnary2OpndRTL(SMP_UNARY_NUMERIC_OPERATION);

		case NN_bt:                  // Bit Test
			return this->BuildFlagsDestBinaryRTL(SMP_BINARY_NUMERIC_OPERATION);

		case NN_btc:                 // Bit Test and Complement
		case NN_btr:                 // Bit Test and Reset
		case NN_bts:                 // Bit Test and Set
			// Has effects on both the carry flag and the first operand
			this->RTL.ExtraKills.push_back(FlagsOp);
			return this->BuildBinaryRTL(SMP_BINARY_NUMERIC_OPERATION);

		case NN_call:                // Call Procedure
		case NN_callfi:              // Indirect Call Far Procedure
		case NN_callni:              // Indirect Call Near Procedure
			return this->BuildCallRTL();

		case NN_cbw:                 // AL -> AX (with sign)
		case NN_cwde:                // AX -> EAX (with sign)
		case NN_cdqe:                // EAX -> RAX (with sign)
			return this->BuildUnaryRTL(SMP_SIGN_EXTEND);

		case NN_clc:                 // Clear Carry Flag
		case NN_cld:                 // Clear Direction Flag
			return this->BuildUnaryRTL(SMP_UNARY_NUMERIC_OPERATION);

		case NN_cli:                 // Clear Interrupt Flag
		case NN_clts:                // Clear Task-Switched Flag in CR0
			// We don't track the interrupt flag or the special registers,
			//  so we can just consider these to be no-ops.
			// NOTE: Shouldn't we killthe EFLAGS register on NN_cli ??!!??!!
			NopRT = new SMPRegTransfer;
			NopRT->SetParentInst(this);
			NopRT->SetOperator(SMP_NULL_OPERATOR);
			this->RTL.push_back(NopRT);
			NopRT = NULL;
			return true;

		case NN_cmc:                 // Complement Carry Flag
			return this->BuildUnaryRTL(SMP_UNARY_NUMERIC_OPERATION);

		case NN_cmp:                 // Compare Two Operands
			return this->BuildFlagsDestBinaryRTL(SMP_S_COMPARE);

		case NN_cmps:                // Compare Strings
			// Why do we no longer use BuildCompareStringRTL()?  ****!!!!**** Test it!
			return this->BuildFlagsDestBinaryRTL(SMP_U_COMPARE);

		case NN_cwd:                 // AX -> DX:AX (with sign)
		case NN_cdq:                 // EAX -> EDX:EAX (with sign)
		case NN_cqo:                 // RAX -> RDX:RAX (with sign)
			return this->BuildUnary2OpndRTL(SMP_SIGN_EXTEND);

		case NN_daa:                 // Decimal Adjust AL after Addition
		case NN_das:                 // Decimal Adjust AL after Subtraction
			return this->BuildUnaryRTL(SMP_UNARY_NUMERIC_OPERATION);

		case NN_dec:                 // Decrement by 1
			return this->BuildUnaryRTL(SMP_DECREMENT);

		case NN_div:                 // Unsigned Divide
			return this->BuildMultiplyDivideRTL(SMP_U_DIVIDE);

		case NN_enterw:              // Make Stack Frame for Procedure Parameters
		case NN_enter:               // Make Stack Frame for Procedure Parameters
		case NN_enterd:              // Make Stack Frame for Procedure Parameters
		case NN_enterq:              // Make Stack Frame for Procedure Parameters
			return this->BuildEnterRTL();

		case NN_hlt:                 // Halt
			// Treat as a no-op
			NopRT = new SMPRegTransfer;
			NopRT->SetParentInst(this);
			NopRT->SetOperator(SMP_NULL_OPERATOR);
			this->RTL.push_back(NopRT);
			NopRT = NULL;
			return true;

		case NN_idiv:                // Signed Divide
			return this->BuildMultiplyDivideRTL(SMP_S_DIVIDE);

		case NN_imul:                // Signed Multiply
			return this->BuildMultiplyDivideRTL(SMP_S_MULTIPLY);

		case NN_in:                  // Input from Port
			return this->BuildUnary2OpndRTL(SMP_INPUT);

		case NN_inc:                 // Increment by 1
			return this->BuildUnaryRTL(SMP_INCREMENT);

		case NN_ins:                 // Input Byte(s) from Port to String
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);
			break;

		case NN_int:                 // Call to Interrupt Procedure
		case NN_into:                // Call to Interrupt Procedure if Overflow Flag = 1
		case NN_int3:                // Trap to Debugger
			return this->BuildCallRTL();

		case NN_iretw:               // Interrupt Return
		case NN_iret:                // Interrupt Return
		case NN_iretd:               // Interrupt Return (use32)
		case NN_iretq:               // Interrupt Return (use64)
			return this->BuildReturnRTL();

		case NN_ja:                  // Jump if Above (CF=0 & ZF=0)
		case NN_jae:                 // Jump if Above or Equal (CF=0)
		case NN_jb:                  // Jump if Below (CF=1)
		case NN_jbe:                 // Jump if Below or Equal (CF=1 | ZF=1)
		case NN_jc:                  // Jump if Carry (CF=1)
			return this->BuildJumpRTL(SMP_BINARY_NUMERIC_OPERATION);

		case NN_jcxz:                // Jump if CX is 0
		case NN_jecxz:               // Jump if ECX is 0
		case NN_jrcxz:               // Jump if RCX is 0
			return this->BuildJumpRTL(SMP_EQUAL); // special case in BuildJumpRTL()

		case NN_je:                  // Jump if Equal (ZF=1)
			return this->BuildJumpRTL(SMP_EQUAL);

		case NN_jg:                  // Jump if Greater (ZF=0 & SF=OF)
			return this->BuildJumpRTL(SMP_GREATER_THAN);

		case NN_jge:                 // Jump if Greater or Equal (SF=OF)
			return this->BuildJumpRTL(SMP_GREATER_EQUAL);

		case NN_jl:                  // Jump if Less (SF!=OF)
			return this->BuildJumpRTL(SMP_LESS_THAN);

		case NN_jle:                 // Jump if Less or Equal (ZF=1 | SF!=OF)
			return this->BuildJumpRTL(SMP_LESS_EQUAL);

		case NN_jna:                 // Jump if Not Above (CF=1 | ZF=1)
		case NN_jnae:                // Jump if Not Above or Equal (CF=1)
		case NN_jnb:                 // Jump if Not Below (CF=0)
		case NN_jnbe:                // Jump if Not Below or Equal (CF=0 & ZF=0) a.k.a. ja
		case NN_jnc:                 // Jump if Not Carry (CF=0)
			return this->BuildJumpRTL(SMP_BINARY_NUMERIC_OPERATION);

		case NN_jne:                 // Jump if Not Equal (ZF=0)
			return this->BuildJumpRTL(SMP_NOT_EQUAL);

		case NN_jng:                 // Jump if Not Greater (ZF=1 | SF!=OF) a.k.a. jle
			return this->BuildJumpRTL(SMP_LESS_EQUAL);

		case NN_jnge:                // Jump if Not Greater or Equal (SF != OF) **
			return this->BuildJumpRTL(SMP_LESS_THAN);

		case NN_jnl:                 // Jump if Not Less (SF=OF) a.k.a. jge
			return this->BuildJumpRTL(SMP_GREATER_EQUAL);

		case NN_jnle:                // Jump if Not Less or Equal (ZF=0 & SF=OF) a.k.a. jg
			return this->BuildJumpRTL(SMP_GREATER_THAN);

		case NN_jno:                 // Jump if Not Overflow (OF=0)
		case NN_jnp:                 // Jump if Not Parity (PF=0)
		case NN_jns:                 // Jump if Not Sign (SF=0)
			return this->BuildJumpRTL(SMP_BINARY_NUMERIC_OPERATION);

		case NN_jnz:                 // Jump if Not Zero (ZF=0)  a.k.a. jne
			return this->BuildJumpRTL(SMP_NOT_EQUAL);

		case NN_jo:                  // Jump if Overflow (OF=1)
		case NN_jp:                  // Jump if Parity (PF=1)
		case NN_jpe:                 // Jump if Parity Even (PF=1)
		case NN_jpo:                 // Jump if Parity Odd  (PF=0)
		case NN_js:                  // Jump if Sign (SF=1)
			return this->BuildJumpRTL(SMP_BINARY_NUMERIC_OPERATION);

		case NN_jz:                  // Jump if Zero (ZF=1)
			return this->BuildJumpRTL(SMP_EQUAL);

		case NN_jmp:                 // Jump
		case NN_jmpfi:               // Indirect Far Jump
		case NN_jmpni:               // Indirect Near Jump
		case NN_jmpshort:            // Jump Short (not used)
			return this->BuildJumpRTL(SMP_NULL_OPERATOR);

		case NN_lahf:                // Load Flags into AH Register
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);

		case NN_lar:                 // Load Access Right Byte
			return false;
			break;

		case NN_lea:                 // Load Effective Address
			return this->BuildLeaRTL();
			break;

		case NN_leavew:              // High Level Procedure Exit
		case NN_leave:               // High Level Procedure Exit
		case NN_leaved:              // High Level Procedure Exit
		case NN_leaveq:              // High Level Procedure Exit
			return this->BuildLeaveRTL();
			break;

		case NN_lgdt:                // Load Global Descriptor Table Register
		case NN_lidt:                // Load Interrupt Descriptor Table Register
			return false;
			break;

		case NN_lgs:                 // Load Full Pointer to GS:xx
		case NN_lss:                 // Load Full Pointer to SS:xx
		case NN_lds:                 // Load Full Pointer to DS:xx
		case NN_les:                 // Load Full Pointer to ES:xx
		case NN_lfs:                 // Load Full Pointer to FS:xx
			// These instructions differ from NN_lea only in setting
			//  a segment register in addition to a pointer. We are
			//  not yet tracking segment registers.
			return this->BuildLeaRTL();
			break;

		case NN_lldt:                // Load Local Descriptor Table Register
		case NN_lmsw:                // Load Machine Status Word
		case NN_lock:                // Assert LOCK# Signal Prefix  NOTE: This is now a no-op
			return false;
			break;

		case NN_lods:                // Load String
			return this->BuildLoadStringRTL();
			break;

		case NN_loopw:               // Loop while ECX != 0
		case NN_loop:                // Loop while CX != 0
		case NN_loopd:               // Loop while ECX != 0
		case NN_loopq:               // Loop while RCX != 0
		case NN_loopwe:              // Loop while CX != 0 and ZF=1
		case NN_loope:               // Loop while rCX != 0 and ZF=1
		case NN_loopde:              // Loop while ECX != 0 and ZF=1
		case NN_loopqe:              // Loop while RCX != 0 and ZF=1
		case NN_loopwne:             // Loop while CX != 0 and ZF=0
		case NN_loopne:              // Loop while rCX != 0 and ZF=0
		case NN_loopdne:             // Loop while ECX != 0 and ZF=0
		case NN_loopqne:             // Loop while RCX != 0 and ZF=0
			return this->BuildLoopRTL(SMP_NULL_OPERATOR);
			break;

		case NN_lsl:                 // Load Segment Limit
		case NN_ltr:                 // Load Task Register
			return false;
			break;

		case NN_mov:                 // Move Data
		case NN_movsp:               // Move to/from Special Registers
		case NN_movs:                // Move Byte(s) from String to String
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);

		case NN_movsx:               // Move with Sign-Extend
			return this->BuildUnary2OpndRTL(SMP_SIGN_EXTEND);

		case NN_movzx:               // Move with Zero-Extend
			return this->BuildUnary2OpndRTL(SMP_ZERO_EXTEND);

		case NN_mul:                 // Unsigned Multiplication of AL or AX
			return this->BuildMultiplyDivideRTL(SMP_U_MULTIPLY);

		case NN_neg:                 // Two's Complement Negation
			return this->BuildUnaryRTL(SMP_NEGATE);

		case NN_nop:                 // No Operation
			NopRT = new SMPRegTransfer;
			NopRT->SetParentInst(this);
			NopRT->SetOperator(SMP_NULL_OPERATOR);
			this->RTL.push_back(NopRT);
			NopRT = NULL;
			return true;

		case NN_not:                 // One's Complement Negation
			return this->BuildUnaryRTL(SMP_BITWISE_NOT);

		case NN_or:                  // Logical Inclusive OR
			return this->BuildBinaryRTL(SMP_BITWISE_OR);

		case NN_out:                 // Output to Port
			return this->BuildUnary2OpndRTL(SMP_OUTPUT);

		case NN_outs:                // Output Byte(s) to Port
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);
			break;

		case NN_pop:                 // Pop a word from the Stack
		case NN_popaw:               // Pop all General Registers
		case NN_popa:                // Pop all General Registers
		case NN_popad:               // Pop all General Registers (use32)
		case NN_popaq:               // Pop all General Registers (use64)
		case NN_popfw:               // Pop Stack into Flags Register
		case NN_popf:                // Pop Stack into Flags Register
		case NN_popfd:               // Pop Stack into Eflags Register
		case NN_popfq:               // Pop Stack into Rflags Register
			return this->BuildPopRTL();

		case NN_push:                // Push Operand onto the Stack
		case NN_pushaw:              // Push all General Registers
		case NN_pusha:               // Push all General Registers
		case NN_pushad:              // Push all General Registers (use32)
		case NN_pushaq:              // Push all General Registers (use64)
		case NN_pushfw:              // Push Flags Register onto the Stack
		case NN_pushf:               // Push Flags Register onto the Stack
		case NN_pushfd:              // Push Flags Register onto the Stack (use32)
		case NN_pushfq:              // Push Flags Register onto the Stack (use64)
			return this->BuildPushRTL();

		case NN_rcl:                 // Rotate Through Carry Left
			return this->BuildBinaryPlusFlagsRTL(SMP_ROTATE_LEFT_CARRY);

		case NN_rcr:                 // Rotate Through Carry Right
			return this->BuildBinaryPlusFlagsRTL(SMP_ROTATE_RIGHT_CARRY);

		case NN_rol:                 // Rotate Left
			return this->BuildBinaryRTL(SMP_ROTATE_LEFT);

		case NN_ror:                 // Rotate Right
			return this->BuildBinaryRTL(SMP_ROTATE_RIGHT);

		case NN_rep:                 // Repeat String Operation
		case NN_repe:                // Repeat String Operation while ZF=1
		case NN_repne:               // Repeat String Operation while ZF=0
			return false;
			break;

		case NN_retn:                // Return Near from Procedure
		case NN_retf:                // Return Far from Procedure
			return this->BuildReturnRTL();

		case NN_sahf:                // Store AH into Flags Register
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);

		case NN_sal:                 // Shift Arithmetic Left
			return this->BuildBinaryRTL(SMP_S_LEFT_SHIFT);

		case NN_sar:                 // Shift Arithmetic Right
			return this->BuildBinaryRTL(SMP_S_RIGHT_SHIFT);

		case NN_shl:                 // Shift Logical Left
			return this->BuildBinaryRTL(SMP_U_LEFT_SHIFT);

		case NN_shr:                 // Shift Logical Right
			return this->BuildBinaryRTL(SMP_U_RIGHT_SHIFT);

		case NN_sbb:                 // Integer Subtraction with Borrow
#if SMP_BUILD_SPECIAL_ADC_SBB_RTL
			return this->BuildBinaryPlusFlagsRTL(SMP_SUBTRACT_BORROW);
#else
			return this->BuildBinaryRTL(SMP_SUBTRACT_BORROW);
#endif

		case NN_scas:                // Scan String
			return this->BuildFlagsDestBinaryRTL(SMP_U_COMPARE);

		case NN_seta:                // Set Byte if Above (CF=0 & ZF=0)
		case NN_setae:               // Set Byte if Above or Equal (CF=0)
		case NN_setb:                // Set Byte if Below (CF=1)
		case NN_setbe:               // Set Byte if Below or Equal (CF=1 | ZF=1)
		case NN_setc:                // Set Byte if Carry (CF=1)
		case NN_sete:                // Set Byte if Equal (ZF=1)
		case NN_setg:                // Set Byte if Greater (ZF=0 & SF=OF)
		case NN_setge:               // Set Byte if Greater or Equal (SF=OF)
		case NN_setl:                // Set Byte if Less (SF!=OF)
		case NN_setle:               // Set Byte if Less or Equal (ZF=1 | SF!=OF)
		case NN_setna:               // Set Byte if Not Above (CF=1 | ZF=1)
		case NN_setnae:              // Set Byte if Not Above or Equal (CF=1)
		case NN_setnb:               // Set Byte if Not Below (CF=0)
		case NN_setnbe:              // Set Byte if Not Below or Equal (CF=0 & ZF=0)
		case NN_setnc:               // Set Byte if Not Carry (CF=0)
		case NN_setne:               // Set Byte if Not Equal (ZF=0)
		case NN_setng:               // Set Byte if Not Greater (ZF=1 | SF!=OF)
		case NN_setnge:              // Set Byte if Not Greater or Equal (ZF=1)
		case NN_setnl:               // Set Byte if Not Less (SF=OF)
		case NN_setnle:              // Set Byte if Not Less or Equal (ZF=0 & SF=OF)
		case NN_setno:               // Set Byte if Not Overflow (OF=0)
		case NN_setnp:               // Set Byte if Not Parity (PF=0)
		case NN_setns:               // Set Byte if Not Sign (SF=0)
		case NN_setnz:               // Set Byte if Not Zero (ZF=0)
		case NN_seto:                // Set Byte if Overflow (OF=1)
		case NN_setp:                // Set Byte if Parity (PF=1)
		case NN_setpe:               // Set Byte if Parity Even (PF=1)
		case NN_setpo:               // Set Byte if Parity Odd  (PF=0)
		case NN_sets:                // Set Byte if Sign (SF=1)
		case NN_setz:                // Set Byte if Zero (ZF=1)
			// Destination always get set to NUMERIC 0 or 1, depending on
			//  the condition and the relevant flags bits. Best way to model
			//  this in an RTL is to perform an unspecified unary NUMERIC
			//  operation on the flags register and assign the result to the
			//  destination operand, making it always NUMERIC.
			return this->BuildUnary2OpndRTL(SMP_UNARY_NUMERIC_OPERATION);

		case NN_sgdt:                // Store Global Descriptor Table Register
		case NN_sidt:                // Store Interrupt Descriptor Table Register
			return false;
			break;

		case NN_shld:                // Double Precision Shift Left
			return this->BuildDoubleShiftRTL(SMP_U_LEFT_SHIFT);

		case NN_shrd:                // Double Precision Shift Right
			return this->BuildDoubleShiftRTL(SMP_U_RIGHT_SHIFT);

		case NN_sldt:                // Store Local Descriptor Table Register
		case NN_smsw:                // Store Machine Status Word
			return false;
			break;

		case NN_stc:                 // Set Carry Flag
		case NN_std:                 // Set Direction Flag
			return this->BuildUnaryRTL(SMP_UNARY_NUMERIC_OPERATION);

		case NN_sti:                 // Set Interrupt Flag
			NopRT = new SMPRegTransfer;
			NopRT->SetParentInst(this);
			NopRT->SetOperator(SMP_NULL_OPERATOR);
			this->RTL.push_back(NopRT);
			NopRT = NULL;
			return true;

		case NN_stos:                // Store String
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);

		case NN_str:                 // Store Task Register
			return false;
			break;

		case NN_sub:                 // Integer Subtraction
			return this->BuildBinaryRTL(SMP_SUBTRACT);

		case NN_test:                // Logical Compare
			return this->BuildFlagsDestBinaryRTL(SMP_U_COMPARE);

		case NN_verr:                // Verify a Segment for Reading
		case NN_verw:                // Verify a Segment for Writing
		case NN_wait:                // Wait until BUSY# Pin is Inactive (HIGH)
			NopRT = new SMPRegTransfer;
			NopRT->SetParentInst(this);
			NopRT->SetOperator(SMP_NULL_OPERATOR);
			this->RTL.push_back(NopRT);
			NopRT = NULL;
			if (NN_wait != this->SMPcmd.itype)
				this->RTL.ExtraKills.push_back(FlagsOp);
			return true;

		case NN_xchg:                // Exchange Register/Memory with Register
			return this->BuildExchangeRTL();

		case NN_xlat:                // Table Lookup Translation
			return false;
			break;

		case NN_xor:                 // Logical Exclusive OR
			return this->BuildBinaryRTL(SMP_BITWISE_XOR);


		//
		//      486 instructions
		//

		case NN_cmpxchg:             // Compare and Exchange
			return this->BuildCompareExchangeRTL();

		case NN_bswap:               // Swap bits in EAX
			return this->BuildUnaryRTL(SMP_UNARY_NUMERIC_OPERATION);

		case NN_xadd:                // t<-dest; dest<-src+dest; src<-t
			return this->BuildExchangeAddRTL();

		case NN_invd:                // Invalidate Data Cache
		case NN_wbinvd:              // Invalidate Data Cache (write changes)
		case NN_invlpg:              // Invalidate TLB entry
			NopRT = new SMPRegTransfer;
			NopRT->SetParentInst(this);
			NopRT->SetOperator(SMP_NULL_OPERATOR);
			this->RTL.push_back(NopRT);
			NopRT = NULL;
			return true;

		//
		//      Pentium instructions
		//

		case NN_rdmsr:               // Read Machine Status Register
			return this->BuildOptType8RTL();

		case NN_wrmsr:               // Write Machine Status Register
			return false;
			break;

		case NN_cpuid:               // Get CPU ID
			return this->BuildOptType8RTL();

		case NN_cmpxchg8b:           // Compare and Exchange Eight Bytes
			return false;
			break;

		case NN_rdtsc:               // Read Time Stamp Counter
			return this->BuildOptType8RTL();

		case NN_rsm:                 // Resume from System Management Mode
			NopRT = new SMPRegTransfer;
			NopRT->SetParentInst(this);
			NopRT->SetOperator(SMP_NULL_OPERATOR);
			this->RTL.push_back(NopRT);
			NopRT = NULL;
			return true;


		//
		//      Pentium Pro instructions
		//

		case NN_cmova:               // Move if Above (CF=0 & ZF=0)
		case NN_cmovb:               // Move if Below (CF=1)
		case NN_cmovbe:              // Move if Below or Equal (CF=1 | ZF=1)
			return this->BuildMoveRTL(SMP_BINARY_NUMERIC_OPERATION);

		case NN_cmovg:               // Move if Greater (ZF=0 & SF=OF)
			return this->BuildMoveRTL(SMP_GREATER_THAN);

		case NN_cmovge:              // Move if Greater or Equal (SF=OF)
			return this->BuildMoveRTL(SMP_GREATER_EQUAL);

		case NN_cmovl:               // Move if Less (SF!=OF)
			return this->BuildMoveRTL(SMP_LESS_THAN);

		case NN_cmovle:              // Move if Less or Equal (ZF=1 | SF!=OF)
			return this->BuildMoveRTL(SMP_LESS_EQUAL);

		case NN_cmovnb:              // Move if Not Below (CF=0)
		case NN_cmovno:              // Move if Not Overflow (OF=0)
		case NN_cmovnp:              // Move if Not Parity (PF=0)
		case NN_cmovns:              // Move if Not Sign (SF=0)
			return this->BuildMoveRTL(SMP_BINARY_NUMERIC_OPERATION);

		case NN_cmovnz:              // Move if Not Zero (ZF=0)
			return this->BuildMoveRTL(SMP_NOT_EQUAL);

		case NN_cmovo:               // Move if Overflow (OF=1)
		case NN_cmovp:               // Move if Parity (PF=1)
		case NN_cmovs:               // Move if Sign (SF=1)
			return this->BuildMoveRTL(SMP_BINARY_NUMERIC_OPERATION);

		case NN_cmovz:               // Move if Zero (ZF=1)
			return this->BuildMoveRTL(SMP_EQUAL);

		case NN_fcmovb:              // Floating Move if Below
			return this->BuildMoveRTL(SMP_BINARY_NUMERIC_OPERATION);

		case NN_fcmove:              // Floating Move if Equal
			return this->BuildMoveRTL(SMP_EQUAL);

		case NN_fcmovbe:             // Floating Move if Below or Equal
			return this->BuildMoveRTL(SMP_BINARY_NUMERIC_OPERATION);

		case NN_fcmovu:              // Floating Move if Unordered
			return this->BuildMoveRTL(SMP_BINARY_NUMERIC_OPERATION);

		case NN_fcmovnb:             // Floating Move if Not Below
			return this->BuildMoveRTL(SMP_BINARY_NUMERIC_OPERATION);

		case NN_fcmovne:             // Floating Move if Not Equal
			return this->BuildMoveRTL(SMP_NOT_EQUAL);

		case NN_fcmovnbe:            // Floating Move if Not Below or Equal
			return this->BuildMoveRTL(SMP_BINARY_NUMERIC_OPERATION);

		case NN_fcmovnu:             // Floating Move if Not Unordered
			return this->BuildMoveRTL(SMP_BINARY_NUMERIC_OPERATION);


		case NN_fcomi:               // FP Compare: result in EFLAGS
		case NN_fucomi:              // FP Unordered Compare: result in EFLAGS
		case NN_fcomip:              // FP Compare: result in EFLAGS: pop stack
		case NN_fucomip:             // FP Unordered Compare: result in EFLAGS: pop stack
			return this->BuildFlagsDestBinaryRTL(SMP_S_COMPARE);
			break;

		case NN_rdpmc:               // Read Performance Monitor Counter
			return this->BuildOptType8RTL();

		//
		//      FPP instructions
		//

		case NN_fld:                 // Load Real
		case NN_fst:                 // Store Real
		case NN_fstp:                // Store Real and Pop
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);

		case NN_fxch:                // Exchange Registers
			// FP registers remain NUMERIC anyway, so this is a no-op to our type system.
			NopRT = new SMPRegTransfer;
			NopRT->SetParentInst(this);
			NopRT->SetOperator(SMP_NULL_OPERATOR);
			this->RTL.push_back(NopRT);
			NopRT = NULL;
			return true;

		case NN_fild:                // Load Integer
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);

		case NN_fist:                // Store Integer
		case NN_fistp:               // Store Integer and Pop
			return this->BuildBinaryRTL(SMP_CONVERT_FP_TO_INT);

		case NN_fbld:                // Load BCD
		case NN_fbstp:               // Store BCD and Pop
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);

		case NN_fadd:                // Add Real
		case NN_faddp:               // Add Real and Pop
		case NN_fiadd:               // Add Integer
		case NN_fsub:                // Subtract Real
		case NN_fsubp:               // Subtract Real and Pop
		case NN_fisub:               // Subtract Integer
		case NN_fsubr:               // Subtract Real Reversed
		case NN_fsubrp:              // Subtract Real Reversed and Pop
		case NN_fisubr:              // Subtract Integer Reversed
		case NN_fmul:                // Multiply Real
		case NN_fmulp:               // Multiply Real and Pop
		case NN_fimul:               // Multiply Integer
		case NN_fdiv:                // Divide Real
		case NN_fdivp:               // Divide Real and Pop
		case NN_fidiv:               // Divide Integer
		case NN_fdivr:               // Divide Real Reversed
		case NN_fdivrp:              // Divide Real Reversed and Pop
		case NN_fidivr:              // Divide Integer Reversed
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC, true);

		case NN_fsqrt:               // Square Root
		case NN_fscale:              // Scale:  st(0) <- st(0) * 2^st(1)
		case NN_fprem:               // Partial Remainder
		case NN_frndint:             // Round to Integer
		case NN_fxtract:             // Extract exponent and significand
		case NN_fabs:                // Absolute value
		case NN_fchs:                // Change Sign
			return this->BuildUnaryRTL(SMP_UNARY_FLOATING_ARITHMETIC);

		case NN_fcom:                // Compare Real
		case NN_fcomp:               // Compare Real and Pop
		case NN_fcompp:              // Compare Real and Pop Twice
		case NN_ficom:               // Compare Integer
		case NN_ficomp:              // Compare Integer and Pop
		case NN_ftst:                // Test
		case NN_fxam:                // Examine
			// Floating comparison instructions use FP reg stack locations
			//  as sources and set only the FP flags. All of these are numeric
			//  type and we don't track any of them, so all such instructions
			//  can be considered to be no-ops.
			NopRT = new SMPRegTransfer;
			NopRT->SetParentInst(this);
			NopRT->SetOperator(SMP_NULL_OPERATOR);
			this->RTL.push_back(NopRT);
			NopRT = NULL;
			return true;

		case NN_fptan:               // Partial tangent
		case NN_fpatan:              // Partial arctangent
		case NN_f2xm1:               // 2^x - 1
		case NN_fyl2x:               // Y * lg2(X)
		case NN_fyl2xp1:             // Y * lg2(X+1)
			// We can consider it a unary operation when both arguments come
			//  off the floating point register stack, unless we ever start
			//  modeling the different locations in the FP register stack.
			return this->BuildUnaryRTL(SMP_UNARY_FLOATING_ARITHMETIC);

		case NN_fldz:                // Load +0.0
		case NN_fld1:                // Load +1.0
		case NN_fldpi:               // Load PI=3.14...
		case NN_fldl2t:              // Load lg2(10)
		case NN_fldl2e:              // Load lg2(e)
		case NN_fldlg2:              // Load lg10(2)
		case NN_fldln2:              // Load ln(2)
		case NN_finit:               // Initialize Processor
		case NN_fninit:              // Initialize Processor (no wait)
		case NN_fsetpm:              // Set Protected Mode
		case NN_fldcw:               // Load Control Word
		case NN_fstcw:               // Store Control Word
		case NN_fnstcw:              // Store Control Word (no wait)
		case NN_fstsw:               // Store Status Word
		case NN_fnstsw:              // Store Status Word (no wait)
		case NN_fclex:               // Clear Exceptions
		case NN_fnclex:              // Clear Exceptions (no wait)
			// Floating point stack and control word and flags operations
			//  with no memory operands are no-ops to us.
			// NOTE: We might want to deal with the memory operands in some
			//  of these opcodes later.
			NopRT = new SMPRegTransfer;
			NopRT->SetParentInst(this);
			NopRT->SetOperator(SMP_NULL_OPERATOR);
			this->RTL.push_back(NopRT);
			NopRT = NULL;
			return true;

		case NN_fstenv:              // Store Environment
		case NN_fnstenv:             // Store Environment (no wait)
		case NN_fldenv:              // Load Environment
		case NN_fsave:               // Save State
		case NN_fnsave:              // Save State (no wait)
		case NN_frstor:              // Restore State
		case NN_fincstp:             // Increment Stack Pointer
		case NN_fdecstp:             // Decrement Stack Pointer
		case NN_ffree:               // Free Register
			// Floating point stack and control word and flags operations
			//  with no memory operands are no-ops to us.
			// NOTE: We might want to deal with the memory operands in some
			//  of these opcodes later.
			NopRT = new SMPRegTransfer;
			NopRT->SetParentInst(this);
			NopRT->SetOperator(SMP_NULL_OPERATOR);
			this->RTL.push_back(NopRT);
			NopRT = NULL;
			return true;

		case NN_fnop:                // No Operation
			NopRT = new SMPRegTransfer;
			NopRT->SetParentInst(this);
			NopRT->SetOperator(SMP_NULL_OPERATOR);
			this->RTL.push_back(NopRT);
			NopRT = NULL;
			return true;

		case NN_feni:                // (8087 only)
		case NN_fneni:               // (no wait) (8087 only)
		case NN_fdisi:               // (8087 only)
		case NN_fndisi:              // (no wait) (8087 only)
			return false;
			break;


		//
		//      80387 instructions
		//

		case NN_fprem1:              // Partial Remainder ( < half )
		case NN_fsincos:             // t<-cos(st); st<-sin(st); push t
		case NN_fsin:                // Sine
		case NN_fcos:                // Cosine
		case NN_fucom:               // Compare Unordered Real
		case NN_fucomp:              // Compare Unordered Real and Pop
		case NN_fucompp:             // Compare Unordered Real and Pop Twice
			// Floating point stack and control word and flags operations
			//  with no memory operands are no-ops to us.
			NopRT = new SMPRegTransfer;
			NopRT->SetParentInst(this);
			NopRT->SetOperator(SMP_NULL_OPERATOR);
			this->RTL.push_back(NopRT);
			NopRT = NULL;
			return true;


		//
		//      Instructions added 28.02.96
		//

		case NN_setalc:              // Set AL to Carry Flag
		case NN_svdc:                // Save Register and Descriptor
		case NN_rsdc:                // Restore Register and Descriptor
		case NN_svldt:               // Save LDTR and Descriptor
		case NN_rsldt:               // Restore LDTR and Descriptor
		case NN_svts:                // Save TR and Descriptor
		case NN_rsts:                // Restore TR and Descriptor
		case NN_icebp:               // ICE Break Point
		case NN_loadall:             // Load the entire CPU state from ES:EDI
			return false;
			break;

		//
		//      MMX instructions
		//

		case NN_emms:                // Empty MMX state
			NopRT = new SMPRegTransfer;
			NopRT->SetParentInst(this);
			NopRT->SetOperator(SMP_NULL_OPERATOR);
			this->RTL.push_back(NopRT);
			NopRT = NULL;
			return true;
			break;

		case NN_movd:                // Move 32 bits
		case NN_movq:                // Move 64 bits
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);
			break;

		case NN_packsswb:            // Pack with Signed Saturation (Word->Byte)
		case NN_packssdw:            // Pack with Signed Saturation (Dword->Word)
			return this->BuildBinaryRTL(SMP_PACK_S);
			break;

		case NN_packuswb:            // Pack with Unsigned Saturation (Word->Byte)
			return this->BuildBinaryRTL(SMP_PACK_U);
			break;

		case NN_paddb:               // Packed Add Byte
		case NN_paddw:               // Packed Add Word
		case NN_paddd:               // Packed Add Dword
		case NN_paddsb:              // Packed Add with Saturation (Byte)
		case NN_paddsw:              // Packed Add with Saturation (Word)
		case NN_paddusb:             // Packed Add Unsigned with Saturation (Byte)
		case NN_paddusw:             // Packed Add Unsigned with Saturation (Word)
			return this->BuildBinaryRTL(SMP_ADD);
			break;

		case NN_pand:                // Bitwise Logical And
			return this->BuildBinaryRTL(SMP_BITWISE_AND);
			break;

		case NN_pandn:               // Bitwise Logical And Not
			return this->BuildBinaryRTL(SMP_BITWISE_AND_NOT);
			break;

		case NN_pcmpeqb:             // Packed Compare for Equal (Byte)
		case NN_pcmpeqw:             // Packed Compare for Equal (Word)
		case NN_pcmpeqd:             // Packed Compare for Equal (Dword)
			return this->BuildBinaryRTL(SMP_COMPARE_EQ_AND_SET);
			break;

		case NN_pcmpgtb:             // Packed Compare for Greater Than (Byte)
		case NN_pcmpgtw:             // Packed Compare for Greater Than (Word)
		case NN_pcmpgtd:             // Packed Compare for Greater Than (Dword)
			return this->BuildBinaryRTL(SMP_COMPARE_GT_AND_SET);
			break;

		case NN_pmaddwd:             // Packed Multiply and Add
			return this->BuildBinaryRTL(SMP_MULTIPLY_AND_ADD);
			break;

		case NN_pmulhw:              // Packed Multiply High
		case NN_pmullw:              // Packed Multiply Low
			return this->BuildBinaryRTL(SMP_U_MULTIPLY);
			break;

		case NN_por:                 // Bitwise Logical Or
			return this->BuildBinaryRTL(SMP_BITWISE_OR);
			break;

		case NN_psllw:               // Packed Shift Left Logical (Word)
		case NN_pslld:               // Packed Shift Left Logical (Dword)
		case NN_psllq:               // Packed Shift Left Logical (Qword)
			return this->BuildBinaryRTL(SMP_U_LEFT_SHIFT);
			break;

		case NN_psraw:               // Packed Shift Right Arithmetic (Word)
		case NN_psrad:               // Packed Shift Right Arithmetic (Dword)
			return this->BuildBinaryRTL(SMP_S_RIGHT_SHIFT);
			break;

		case NN_psrlw:               // Packed Shift Right Logical (Word)
		case NN_psrld:               // Packed Shift Right Logical (Dword)
		case NN_psrlq:               // Packed Shift Right Logical (Qword)
			return this->BuildBinaryRTL(SMP_U_RIGHT_SHIFT);
			break;

		case NN_psubb:               // Packed Subtract Byte
		case NN_psubw:               // Packed Subtract Word
		case NN_psubd:               // Packed Subtract Dword
			return this->BuildBinaryRTL(SMP_SUBTRACT);
			break;

		case NN_psubsb:              // Packed Subtract with Saturation (Byte)
		case NN_psubsw:              // Packed Subtract with Saturation (Word)
			return this->BuildBinaryRTL(SMP_SUBTRACT);
			break;

		case NN_psubusb:             // Packed Subtract Unsigned with Saturation (Byte)
		case NN_psubusw:             // Packed Subtract Unsigned with Saturation (Word)
			return this->BuildBinaryRTL(SMP_SUBTRACT);
			break;

		case NN_punpckhbw:           // Unpack High Packed Data (Byte->Word)
		case NN_punpckhwd:           // Unpack High Packed Data (Word->Dword)
		case NN_punpckhdq:           // Unpack High Packed Data (Dword->Qword)
		case NN_punpcklbw:           // Unpack Low Packed Data (Byte->Word)
		case NN_punpcklwd:           // Unpack Low Packed Data (Word->Dword)
		case NN_punpckldq:           // Unpack Low Packed Data (Dword->Qword)
			return this->BuildBinaryRTL(SMP_INTERLEAVE);
			break;

		case NN_pxor:                // Bitwise Logical Exclusive Or
			return this->BuildBinaryRTL(SMP_BITWISE_XOR);
			break;

		//
		//      Undocumented Deschutes processor instructions
		//

		case NN_fxsave:              // Fast save FP context
		case NN_fxrstor:             // Fast restore FP context
			return false;
			break;

		//      Pentium II instructions

		case NN_sysenter:            // Fast Transition to System Call Entry Point
		case NN_sysexit:             // Fast Transition from System Call Entry Point
			return false;
			break;

		//      3DNow! instructions

		case NN_pavgusb:             // Packed 8-bit Unsigned Integer Averaging
			return this->BuildBinaryRTL(SMP_AVERAGE_U);
			break;

		case NN_pfadd:               // Packed Floating-Point Addition
			return this->BuildBinaryRTL(SMP_ADD);
			break;

		case NN_pfsub:               // Packed Floating-Point Subtraction
		case NN_pfsubr:              // Packed Floating-Point Reverse Subtraction   !!!!****!!!! Fix this reversal if we care about the details
			return this->BuildBinaryRTL(SMP_SUBTRACT);
			break;

		case NN_pfacc:               // Packed Floating-Point Accumulate
			return this->BuildBinaryRTL(SMP_ADD);
			break;

		case NN_pfcmpge:             // Packed Floating-Point Comparison: Greater or Equal
			return this->BuildBinaryRTL(SMP_COMPARE_GE_AND_SET);
			break;

		case NN_pfcmpgt:             // Packed Floating-Point Comparison: Greater
			return this->BuildBinaryRTL(SMP_COMPARE_GT_AND_SET);
			break;

		case NN_pfcmpeq:             // Packed Floating-Point Comparison: Equal
			return this->BuildBinaryRTL(SMP_COMPARE_EQ_AND_SET);
			break;

		case NN_pfmin:               // Packed Floating-Point Minimum
			return this->BuildBinaryRTL(SMP_MIN_S);
			break;

		case NN_pfmax:               // Packed Floating-Point Maximum
			return this->BuildBinaryRTL(SMP_MAX_S);
			break;

		case NN_pi2fd:               // Packed 32-bit Integer to Floating-Point
			return this->BuildBinaryRTL(SMP_CONVERT_INT_TO_FP);
			break;

		case NN_pf2id:               // Packed Floating-Point to 32-bit Integer
			return this->BuildBinaryRTL(SMP_CONVERT_FP_TO_INT);
			break;

		case NN_pfrcp:               // Packed Floating-Point Reciprocal Approximation
		case NN_pfrsqrt:             // Packed Floating-Point Reciprocal Square Root Approximation
			return this->BuildUnary2OpndRTL(SMP_UNARY_FLOATING_ARITHMETIC);
			break;

		case NN_pfmul:               // Packed Floating-Point Multiplication
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_pfrcpit1:            // Packed Floating-Point Reciprocal First Iteration Step
		case NN_pfrsqit1:            // Packed Floating-Point Reciprocal Square Root First Iteration Step
		case NN_pfrcpit2:            // Packed Floating-Point Reciprocal Second Iteration Step
			return this->BuildUnary2OpndRTL(SMP_UNARY_FLOATING_ARITHMETIC);
			break;

		case NN_pmulhrw:             // Packed Floating-Point 16-bit Integer Multiply with rounding
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_femms:               // Faster entry/exit of the MMX or floating-point state
			NopRT = new SMPRegTransfer;
			NopRT->SetParentInst(this);
			NopRT->SetOperator(SMP_NULL_OPERATOR);
			this->RTL.push_back(NopRT);
			NopRT = NULL;
			return true;
			break;

		case NN_prefetch:            // Prefetch at least a 32-byte line into L1 data cache
		case NN_prefetchw:           // Prefetch processor cache line into L1 data cache (mark as modified)
			// Prefetch opcodes are no-ops to us.
			NopRT = new SMPRegTransfer;
			NopRT->SetParentInst(this);
			NopRT->SetOperator(SMP_NULL_OPERATOR);
			this->RTL.push_back(NopRT);
			NopRT = NULL;
			return true;

		//      Pentium III instructions

		case NN_addps:               // Packed Single-FP Add
		case NN_addss:               // Scalar Single-FP Add
		case NN_andnps:              // Bitwise Logical And Not for Single-FP
		case NN_andps:               // Bitwise Logical And for Single-FP
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_cmpps:               // Packed Single-FP Compare
		case NN_cmpss:               // Scalar Single-FP Compare
		case NN_comiss:              // Scalar Ordered Single-FP Compare and Set EFLAGS
			return false;
			break;

		case NN_cvtpi2ps:            // Packed signed INT32 to Packed Single-FP conversion
			return this->BuildBinaryRTL(SMP_CONVERT_INT_TO_FP);
			break;

		case NN_cvtps2pi:            // Packed Single-FP to Packed INT32 conversion
			return this->BuildBinaryRTL(SMP_CONVERT_FP_TO_INT);
			break;

		case NN_cvtsi2ss:            // Scalar signed INT32 to Single-FP conversion
			return this->BuildBinaryRTL(SMP_CONVERT_INT_TO_FP);
			break;

		case NN_cvtss2si:            // Scalar Single-FP to signed INT32 conversion
		case NN_cvttps2pi:           // Packed Single-FP to Packed INT32 conversion (truncate)
		case NN_cvttss2si:           // Scalar Single-FP to signed INT32 conversion (truncate)
			return this->BuildBinaryRTL(SMP_CONVERT_FP_TO_INT);
			break;

		case NN_divps:               // Packed Single-FP Divide
		case NN_divss:               // Scalar Single-FP Divide
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_ldmxcsr:             // Load Streaming SIMD Extensions Technology Control/Status Register
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);
			break;

		case NN_maxps:               // Packed Single-FP Maximum
		case NN_maxss:               // Scalar Single-FP Maximum
			return this->BuildBinaryRTL(SMP_MAX_S);
			break;

		case NN_minps:               // Packed Single-FP Minimum
		case NN_minss:               // Scalar Single-FP Minimum
			return this->BuildBinaryRTL(SMP_MIN_S);
			break;

		case NN_movaps:              // Move Aligned Four Packed Single-FP
		case NN_movhlps:             // Move High to Low Packed Single-FP
		case NN_movhps:              // Move High Packed Single-FP
		case NN_movlhps:             // Move Low to High Packed Single-FP
		case NN_movlps:              // Move Low Packed Single-FP
		case NN_movmskps:            // Move Mask to Register
		case NN_movss:               // Move Scalar Single-FP
		case NN_movups:              // Move Unaligned Four Packed Single-FP
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);
			break;

		case NN_mulps:               // Packed Single-FP Multiply
		case NN_mulss:               // Scalar Single-FP Multiply
		case NN_orps:                // Bitwise Logical OR for Single-FP Data
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_rcpps:               // Packed Single-FP Reciprocal
		case NN_rcpss:               // Scalar Single-FP Reciprocal
		case NN_rsqrtps:             // Packed Single-FP Square Root Reciprocal
		case NN_rsqrtss:             // Scalar Single-FP Square Root Reciprocal
			return this->BuildUnary2OpndRTL(SMP_UNARY_FLOATING_ARITHMETIC);
			break;

		case NN_shufps:              // Shuffle Single-FP
			return this->BuildBinaryRTL(SMP_SHUFFLE);
			break;

		case NN_sqrtps:              // Packed Single-FP Square Root
		case NN_sqrtss:              // Scalar Single-FP Square Root
			return this->BuildUnary2OpndRTL(SMP_UNARY_FLOATING_ARITHMETIC);
			break;

		case NN_stmxcsr:             // Store Streaming SIMD Extensions Technology Control/Status Register
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);
			break;

		case NN_subps:               // Packed Single-FP Subtract
		case NN_subss:               // Scalar Single-FP Subtract
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_ucomiss:             // Scalar Unordered Single-FP Compare and Set EFLAGS
			return this->BuildFlagsDestBinaryRTL(SMP_S_COMPARE);
			break;

		case NN_unpckhps:            // Unpack High Packed Single-FP Data
		case NN_unpcklps:            // Unpack Low Packed Single-FP Data
			return this->BuildBinaryRTL(SMP_INTERLEAVE);
			break;

		case NN_xorps:               // Bitwise Logical XOR for Single-FP Data
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_pavgb:               // Packed Average (Byte)
		case NN_pavgw:               // Packed Average (Word)
			return this->BuildBinaryRTL(SMP_AVERAGE_U);
			break;

		case NN_pextrw:              // Extract Word
			return this->BuildBinaryPlusImmedRTL(SMP_EXTRACT_ZERO_EXTEND, SMP_CREATE_MASK);
			break;

		case NN_pinsrw:              // Insert Word
			return this->BuildBinaryPlusImmedRTL(SMP_BITWISE_AND, SMP_CREATE_MASK);
			break;

		case NN_pmaxsw:              // Packed Signed Integer Word Maximum
			return this->BuildBinaryRTL(SMP_MAX_S);
			break;

		case NN_pmaxub:              // Packed Unsigned Integer Byte Maximum
			return this->BuildBinaryRTL(SMP_MAX_U);
			break;

		case NN_pminsw:              // Packed Signed Integer Word Minimum
			return this->BuildBinaryRTL(SMP_MIN_S);
			break;

		case NN_pminub:              // Packed Unsigned Integer Byte Minimum
			return this->BuildBinaryRTL(SMP_MIN_U);
			break;

		case NN_pmovmskb:            // Move Byte Mask to Integer
			return this->BuildBinaryRTL(SMP_SHUFFLE);
			break;

		case NN_pmulhuw:             // Packed Multiply High Unsigned
			return this->BuildBinaryRTL(SMP_U_MULTIPLY);
			break;

		case NN_psadbw:              // Packed Sum of Absolute Differences
			return this->BuildBinaryRTL(SMP_SUM_OF_DIFFS);
			break;

		case NN_pshufw:              // Packed Shuffle Word
			return this->BuildBinaryRTL(SMP_SHUFFLE);
			break;

		case NN_maskmovq:            // Byte Mask write
			return false;
			break;

		case NN_movntps:             // Move Aligned Four Packed Single-FP Non Temporal
		case NN_movntq:              // Move 64 Bits Non Temporal
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);
			break;

		case NN_prefetcht0:          // Prefetch to all cache levels
		case NN_prefetcht1:          // Prefetch to all cache levels
		case NN_prefetcht2:          // Prefetch to L2 cache
		case NN_prefetchnta:         // Prefetch to L1 cache
		case NN_sfence:              // Store Fence
			// Cache prefetch and store fence opcodes are no-ops to us.
			NopRT = new SMPRegTransfer;
			NopRT->SetParentInst(this);
			NopRT->SetOperator(SMP_NULL_OPERATOR);
			this->RTL.push_back(NopRT);
			NopRT = NULL;
			return true;

		// Pentium III Pseudo instructions

		case NN_cmpeqps:             // Packed Single-FP Compare EQ
			return this->BuildBinaryRTL(SMP_COMPARE_EQ_AND_SET);
			break;

		case NN_cmpltps:             // Packed Single-FP Compare LT
			return this->BuildBinaryRTL(SMP_COMPARE_LT_AND_SET);
			break;

		case NN_cmpleps:             // Packed Single-FP Compare LE
			return this->BuildBinaryRTL(SMP_COMPARE_LE_AND_SET);
			break;

		case NN_cmpunordps:          // Packed Single-FP Compare UNORD
			return false;
			break;

		case NN_cmpneqps:            // Packed Single-FP Compare NOT EQ
			return this->BuildBinaryRTL(SMP_COMPARE_NE_AND_SET);
			break;

		case NN_cmpnltps:            // Packed Single-FP Compare NOT LT
			return this->BuildBinaryRTL(SMP_COMPARE_LT_AND_SET);
			break;

		case NN_cmpnleps:            // Packed Single-FP Compare NOT LE
			return this->BuildBinaryRTL(SMP_COMPARE_GT_AND_SET);
			break;

		case NN_cmpordps:            // Packed Single-FP Compare ORDERED
			return false;
			break;

		case NN_cmpeqss:             // Scalar Single-FP Compare EQ
			return this->BuildBinaryRTL(SMP_COMPARE_EQ_AND_SET);
			break;

		case NN_cmpltss:             // Scalar Single-FP Compare LT
			return this->BuildBinaryRTL(SMP_COMPARE_LT_AND_SET);
			break;

		case NN_cmpless:             // Scalar Single-FP Compare LE
			return this->BuildBinaryRTL(SMP_COMPARE_LE_AND_SET);
			break;

		case NN_cmpunordss:          // Scalar Single-FP Compare UNORD
			return false;
			break;

		case NN_cmpneqss:            // Scalar Single-FP Compare NOT EQ
			return this->BuildBinaryRTL(SMP_COMPARE_NE_AND_SET);
			break;

		case NN_cmpnltss:            // Scalar Single-FP Compare NOT LT
			return this->BuildBinaryRTL(SMP_COMPARE_LT_AND_SET);
			break;

		case NN_cmpnless:            // Scalar Single-FP Compare NOT LE
			return this->BuildBinaryRTL(SMP_COMPARE_LE_AND_SET);
			break;

		case NN_cmpordss:            // Scalar Single-FP Compare ORDERED
			return false;
			break;

		// AMD K7 instructions

		case NN_pf2iw:               // Packed Floating-Point to Integer with Sign Extend
			return this->BuildBinaryRTL(SMP_CONVERT_FP_TO_INT);
			break;

		case NN_pfnacc:              // Packed Floating-Point Negative Accumulate
		case NN_pfpnacc:             // Packed Floating-Point Mixed Positive-Negative Accumulate
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_pi2fw:               // Packed 16-bit Integer to Floating-Point
			return this->BuildBinaryRTL(SMP_CONVERT_INT_TO_FP);
			break;

		case NN_pswapd:              // Packed Swap Double Word
			return this->BuildExchangeRTL();
			break;

		// Undocumented FP instructions (thanks to norbert.juffa@adm.com)

		case NN_fstp1:               // Alias of Store Real and Pop
		case NN_fcom2:               // Alias of Compare Real
		case NN_fcomp3:              // Alias of Compare Real and Pop
		case NN_fxch4:               // Alias of Exchange Registers
		case NN_fcomp5:              // Alias of Compare Real and Pop
			return false;
			break;

		case NN_ffreep:              // Free Register and Pop; used in mplayer binary
			// Floating point stack and control word and flags operations
			//  with no memory operands are no-ops to us.
			NopRT = new SMPRegTransfer;
			NopRT->SetParentInst(this);
			NopRT->SetOperator(SMP_NULL_OPERATOR);
			this->RTL.push_back(NopRT);
			NopRT = NULL;
			return true;


		case NN_fxch7:               // Alias of Exchange Registers
		case NN_fstp8:               // Alias of Store Real and Pop
		case NN_fstp9:               // Alias of Store Real and Pop
			return false;
			break;

		// Pentium 4 instructions

		case NN_addpd:               // Add Packed Double-Precision Floating-Point Values
		case NN_addsd:               // Add Scalar Double-Precision Floating-Point Values
		case NN_andnpd:              // Bitwise Logical AND NOT of Packed Double-Precision Floating-Point Values
		case NN_andpd:               // Bitwise Logical AND of Packed Double-Precision Floating-Point Values
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_clflush:             // Flush Cache Line
		case NN_cmppd:               // Compare Packed Double-Precision Floating-Point Values
		case NN_cmpsd:               // Compare Scalar Double-Precision Floating-Point Values
		case NN_comisd:              // Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS
			return false;
			break;

		case NN_cvtdq2pd:            // Convert Packed Doubleword Integers to Packed Single-Precision Floating-Point Values
		case NN_cvtdq2ps:            // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values
			return this->BuildBinaryRTL(SMP_CONVERT_INT_TO_FP);
			break;

		case NN_cvtpd2dq:            // Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers
		case NN_cvtpd2pi:            // Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers
		case NN_cvtpd2ps:            // Convert Packed Double-Precision Floating-Point Values to Packed Single-Precision Floating-Point Values
			return this->BuildBinaryRTL(SMP_CONVERT_FP_TO_INT);
			break;


		case NN_cvtpi2pd:            // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values
			return this->BuildBinaryRTL(SMP_CONVERT_INT_TO_FP);
			break;

		case NN_cvtps2dq:            // Convert Packed Single-Precision Floating-Point Values to Packed Doubleword Integers
		case NN_cvtps2pd:            // Convert Packed Single-Precision Floating-Point Values to Packed Double-Precision Floating-Point Values
		case NN_cvtsd2si:            // Convert Scalar Double-Precision Floating-Point Value to Doubleword Integer
		case NN_cvtsd2ss:            // Convert Scalar Double-Precision Floating-Point Value to Scalar Single-Precision Floating-Point Value
			return this->BuildBinaryRTL(SMP_CONVERT_FP_TO_INT);
			break;

		case NN_cvtsi2sd:            // Convert Doubleword Integer to Scalar Double-Precision Floating-Point Value
			return this->BuildBinaryRTL(SMP_CONVERT_INT_TO_FP);
			break;

		case NN_cvtss2sd:            // Convert Scalar Single-Precision Floating-Point Value to Scalar Double-Precision Floating-Point Value
		case NN_cvttpd2dq:           // Convert With Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers
		case NN_cvttpd2pi:           // Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers
		case NN_cvttps2dq:           // Convert With Truncation Packed Single-Precision Floating-Point Values to Packed Doubleword Integers
		case NN_cvttsd2si:           // Convert with Truncation Scalar Double-Precision Floating-Point Value to Doubleword Integer
			return this->BuildBinaryRTL(SMP_CONVERT_FP_TO_INT);
			break;

		case NN_divpd:               // Divide Packed Double-Precision Floating-Point Values
		case NN_divsd:               // Divide Scalar Double-Precision Floating-Point Values
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_lfence:              // Load Fence
			NopRT = new SMPRegTransfer;
			NopRT->SetParentInst(this);
			NopRT->SetOperator(SMP_NULL_OPERATOR);
			this->RTL.push_back(NopRT);
			NopRT = NULL;
			return true;

		case NN_maskmovdqu:          // Store Selected Bytes of Double Quadword
			return false;
			break;

		case NN_maxpd:               // Return Maximum Packed Double-Precision Floating-Point Values
		case NN_maxsd:               // Return Maximum Scalar Double-Precision Floating-Point Value
			return this->BuildBinaryRTL(SMP_MAX_S);
			break;

		case NN_mfence:              // Memory Fence
			NopRT = new SMPRegTransfer;
			NopRT->SetParentInst(this);
			NopRT->SetOperator(SMP_NULL_OPERATOR);
			this->RTL.push_back(NopRT);
			NopRT = NULL;
			return true;

		case NN_minpd:               // Return Minimum Packed Double-Precision Floating-Point Values
		case NN_minsd:               // Return Minimum Scalar Double-Precision Floating-Point Value
			return this->BuildBinaryRTL(SMP_MIN_S);
			break;

		case NN_movapd:              // Move Aligned Packed Double-Precision Floating-Point Values
		case NN_movdq2q:             // Move Quadword from XMM to MMX Register
		case NN_movdqa:              // Move Aligned Double Quadword
		case NN_movdqu:              // Move Unaligned Double Quadword
		case NN_movhpd:              // Move High Packed Double-Precision Floating-Point Values
		case NN_movlpd:              // Move Low Packed Double-Precision Floating-Point Values
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);
			break;

		case NN_movmskpd:            // Extract Packed Double-Precision Floating-Point Sign Mask
			return false;
			break;

		case NN_movntdq:             // Store Double Quadword Using Non-Temporal Hint
		case NN_movnti:              // Store Doubleword Using Non-Temporal Hint
		case NN_movntpd:             // Store Packed Double-Precision Floating-Point Values Using Non-Temporal Hint
		case NN_movq2dq:             // Move Quadword from MMX to XMM Register
		case NN_movsd:               // Move Scalar Double-Precision Floating-Point Values
		case NN_movupd:              // Move Unaligned Packed Double-Precision Floating-Point Values
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);
			break;

		case NN_mulpd:               // Multiply Packed Double-Precision Floating-Point Values
		case NN_mulsd:               // Multiply Scalar Double-Precision Floating-Point Values
		case NN_orpd:                // Bitwise Logical OR of Double-Precision Floating-Point Values
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_paddq:               // Add Packed Quadword Integers
			return this->BuildBinaryRTL(SMP_ADD);
			break;

		case NN_pause:               // Spin Loop Hint
			NopRT = new SMPRegTransfer;
			NopRT->SetParentInst(this);
			NopRT->SetOperator(SMP_NULL_OPERATOR);
			this->RTL.push_back(NopRT);
			NopRT = NULL;
			return true;

		case NN_pmuludq:             // Multiply Packed Unsigned Doubleword Integers
			return this->BuildBinaryRTL(SMP_U_MULTIPLY);
			break;

		case NN_pshufd:              // Shuffle Packed Doublewords
		case NN_pshufhw:             // Shuffle Packed High Words
		case NN_pshuflw:             // Shuffle Packed Low Words
			return this->BuildBinaryRTL(SMP_SHUFFLE);
			break;

		case NN_pslldq:              // Shift Double Quadword Left Logical
			return this->BuildBinaryRTL(SMP_U_LEFT_SHIFT);
			break;

		case NN_psrldq:              // Shift Double Quadword Right Logical
			return this->BuildBinaryRTL(SMP_U_RIGHT_SHIFT);
			break;

		case NN_psubq:               // Subtract Packed Quadword Integers
			return this->BuildBinaryRTL(SMP_SUBTRACT);
			break;

		case NN_punpckhqdq:          // Unpack High Data
		case NN_punpcklqdq:          // Unpack Low Data
			return this->BuildBinaryRTL(SMP_INTERLEAVE);
			break;

		case NN_shufpd:              // Shuffle Packed Double-Precision Floating-Point Values
			return this->BuildBinaryRTL(SMP_SHUFFLE);
			break;

		case NN_sqrtpd:              // Compute Square Roots of Packed Double-Precision Floating-Point Values
		case NN_sqrtsd:              // Compute Square Rootof Scalar Double-Precision Floating-Point Value
			return this->BuildUnary2OpndRTL(SMP_UNARY_FLOATING_ARITHMETIC);
			break;

		case NN_subpd:               // Subtract Packed Double-Precision Floating-Point Values
		case NN_subsd:               // Subtract Scalar Double-Precision Floating-Point Values
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_ucomisd:             // Unordered Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS
			return this->BuildFlagsDestBinaryRTL(SMP_S_COMPARE);
			break;

		case NN_unpckhpd:            // Unpack and Interleave High Packed Double-Precision Floating-Point Values
		case NN_unpcklpd:            // Unpack and Interleave Low Packed Double-Precision Floating-Point Values
			return this->BuildBinaryRTL(SMP_INTERLEAVE);
			break;

		case NN_xorpd:               // Bitwise Logical OR of Double-Precision Floating-Point Values
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		// AMD syscall/sysret instructions

		case NN_syscall:             // Low latency system call
		case NN_sysret:              // Return from system call

		// AMD64 instructions

		case NN_swapgs:              // Exchange GS base with KernelGSBase MSR
			return false;
			break;

		// New Pentium instructions (SSE3)

		case NN_movddup:             // Move One Double-FP and Duplicate
		case NN_movshdup:            // Move Packed Single-FP High and Duplicate
		case NN_movsldup:            // Move Packed Single-FP Low and Duplicate
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);
			break;

		// Missing AMD64 instructions : NOTE: Also found in Intel manual -- clc

		case NN_movsxd:              // Move with Sign-Extend Doubleword
			return this->BuildUnary2OpndRTL(SMP_SIGN_EXTEND);

		case NN_cmpxchg16b:          // Compare and Exchange 16 Bytes
			return false;
			break;

		// SSE3 instructions

		case NN_addsubpd:            // Add /Sub packed DP FP numbers
		case NN_addsubps:            // Add /Sub packed SP FP numbers
		case NN_haddpd:              // Add horizontally packed DP FP numbers
		case NN_haddps:              // Add horizontally packed SP FP numbers
		case NN_hsubpd:              // Sub horizontally packed DP FP numbers
		case NN_hsubps:              // Sub horizontally packed SP FP numbers
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_monitor:             // Set up a linear address range to be monitored by hardware
		case NN_mwait:               // Wait until write-back store performed within the range specified by the MONITOR instruction
			return false;
			break;

		case NN_fisttp:              // Store ST in intXX (chop) and pop
			return this->BuildBinaryRTL(SMP_CONVERT_FP_TO_INT);
			break;

		case NN_lddqu:               // Load unaligned integer 128-bit
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);
			break;

		// SSSE3 instructions

		case NN_psignb:              // Packed SIGN Byte
		case NN_psignw:              // Packed SIGN Word
		case NN_psignd:              // Packed SIGN Doubleword
		case NN_pshufb:              // Packed Shuffle Bytes
			return this->BuildBinaryRTL(SMP_SHUFFLE);
			break;

		case NN_pmulhrsw:            // Packed Multiply High with Round and Scale
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_pmaddubsw:           // Multiply and Add Packed Signed and Unsigned Bytes
			return this->BuildBinaryRTL(SMP_MULTIPLY_AND_ADD);
			break;

		case NN_phsubsw:             // Packed Horizontal Subtract and Saturate
			return this->BuildBinaryRTL(SMP_SUBTRACT);
			break;

		case NN_phaddsw:             // Packed Horizontal Add and Saturate
			return this->BuildBinaryRTL(SMP_ADD);
			break;

		case NN_phaddw:              // Packed Horizontal Add Word
		case NN_phaddd:              // Packed Horizontal Add Doubleword
			return this->BuildBinaryRTL(SMP_ADD);
			break;

		case NN_phsubw:              // Packed Horizontal Subtract Word
		case NN_phsubd:              // Packed Horizontal Subtract Doubleword
			return this->BuildBinaryRTL(SMP_SUBTRACT);
			break;

		case NN_palignr:             // Packed Align Right
			return this->BuildPackShiftRTL(SMP_CONCATENATE, SMP_REVERSE_SHIFT_U);
			break;

		case NN_pabsb:               // Packed Absolute Value Byte
		case NN_pabsw:               // Packed Absolute Value Word
		case NN_pabsd:               // Packed Absolute Value Doubleword
			return this->BuildUnary2OpndRTL(SMP_ABSOLUTE_VALUE);
			break;

		// VMX instructions

		case NN_vmcall:              // Call to VM Monitor
		case NN_vmclear:             // Clear Virtual Machine Control Structure
		case NN_vmlaunch:            // Launch Virtual Machine
		case NN_vmresume:            // Resume Virtual Machine
		case NN_vmptrld:             // Load Pointer to Virtual Machine Control Structure
		case NN_vmptrst:             // Store Pointer to Virtual Machine Control Structure
		case NN_vmread:              // Read Field from Virtual Machine Control Structure
		case NN_vmwrite:             // Write Field from Virtual Machine Control Structure
		case NN_vmxoff:              // Leave VMX Operation
		case NN_vmxon:               // Enter VMX Operation
			return false;
			break;

#if 599 < IDA_SDK_VERSION

		case NN_ud2:                 // Undefined Instruction
			return false;
			break;

		// Added with x86-64

		case NN_rdtscp:             // Read Time-Stamp Counter and Processor ID
			return false;
			break;

		// Geode LX 3DNow! extensions

		case NN_pfrcpv:              // Reciprocal Approximation for a Pair of 32-bit Floats
		case NN_pfrsqrtv:            // Reciprocal Square Root Approximation for a Pair of 32-bit Floats
			return false;
			break;

		// SSE2 pseudoinstructions

		case NN_cmpeqpd:             // Packed Double-FP Compare EQ
			return this->BuildBinaryRTL(SMP_COMPARE_EQ_AND_SET);
			break;

		case NN_cmpltpd:             // Packed Double-FP Compare LT
			return this->BuildBinaryRTL(SMP_COMPARE_LT_AND_SET);
			break;

		case NN_cmplepd:             // Packed Double-FP Compare LE
			return this->BuildBinaryRTL(SMP_COMPARE_LE_AND_SET);
			break;

		case NN_cmpunordpd:          // Packed Double-FP Compare UNORD
			return this->BuildBinaryRTL(SMP_COMPARE_EQ_AND_SET);
			break;

		case NN_cmpneqpd:            // Packed Double-FP Compare NOT EQ
			return this->BuildBinaryRTL(SMP_COMPARE_NE_AND_SET);
			break;

		case NN_cmpnltpd:            // Packed Double-FP Compare NOT LT
			return this->BuildBinaryRTL(SMP_COMPARE_GE_AND_SET);
			break;

		case NN_cmpnlepd:            // Packed Double-FP Compare NOT LE
			return this->BuildBinaryRTL(SMP_COMPARE_GT_AND_SET);
			break;

		case NN_cmpordpd:            // Packed Double-FP Compare ORDERED
			return this->BuildBinaryRTL(SMP_COMPARE_EQ_AND_SET);
			break;

		case NN_cmpeqsd:             // Scalar Double-FP Compare EQ
			return this->BuildBinaryRTL(SMP_COMPARE_EQ_AND_SET);
			break;

		case NN_cmpltsd:             // Scalar Double-FP Compare LT
			return this->BuildBinaryRTL(SMP_COMPARE_LT_AND_SET);
			break;

		case NN_cmplesd:             // Scalar Double-FP Compare LE
			return this->BuildBinaryRTL(SMP_COMPARE_LE_AND_SET);
			break;

		case NN_cmpunordsd:          // Scalar Double-FP Compare UNORD
			return this->BuildBinaryRTL(SMP_COMPARE_EQ_AND_SET);
			break;

		case NN_cmpneqsd:            // Scalar Double-FP Compare NOT EQ
			return this->BuildBinaryRTL(SMP_COMPARE_NE_AND_SET);
			break;

		case NN_cmpnltsd:            // Scalar Double-FP Compare NOT LT
			return this->BuildBinaryRTL(SMP_COMPARE_GE_AND_SET);
			break;

		case NN_cmpnlesd:            // Scalar Double-FP Compare NOT LE
			return this->BuildBinaryRTL(SMP_COMPARE_GT_AND_SET);
			break;

		case NN_cmpordsd:            // Scalar Double-FP Compare ORDERED
			return this->BuildBinaryRTL(SMP_COMPARE_EQ_AND_SET);
			break;

		// SSSE4.1 instructions

		case NN_blendpd:              // Blend Packed Double Precision Floating-Point Values
		case NN_blendps:              // Blend Packed Single Precision Floating-Point Values
		case NN_blendvpd:             // Variable Blend Packed Double Precision Floating-Point Values
		case NN_blendvps:             // Variable Blend Packed Single Precision Floating-Point Values
			return this->BuildBinaryRTL(SMP_SHUFFLE);
			break;

		case NN_dppd:                 // Dot Product of Packed Double Precision Floating-Point Values
		case NN_dpps:                 // Dot Product of Packed Single Precision Floating-Point Values
			return false;
			break;

		case NN_extractps:            // Extract Packed Single Precision Floating-Point Value
		case NN_insertps:             // Insert Packed Single Precision Floating-Point Value
		case NN_movntdqa:             // Load Double Quadword Non-Temporal Aligned Hint
		case NN_mpsadbw:              // Compute Multiple Packed Sums of Absolute Difference
		case NN_packusdw:             // Pack with Unsigned Saturation
			return false;
			break;

		case NN_pblendvb:             // Variable Blend Packed Bytes
		case NN_pblendw:              // Blend Packed Words
			return this->BuildBinaryRTL(SMP_SHUFFLE);
			break;

		case NN_pcmpeqq:              // Compare Packed Qword Data for Equal
			return false;
			break;

		case NN_pextrb:               // Extract Byte
		case NN_pextrd:               // Extract Dword
		case NN_pextrq:               // Extract Qword
			return this->BuildBinaryPlusImmedRTL(SMP_EXTRACT_ZERO_EXTEND, SMP_CREATE_MASK);

		case NN_phminposuw:           // Packed Horizontal Word Minimum
			return false;
			break;

		case NN_pinsrb:               // Insert Byte 
		case NN_pinsrd:               // Insert Dword
		case NN_pinsrq:               // Insert Qword
			return this->BuildBinaryPlusImmedRTL(SMP_BITWISE_AND, SMP_CREATE_MASK);
			break;

		case NN_pmaxsb:               // Maximum of Packed Signed Byte Integers
		case NN_pmaxsd:               // Maximum of Packed Signed Dword Integers
			return this->BuildBinaryRTL(SMP_MAX_S);
			break;

		case NN_pmaxud:               // Maximum of Packed Unsigned Dword Integers
		case NN_pmaxuw:               // Maximum of Packed Word Integers
			return this->BuildBinaryRTL(SMP_MAX_U);
			break;

		case NN_pminsb:               // Minimum of Packed Signed Byte Integers
		case NN_pminsd:               // Minimum of Packed Signed Dword Integers
			return this->BuildBinaryRTL(SMP_MIN_S);
			break;

		case NN_pminud:               // Minimum of Packed Unsigned Dword Integers
		case NN_pminuw:               // Minimum of Packed Word Integers
			return this->BuildBinaryRTL(SMP_MIN_U);
			break;

		case NN_pmovsxbw:             // Packed Move with Sign Extend
		case NN_pmovsxbd:             // Packed Move with Sign Extend
		case NN_pmovsxbq:             // Packed Move with Sign Extend
		case NN_pmovsxwd:             // Packed Move with Sign Extend
		case NN_pmovsxwq:             // Packed Move with Sign Extend
		case NN_pmovsxdq:             // Packed Move with Sign Extend
			return this->BuildUnary2OpndRTL(SMP_SIGN_EXTEND);
			break;

		case NN_pmovzxbw:             // Packed Move with Zero Extend
		case NN_pmovzxbd:             // Packed Move with Zero Extend
		case NN_pmovzxbq:             // Packed Move with Zero Extend
		case NN_pmovzxwd:             // Packed Move with Zero Extend
		case NN_pmovzxwq:             // Packed Move with Zero Extend
		case NN_pmovzxdq:             // Packed Move with Zero Extend
			return this->BuildUnary2OpndRTL(SMP_ZERO_EXTEND);
			break;

		case NN_pmuldq:               // Multiply Packed Signed Dword Integers
		case NN_pmulld:               // Multiply Packed Signed Dword Integers and Store Low Result
			return false;
			break;

		case NN_ptest:                // Logical Compare
			return this->BuildFlagsDestBinaryRTL(SMP_U_COMPARE);

		case NN_roundpd:              // Round Packed Double Precision Floating-Point Values
		case NN_roundps:              // Round Packed Single Precision Floating-Point Values
		case NN_roundsd:              // Round Scalar Double Precision Floating-Point Values
		case NN_roundss:              // Round Scalar Single Precision Floating-Point Values
			return false;
			break;

		// SSSE4.2 instructions
		case NN_crc32:                // Accumulate CRC32 Value
			return false;
			break;

		case NN_pcmpestri:            // Packed Compare Explicit Length Strings, Return Index
		case NN_pcmpestrm:            // Packed Compare Explicit Length Strings, Return Mask
		case NN_pcmpistri:            // Packed Compare Implicit Length Strings, Return Index
		case NN_pcmpistrm:            // Packed Compare Implicit Length Strings, Return Mask
			return BuildBinaryIgnoreImmedRTL(SMP_GENERAL_COMPARE);
			break;

		case NN_pcmpgtq:              // Compare Packed Data for Greater Than
		case NN_popcnt:               // Return the Count of Number of Bits Set to 1
			return false;
			break;

		// AMD SSE4a instructions

		case NN_extrq:                // Extract Field From Register
		case NN_insertq:              // Insert Field
		case NN_movntsd:              // Move Non-Temporal Scalar Double-Precision Floating-Point
		case NN_movntss:              // Move Non-Temporal Scalar Single-Precision Floating-Point
		case NN_lzcnt:                // Leading Zero Count
			return false;
			break;

		// xsave/xrstor instructions

		case NN_xgetbv:               // Get Value of Extended Control Register
			return this->BuildOptType8RTL();

		case NN_xrstor:               // Restore Processor Extended States
		case NN_xsave:                // Save Processor Extended States
		case NN_xsetbv:               // Set Value of Extended Control Register
			return false;
			break;

		// Intel Safer Mode Extensions (SMX)

		case NN_getsec:               // Safer Mode Extensions (SMX) Instruction
			return false;
			break;

		// AMD-V Virtualization ISA Extension

		case NN_clgi:                 // Clear Global Interrupt Flag
		case NN_invlpga:              // Invalidate TLB Entry in a Specified ASID
		case NN_skinit:               // Secure Init and Jump with Attestation
		case NN_stgi:                 // Set Global Interrupt Flag
		case NN_vmexit:               // Stop Executing Guest, Begin Executing Host
		case NN_vmload:               // Load State from VMCB
		case NN_vmmcall:              // Call VMM
		case NN_vmrun:                // Run Virtual Machine
		case NN_vmsave:               // Save State to VMCB
			return false;
			break;

		// VMX+ instructions

		case NN_invept:               // Invalidate Translations Derived from EPT
		case NN_invvpid:              // Invalidate Translations Based on VPID
			return false;
			break;

		// Intel Atom instructions

		case NN_movbe:                // Move Data After Swapping Bytes
			return false;
			break;

		// Intel AES instructions

		case NN_aesenc:                // Perform One Round of an AES Encryption Flow
		case NN_aesenclast:            // Perform the Last Round of an AES Encryption Flow
		case NN_aesdec:                // Perform One Round of an AES Decryption Flow
		case NN_aesdeclast:            // Perform the Last Round of an AES Decryption Flow
		case NN_aesimc:                // Perform the AES InvMixColumn Transformation
		case NN_aeskeygenassist:       // AES Round Key Generation Assist
			return this->BuildBinaryRTL(SMP_ENCRYPTION_OPERATION);
			break;

		// Carryless multiplication

		case NN_pclmulqdq:            // Carry-Less Multiplication Quadword
			return BuildBinaryIgnoreImmedRTL(SMP_U_MULTIPLY);
			break;

// Returns modified by operand size prefixes

		case NN_retnw:               // Return Near from Procedure (use16)
		case NN_retnd:               // Return Near from Procedure (use32)
		case NN_retnq:               // Return Near from Procedure (use64)
		case NN_retfw:               // Return Far from Procedure (use16)
		case NN_retfd:               // Return Far from Procedure (use32)
		case NN_retfq:               // Return Far from Procedure (use64)
			return this->BuildReturnRTL();

// RDRAND support

		case NN_rdrand:              // Read Random Number
			return this->BuildUnaryRTL(SMP_UNARY_NUMERIC_OPERATION);

// new GPR instructions

		case NN_adcx:                 // Unsigned Integer Addition of Two Operands with Carry Flag
			return this->BuildBinaryPlusFlagsRTL(SMP_ADD_CARRY);

		case NN_adox:                 // Unsigned Integer Addition of Two Operands with Overflow Flag
		case NN_andn:                 // Logical AND NOT
		case NN_bextr:                // Bit Field Extract
		case NN_blsi:                 // Extract Lowest Set Isolated Bit
		case NN_blsmsk:               // Get Mask Up to Lowest Set Bit
		case NN_blsr:                 // Reset Lowest Set Bit
		case NN_bzhi:                 // Zero High Bits Starting with Specified Bit Position
			return this->BuildBinaryPlusFlagsRTL(SMP_BINARY_NUMERIC_OPERATION);

		case NN_clac:                 // Clear AC Flag in EFLAGS Register
			return false;

		case NN_mulx:                 // Unsigned Multiply Without Affecting Flags
			return this->BuildBinaryRTL(SMP_U_MULTIPLY);

		case NN_pdep:                 // Parallel Bits Deposit
		case NN_pext:                 // Parallel Bits Extract
			return this->BuildBinaryRTL(SMP_BINARY_NUMERIC_OPERATION);

		case NN_rorx:                 // Rotate Right Logical Without Affecting Flags
			return this->BuildBinaryRTL(SMP_ROTATE_RIGHT);

		case NN_sarx:                 // Shift Arithmetically Right Without Affecting Flags
			return this->BuildBinaryRTL(SMP_S_RIGHT_SHIFT);

		case NN_shlx:                 // Shift Logically Left Without Affecting Flags

		case NN_shrx:                 // Shift Logically Right Without Affecting Flags
			return this->BuildBinaryRTL(SMP_U_RIGHT_SHIFT);

		case NN_stac:                 // Set AC Flag in EFLAGS Register
			return false;

		case NN_tzcnt:                // Count the Number of Trailing Zero Bits
			return this->BuildBinaryRTL(SMP_BINARY_NUMERIC_OPERATION);

		case NN_xsaveopt:             // Save Processor Extended States Optimized
		case NN_invpcid:              // Invalidate Processor Context ID
			return false;

		case NN_rdseed:               // Read Random Seed
			return this->BuildBinaryRTL(SMP_BINARY_NUMERIC_OPERATION);

		case NN_rdfsbase:             // Read FS Segment Base
		case NN_rdgsbase:             // Read GS Segment Base
		case NN_wrfsbase:             // Write FS Segment Base
		case NN_wrgsbase:             // Write GS Segment Base
			return false;

// new AVX instructions

		case NN_vaddpd:               // Add Packed Double-Precision Floating-Point Values
		case NN_vaddps:               // Packed Single-FP Add
		case NN_vaddsd:               // Add Scalar Double-Precision Floating-Point Values
		case NN_vaddss:               // Scalar Single-FP Add
		case NN_vaddsubpd:            // Add /Sub packed DP FP numbers
		case NN_vaddsubps:            // Add /Sub packed SP FP numbers
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_vaesdec:              // Perform One Round of an AES Decryption Flow
		case NN_vaesdeclast:          // Perform the Last Round of an AES Decryption Flow
		case NN_vaesenc:              // Perform One Round of an AES Encryption Flow
		case NN_vaesenclast:          // Perform the Last Round of an AES Encryption Flow
		case NN_vaesimc:              // Perform the AES InvMixColumn Transformation
		case NN_vaeskeygenassist:     // AES Round Key Generation Assist
			return this->BuildBinaryRTL(SMP_ENCRYPTION_OPERATION);
			break;

		case NN_vandnpd:              // Bitwise Logical AND NOT of Packed Double-Precision Floating-Point Values
		case NN_vandnps:              // Bitwise Logical And Not for Single-FP
		case NN_vandpd:               // Bitwise Logical AND of Packed Double-Precision Floating-Point Values
		case NN_vandps:               // Bitwise Logical And for Single-FP
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_vblendpd:             // Blend Packed Double Precision Floating-Point Values
		case NN_vblendps:             // Blend Packed Single Precision Floating-Point Values
		case NN_vblendvpd:            // Variable Blend Packed Double Precision Floating-Point Values
		case NN_vblendvps:            // Variable Blend Packed Single Precision Floating-Point Values
			return this->BuildBinaryRTL(SMP_SHUFFLE);
			break;

		case NN_vbroadcastf128:       // Broadcast 128 Bits of Floating-Point Data
		case NN_vbroadcasti128:       // Broadcast 128 Bits of Integer Data
		case NN_vbroadcastsd:         // Broadcast Double-Precision Floating-Point Element
		case NN_vbroadcastss:         // Broadcast Single-Precision Floating-Point Element
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);
			break;

		case NN_vcmppd:               // Compare Packed Double-Precision Floating-Point Values
		case NN_vcmpps:               // Packed Single-FP Compare
		case NN_vcmpsd:               // Compare Scalar Double-Precision Floating-Point Values
		case NN_vcmpss:               // Scalar Single-FP Compare
		case NN_vcomisd:              // Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS
		case NN_vcomiss:              // Scalar Ordered Single-FP Compare and Set EFLAGS
		case NN_vcvtdq2pd:            // Convert Packed Doubleword Integers to Packed Single-Precision Floating-Point Values
		case NN_vcvtdq2ps:            // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values
		case NN_vcvtpd2dq:            // Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers
		case NN_vcvtpd2ps:            // Convert Packed Double-Precision Floating-Point Values to Packed Single-Precision Floating-Point Values
		case NN_vcvtph2ps:            // Convert 16-bit FP Values to Single-Precision FP Values
		case NN_vcvtps2dq:            // Convert Packed Single-Precision Floating-Point Values to Packed Doubleword Integers
		case NN_vcvtps2pd:            // Convert Packed Single-Precision Floating-Point Values to Packed Double-Precision Floating-Point Values
		case NN_vcvtps2ph:            // Convert Single-Precision FP value to 16-bit FP value
		case NN_vcvtsd2si:            // Convert Scalar Double-Precision Floating-Point Value to Doubleword Integer
		case NN_vcvtsd2ss:            // Convert Scalar Double-Precision Floating-Point Value to Scalar Single-Precision Floating-Point Value
		case NN_vcvtsi2sd:            // Convert Doubleword Integer to Scalar Double-Precision Floating-Point Value
		case NN_vcvtsi2ss:            // Scalar signed INT32 to Single-FP conversion
		case NN_vcvtss2sd:            // Convert Scalar Single-Precision Floating-Point Value to Scalar Double-Precision Floating-Point Value
		case NN_vcvtss2si:            // Scalar Single-FP to signed INT32 conversion
		case NN_vcvttpd2dq:           // Convert With Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers
		case NN_vcvttps2dq:           // Convert With Truncation Packed Single-Precision Floating-Point Values to Packed Doubleword Integers
		case NN_vcvttsd2si:           // Convert with Truncation Scalar Double-Precision Floating-Point Value to Doubleword Integer
		case NN_vcvttss2si:           // Scalar Single-FP to signed INT32 conversion (truncate)
		case NN_vdivpd:               // Divide Packed Double-Precision Floating-Point Values
		case NN_vdivps:               // Packed Single-FP Divide
		case NN_vdivsd:               // Divide Scalar Double-Precision Floating-Point Values
		case NN_vdivss:               // Scalar Single-FP Divide
		case NN_vdppd:                // Dot Product of Packed Double Precision Floating-Point Values
		case NN_vdpps:                // Dot Product of Packed Single Precision Floating-Point Values
			return false;
			break;

		case NN_vextractf128:         // Extract Packed Floating-Point Values
		case NN_vextracti128:         // Extract Packed Integer Values
		case NN_vextractps:           // Extract Packed Floating-Point Values
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);
			break;

		case NN_vfmadd132pd:          // Fused Multiply-Add of Packed Double-Precision Floating-Point Values
		case NN_vfmadd132ps:          // Fused Multiply-Add of Packed Single-Precision Floating-Point Values
		case NN_vfmadd132sd:          // Fused Multiply-Add of Scalar Double-Precision Floating-Point Values
		case NN_vfmadd132ss:          // Fused Multiply-Add of Scalar Single-Precision Floating-Point Values
		case NN_vfmadd213pd:          // Fused Multiply-Add of Packed Double-Precision Floating-Point Values
		case NN_vfmadd213ps:          // Fused Multiply-Add of Packed Single-Precision Floating-Point Values
		case NN_vfmadd213sd:          // Fused Multiply-Add of Scalar Double-Precision Floating-Point Values
		case NN_vfmadd213ss:          // Fused Multiply-Add of Scalar Single-Precision Floating-Point Values
		case NN_vfmadd231pd:          // Fused Multiply-Add of Packed Double-Precision Floating-Point Values
		case NN_vfmadd231ps:          // Fused Multiply-Add of Packed Single-Precision Floating-Point Values
		case NN_vfmadd231sd:          // Fused Multiply-Add of Scalar Double-Precision Floating-Point Values
		case NN_vfmadd231ss:          // Fused Multiply-Add of Scalar Single-Precision Floating-Point Values
		case NN_vfmaddsub132pd:       // Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values
		case NN_vfmaddsub132ps:       // Fused Multiply-Alternating Add/Subtract of Packed Single-Precision Floating-Point Values
		case NN_vfmaddsub213pd:       // Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values
		case NN_vfmaddsub213ps:       // Fused Multiply-Alternating Add/Subtract of Packed Single-Precision Floating-Point Values
		case NN_vfmaddsub231pd:       // Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values
		case NN_vfmaddsub231ps:       // Fused Multiply-Alternating Add/Subtract of Packed Single-Precision Floating-Point Values
		case NN_vfmsub132pd:          // Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values
		case NN_vfmsub132ps:          // Fused Multiply-Subtract of Packed Single-Precision Floating-Point Values
		case NN_vfmsub132sd:          // Fused Multiply-Subtract of Scalar Double-Precision Floating-Point Values
		case NN_vfmsub132ss:          // Fused Multiply-Subtract of Scalar Single-Precision Floating-Point Values
		case NN_vfmsub213pd:          // Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values
		case NN_vfmsub213ps:          // Fused Multiply-Subtract of Packed Single-Precision Floating-Point Values
		case NN_vfmsub213sd:          // Fused Multiply-Subtract of Scalar Double-Precision Floating-Point Values
		case NN_vfmsub213ss:          // Fused Multiply-Subtract of Scalar Single-Precision Floating-Point Values
		case NN_vfmsub231pd:          // Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values
		case NN_vfmsub231ps:          // Fused Multiply-Subtract of Packed Single-Precision Floating-Point Values
		case NN_vfmsub231sd:          // Fused Multiply-Subtract of Scalar Double-Precision Floating-Point Values
		case NN_vfmsub231ss:          // Fused Multiply-Subtract of Scalar Single-Precision Floating-Point Values
		case NN_vfmsubadd132pd:       // Fused Multiply-Alternating Subtract/Add of Packed Double-Precision Floating-Point Values
		case NN_vfmsubadd132ps:       // Fused Multiply-Alternating Subtract/Add of Packed Single-Precision Floating-Point Values
		case NN_vfmsubadd213pd:       // Fused Multiply-Alternating Subtract/Add of Packed Double-Precision Floating-Point Values
		case NN_vfmsubadd213ps:       // Fused Multiply-Alternating Subtract/Add of Packed Single-Precision Floating-Point Values
		case NN_vfmsubadd231pd:       // Fused Multiply-Alternating Subtract/Add of Packed Double-Precision Floating-Point Values
		case NN_vfmsubadd231ps:       // Fused Multiply-Alternating Subtract/Add of Packed Single-Precision Floating-Point Values
		case NN_vfnmadd132pd:         // Fused Negative Multiply-Add of Packed Double-Precision Floating-Point Values
		case NN_vfnmadd132ps:         // Fused Negative Multiply-Add of Packed Single-Precision Floating-Point Values
		case NN_vfnmadd132sd:         // Fused Negative Multiply-Add of Scalar Double-Precision Floating-Point Values
		case NN_vfnmadd132ss:         // Fused Negative Multiply-Add of Scalar Single-Precision Floating-Point Values
		case NN_vfnmadd213pd:         // Fused Negative Multiply-Add of Packed Double-Precision Floating-Point Values
		case NN_vfnmadd213ps:         // Fused Negative Multiply-Add of Packed Single-Precision Floating-Point Values
		case NN_vfnmadd213sd:         // Fused Negative Multiply-Add of Scalar Double-Precision Floating-Point Values
		case NN_vfnmadd213ss:         // Fused Negative Multiply-Add of Scalar Single-Precision Floating-Point Values
		case NN_vfnmadd231pd:         // Fused Negative Multiply-Add of Packed Double-Precision Floating-Point Values
		case NN_vfnmadd231ps:         // Fused Negative Multiply-Add of Packed Single-Precision Floating-Point Values
		case NN_vfnmadd231sd:         // Fused Negative Multiply-Add of Scalar Double-Precision Floating-Point Values
		case NN_vfnmadd231ss:         // Fused Negative Multiply-Add of Scalar Single-Precision Floating-Point Values
		case NN_vfnmsub132pd:         // Fused Negative Multiply-Subtract of Packed Double-Precision Floating-Point Values
		case NN_vfnmsub132ps:         // Fused Negative Multiply-Subtract of Packed Single-Precision Floating-Point Values
		case NN_vfnmsub132sd:         // Fused Negative Multiply-Subtract of Scalar Double-Precision Floating-Point Values
		case NN_vfnmsub132ss:         // Fused Negative Multiply-Subtract of Scalar Single-Precision Floating-Point Values
		case NN_vfnmsub213pd:         // Fused Negative Multiply-Subtract of Packed Double-Precision Floating-Point Values
		case NN_vfnmsub213ps:         // Fused Negative Multiply-Subtract of Packed Single-Precision Floating-Point Values
		case NN_vfnmsub213sd:         // Fused Negative Multiply-Subtract of Scalar Double-Precision Floating-Point Values
		case NN_vfnmsub213ss:         // Fused Negative Multiply-Subtract of Scalar Single-Precision Floating-Point Values
		case NN_vfnmsub231pd:         // Fused Negative Multiply-Subtract of Packed Double-Precision Floating-Point Values
		case NN_vfnmsub231ps:         // Fused Negative Multiply-Subtract of Packed Single-Precision Floating-Point Values
		case NN_vfnmsub231sd:         // Fused Negative Multiply-Subtract of Scalar Double-Precision Floating-Point Values
		case NN_vfnmsub231ss:         // Fused Negative Multiply-Subtract of Scalar Single-Precision Floating-Point Values
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_vgatherdps:           // Gather Packed SP FP Values Using Signed Dword Indices
		case NN_vgatherdpd:           // Gather Packed DP FP Values Using Signed Dword Indices
		case NN_vgatherqps:           // Gather Packed SP FP Values Using Signed Qword Indices
		case NN_vgatherqpd:           // Gather Packed DP FP Values Using Signed Qword Indices
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);
			break;

		case NN_vhaddpd:              // Add horizontally packed DP FP numbers
		case NN_vhaddps:              // Add horizontally packed SP FP numbers
		case NN_vhsubpd:              // Sub horizontally packed DP FP numbers
		case NN_vhsubps:              // Sub horizontally packed SP FP numbers
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_vinsertf128:          // Insert Packed Floating-Point Values
		case NN_vinserti128:          // Insert Packed Integer Values
		case NN_vinsertps:            // Insert Packed Single Precision Floating-Point Value
		case NN_vlddqu:               // Load Unaligned Packed Integer Values
		case NN_vldmxcsr:             // Load Streaming SIMD Extensions Technology Control/Status Register
			return false;
			break;

		case NN_vmaskmovdqu:          // Store Selected Bytes of Double Quadword with NT Hint
		case NN_vmaskmovpd:           // Conditionally Load Packed Double-Precision Floating-Point Values
		case NN_vmaskmovps:           // Conditionally Load Packed Single-Precision Floating-Point Values
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);
			break;

		case NN_vmaxpd:               // Return Maximum Packed Double-Precision Floating-Point Values
		case NN_vmaxps:               // Packed Single-FP Maximum
		case NN_vmaxsd:               // Return Maximum Scalar Double-Precision Floating-Point Value
		case NN_vmaxss:               // Scalar Single-FP Maximum
		case NN_vminpd:               // Return Minimum Packed Double-Precision Floating-Point Values
		case NN_vminps:               // Packed Single-FP Minimum
		case NN_vminsd:               // Return Minimum Scalar Double-Precision Floating-Point Value
		case NN_vminss:               // Scalar Single-FP Minimum
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_vmovapd:              // Move Aligned Packed Double-Precision Floating-Point Values
		case NN_vmovaps:              // Move Aligned Four Packed Single-FP
		case NN_vmovd:                // Move 32 bits
		case NN_vmovddup:             // Move One Double-FP and Duplicate
		case NN_vmovdqa:              // Move Aligned Double Quadword
		case NN_vmovdqu:              // Move Unaligned Double Quadword
		case NN_vmovhlps:             // Move High to Low Packed Single-FP
		case NN_vmovhpd:              // Move High Packed Double-Precision Floating-Point Values
		case NN_vmovhps:              // Move High Packed Single-FP
		case NN_vmovlhps:             // Move Low to High Packed Single-FP
		case NN_vmovlpd:              // Move Low Packed Double-Precision Floating-Point Values
		case NN_vmovlps:              // Move Low Packed Single-FP
		case NN_vmovmskpd:            // Extract Packed Double-Precision Floating-Point Sign Mask
		case NN_vmovmskps:            // Move Mask to Register
		case NN_vmovntdq:             // Store Double Quadword Using Non-Temporal Hint
		case NN_vmovntdqa:            // Load Double Quadword Non-Temporal Aligned Hint
		case NN_vmovntpd:             // Store Packed Double-Precision Floating-Point Values Using Non-Temporal Hint
		case NN_vmovntps:             // Move Aligned Four Packed Single-FP Non Temporal
		case NN_vmovntsd:             // Move Non-Temporal Scalar Double-Precision Floating-Point
		case NN_vmovntss:             // Move Non-Temporal Scalar Single-Precision Floating-Point
		case NN_vmovq:                // Move 64 bits
		case NN_vmovsd:               // Move Scalar Double-Precision Floating-Point Values
		case NN_vmovshdup:            // Move Packed Single-FP High and Duplicate
		case NN_vmovsldup:            // Move Packed Single-FP Low and Duplicate
		case NN_vmovss:               // Move Scalar Single-FP
		case NN_vmovupd:              // Move Unaligned Packed Double-Precision Floating-Point Values
		case NN_vmovups:              // Move Unaligned Four Packed Single-FP
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);
			break;

		case NN_vmpsadbw:             // Compute Multiple Packed Sums of Absolute Difference
		case NN_vmulpd:               // Multiply Packed Double-Precision Floating-Point Values
		case NN_vmulps:               // Packed Single-FP Multiply
		case NN_vmulsd:               // Multiply Scalar Double-Precision Floating-Point Values
		case NN_vmulss:               // Scalar Single-FP Multiply
		case NN_vorpd:                // Bitwise Logical OR of Double-Precision Floating-Point Values
		case NN_vorps:                // Bitwise Logical OR for Single-FP Data
		case NN_vpabsb:               // Packed Absolute Value Byte
		case NN_vpabsd:               // Packed Absolute Value Doubleword
		case NN_vpabsw:               // Packed Absolute Value Word
		case NN_vpackssdw:            // Pack with Signed Saturation (Dword->Word)
		case NN_vpacksswb:            // Pack with Signed Saturation (Word->Byte)
		case NN_vpackusdw:            // Pack with Unsigned Saturation
		case NN_vpackuswb:            // Pack with Unsigned Saturation (Word->Byte)
		case NN_vpaddb:               // Packed Add Byte
		case NN_vpaddd:               // Packed Add Dword
		case NN_vpaddq:               // Add Packed Quadword Integers
		case NN_vpaddsb:              // Packed Add with Saturation (Byte)
		case NN_vpaddsw:              // Packed Add with Saturation (Word)
		case NN_vpaddusb:             // Packed Add Unsigned with Saturation (Byte)
		case NN_vpaddusw:             // Packed Add Unsigned with Saturation (Word)
		case NN_vpaddw:               // Packed Add Word
		case NN_vpalignr:             // Packed Align Right
		case NN_vpand:                // Bitwise Logical And
		case NN_vpandn:               // Bitwise Logical And Not
		case NN_vpavgb:               // Packed Average (Byte)
		case NN_vpavgw:               // Packed Average (Word)
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_vpblendd:             // Blend Packed Dwords
		case NN_vpblendvb:            // Variable Blend Packed Bytes
		case NN_vpblendw:             // Blend Packed Words
			return this->BuildBinaryRTL(SMP_SHUFFLE);
			break;

		case NN_vpbroadcastb:         // Broadcast a Byte Integer
		case NN_vpbroadcastd:         // Broadcast a Dword Integer
		case NN_vpbroadcastq:         // Broadcast a Qword Integer
		case NN_vpbroadcastw:         // Broadcast a Word Integer
		case NN_vpclmulqdq:           // Carry-Less Multiplication Quadword
		case NN_vpcmpeqb:             // Packed Compare for Equal (Byte)
		case NN_vpcmpeqd:             // Packed Compare for Equal (Dword)
		case NN_vpcmpeqq:             // Compare Packed Qword Data for Equal
		case NN_vpcmpeqw:             // Packed Compare for Equal (Word)
		case NN_vpcmpestri:           // Packed Compare Explicit Length Strings, Return Index
		case NN_vpcmpestrm:           // Packed Compare Explicit Length Strings, Return Mask
		case NN_vpcmpgtb:             // Packed Compare for Greater Than (Byte)
		case NN_vpcmpgtd:             // Packed Compare for Greater Than (Dword)
		case NN_vpcmpgtq:             // Compare Packed Data for Greater Than
		case NN_vpcmpgtw:             // Packed Compare for Greater Than (Word)
		case NN_vpcmpistri:           // Packed Compare Implicit Length Strings, Return Index
		case NN_vpcmpistrm:           // Packed Compare Implicit Length Strings, Return Mask
		case NN_vperm2f128:           // Permute Floating-Point Values
		case NN_vperm2i128:           // Permute Integer Values
		case NN_vpermd:               // Full Doublewords Element Permutation
		case NN_vpermilpd:            // Permute Double-Precision Floating-Point Values
		case NN_vpermilps:            // Permute Single-Precision Floating-Point Values
		case NN_vpermpd:              // Permute Double-Precision Floating-Point Elements
		case NN_vpermps:              // Permute Single-Precision Floating-Point Elements
		case NN_vpermq:               // Qwords Element Permutation
		case NN_vpextrb:              // Extract Byte
		case NN_vpextrd:              // Extract Dword
		case NN_vpextrq:              // Extract Qword
		case NN_vpextrw:              // Extract Word
		case NN_vpgatherdd:           // Gather Packed Dword Values Using Signed Dword Indices
		case NN_vpgatherdq:           // Gather Packed Qword Values Using Signed Dword Indices
		case NN_vpgatherqd:           // Gather Packed Dword Values Using Signed Qword Indices
		case NN_vpgatherqq:           // Gather Packed Qword Values Using Signed Qword Indices
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_vphaddd:              // Packed Horizontal Add Doubleword
		case NN_vphaddsw:             // Packed Horizontal Add and Saturate
		case NN_vphaddw:              // Packed Horizontal Add Word
		case NN_vphminposuw:          // Packed Horizontal Word Minimum
		case NN_vphsubd:              // Packed Horizontal Subtract Doubleword
		case NN_vphsubsw:             // Packed Horizontal Subtract and Saturate
		case NN_vphsubw:              // Packed Horizontal Subtract Word
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_vpinsrb:              // Insert Byte
		case NN_vpinsrd:              // Insert Dword
		case NN_vpinsrq:              // Insert Qword
		case NN_vpinsrw:              // Insert Word
			return false;
			break;

		case NN_vpmaddubsw:           // Multiply and Add Packed Signed and Unsigned Bytes
		case NN_vpmaddwd:             // Packed Multiply and Add
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_vpmaskmovd:           // Conditionally Store Dword Values Using Mask
		case NN_vpmaskmovq:           // Conditionally Store Qword Values Using Mask
			return false;
			break;

		case NN_vpmaxsb:              // Maximum of Packed Signed Byte Integers
		case NN_vpmaxsd:              // Maximum of Packed Signed Dword Integers
		case NN_vpmaxsw:              // Packed Signed Integer Word Maximum
			return this->BuildBinaryRTL(SMP_MAX_S);
			break;

		case NN_vpmaxub:              // Packed Unsigned Integer Byte Maximum
		case NN_vpmaxud:              // Maximum of Packed Unsigned Dword Integers
		case NN_vpmaxuw:              // Maximum of Packed Word Integers
			return this->BuildBinaryRTL(SMP_MAX_U);
			break;

		case NN_vpminsb:              // Minimum of Packed Signed Byte Integers
		case NN_vpminsd:              // Minimum of Packed Signed Dword Integers
		case NN_vpminsw:              // Packed Signed Integer Word Minimum
			return this->BuildBinaryRTL(SMP_MIN_S);
			break;

		case NN_vpminub:              // Packed Unsigned Integer Byte Minimum
		case NN_vpminud:              // Minimum of Packed Unsigned Dword Integers
		case NN_vpminuw:              // Minimum of Packed Word Integers
			return this->BuildBinaryRTL(SMP_MIN_U);
			break;

		case NN_vpmovmskb:            // Move Byte Mask to Integer
			return this->BuildMoveRTL(SMP_NULL_OPERATOR);
			break;

		case NN_vpmovsxbd:            // Packed Move with Sign Extend
		case NN_vpmovsxbq:            // Packed Move with Sign Extend
		case NN_vpmovsxbw:            // Packed Move with Sign Extend
		case NN_vpmovsxdq:            // Packed Move with Sign Extend
		case NN_vpmovsxwd:            // Packed Move with Sign Extend
		case NN_vpmovsxwq:            // Packed Move with Sign Extend
			return this->BuildUnary2OpndRTL(SMP_SIGN_EXTEND);
			break;

		case NN_vpmovzxbd:            // Packed Move with Zero Extend
		case NN_vpmovzxbq:            // Packed Move with Zero Extend
		case NN_vpmovzxbw:            // Packed Move with Zero Extend
		case NN_vpmovzxdq:            // Packed Move with Zero Extend
		case NN_vpmovzxwd:            // Packed Move with Zero Extend
		case NN_vpmovzxwq:            // Packed Move with Zero Extend
			return this->BuildUnary2OpndRTL(SMP_ZERO_EXTEND);
			break;

		case NN_vpmuldq:              // Multiply Packed Signed Dword Integers
		case NN_vpmulhrsw:            // Packed Multiply High with Round and Scale
		case NN_vpmulhuw:             // Packed Multiply High Unsigned
		case NN_vpmulhw:              // Packed Multiply High
		case NN_vpmulld:              // Multiply Packed Signed Dword Integers and Store Low Result
		case NN_vpmullw:              // Packed Multiply Low
		case NN_vpmuludq:             // Multiply Packed Unsigned Doubleword Integers
		case NN_vpor:                 // Bitwise Logical Or
		case NN_vpsadbw:              // Packed Sum of Absolute Differences
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_vpshufb:              // Packed Shuffle Bytes
		case NN_vpshufd:              // Shuffle Packed Doublewords
		case NN_vpshufhw:             // Shuffle Packed High Words
		case NN_vpshuflw:             // Shuffle Packed Low Words
			return this->BuildBinaryRTL(SMP_SHUFFLE);
			break;

		case NN_vpsignb:              // Packed SIGN Byte
		case NN_vpsignd:              // Packed SIGN Doubleword
		case NN_vpsignw:              // Packed SIGN Word
			return false;
			break;

		case NN_vpslld:               // Packed Shift Left Logical (Dword)
		case NN_vpslldq:              // Shift Double Quadword Left Logical
		case NN_vpsllq:               // Packed Shift Left Logical (Qword)
		case NN_vpsllvd:              // Variable Bit Shift Left Logical (Dword)
		case NN_vpsllvq:              // Variable Bit Shift Left Logical (Qword)
		case NN_vpsllw:               // Packed Shift Left Logical (Word)
		case NN_vpsrad:               // Packed Shift Right Arithmetic (Dword)
		case NN_vpsravd:              // Variable Bit Shift Right Arithmetic
		case NN_vpsraw:               // Packed Shift Right Arithmetic (Word)
		case NN_vpsrld:               // Packed Shift Right Logical (Dword)
		case NN_vpsrldq:              // Shift Double Quadword Right Logical (Qword)
		case NN_vpsrlq:               // Packed Shift Right Logical (Qword)
		case NN_vpsrlvd:              // Variable Bit Shift Right Logical (Dword)
		case NN_vpsrlvq:              // Variable Bit Shift Right Logical (Qword)
		case NN_vpsrlw:               // Packed Shift Right Logical (Word)
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_vpsubb:               // Packed Subtract Byte
		case NN_vpsubd:               // Packed Subtract Dword
		case NN_vpsubq:               // Subtract Packed Quadword Integers
		case NN_vpsubsb:              // Packed Subtract with Saturation (Byte)
		case NN_vpsubsw:              // Packed Subtract with Saturation (Word)
		case NN_vpsubusb:             // Packed Subtract Unsigned with Saturation (Byte)
		case NN_vpsubusw:             // Packed Subtract Unsigned with Saturation (Word)
		case NN_vpsubw:               // Packed Subtract Word
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_vptest:               // Logical Compare
			return false;
			break;

		case NN_vpunpckhbw:           // Unpack High Packed Data (Byte->Word)
		case NN_vpunpckhdq:           // Unpack High Packed Data (Dword->Qword)
		case NN_vpunpckhqdq:          // Unpack High Packed Data (Qword->Xmmword)
		case NN_vpunpckhwd:           // Unpack High Packed Data (Word->Dword)
		case NN_vpunpcklbw:           // Unpack Low Packed Data (Byte->Word)
		case NN_vpunpckldq:           // Unpack Low Packed Data (Dword->Qword)
		case NN_vpunpcklqdq:          // Unpack Low Packed Data (Qword->Xmmword)
		case NN_vpunpcklwd:           // Unpack Low Packed Data (Word->Dword)
			return this->BuildBinaryRTL(SMP_INTERLEAVE);
			break;

		case NN_vpxor:                // Bitwise Logical Exclusive Or
		case NN_vrcpps:               // Packed Single-FP Reciprocal
		case NN_vrcpss:               // Scalar Single-FP Reciprocal
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_vroundpd:             // Round Packed Double Precision Floating-Point Values
		case NN_vroundps:             // Round Packed Single Precision Floating-Point Values
		case NN_vroundsd:             // Round Scalar Double Precision Floating-Point Values
		case NN_vroundss:             // Round Scalar Single Precision Floating-Point Values
		case NN_vrsqrtps:             // Packed Single-FP Square Root Reciprocal
		case NN_vrsqrtss:             // Scalar Single-FP Square Root Reciprocal
			return false;
			break;

		case NN_vshufpd:              // Shuffle Packed Double-Precision Floating-Point Values
		case NN_vshufps:              // Shuffle Single-FP
			return this->BuildBinaryRTL(SMP_SHUFFLE);
			break;

		case NN_vsqrtpd:              // Compute Square Roots of Packed Double-Precision Floating-Point Values
		case NN_vsqrtps:              // Packed Single-FP Square Root
		case NN_vsqrtsd:              // Compute Square Rootof Scalar Double-Precision Floating-Point Value
		case NN_vsqrtss:              // Scalar Single-FP Square Root
		case NN_vstmxcsr:             // Store Streaming SIMD Extensions Technology Control/Status Register
			return false;
			break;

		case NN_vsubpd:               // Subtract Packed Double-Precision Floating-Point Values
		case NN_vsubps:               // Packed Single-FP Subtract
		case NN_vsubsd:               // Subtract Scalar Double-Precision Floating-Point Values
		case NN_vsubss:               // Scalar Single-FP Subtract
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_vtestpd:              // Packed Double-Precision Floating-Point Bit Test
		case NN_vtestps:              // Packed Single-Precision Floating-Point Bit Test
		case NN_vucomisd:             // Unordered Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS
		case NN_vucomiss:             // Scalar Unordered Single-FP Compare and Set EFLAGS
			return false;
			break;

		case NN_vunpckhpd:            // Unpack and Interleave High Packed Double-Precision Floating-Point Values
		case NN_vunpckhps:            // Unpack High Packed Single-FP Data
		case NN_vunpcklpd:            // Unpack and Interleave Low Packed Double-Precision Floating-Point Values
		case NN_vunpcklps:            // Unpack Low Packed Single-FP Data
			return this->BuildBinaryRTL(SMP_INTERLEAVE);
			break;

		case NN_vxorpd:               // Bitwise Logical OR of Double-Precision Floating-Point Values
		case NN_vxorps:               // Bitwise Logical XOR for Single-FP Data
			return this->BuildBinaryRTL(SMP_BINARY_FLOATING_ARITHMETIC);
			break;

		case NN_vzeroall:             // Zero All YMM Registers
		case NN_vzeroupper:           // Zero Upper Bits of YMM Registers
			NopRT = new SMPRegTransfer;
			NopRT->SetParentInst(this);
			NopRT->SetOperator(SMP_NULL_OPERATOR);
			this->RTL.push_back(NopRT);
			NopRT = NULL;
			return true;

// Transactional Synchronization Extensions

		case NN_xabort:               // Transaction Abort
		case NN_xbegin:               // Transaction Begin
		case NN_xend:                 // Transaction End
		case NN_xtest:                // Test If In Transactional Execution
			return false;
			break;

// Virtual PC synthetic instructions

		case NN_vmgetinfo:            // Virtual PC - Get VM Information
		case NN_vmsetinfo:            // Virtual PC - Set VM Information
		case NN_vmdxdsbl:             // Virtual PC - Disable Direct Execution
		case NN_vmdxenbl:             // Virtual PC - Enable Direct Execution
		case NN_vmcpuid:              // Virtual PC - Virtualized CPU Information
		case NN_vmhlt:                // Virtual PC - Halt
		case NN_vmsplaf:              // Virtual PC - Spin Lock Acquisition Failed
		case NN_vmpushfd:             // Virtual PC - Push virtualized flags register
		case NN_vmpopfd:              // Virtual PC - Pop virtualized flags register
		case NN_vmcli:                // Virtual PC - Clear Interrupt Flag
		case NN_vmsti:                // Virtual PC - Set Interrupt Flag
		case NN_vmiretd:              // Virtual PC - Return From Interrupt
		case NN_vmsgdt:               // Virtual PC - Store Global Descriptor Table
		case NN_vmsidt:               // Virtual PC - Store Interrupt Descriptor Table
		case NN_vmsldt:               // Virtual PC - Store Local Descriptor Table
		case NN_vmstr:                // Virtual PC - Store Task Register
		case NN_vmsdte:               // Virtual PC - Store to Descriptor Table Entry
		case NN_vpcext:               // Virtual PC - ISA extension
			return false;
			break;

#endif // 599 < IDA_SDK_VERSION

		default:
			SMP_msg("ERROR: Unknown instruction opcode at %lx : %s\n", (unsigned long) this->GetAddr(),
				DisAsmText.GetDisAsm(this->GetAddr()));
			return false;
			break;
	} // end switch on opcode
	return true;
} // end SMPInstr::BuildRTL()

// Iterate through all reg transfers and call SyncRTLDefUse for each.
void SMPInstr::SyncAllRTs(bool UseFP, sval_t FPDelta) {
	for (size_t index = 0; index < this->RTL.GetCount(); ++index) {
		this->SyncRTLDefUse(this->RTL.GetRT(index), UseFP, FPDelta);
	}
	return;
} // end of SMPInstr:SyncAllRTs()

// Ensure that each operand of the RTL is found in the appropriate DEF or USE list.
void SMPInstr::SyncRTLDefUse(SMPRegTransfer *CurrRT, bool UseFP, sval_t FPDelta) {
	// The ExtraKills are almost never represented in the DEF 
	//  lists. When they are, they are added in MDFixupDefUseLists(), so we ignore them here.

	// The only DEFs should come from left operands of SMP_ASSIGN operators, i.e. the effects
	//  of register transfers.
	op_t LeftOp, RightOp;
	set<DefOrUse, LessDefUse>::iterator CurrDef, CurrUse;
	bool DebugFlag = false;
#if SMP_VERBOSE_DEBUG_BUILD_RTL
	DebugFlag |= (0 == strcmp("__libc_csu_fini", this->BasicBlock->GetFunc()->GetFuncName()));
#endif

	if (DebugFlag) {
		SMP_msg("SyncRTLDefUse entered. Dump of USE list:\n");
		this->Uses.Dump();
	}

	LeftOp = CurrRT->GetLeftOperand();
	if (SMP_ASSIGN == CurrRT->GetOperator()) {
		assert(o_void != LeftOp.type);
		assert(o_imm != LeftOp.type);
		CurrDef = this->Defs.FindRef(LeftOp);
		if (CurrDef == this->GetLastDef() && !LeftOp.is_reg(R_ip)) {
#if SMP_VERBOSE_DEBUG_BUILD_RTL
			SMP_msg("WARNING: DEF not found for SMP_ASSIGN in %s ; added op:", DisAsmText.GetDisAsm(this->GetAddr()));
			PrintOperand(LeftOp);
			SMP_msg("\n");
#endif
			this->Defs.SetRef(LeftOp, CurrRT->GetOperatorType());
		}
	}
	else { // not SMP_ASSIGN; left operand should be a USE
		if (o_void != LeftOp.type) {
			CurrUse = this->Uses.FindRef(LeftOp);
			if (CurrUse == this->GetLastUse()) {
#if SMP_VERBOSE_DEBUG_BUILD_RTL_DEF_USE
				SMP_msg("WARNING: USE not found for ");
				PrintOperand(LeftOp);
				SMP_msg(" in %s ; added\n", DisAsmText.GetDisAsm(this->GetAddr()));
#endif
				this->Uses.SetRef(LeftOp);
			}
		}
	}
	if (!CurrRT->HasRightSubTree()) {
		RightOp = CurrRT->GetRightOperand();  // right operand should be a USE
		if (o_void != RightOp.type) {
			CurrUse = this->Uses.FindRef(RightOp);
			if (CurrUse == this->GetLastUse()) {
#if SMP_VERBOSE_DEBUG_BUILD_RTL_DEF_USE
				SMP_msg("WARNING: USE not found for ");
				PrintOperand(RightOp);
				SMP_msg(" in %s ; added\n", DisAsmText.GetDisAsm(this->GetAddr()));
#endif
				this->Uses.SetRef(RightOp);
			}
		}
	}
	else { // recurse into right subtree
		this->SyncRTLDefUse(CurrRT->GetRightTree(), UseFP, FPDelta);
	}

	// Guard operands can only be USEs.
	SMPGuard *GuardExpr = CurrRT->GetGuard();
	if (NULL != GuardExpr) {
		LeftOp = GuardExpr->GetLeftOperand();
		if ((o_void != LeftOp.type) && (o_imm != LeftOp.type)) {
			CurrUse = this->Uses.FindRef(LeftOp);
			if (CurrUse == this->GetLastUse()) {
				this->Uses.SetRef(LeftOp);
			}
		}
		RightOp = GuardExpr->GetRightOperand();
		if ((o_void != RightOp.type) && (o_imm != RightOp.type)) {
			CurrUse = this->Uses.FindRef(RightOp);
			if (CurrUse == this->GetLastUse()) {
				this->Uses.SetRef(RightOp);
			}
		}
	}
	return;
} // end of SMPInstr::SyncRTLDefUse()

// SetOperatorType - set the type of the operator, take into account the speculative (profiler) status
void SMPRegTransfer::SetOperatorType(SMPOperandType OpType, const SMPInstr* Instr) { 
	SMPOperandType OldType = RTop.type;
	SMPOperandType NewType = OpType;
	if (Instr->GetBlock()->GetFunc()->GetIsSpeculative()) {
		NewType = (SMPOperandType) (((int)NewType) | PROF_BASE);
#if SMP_TRACK_NONSPEC_OPER_TYPE
		if (!IsProfDerived(OldType))
			RTop.NonSpeculativeType = OldType;
#endif
	}

	RTop.type = NewType; 
} // end of SMPRegTransfer::SetOperatorType

// Does UseOp arithmetically affect the value of the NonFlagsDef for this RTL?
bool SMPRegTransfer::OperandTransfersValueToDef(op_t UseOp) const {
	bool FoundTransfer = false;
	op_t DefOp = this->GetLeftOperand();
	SMPoperator CurrOp = this->GetOperator();
	if ((SMP_ASSIGN == CurrOp) && (DefOp.type != o_void) && (!DefOp.is_reg(MD_FLAGS_REG))) {
		// We have an assignment to a non-flag DefOp. The only remaining question is whether
		//  UseOp appears in the right hand side of the RT as something besides an address register
		//  inside a memory operand.
		if (this->HasRightSubTree()) {
			FoundTransfer = this->GetRightTree()->OperandTransfersHelper(UseOp);
		}
		else {
			op_t RightOp = this->GetRightOperand();
			if (IsEqOpIgnoreBitwidth(UseOp, RightOp)) {
				// Found UseOp.
				FoundTransfer = true;
			}
		}
	}
	return FoundTransfer;
} // end of SMPRegTransfer::OperandTransfersValueToDef()

// Does UseOp arithmetically affect the value of the NonFlagsDef for this RT?
//  Recursive helper for OperandTransfersValueToDef().
bool SMPRegTransfer::OperandTransfersHelper(op_t UseOp) const {
	bool FoundTransfer = false;
	op_t LeftOp = this->GetLeftOperand();
	SMPoperator CurrOp = this->GetOperator();
	// Have to check left and right operands to see if they are UseOp.
	if (IsEqOpIgnoreBitwidth(UseOp, LeftOp)) {
		FoundTransfer = true; // Found UseOp.
	}
	else if (this->HasRightSubTree()) { // recurse
		FoundTransfer = this->GetRightTree()->OperandTransfersHelper(UseOp);
	}
	else {
		op_t RightOp = this->GetRightOperand();
		if (IsEqOpIgnoreBitwidth(UseOp, RightOp)) {
			// Found UseOp.
			FoundTransfer = true;
		}
	}

	return FoundTransfer;
} // end of SMPRegTransfer::OperandTransfersHelper()

// Update the memory source operands to have the new type from profiling info.
void SMPInstr::UpdateMemLoadTypes(SMPOperandType newType) {
	bool MemSrc = false;
    op_t Opnd;
	set<DefOrUse, LessDefUse>::iterator UseIter;
	for (UseIter = this->GetFirstUse(); UseIter != this->GetLastUse(); ++UseIter) {
		Opnd = UseIter->GetOp();
		optype_t CurrType = Opnd.type;
		MemSrc = ((CurrType == o_mem) || (CurrType == o_phrase) || (CurrType == o_displ));
		if (MemSrc) {
			SMPOperandType type = UseIter->GetType();

			assert(newType == (NUMERIC|PROF_BASE));
			if (type == UNINIT) {
				this->SetUseType(Opnd, newType);
				break;
			}
			else if (type >= POINTER) {
				this->SetUseType(Opnd, (SMPOperandType)(UNKNOWN|PROF_BASE));
				break;
			}
		}
	}
	return ;
} // end of SMPInstr::UpdateMemLoadTypes()

// Return true if we have register DefOp += ImmOp.
bool SMPInstr::MDIsAddImmediateToReg(op_t &DefOp, op_t &ImmOp) {
	bool FoundAddImmed = false;
	bool FoundImmed = false;
	bool FoundRegUse = false;

	if (NN_add == this->SMPcmd.itype) {
		set<DefOrUse, LessDefUse>::iterator UseIter = this->GetFirstUse();
		while (UseIter != this->GetLastUse()) {
			op_t UseOp = UseIter->GetOp();
			if (o_imm == UseOp.type) {
				ImmOp = UseOp;
				FoundImmed = true;
			}
			else if (o_reg == UseOp.type) {
				set<DefOrUse, LessDefUse>::iterator DefIter = this->GetFirstNonFlagsDef();
				op_t TempDefOp = DefIter->GetOp();
				if (o_reg != TempDefOp.type) {
					return false;
				}
				if (MDLessReg(UseOp.reg, TempDefOp.reg) || MDLessReg(TempDefOp.reg, UseOp.reg)) {
					return false;
				}
				// If we make it here, we have the same register DEFed as we found USEd.
				DefOp = TempDefOp;
				FoundRegUse = true;
			}
			++UseIter;
		}
		FoundAddImmed = (FoundImmed && FoundRegUse);
	}
	return FoundAddImmed;
} // end of SMPInstr::MDIsAddImmediateToReg()