diff --git a/SMPInstr.cpp b/SMPInstr.cpp
index 18411c253e34bc3384a5dc8d11d771e2f495cee6..419540c02b1dc59225ee052e2d0e523ce2b4d34a 100644
--- a/SMPInstr.cpp
+++ b/SMPInstr.cpp
@@ -1324,8 +1324,11 @@ bool SMPInstr::InferOperatorType(SMPRegTransfer *CurrRT) {
 	bool LeftPointer, RightPointer;
 	set<DefOrUse, LessDefUse>::iterator CurrDef;
 	set<DefOrUse, LessDefUse>::iterator CurrUse;
+	set<DefOrUse, LessDefUse>::iterator LeftUse;
+	set<DefOrUse, LessDefUse>::iterator RightUse;
 	SMPOperandType LeftType = UNINIT;
 	SMPOperandType RightType = UNINIT;
+	SMPOperandType OperType = UNINIT;
 	op_t UseOp, DefOp, LeftOp, RightOp;
 	SMPoperator CurrOp = CurrRT->GetOperator();
 	bool DebugFlag = false;
@@ -1490,7 +1493,6 @@ bool SMPInstr::InferOperatorType(SMPRegTransfer *CurrRT) {
 			break;
 
 		case SMP_ADD:
-		case SMP_SUBTRACT:
 		case SMP_BITWISE_AND:
 		case SMP_BITWISE_OR:
 			// Extract the current types of right and left operands and the operator.
@@ -1578,10 +1580,6 @@ bool SMPInstr::InferOperatorType(SMPRegTransfer *CurrRT) {
 						// We assume (A-B) is being added to B or vice versa **!!**
 						CurrRT->SetOperatorType(POINTER);
 					}
-					else if (SMP_SUBTRACT == CurrOp) {
-						// We assume B - (B - A) == A    **!!**
-						CurrRT->SetOperatorType(POINTER);
-					}
 					else { // bitwise AND or OR of pointer and pointer difference
 						msg("WARNING: hash of PTROFFSET and POINTER at %x in %s\n",
 							this->GetAddr(), this->GetDisasm());
@@ -1619,6 +1617,130 @@ bool SMPInstr::InferOperatorType(SMPRegTransfer *CurrRT) {
 			}
 			break;
 
+		case SMP_SUBTRACT:
+			// Extract the current types of right and left operands and the operator.
+			OperType = CurrRT->GetOperatorType();
+			LeftOp = CurrRT->GetLeftOperand();
+			LeftUse = this->Uses.FindRef(LeftOp);
+			assert(LeftUse != this->GetLastUse()); // found it
+			LeftType = LeftUse->GetType();
+			if (CurrRT->HasRightSubTree()) {
+				RightType = CurrRT->GetRightTree()->GetOperatorType();
+			}
+			else {
+				RightOp = CurrRT->GetRightOperand();
+				if (o_void == RightOp.type) {
+					msg("ERROR: void operand in %s\n", this->GetDisasm());
+					return false;
+				}
+				else {
+					RightUse = this->Uses.FindRef(RightOp);
+					if (RightUse == this->GetLastUse()) {
+						msg("WARNING: Adding missing USE of ");
+						PrintOperand(RightOp);
+						msg(" in %s\n", this->GetDisasm());
+						this->Uses.SetRef(RightOp);
+						updated = true;
+						break;
+					}
+					else {
+						RightType = RightUse->GetType();
+					}
+				}
+			}
+			// If left operand is NUMERIC, operator is NUMERIC.
+			LeftNumeric = (NUMERIC == LeftType);
+			RightNumeric = (NUMERIC == RightType);
+			LeftPointer = ((LeftType >= POINTER) && (LeftType <= HEAPPTR));
+			RightPointer = ((RightType >= POINTER) && (RightType <= HEAPPTR));
+			if (LeftNumeric) {
+				// Subtracting anything from a NUMERIC leaves it NUMERIC.
+				if (UNINIT == OperType) {
+					CurrRT->SetOperatorType(NUMERIC);
+					updated = true;
+				}
+				else if (NUMERIC != OperType) {
+					msg("ERROR: SMP_SUBTRACT from NUMERIC should be NUMERIC operator.");
+					msg(" Operator type is %d in: %s\n", OperType, this->GetDisasm());
+				}
+				if (!RightNumeric) {
+					// Right operand is being used as a NUMERIC, so propagate NUMERIC to it.
+					if (CurrRT->HasRightSubTree()) {
+						CurrRT->GetRightTree()->SetOperatorType(NUMERIC);
+					}
+					else {
+						RightUse = this->SetUseType(RightOp, NUMERIC);
+					}
+					updated = true;
+				}
+			} // end if LeftNumeric
+			else if (LeftPointer) {
+				if (UNINIT == OperType) {
+					// If we subtract another pointer type, we produce PTROFFSET.
+					if (RightPointer) {
+						CurrRT->SetOperatorType(PTROFFSET);
+						updated = true;
+					}
+					else if (RightType == PTROFFSET) {
+						// We assume B - (B - A) == A    **!!**
+						CurrRT->SetOperatorType(POINTER);
+						msg("WARNING: PTR - PTROFFSET produces PTR in %s\n", this->GetDisasm());
+						updated = true;
+					}
+					else if (RightNumeric) {
+						// pointer minus NUMERIC keeps same pointer type
+						CurrRT->SetOperatorType(LeftType);
+						updated = true;
+					}
+				}
+				else { // we have an operator type for the SMP_SUBTRACT
+					bool OperatorPointer = ((OperType >= POINTER) && (OperType <= HEAPPTR));
+					if (CurrRT->HasRightSubTree()) {
+						// Must need to iterate through the right tree again, as the operator
+						//  has been typed.
+						if (UNINIT == RightType) {
+							if (OperatorPointer) {
+								// PTR := PTR - ?? ==> ?? is NUMERIC
+								CurrRT->GetRightTree()->SetOperatorType(NUMERIC);
+								updated = true;
+							}
+							else if (OperType == PTROFFSET) {
+								// PTROFFSET := PTR - ?? ==? ?? is PTR
+								CurrRT->GetRightTree()->SetOperatorType(LeftType);
+								updated = true;
+							}
+						}
+						updated |= this->InferOperatorType(CurrRT->GetRightTree());
+						break;
+					}
+					else { // right operand; propagate operator type if needed
+						if (UNINIT == RightType) {
+							if (OperatorPointer) {
+								// PTR := PTR - ?? ==> ?? is NUMERIC
+								RightUse = this->SetUseType(RightOp, NUMERIC);
+								updated = true;
+								assert(RightUse != this->GetLastUse());
+							}
+							else if (OperType == PTROFFSET) {
+								// PTROFFSET := PTR - ?? ==? ?? is PTR
+								RightUse = this->SetUseType(RightOp, LeftType);
+								updated = true;
+							}
+							break;
+						}
+					}
+				} // end if OperType is UNINIT ... else ...
+			} // end if LeftNumeric ... else if LeftPointer ...
+			else if (UNINIT == LeftType) {
+				if (UNINIT != OperType) {
+					LeftUse = this->SetUseType(LeftOp, OperType);
+					assert(LeftUse != this->GetLastUse());
+					updated = true;
+				}
+			}
+			break;
+
+
 		case SMP_ASSIGN:
 			// Extract the current types of right and left operands and SMP_ASSIGN operator.
 			DefOp = CurrRT->GetLeftOperand();