Skip to content
Snippets Groups Projects
SMPInstr.cpp 318 KiB
Newer Older
		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->SetOperator(SMP_NULL_OPERATOR);
			this->RTL.push_back(NopRT);
			NopRT = NULL;
			return true;

		case NN_fild:                // Load Integer
		case NN_fist:                // Store Integer
		case NN_fistp:               // Store Integer and Pop
		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);

		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->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.
			NopRT = new SMPRegTransfer;
			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
		case NN_fnop:                // No Operation
			NopRT = new SMPRegTransfer;
			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->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

		//
		//      MMX instructions
		//

		case NN_emms:                // Empty MMX state
		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)
		case NN_packuswb:            // Pack with Unsigned Saturation (Word->Byte)
		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)
		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_EQ_AND_SET);
			break;

		case NN_pmaddwd:             // Packed Multiply and Add
		case NN_pmulhw:              // Packed Multiply High
		case NN_pmullw:              // Packed Multiply Low
		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

		//      Pentium II instructions

		case NN_sysenter:            // Fast Transition to System Call Entry Point
		case NN_sysexit:             // Fast Transition from System Call Entry Point

		//      3DNow! instructions

		case NN_pavgusb:             // Packed 8-bit Unsigned Integer Averaging
		case NN_pfadd:               // Packed Floating-Point Addition
		case NN_pfsub:               // Packed Floating-Point Subtraction
		case NN_pfsubr:              // Packed Floating-Point Reverse Subtraction
		case NN_pfacc:               // Packed Floating-Point Accumulate
		case NN_pfcmpge:             // Packed Floating-Point Comparison: Greater or Equal
		case NN_pfcmpgt:             // Packed Floating-Point Comparison: Greater
		case NN_pfcmpeq:             // Packed Floating-Point Comparison: Equal
		case NN_pfmin:               // Packed Floating-Point Minimum
		case NN_pfmax:               // Packed Floating-Point Maximum
		case NN_pi2fd:               // Packed 32-bit Integer to Floating-Point
		case NN_pf2id:               // Packed Floating-Point to 32-bit Integer
		case NN_pfrcp:               // Packed Floating-Point Reciprocal Approximation
		case NN_pfrsqrt:             // Packed Floating-Point Reciprocal Square Root Approximation
		case NN_pfmul:               // Packed Floating-Point Multiplication
		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
		case NN_pmulhrw:             // Packed Floating-Point 16-bit Integer Multiply with rounding
		case NN_femms:               // Faster entry/exit of the MMX or floating-point state
		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->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
		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
		case NN_cvtpi2ps:            // Packed signed INT32 to Packed Single-FP conversion
		case NN_cvtps2pi:            // Packed Single-FP to Packed INT32 conversion
		case NN_cvtsi2ss:            // Scalar signed INT32 to Single-FP conversion
		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)
		case NN_divps:               // Packed Single-FP Divide
		case NN_divss:               // Scalar Single-FP Divide
		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
		case NN_minps:               // Packed Single-FP Minimum
		case NN_minss:               // Scalar Single-FP Minimum
		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
		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
		case NN_shufps:              // Shuffle Single-FP
		case NN_sqrtps:              // Packed Single-FP Square Root
		case NN_sqrtss:              // Scalar Single-FP Square Root
		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
		case NN_ucomiss:             // Scalar Unordered Single-FP Compare and Set EFLAGS
		case NN_unpckhps:            // Unpack High Packed Single-FP Data
		case NN_unpcklps:            // Unpack Low Packed Single-FP Data
		case NN_xorps:               // Bitwise Logical XOR for Single-FP Data
		case NN_pavgb:               // Packed Average (Byte)
		case NN_pavgw:               // Packed Average (Word)
		case NN_pextrw:              // Extract Word
		case NN_pinsrw:              // Insert Word
		case NN_pmaxsw:              // Packed Signed Integer Word Maximum
		case NN_pmaxub:              // Packed Unsigned Integer Byte Maximum
		case NN_pminsw:              // Packed Signed Integer Word Minimum
		case NN_pminub:              // Packed Unsigned Integer Byte Minimum
		case NN_pmovmskb:            // Move Byte Mask to Integer
			return this->BuildBinaryRTL(SMP_SHUFFLE);
			break;

		case NN_pmulhuw:             // Packed Multiply High Unsigned
		case NN_psadbw:              // Packed Sum of Absolute Differences
		case NN_pshufw:              // Packed Shuffle Word
			return this->BuildBinaryRTL(SMP_SHUFFLE);
			break;

		case NN_maskmovq:            // Byte Mask write
		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->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
		case NN_cmpltps:             // Packed Single-FP Compare LT
		case NN_cmpleps:             // Packed Single-FP Compare LE
		case NN_cmpunordps:          // Packed Single-FP Compare UNORD
		case NN_cmpneqps:            // Packed Single-FP Compare NOT EQ
		case NN_cmpnltps:            // Packed Single-FP Compare NOT LT
		case NN_cmpnleps:            // Packed Single-FP Compare NOT LE
		case NN_cmpordps:            // Packed Single-FP Compare ORDERED
		case NN_cmpeqss:             // Scalar Single-FP Compare EQ
		case NN_cmpltss:             // Scalar Single-FP Compare LT
		case NN_cmpless:             // Scalar Single-FP Compare LE
		case NN_cmpunordss:          // Scalar Single-FP Compare UNORD
		case NN_cmpneqss:            // Scalar Single-FP Compare NOT EQ
		case NN_cmpnltss:            // Scalar Single-FP Compare NOT LT
		case NN_cmpnless:            // Scalar Single-FP Compare NOT LE
		case NN_cmpordss:            // Scalar Single-FP Compare ORDERED

		// AMD K7 instructions

		case NN_pf2iw:               // Packed Floating-Point to Integer with Sign Extend
		case NN_pfnacc:              // Packed Floating-Point Negative Accumulate
		case NN_pfpnacc:             // Packed Floating-Point Mixed Positive-Negative Accumulate
		case NN_pi2fw:               // Packed 16-bit Integer to Floating-Point
		case NN_pswapd:              // Packed Swap Double Word

		// 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
		case NN_ffreep:              // Free Register and Pop
		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
		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
		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
		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
		case NN_cvtpi2pd:            // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values
		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
		case NN_cvtsi2sd:            // Convert Doubleword Integer to Scalar Double-Precision Floating-Point Value
		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
		case NN_divpd:               // Divide Packed Double-Precision Floating-Point Values
		case NN_divsd:               // Divide Scalar Double-Precision Floating-Point Values
		case NN_lfence:              // Load Fence
		case NN_maskmovdqu:          // Store Selected Bytes of Double Quadword
		case NN_maxpd:               // Return Maximum Packed Double-Precision Floating-Point Values
		case NN_maxsd:               // Return Maximum Scalar Double-Precision Floating-Point Value
		case NN_mfence:              // Memory Fence
		case NN_minpd:               // Return Minimum Packed Double-Precision Floating-Point Values
		case NN_minsd:               // Return Minimum Scalar Double-Precision Floating-Point Value
		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
		case NN_paddq:               // Add Packed Quadword Integers
		case NN_pause:               // Spin Loop Hint
		case NN_pmuludq:             // Multiply Packed Unsigned Doubleword Integers
		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
		case NN_subpd:               // Subtract Packed Double-Precision Floating-Point Values
		case NN_subsd:               // Subtract Scalar Double-Precision Floating-Point Values
		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

		// 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
		case NN_lddqu:               // Load unaligned integer 128-bit

		// 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
		case NN_pmaddubsw:           // Multiply and Add Packed Signed and Unsigned Bytes
		case NN_phsubsw:             // Packed Horizontal Subtract and Saturate
		case NN_phaddsw:             // Packed Horizontal Add and Saturate
		case NN_phaddw:              // Packed Horizontal Add Word
		case NN_phaddd:              // Packed Horizontal Add Doubleword
		case NN_phsubw:              // Packed Horizontal Subtract Word
		case NN_phsubd:              // Packed Horizontal Subtract Doubleword
		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

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

		default:
			msg("ERROR: Unknown instruction opcode at %x : %s\n", this->GetAddr(),
				this->GetDisasm());
			break;
	} // end switch on opcode
	return true;
} // end SMPInstr::BuildRTL()

