Newer
Older
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
case NN_fisttp: // Store ST in intXX (chop) and pop
case NN_lddqu: // Load unaligned integer 128-bit
return false;
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
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
return false;
break;
case NN_palignr: // Packed Align Right
return this->BuildPackShiftRTL(SMP_CONCATENATE, SMP_REVERSE_SHIFT_U);
break;
case NN_pabsb: // Packed Absolute Value Byte
case NN_pabsw: // Packed Absolute Value Word
case NN_pabsd: // Packed Absolute Value Doubleword
return false;
break;
11107
11108
11109
11110
11111
11112
11113
11114
11115
11116
11117
11118
11119
11120
11121
11122
11123
// 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:
clc5q
committed
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 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) {
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);
}
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
// 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
11245
11246
11247
11248
11249
11250
11251
11252
11253
11254
11255
11256
11257
11258
11259
11260
11261
11262
11263
11264
11265
11266
11267
11268
11269
11270
11271
11272
11273
11274
11275
11276
11277
11278
// 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()