Skip to content
Snippets Groups Projects
SMPInstr.cpp 373 KiB
Newer Older
		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:
			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(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()));
		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());
	}
	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()

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