diff --git a/SMPProgram.cpp b/SMPProgram.cpp
index b69e729901e075376238f40e2670a883215a167e..c99aff62dde2aa2db3f482892cbd0488cc7f7981 100644
--- a/SMPProgram.cpp
+++ b/SMPProgram.cpp
@@ -34,10 +34,48 @@
 
 // Set to 1 for debugging output
 #define SMP_DEBUG 1
-#define SMP_DEBUG_GLOBAL_GRANULARITY 0
+#define SMP_DEBUG_GLOBAL_GRANULARITY 1
 
 // Compute fine-grained global static data boundaries?
 #define SMP_COMPUTE_GLOBAL_GRANULARITY 1
+// Distinguish between indexed and direct accesses in global granularity?
+#define SMP_DETECT_INDEXED_ACCESSES 0
+
+// Does the instruction at InstAddr access the global data offset in GlobalAddr
+//  using an index register?
+bool MDIsIndexedAccess(ea_t InstAddr, ea_t GlobalAddr) {
+	int InstLen = ua_ana0(InstAddr);
+	bool DebugFlag = (InstAddr == 0x80502d3);
+#if SMP_DETECT_INDEXED_ACCESSES
+	if (0 >= InstLen)
+#endif
+		return false;
+	for (int i = 0; i < UA_MAXOP; ++i) {
+		op_t CurrOp = cmd.Operands[i];
+		if ((CurrOp.type == o_mem) || (CurrOp.type == o_displ)) {
+			if (GlobalAddr == CurrOp.addr) {
+				if (CurrOp.hasSIB) {
+					// GlobalAddr is referenced, and SIB byte is present, so we might have
+					//  an indexed access to GlobalAddr.
+					regnum_t IndexReg = sib_index(CurrOp);
+					if (R_sp != IndexReg) {
+						// R_sp is a SIB index dummy value; means no index register
+						return true;
+					}
+				}
+				else if (o_displ == CurrOp.type) { // index reg in reg field, not in SIB byte
+					return true;
+				}
+				else if (DebugFlag) {
+					msg("Failed to find index in operand: ");
+					PrintOneOperand(CurrOp, 0, -1);
+					msg("\n");
+				}
+			}
+		}
+	} // end for all operands
+	return false;
+} // end MDIsIndexedAccess()
 
 // *****************************************************************
 // Class SMPProgram
@@ -143,11 +181,21 @@ void SMPProgram::InitStaticDataTable(void) {
 	return;
 } // end of SMPProgram::InitStaticDataTable()
 
