diff --git a/include/interfaces/irdb/STARSOp.h b/include/interfaces/irdb/STARSOp.h
index b1e333f864633b9a18874787ca6441c4a8614e98..665f9af03b70f47a9eccead757eaa826d99bed39 100644
--- a/include/interfaces/irdb/STARSOp.h
+++ b/include/interfaces/irdb/STARSOp.h
@@ -111,14 +111,16 @@ class STARS_IRDB_op_t : public STARS_op_t
 		virtual uint16_t GetSegReg(void) const { return SegReg;  } // Get segment register of operand; R_none if no segment register
 
 		// return SIB byte if exists.
-		virtual char GetSIB(void) const { return SIB; } // Get x86 SIB byte (dense encoding of base reg, index reg, and scale factor)
+		 // Get x86 SIB byte (dense encoding of base reg, index reg, and scale factor)
+		virtual char GetSIB(void) const;
+
 		virtual int MDGetSIBBaseReg(void) const { return operand.mem.base;  } // Get x86 SIB byte base register
 		virtual short MDGetSIBIndexReg(void) const { return operand.mem.index; } // Get x86 SIB byte index register
 		virtual int GetSIBScaleFactor(void) const { return operand.mem.scale; } // Extract scale factor from SIB byte
 
 		// clc to investigate removing need for this function in base class
 		// probably will still use in STARS_IDA_Op_t.
-		virtual char GetSpecFlag4(void) const { assert(0); } // Get specflag4 byte, used to hold a copy of the auxpref byte in x86-64 programs.
+		virtual char GetSpecFlag4(void) const { return 0; } // Get specflag4 byte, used to hold a copy of the auxpref byte in x86-64 programs.
 
 		// Get value field for immediate operands; uint32 for x86-32, uint64 for x86-64
 		virtual STARS_uval_t GetImmedValue(void) const { assert(OpType==op_Imm);  return operand.imm.imm; } 
@@ -140,10 +142,10 @@ class STARS_IRDB_op_t : public STARS_op_t
 
 		virtual void SetReg(uint16_t NewReg) { assert(OpType==op_Reg); operand.reg.RegNum=(STARS_RegNo)NewReg; }
 		virtual void SetAddr(STARS_ea_t NewAddr) { assert(OpType==op_Mem); operand.mem.disp=NewAddr; }
-		virtual void SetSIB(char value) { assert(OpType==op_Mem); operand.mem.sib_byte=value;  operand.mem.hasSIB=true; }
+		virtual void SetSIB(char value);
 
 		// clc to review, going away?
-		virtual void SetSpecFlag4(char value) { assert(0); }
+		virtual void SetSpecFlag4(char value) { /* intentionally empty */ }
 		virtual void SetBitInSpecFlag4(char value) { assert(0); } // OR in the value to set a bit
 
 		
@@ -232,8 +234,7 @@ class STARS_IRDB_op_t : public STARS_op_t
 
 		STARS_RegNo SegReg;
 		int byteWidth;
-		char hasSIB:1;
-		char SIB;
+		char AuxPrefix4; // REX byte.
 
 		enum OperandType_t { op_Reg, op_Mem, op_Imm, op_Void, op_CrReg, op_DrReg, op_Eflags, op_MMXReg, op_XMMReg, op_YMMReg, op_FPReg, op_Mxcsr, op_SegReg, op_Addr } OpType;
 		union 
@@ -246,10 +247,9 @@ class STARS_IRDB_op_t : public STARS_op_t
 			{
 				STARS_RegNo base;
 				STARS_RegNo index;
-				int scale:2;	
+				unsigned int scale:4;	 // can take values 0, 1, 2, 4, 8.
 				libIRDB::virtual_offset_t disp;	// may be 64-bit imm in some x86-64 instructions.
 				bool hasSIB:1;
-				unsigned char sib_byte;
 			} mem;
 			struct 
 			{
@@ -276,8 +276,6 @@ class STARS_IRDB_op_t : public STARS_op_t
 
 			visible=0;
 			byteWidth=0;
-			hasSIB=0;
-			SIB=0;
 		}
 
 			
diff --git a/src/base/SMPDataFlowAnalysis.cpp b/src/base/SMPDataFlowAnalysis.cpp
index 2dc07efae8cff6f0002bcc8ceea3f68859d7eed4..8cf77931bee52d1ada07e2a48fe52b1bd231d3b2 100644
--- a/src/base/SMPDataFlowAnalysis.cpp
+++ b/src/base/SMPDataFlowAnalysis.cpp
@@ -328,40 +328,24 @@ bool MDIsGeneralPurposeReg(const STARSOpndTypePtr &CurrOp) {
 }
 
 // Are operands equal?
