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

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

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

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

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

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

		// Missing AMD64 instructions

		case NN_movsxd:              // Move with Sign-Extend Doubleword
		case NN_cmpxchg16b:          // Compare and Exchange 16 Bytes

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

		// 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
		case NN_cmpltpd:             // Packed Double-FP Compare LT
		case NN_cmplepd:             // Packed Double-FP Compare LE
		case NN_cmpunordpd:          // Packed Double-FP Compare UNORD
		case NN_cmpneqpd:            // Packed Double-FP Compare NOT EQ
		case NN_cmpnltpd:            // Packed Double-FP Compare NOT LT
		case NN_cmpnlepd:            // Packed Double-FP Compare NOT LE
		case NN_cmpordpd:            // Packed Double-FP Compare ORDERED
		case NN_cmpeqsd:             // Scalar Double-FP Compare EQ
		case NN_cmpltsd:             // Scalar Double-FP Compare LT
		case NN_cmplesd:             // Scalar Double-FP Compare LE
		case NN_cmpunordsd:          // Scalar Double-FP Compare UNORD
		case NN_cmpneqsd:            // Scalar Double-FP Compare NOT EQ
		case NN_cmpnltsd:            // Scalar Double-FP Compare NOT LT
		case NN_cmpnlesd:            // Scalar Double-FP Compare NOT LE
		case NN_cmpordsd:            // Scalar Double-FP Compare ORDERED
			return false;
			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
		case NN_dppd:                 // Dot Product of Packed Double Precision Floating-Point Values
		case NN_dpps:                 // Dot Product of Packed Single Precision Floating-Point Values
		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
		case NN_pblendvb:             // Variable Blend Packed Bytes
		case NN_pblendw:              // Blend Packed Words
		case NN_pcmpeqq:              // Compare Packed Qword Data for Equal
		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
		case NN_pmaxud:               // Maximum of Packed Unsigned Dword Integers
		case NN_pmaxuw:               // Maximum of Packed Word Integers
		case NN_pminsb:               // Minimum of Packed Signed Byte Integers
		case NN_pminsd:               // Minimum of Packed Signed Dword Integers
		case NN_pminud:               // Minimum of Packed Unsigned Dword Integers
		case NN_pminuw:               // Minimum of Packed Word Integers
		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
		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
		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
		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);
			SMP_msg("ERROR: Unknown instruction opcode at %x : %s\n", this->GetAddr(),
				DisAsmText.GetDisAsm(this->GetAddr()));
			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()));
		SMP_msg("SyncRTLDefUse entered. Dump of USE list:\n");
	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);
			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
				PrintOperand(LeftOp);
				SMP_msg(" in %s ; added\n", DisAsmText.GetDisAsm(this->GetAddr()));
				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
				PrintOperand(RightOp);
				SMP_msg(" in %s ; added\n", DisAsmText.GetDisAsm(this->GetAddr()));
				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()