+// Find the direct and indexed accesses to offsets within each static data table entry.
+//  Record the offset and kind of access (indexed or not) and conservatively mark the
+//  field boundaries based on the unindexed accesses.
 void SMPProgram::ComputeGlobalFieldOffsets(struct GlobalVar &CurrGlobal) {
 	xrefblk_t xb;
 	ea_t addr;
 	size_t offset;
+	bool DebugFlag = false;
+	DebugFlag |= (0 == strcmp("spec_fd", CurrGlobal.name));
 	for (addr = CurrGlobal.addr; addr < CurrGlobal.addr + CurrGlobal.size; ++addr) {
+		bool Referenced = false;
+		offset = addr - CurrGlobal.addr;
+		pair<size_t, bool> TempOffset;
+		TempOffset.first = offset;
+		TempOffset.second = false; // No indexed accesses seen yet
 		for (bool ok = xb.first_to(addr, XREF_ALL); ok; ok = xb.next_to()) {
 			uchar XrefType = xb.type & XREF_MASK;
 			if (xb.iscode) {
@@ -159,12 +207,13 @@ void SMPProgram::ComputeGlobalFieldOffsets(struct GlobalVar &CurrGlobal) {
 			else {
 				if ((XrefType == dr_O) || (XrefType == dr_W) || (XrefType == dr_R)) {
 #if SMP_DEBUG_GLOBAL_GRANULARITY
-					msg("Data xref to global data at %x from code at %x\n", addr,
-						xb.from);
+					SMPInstr TempInstr(xb.from);
+					TempInstr.Analyze();
+					msg("Data xref to global data %s at %x from code at %x %s\n",
+						CurrGlobal.name, addr, xb.from, TempInstr.GetDisasm());
 #endif
-					offset = addr - CurrGlobal.addr;
-					CurrGlobal.FieldOffsets.insert(offset);
-					continue;  // only need one xref per offset addr to identify offset
+					Referenced = true;
+					TempOffset.second |= MDIsIndexedAccess(xb.from, addr);
 				}
 				else {
 #if SMP_DEBUG_GLOBAL_GRANULARITY
@@ -173,8 +222,11 @@ void SMPProgram::ComputeGlobalFieldOffsets(struct GlobalVar &CurrGlobal) {
 					;
 				}
 			}
+		} // end for (bool ok = iterate through xrefs ...)
+		if (Referenced) {
+			CurrGlobal.FieldOffsets.insert(TempOffset);
 		}
-	}
+	} // end for all addrs in current global
 
 	return;
 } // end of SMPProgram::ComputeGlobalFieldOffsets()
@@ -239,15 +291,27 @@ void SMPProgram::EmitAnnotations(FILE *AnnotFile) {
 	    // Output the name, address, size, and type info.
 		struct GlobalVar TempGlobal = GlobalIter->second;
 		// If we have an offset other than 0 but not 0, add 0 to offsets.
-		if (0 != *(TempGlobal.FieldOffsets.begin())) {
-			TempGlobal.FieldOffsets.insert(0);
+		pair<size_t,bool> FirstOffset = (*(TempGlobal.FieldOffsets.begin()));
+		if (0 != FirstOffset.first) {
+			pair<size_t,bool> TempOffset;
+			TempOffset.first = 0;
+			TempOffset.second = false;
+			TempGlobal.FieldOffsets.insert(TempOffset);
 #if SMP_DEBUG_GLOBAL_GRANULARITY
 			msg("Inserted offset 0 for global var %s\n", TempGlobal.name);
 #endif
 		}
 		unsigned long ParentReferentID = DataReferentID++;
-		// If 0 is the only offset, the data is not structured.
-		if (2 > TempGlobal.FieldOffsets.size()) { // No fields within object
+		bool DirectAccesses = false;  // Any direct field accesses in this global?
+		set<pair<size_t, bool>, LessOff>::iterator CurrOffset;
+		for (CurrOffset = TempGlobal.FieldOffsets.begin(); CurrOffset != TempGlobal.FieldOffsets.end(); ++CurrOffset) {
+			pair<size_t, bool> TempOffset = *CurrOffset;
+			if (!TempOffset.second)
+				DirectAccesses = true;
+		}
+		// If 0 is the only direct offset, the data is not structured.
+		if (!DirectAccesses || (2 > TempGlobal.FieldOffsets.size())) {
+			// No fields within object, or all fields were accessed through indices
 			if (TempGlobal.ReadOnly) {
 				qfprintf(AnnotFile, 
 					"%10x %6d DATAREF GLOBAL %d %x PARENT %s  %s RO\n",
@@ -276,22 +340,30 @@ void SMPProgram::EmitAnnotations(FILE *AnnotFile) {
 					TempGlobal.name, DataTypes[get_optype_flags0(TempGlobal.flags) >> 20]);
 			}
 			// Now, emit an annotation for each field offset.
-			set<size_t>::iterator FieldIter, TempIter;
+			set<pair<size_t,bool>, LessOff>::iterator FieldIter, TempIter;
 			size_t counter = 1;
 			size_t FieldSize;
 			for (FieldIter = TempGlobal.FieldOffsets.begin(); FieldIter != TempGlobal.FieldOffsets.end(); ++FieldIter, ++counter) {
+				pair<size_t,bool> CurrOffset = (*FieldIter);
 				if (counter < TempGlobal.FieldOffsets.size()) {
-					TempIter = ++FieldIter;
-					--FieldIter;
-					FieldSize = (*TempIter) - (*FieldIter);
+					TempIter = FieldIter;
+					++TempIter;
+					pair<size_t,bool> TempOffset = (*TempIter);
+					FieldSize = TempOffset.first - CurrOffset.first;
 				}
 				else {
-					FieldSize = TempGlobal.size - (*FieldIter);
+					FieldSize = TempGlobal.size - CurrOffset.first;
 				}
 				qfprintf(AnnotFile, 
-					"%10x %6d DATAREF GLOBAL %d %x CHILDOF %d OFFSET %d %s + %d FIELD\n",
+					"%10x %6d DATAREF GLOBAL %d %x CHILDOF %d OFFSET %d %s + %d FIELD",
 					0, FieldSize, DataReferentID, TempGlobal.addr, ParentReferentID, 
-					(*FieldIter), TempGlobal.name, *FieldIter);
+					CurrOffset.first, TempGlobal.name, CurrOffset.first);
+				if (CurrOffset.second) { // indexed accesses to this field
+					qfprintf(AnnotFile, " INDEXED\n");
+				}
+				else { // only direct accesses to this field
+					qfprintf(AnnotFile, " DIRECT\n");
+				}
 				++DataReferentID;
 			}
 		} // end if unstructured data ... else ... 
diff --git a/SMPProgram.h b/SMPProgram.h
index f77283da73bcdaf3396f6a4e6233d982700ef65e..9afc9f1e914c3db5cc27f2921d3bd2fe9954cdf1 100644
--- a/SMPProgram.h
+++ b/SMPProgram.h
@@ -24,13 +24,21 @@
 
 using namespace std;
 
+class LessOff {
+public:
+	bool operator()(const pair<size_t, bool> &Off1, const pair<size_t, bool> &Off2) const {
+		return (Off1.first < Off2.first);
+	} // end operator
+}; // end class LessOff
+
 struct GlobalVar {
 	ea_t addr;
 	size_t size;
 	char name[MAXSTR];
 	bool ReadOnly;  // came from read-only data segment type
+	bool IndexedAccess; 
 	flags_t flags;
-	set<size_t> FieldOffsets;
+	set<pair<size_t, bool>, LessOff> FieldOffsets; // bool = accessed through index register by any instruction?
 };
 
 // Class encapsulating all that the SMP static analyzer cares to know