-bool IsEqOp(const STARSOpndTypePtr &Opnd1, const STARSOpndTypePtr &Opnd2) {
+bool IsEqOp(const STARSOpndTypePtr &Opnd1, const STARSOpndTypePtr &Opnd2) 
+{
+	if ((nullptr == Opnd1) && (nullptr == Opnd2))
+		return true;
 	if ((nullptr == Opnd1) || (nullptr == Opnd2))
 		return false;
 
-	if (Opnd1->GetOpType() != Opnd2->GetOpType())
-		return false;
+	// this expression is logically equiv. to "equal"
+	//
+	// truth table:
+	//  
+	//   O1 O2  O1<O2 !(O1<O2) O2<O1 !(O2<O1)  !(O1<O2)&&!(O2<O1) ==
+        //    0  0      0        1     0        1                   1  1
+        //    0  1      1        0     0        0                   0  0
+        //    1  0      0        1     1        0                   0  0
+        //    1  1      0        1     0        0                   1  1
+	return !(*Opnd1 < *Opnd2) && !(*Opnd2 < *Opnd1);
 
-	if (Opnd1->IsVoidOp())
-		return true;
-	if (Opnd1->IsRegOp())
-		return ((Opnd1->GetReg() == Opnd2->GetReg()) && (Opnd1->GetByteWidth() == Opnd2->GetByteWidth()));
-	if (Opnd1->IsStaticMemOp())
-		return (Opnd1->GetAddr() == Opnd2->GetAddr());
-	if (Opnd1->IsMemNoDisplacementOp()) {
-		if (Opnd1->HasSIBByte() && Opnd2->HasSIBByte()) return ((Opnd1->GetSIB() == Opnd2->GetSIB()) && (Opnd1->GetSpecFlag4() == Opnd2->GetSpecFlag4()));
-		else if (Opnd1->HasSIBByte() || Opnd2->HasSIBByte()) return false; // no SIB != has SIB
-		else return (Opnd1->GetReg() == Opnd2->GetReg()); // neither has SIB; compare register, e.g. [ebx] to [edx]
-	}
-	if (Opnd1->IsMemDisplacementOp()) {
-		if (Opnd1->HasSIBByte() && Opnd2->HasSIBByte())
-			return ((Opnd1->GetSIB() == Opnd2->GetSIB()) && (Opnd1->GetAddr() == Opnd2->GetAddr()) && (Opnd1->GetSpecFlag4() == Opnd2->GetSpecFlag4()));
-		else if ((!Opnd1->HasSIBByte()) && (!Opnd2->HasSIBByte()))
-			return ((Opnd1->GetAddr() == Opnd2->GetAddr()) && (Opnd1->GetReg() == Opnd2->GetReg()));
-		else return false; // no SIB != has SIB
-	}
-	if (Opnd1->IsImmedOp())
-		return (Opnd1->GetImmedValue() == Opnd2->GetImmedValue());
-	if (Opnd1->IsFarPointer() || Opnd1->IsNearPointer())
-		return (Opnd1->GetAddr() == Opnd2->GetAddr());
-	if (Opnd1->MDIsKnownOpType()) // compare regs for all special-register cases, e.g. MMX, XMM, YMM, debug regs, etc.
-		return (Opnd1->GetReg() == Opnd2->GetReg()); // no subword regs to deal with
-
-	SMP_msg("ERROR: Unknown operand type in IsEqOp.\n"); 
-	return false;
 } // end of function IsEqOp()
 
 // Are operands equal, ignoring bitwidth differences for register operands?
diff --git a/src/interfaces/irdb/STARS_IRDB_Op.cpp b/src/interfaces/irdb/STARS_IRDB_Op.cpp
index 1900ffede6f983aed3d322141a8274c1d9518ebf..cf15cb62b108f6e1d84a953a8e12b564a77d423c 100644
--- a/src/interfaces/irdb/STARS_IRDB_Op.cpp
+++ b/src/interfaces/irdb/STARS_IRDB_Op.cpp
@@ -5,19 +5,28 @@
 
 using namespace std;
 
-static int log2int(int index)
+static int log2int(unsigned int index)
 {
+	assert(index>0);
 	int targetlevel = 0;
 	while (index >>= 1) ++targetlevel;
 	return  targetlevel;
 }
 
 
+static int log2int_or_err(unsigned int index)
+{
+	if(index==0)
+		return -1;
+	return log2int(index);
+}
+
 
 STARS_IRDB_op_t::STARS_IRDB_op_t(const DISASM &d, int indx, const ARGTYPE &the_arg)
 {
 	Init(); // make void
-	int bea_regno=log2int(the_arg.ArgType&0xFFFF);
+	int bea_regno=bea_regno=log2int_or_err(the_arg.ArgType&0xFFFF);
+
 	visible=1;
 	switch((the_arg.ArgType&0xFFFF0000))
 	{
@@ -44,7 +53,7 @@ STARS_IRDB_op_t::STARS_IRDB_op_t(const DISASM &d, int indx, const ARGTYPE &the_a
 			else 
 			{
 				// set the operand.reg.RegNum appropriately.
-				operand.reg.RegNum=(STARS_RegNo)(STARS_x86_R_ax+bea_regno);
+				operand.reg.RegNum=(STARS_RegNo)(STARS_x86_R_ax+bea_regno);		// regno may be -1, but ax-1==none, which is right.
 
 				// if the first character is an r, it's a 64-bit reg.
 				// e.g. rax, rsp, rdi
@@ -67,11 +76,13 @@ STARS_IRDB_op_t::STARS_IRDB_op_t(const DISASM &d, int indx, const ARGTYPE &the_a
   		case REGISTER_TYPE + MMX_REG :
 			byteWidth=8;
 			OpType=op_MMXReg;
+			assert(bea_regno!=-1);
 			operand.reg.RegNum=(STARS_RegNo)(STARS_x86_R_mm0+bea_regno);
 			break;
   		case REGISTER_TYPE + FPU_REG :
 			byteWidth=8;
 			OpType=op_MMXReg;
+			assert(bea_regno!=-1);
 			operand.reg.RegNum=(STARS_RegNo)(STARS_x86_R_st0+bea_regno);
 			break;
   		case REGISTER_TYPE + SSE_REG :
@@ -79,6 +90,7 @@ STARS_IRDB_op_t::STARS_IRDB_op_t(const DISASM &d, int indx, const ARGTYPE &the_a
 			{
 				byteWidth=8;
 				OpType=op_XMMReg;
+				assert(bea_regno!=-1);
 				operand.reg.RegNum=(STARS_RegNo)(STARS_x86_R_xmm0+bea_regno);
 				break;
 			}
@@ -86,6 +98,7 @@ STARS_IRDB_op_t::STARS_IRDB_op_t(const DISASM &d, int indx, const ARGTYPE &the_a
 			{
 				byteWidth=16;
 				OpType=op_YMMReg;
+				assert(bea_regno!=-1);
 				operand.reg.RegNum=(STARS_RegNo)(STARS_x86_R_ymm0+bea_regno);
 				break;
 			}
@@ -135,16 +148,39 @@ no operands for eflags or mxcsr?
 			break;
   		case REGISTER_TYPE + SEGMENT_REG :
 			OpType=op_SegReg;
+			assert(bea_regno!=-1);
 			operand.reg.RegNum=(STARS_RegNo)(STARS_x86_R_es+bea_regno);
 			break;
   		case MEMORY_TYPE:
   		case MEMORY_TYPE + RELATIVE_:
   		case MEMORY_TYPE + ABSOLUTE_:
 		{
-			operand.mem.base=(STARS_RegNo)log2int(the_arg.Memory.BaseRegister);
-			operand.mem.index=(STARS_RegNo)log2int(the_arg.Memory.IndexRegister);
+			// log2int_or_err returns -1 if the value is 0 (since you can't log2(0)
+			// which maps nicely to STARS_NN_None for no-register.
+			operand.mem.base=(STARS_RegNo)log2int_or_err(the_arg.Memory.BaseRegister);
+			operand.mem.index=(STARS_RegNo)log2int_or_err(the_arg.Memory.IndexRegister);
 			operand.mem.scale=the_arg.Memory.Scale;
+			assert(operand.mem.scale==the_arg.Memory.Scale);
 			operand.mem.disp=the_arg.Memory.Displacement;
+
+			// if there's no base reg, and an index reg with scale==1,
+			// ida represents this oddly as a base with no sib.
+			if(operand.mem.base ==  STARS_x86_R_none && operand.mem.scale==1 && operand.mem.index!=STARS_x86_R_none)
+			{
+				// change representation.
+				operand.mem.base=operand.mem.index;
+				operand.mem.index=STARS_x86_R_none;
+				operand.mem.scale=0;
+			}
+
+			// if the scale >0, we have a sib byte.
+			if(operand.mem.scale > 0)
+				operand.mem.hasSIB=1;
+			// if there's both a base and an index, then there's a sib byte.
+			if(operand.mem.base != STARS_x86_R_none && operand.mem.index != STARS_x86_R_none)
+				operand.mem.hasSIB=1;
+
+
 			byteWidth=the_arg.ArgSize;
 			OpType=op_Mem;
 			break;
@@ -246,3 +282,33 @@ bool STARS_IRDB_op_t::operator<(const STARS_op_t &rOp_param) const
 			
 	}
 }
+
+char STARS_IRDB_op_t::GetSIB(void) const
+{
+	char ret=0;
+	ret|=((int)operand.mem.base&0x7)<<0;
+	ret|=((int)operand.mem.index&0x7)<<3;
+	ret|=(log2int((int)operand.mem.scale)&0x3)<<6;
+	return ret;
+} // Get x86 SIB byte (dense encoding of base reg, index reg, and scale factor)
+
+
+void STARS_IRDB_op_t::SetSIB(char value)
+{
+	assert(OpType==op_Mem);
+	operand.mem.hasSIB=true;
+
+	// update the base register.  Odd casting to avoid compiler error bcause base is a STARS_RegNo
+	(*(int*)&operand.mem.base)&=0x7;
+	(*(int*)&operand.mem.base)|=(value&0x7);
+
+	// Set scale.  Odd casting to avoid compiler error bcause base is a STARS_RegNo
+	(*(int*)&operand.mem.index)&=(0x7<<3);
+	(*(int*)&operand.mem.index)|=(value>>3)&0x7;
+
+	// set scale
+	operand.mem.scale= (STARS_RegNo)1<<((value>>6)&0x3);
+	if(operand.mem.index==STARS_x86_R_sp)
+		operand.mem.scale=(STARS_RegNo)0;
+}
+