Newer
Older
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
clc5q
committed
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
clc5q
committed
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
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->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
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->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
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);
case NN_pause: // Spin Loop Hint
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
return false;
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);
// 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
return false;
break;
// Missing AMD64 instructions
case NN_movsxd: // Move with Sign-Extend Doubleword
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
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);
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;
13335
13336
13337
13338
13339
13340
13341
13342
13343
13344
13345
13346
13347
13348
13349
13350
13351
13352
13353
13354
13355
13356
13357
13358
13359
13360
13361
13362
13363
13364
13365
13366
13367
13368
13369
13370
13371
13372
13373
13374
13375
13376
13377
13378
13379
13380
13381
13382
#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
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
case NN_pblendvb: // Variable Blend Packed Bytes
case NN_pblendw: // Blend Packed Words
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);
13402
13403
13404
13405
13406
13407
13408
13409
13410
13411
13412
13413
13414
13415
13416
13417
13418
13419
13420
13421
13422
13423
13424
13425
13426
13427
13428
13429
13430
13431
13432
13433
13434
13435
13436
13437
13438
13439
13440
13441
13442
13443
13444
13445
13446
13447
13448
13449
13450
13451
13452
13453
13454
13455
13456
13457
13458
13459
13460
13461
13462
13463
13464
13465
13466
13467
13468
13469
13470
13471
13472
13473
13474
13475
13476
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
return this->BuildOptType8RTL();
13479
13480
13481
13482
13483
13484
13485
13486
13487
13488
13489
13490
13491
13492
13493
13494
13495
13496
13497
13498
13499
13500
13501
13502
13503
13504
13505
13506
13507
13508
13509
13510
13511
13512
13513
13514
13515
13516
13517
13518
13519
13520
13521
13522
13523
13524
13525
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;
#endif // 599 < IDA_SDK_VERSION
clc5q
committed
SMP_msg("ERROR: Unknown instruction opcode at %x : %s\n", 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) {
clc5q
committed
// 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) {
clc5q
committed
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
clc5q
committed
SMP_msg("WARNING: DEF not found for SMP_ASSIGN in %s ; added op:", DisAsmText.GetDisAsm(this->GetAddr()));
clc5q
committed
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
clc5q
committed
SMP_msg("WARNING: USE not found for ");
clc5q
committed
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
clc5q
committed
SMP_msg("WARNING: USE not found for ");
clc5q
committed
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);
clc5q
committed
13617
13618
13619
13620
13621
13622
13623
13624
13625
13626
13627
13628
13629
13630
13631
13632
13633
13634
13635
// 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 (!IsProfDerived(OldType))
RTop.NonSpeculativeType = OldType;
}
RTop.type = NewType;
} // end of SMPRegTransfer::SetOperatorType
13654
13655
13656
13657
13658
13659
13660
13661
13662
13663
13664
13665
13666
13667
13668
13669
13670
13671
13672
13673
13674
13675
13676
13677
13678
13679
13680
13681
13682
13683
13684
13685
13686
13687
13688
13689
13690
13691
13692
13693
13694
13695
13696
13697
13698
13699
13700
// 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()
clc5q
committed
13726
13727
13728
13729
13730
13731
13732
13733
13734
13735
13736
13737
13738
13739
13740
13741
13742
13743
13744
13745
13746
13747
13748
13749
13750
13751
13752
13753
13754
13755
13756
13757
13758
13759
// 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()