// Iterate through all reg transfers and call SyncRTLDefUse for each.
void SMPInstr::SyncAllRTs(void) {
	for (size_t index = 0; index < this->RTL.GetCount(); ++index) {
		this->SyncRTLDefUse(this->RTL.GetRT(index));
	}
	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) {
	// The Guard expression and ExtraKills are almost never represented in the DEF and USE
	//  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) {
		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
			msg("WARNING: DEF not found for SMP_ASSIGN in %s ; added op:", this->GetDisasm());
			PrintOperand(LeftOp);
			msg("\n");
			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
				msg("WARNING: USE not found for ");
				PrintOperand(LeftOp);
				msg(" in %s ; added\n", this->GetDisasm());
				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
				msg("WARNING: USE not found for ");
				PrintOperand(RightOp);
				msg(" in %s ; added\n", this->GetDisasm());
				this->Uses.SetRef(RightOp);
			}
		}
	}
	else { // recurse into right subtree
		this->SyncRTLDefUse(CurrRT->GetRightTree());
	}
	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

// Update the memory source operands to have the new type
void SMPInstr::UpdateMemLoadTypes(SMPOperandType newType) {
	bool MemSrc = false;
    op_t Opnd;
	for (int i = 0; i < UA_MAXOP; ++i) {
		Opnd = this->SMPcmd.Operands[i];
		optype_t CurrType = Opnd.type;
		if (this->features & UseMacros[i]) { // USE
			MemSrc = ((CurrType == o_mem) || (CurrType == o_phrase) || (CurrType == o_displ));
			if (MemSrc) {
				set<DefOrUse, LessDefUse>::iterator use = this->FindUse(Opnd);
				SMPOperandType type = use->GetType();

				assert(newType == (NUMERIC|PROF_BASE));
				switch (type) {
					case UNINIT:
					case CODEPTR:
						this->SetUseType(Opnd,newType);
						break;
					case POINTER:
						this->SetUseType(Opnd, (SMPOperandType)(UNKNOWN|PROF_BASE));
						break;
					default:
						break;
				}
			}
		}
	}
	return ;
} // end of SMPInstr::UpdateMemLoadTypes()