From cc4458765c0202899eec3818b84fd5d24d904a0a Mon Sep 17 00:00:00 2001
From: clc5q <clc5q@git.zephyr-software.com>
Date: Wed, 30 Apr 2008 19:28:31 +0000
Subject: [PATCH] Add functions MDExtractAddressFields, MDIsIndirectMemoryOpnd,
 and DefOrUseSet::TypesAgreeNoFlags.

---
 SMPDataFlowAnalysis.cpp | 106 +++++++++++++++++++++++++++++++++++++++-
 SMPDataFlowAnalysis.h   |   9 +++-
 2 files changed, 113 insertions(+), 2 deletions(-)

diff --git a/SMPDataFlowAnalysis.cpp b/SMPDataFlowAnalysis.cpp
index e1c9f610..c8f5cb6a 100644
--- a/SMPDataFlowAnalysis.cpp
+++ b/SMPDataFlowAnalysis.cpp
@@ -145,6 +145,89 @@ void SetGlobalIndex(op_t *TempOp, size_t index) {
 	return;
 }
 
+// Return true if CurrOp could be an indirect memory reference.
+bool MDIsIndirectMemoryOpnd(op_t CurrOp, bool UseFP) {
+	bool indirect = false;
+	if ((CurrOp.type != o_mem) && (CurrOp.type != o_phrase) && (CurrOp.type != o_displ))
+		return false;
+
+	if (CurrOp.hasSIB) {
+		int BaseReg = sib_base(CurrOp);
+		short IndexReg = sib_index(CurrOp);
+		if ((R_none != IndexReg) && (R_sp != IndexReg)) { 
+			if ((R_bp == IndexReg) && UseFP)
+				;
+			else
+				indirect = true;
+		}
+		if (0 != sib_scale(CurrOp))
+			indirect = true;
+		if (R_none != BaseReg) {
+			if ((BaseReg == R_bp) && (CurrOp.type == o_mem)) {
+				; // EBP ==> no base register for o_mem type
+			}
+			else if ((BaseReg == R_bp) && UseFP) 
+				;  // EBP used as frame pointer for direct access
+			else if (BaseReg == R_sp)
+				;  // ESP used as stack pointer for direct access
+			else
+				indirect = true; // conservative; some register used for addressing
+								// other than a stack or frame pointer
+		}
+	} // end if hasSIB
+	else { // no SIB; can have base register only
+		ushort BaseReg = CurrOp.reg;
+		if (CurrOp.type == o_mem) { // no base register for o_mem
+			if (!((0 == BaseReg) || (R_bp == BaseReg))) {
+				msg("base reg %d ignored \n", BaseReg);
+			}
+		}
+		else if ((BaseReg == R_bp) && UseFP) 
+			;  // EBP used as frame pointer for direct access
+		else if (BaseReg == R_sp)
+			;  // ESP used as stack pointer for direct access
+		else {
+			indirect = true;
+		}
+	}
+
+	return indirect;
+} // end MDIsIndirectMemoryOpnd()
+
+// Extract the base and index registers and scale factor and displacement from the
+//  memory operand.
+void MDExtractAddressFields(op_t MemOp, int &BaseReg, int &IndexReg, ushort &Scale, ea_t &Offset) {
+	assert((MemOp.type == o_phrase) || (MemOp.type == o_displ) || (MemOp.type == o_mem));
+
+	Scale = 0;
+	BaseReg = R_none;
+	IndexReg = R_none;
+	Offset = MemOp.addr;
+
+	if (MemOp.hasSIB) {
+		BaseReg = sib_base(MemOp);
+		IndexReg = (int) sib_index(MemOp);
+		if (R_sp == IndexReg) // signifies no index register
+			IndexReg = R_none;
+		if (R_none != IndexReg) {
+			Scale = sib_scale(MemOp);
+		}
+		if (R_none != BaseReg) {
+			if ((BaseReg == R_bp) && (MemOp.type == o_mem)) {
+				BaseReg = R_none;
+			}
+		}
+	}
+	else { // no SIB byte; can have base reg but no index reg or scale factor
+		BaseReg = (int) MemOp.reg;  // cannot be R_none for no SIB case
+		if (MemOp.type == o_mem) {
+			BaseReg = R_none; // no Base register for o_mem operands
+		}
+	}
+
+	return;
+} // end of MDExtractAddressFields()
+
 // DEBUG Print DEF and/or USE for an operand.
 void PrintDefUse(ulong feature, int OpNum) {
 	// CF_ macros number the operands from 1 to 6, while OpNum
@@ -425,7 +508,7 @@ set<DefOrUse, LessDefUse>::iterator DefOrUseSet::SetType(op_t CurrOp, SMPOperand
 #if 1
 	if (o_imm == CurrOp.type) {
 		if (UNINIT != CurrRef->GetType()) {
-			msg("ERROR: Changing type of immediate to %d : ", Type);
+			msg("ERROR: Changing type of immediate from %d to %d : ", CurrRef->GetType(), Type);
 			CurrRef->Dump();
 			msg("\n");
 		}
@@ -451,6 +534,27 @@ void DefOrUseSet::Dump(void) {
 	return;
 }
 
+// Do all types agree, ignoring any flags registers in the set?
+bool DefOrUseSet::TypesAgreeNoFlags(void) {
+	bool FoundFirstUse = false;
+	set<DefOrUse, LessDefUse>::iterator CurrUse;
+	SMPOperandType UseType = UNINIT;
+	for (CurrUse = this->Refs.begin(); CurrUse != this->Refs.end(); ++CurrUse) {
+		if (!(CurrUse->GetOp().is_reg(X86_FLAGS_REG))) { // ignore flags
+			if (!FoundFirstUse) {
+				FoundFirstUse = true;
+				UseType = CurrUse->GetType();
+			}
+			else {
+				if (CurrUse->GetType() != UseType) {
+					return false; // inconsistent types
+				}
+			}
+		}
+	}
+	return true;
+} // end of DefOrUseSet::TypesAgreeNoFlags()
+
 
 // *****************************************************************
 // Class DefOrUseList
diff --git a/SMPDataFlowAnalysis.h b/SMPDataFlowAnalysis.h
index ce060987..092e6c46 100644
--- a/SMPDataFlowAnalysis.h
+++ b/SMPDataFlowAnalysis.h
@@ -43,6 +43,12 @@ void PrintOneOperand(op_t Opnd, ulong features, int OpNum);
 void PrintListOperand(op_t Opnd, int SSANum = SMP_SSA_UNINIT); 
 void PrintOperand(op_t Opnd);
 
+// MACHINE DEPENDENT: Could operand be an indirect memory access?
+bool MDIsIndirectMemoryOpnd(op_t CurrOp, bool UseFP);
+
+// MACHINE DEPENDENT: Get base and index registers and displacement/addr from operand.
+void MDExtractAddressFields(op_t MemOp, int &BaseReg, int &IndexReg, ushort &Scale, ea_t &Offset);
+
 // MACHINE DEPENDENT: Is operand type a known type that we want to analyze?
 bool MDKnownOperandType(op_t TempOp);
 
@@ -107,7 +113,7 @@ enum SMPitype {
 	INDIR_JUMP = 16, // indirect unconditional branch,
 	CALL = 32,       // direct call
 	INDIR_CALL = 64, // indirect call
-	RETURN = 128,    // function return
+	RETURN = 128,    // function return OR TAIL CALL
 	HALT = 256       // execution stops
 };
 
@@ -186,6 +192,7 @@ public:
 	// Printing methods
 	void Dump(void);
 	// Analysis methods
+	bool TypesAgreeNoFlags(void); // Are all types consistent, ignoring flags registers?
 private:
 	// Data
 	set<DefOrUse, LessDefUse> Refs;  // Defined or used operand with type and SSA subscript
-- 
GitLab