Automated import from //branches/master/...@142073,142073
diff --git a/dexdump/DexDump.c b/dexdump/DexDump.c
index 879288b..9929264 100644
--- a/dexdump/DexDump.c
+++ b/dexdump/DexDump.c
@@ -1060,6 +1060,45 @@
     return (u1*) (((int) ptr + 3) & ~0x03);
 }
 
+
+/*
+ * Dump a map in the "differential" format.
+ *
+ * TODO: show a hex dump of the compressed data.  (We can show the
+ * uncompressed data if we move the compression code to libdex; otherwise
+ * it's too complex to merit a fast & fragile implementation here.)
+ */
+void dumpDifferentialCompressedMap(const u1** pData)
+{
+    const u1* data = *pData;
+    const u1* dataStart = data -1;      // format byte already removed
+    u1 regWidth;
+    u2 numEntries;
+
+    /* standard header */
+    regWidth = *data++;
+    numEntries = *data++;
+    numEntries |= (*data++) << 8;
+
+    /* compressed data begins with the compressed data length */
+    int compressedLen = readUnsignedLeb128(&data);
+    int addrWidth = 1;
+    if ((*data & 0x80) != 0)
+        addrWidth++;
+
+    int origLen = 4 + (addrWidth + regWidth) * numEntries;
+    int compLen = (data - dataStart) + compressedLen;
+
+    printf("        (differential compression %d -> %d [%d -> %d])\n",
+        origLen, compLen,
+        (addrWidth + regWidth) * numEntries, compressedLen);
+
+    /* skip past end of entry */
+    data += compressedLen;
+
+    *pData = data;
+}
+
 /*
  * Dump register map contents of the current method.
  *
@@ -1090,9 +1129,13 @@
         addrWidth = 1;
     } else if (format == 3) {       /* kRegMapFormatCompact16 */
         addrWidth = 2;
+    } else if (format == 4) {       /* kRegMapFormatDifferential */
+        dumpDifferentialCompressedMap(&data);
+        goto bail;
     } else {
         printf("        (unknown format %d!)\n", format);
-        addrWidth = -1;
+        /* don't know how to skip data; failure will cascade to end of class */
+        goto bail;
     }
 
     if (addrWidth > 0) {
@@ -1117,6 +1160,7 @@
         }
     }
 
+bail:
     //if (addrWidth >= 0)
     //    *pData = align32(data);
     *pData = data;
diff --git a/vm/analysis/RegisterMap.c b/vm/analysis/RegisterMap.c
index 9d88e34..5718507 100644
--- a/vm/analysis/RegisterMap.c
+++ b/vm/analysis/RegisterMap.c
@@ -1548,9 +1548,9 @@
 
         addrDiff = addr - prevAddr;
         assert(addrDiff > 0);
-        if (addrDiff < 7) {
+        if (addrDiff < 8) {
             /* small difference, encode in 3 bits */
-            key = addr - prevAddr;      /* set 00000AAA */
+            key = addrDiff -1;          /* set 00000AAA */
             if (debug)
                 LOGI(" : small %d, key=0x%02x\n", addrDiff, key);
         } else {
@@ -1593,7 +1593,7 @@
          * diff (if it didn't fit in 3 bits), then the changed bit info.
          */
         *tmpPtr++ = key;
-        if (addrDiff >= 7)
+        if ((key & 0x07) == 0x07)
             tmpPtr = writeUnsignedLeb128(tmpPtr, addrDiff);
 
         if ((key & 0x08) != 0) {
@@ -1768,7 +1768,7 @@
             /* address diff follows in ULEB128 */
             addrDiff = readUnsignedLeb128(&srcPtr);
         } else {
-            addrDiff = key & 0x07;
+            addrDiff = (key & 0x07) +1;
         }
 
         addr = prevAddr + addrDiff;