]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Initial rehash of Memcheck's shadow-space management to support both
authorJulian Seward <jseward@acm.org>
Wed, 20 Apr 2005 14:44:11 +0000 (14:44 +0000)
committerJulian Seward <jseward@acm.org>
Wed, 20 Apr 2005 14:44:11 +0000 (14:44 +0000)
32- and 64-bit targets, little- and big-endian.  It does more or less
work on x86 as-is, although is unusably slow since I have knocked out
all the fast-path cases and am concentrating on getting the baseline
functionality correct.  The fast cases will go back in in due course.

The fundamental idea is to retain the old 2-level indexing for speed,
even on a 64-bit target.  Since that's clearly unviable on a 64-bit
target, the primary map handles only first N gigabytes of address
space (probably to be set to 16, 32 or 64G).  Addresses above that are
handled slowly using an auxiliary primary map which explicitly lists
(base, &-of-secondary-map) pairs.  The goal is to have the
address-space-manager try and put everything below the 16/32/64G
boundary, so we hit the fast cases almost all the time.

Performance of the 32-bit case should be unaffected since the fast map
will always cover at least the lowest 4G of address space.

There are many word-size and endianness cleanups.

Jeremy's distinguished-map space-compression scheme is retained, in
modified form, as it is simple and seems effective at reducing
Memcheck's space use.

Note this is all subject to rapid change.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3535

memcheck/mac_leakcheck.c
memcheck/mac_shared.h
memcheck/mc_main.c

index 220d15191cc6852ef70b2b8211d8927736ceff45..bee38b25fb4fe715f86f42b1563de588d401b671 100644 (file)
@@ -316,6 +316,7 @@ static Int lc_markstack_pop(void)
    return ret;
 }
 
+
 /* Scan a block of memory between [start, start+len).  This range may
    be bogus, inaccessable, or otherwise strange; we deal with it.
 
@@ -323,6 +324,7 @@ static Int lc_markstack_pop(void)
    cliques, and clique is the index of the current clique leader. */
 static void _lc_scan_memory(Addr start, SizeT len, Int clique)
 {
+#if 0
    Addr ptr = ROUNDUP(start, sizeof(Addr));
    Addr end = ROUNDDN(start+len, sizeof(Addr));
    vki_sigset_t sigmask;
@@ -372,8 +374,10 @@ static void _lc_scan_memory(Addr start, SizeT len, Int clique)
 
    VG_(sigprocmask)(VKI_SIG_SETMASK, &sigmask, NULL);
    VG_(set_fault_catcher)(NULL);
+#endif
 }
 
+
 static void lc_scan_memory(Addr start, SizeT len)
 {
    _lc_scan_memory(start, len, -1);
index f3a82be2aff66f113a65ceb4e0457db06cdb2dd7..44d9d05ad94c1ac4ac19d0338a1cfd34a223a2d9 100644 (file)
@@ -189,22 +189,23 @@ extern UInt MAC_(event_ctr)[N_PROF_EVENTS];
 
 #endif   /* MAC_PROFILE_MEMORY */
 
-/*------------------------------------------------------------*/
-/*--- V and A bits                                         ---*/
-/*------------------------------------------------------------*/
-
-/* expand 1 bit -> 8 */
-#define BIT_EXPAND(b)  ((~(((UChar)(b) & 1) - 1)) & 0xFF)
-
-#define SECONDARY_SHIFT        16
-#define SECONDARY_SIZE (1 << SECONDARY_SHIFT)
-#define SECONDARY_MASK (SECONDARY_SIZE - 1)
-
-#define PRIMARY_SIZE   (1 << (32 - SECONDARY_SHIFT))
-
-#define SM_OFF(addr)   ((addr) & SECONDARY_MASK)
-#define PM_IDX(addr)   ((addr) >> SECONDARY_SHIFT)
 
+//zz /*------------------------------------------------------------*/
+//zz /*--- V and A bits (Victoria & Albert ?)                   ---*/
+//zz /*------------------------------------------------------------*/
+//zz 
+//zz /* expand 1 bit -> 8 */
+//zz #define BIT_EXPAND(b)     ((~(((UChar)(b) & 1) - 1)) & 0xFF)
+//zz 
+//zz #define SECONDARY_SHIFT   16
+//zz #define SECONDARY_SIZE    (1 << SECONDARY_SHIFT)
+//zz #define SECONDARY_MASK    (SECONDARY_SIZE - 1)
+//zz 
+//zz #define PRIMARY_SIZE      (1 << (32 - SECONDARY_SHIFT))
+//zz 
+//zz #define SM_OFF(addr)      ((addr) & SECONDARY_MASK)
+//zz #define PM_IDX(addr)      ((addr) >> SECONDARY_SHIFT)
+/*
 #define IS_DISTINGUISHED_SM(smap)                 \
    ((smap) >= &distinguished_secondary_maps[0] &&  \
     (smap) < &distinguished_secondary_maps[N_SECONDARY_MAPS])
@@ -215,43 +216,62 @@ extern UInt MAC_(event_ctr)[N_PROF_EVENTS];
    do {                                                           \
       if (IS_DISTINGUISHED(addr)) {                              \
         primary_map[PM_IDX(addr)] = alloc_secondary_map(caller, primary_map[PM_IDX(addr)]); \
-         /* VG_(printf)("new 2map because of %p\n", addr); */     \
+         if (0) VG_(printf)("new 2map because of %p\n", addr);     \
       }                                                           \
-   } while(0)
+  } while(0)
+*/
 
 #define BITARR_SET(aaa_p,iii_p)                         \
    do {                                                 \
-      UInt   iii = (UInt)iii_p;                         \
-      UChar* aaa = (UChar*)aaa_p;                       \
+      UWord   iii = (UWord)iii_p;                       \
+      UChar*  aaa = (UChar*)aaa_p;                      \
       aaa[iii >> 3] |= (1 << (iii & 7));                \
    } while (0)
 
 #define BITARR_CLEAR(aaa_p,iii_p)                       \
    do {                                                 \
-      UInt   iii = (UInt)iii_p;                         \
-      UChar* aaa = (UChar*)aaa_p;                       \
+      UWord   iii = (UWord)iii_p;                       \
+      UChar*  aaa = (UChar*)aaa_p;                      \
       aaa[iii >> 3] &= ~(1 << (iii & 7));               \
    } while (0)
 
 #define BITARR_TEST(aaa_p,iii_p)                        \
-      (0 != (((UChar*)aaa_p)[ ((UInt)iii_p) >> 3 ]      \
-               & (1 << (((UInt)iii_p) & 7))))           \
+      (0 != (((UChar*)aaa_p)[ ((UWord)iii_p) >> 3 ]     \
+               & (1 << (((UWord)iii_p) & 7))))          \
+
+static inline 
+void write_bit_array ( UChar* arr, UWord idx, UWord bit ) 
+{
+   UWord shift = idx & 7;
+   idx >>= 3;
+   bit &= 1;
+   arr[idx] = (arr[idx] & ~(1<<shift)) | (bit << shift);
+}
+
+static inline
+UWord read_bit_array ( UChar* arr, UWord idx )
+{
+   UWord shift = idx & 7;
+   idx >>= 3;
+   return 1 & (arr[idx] >> shift);
+}
+
 
+#define VGM_BIT_VALID       0
+#define VGM_BIT_INVALID     1
 
-#define VGM_BIT_VALID      0
-#define VGM_BIT_INVALID    1
+#define VGM_NIBBLE_VALID    0
+#define VGM_NIBBLE_INVALID  0xF
 
-#define VGM_NIBBLE_VALID   0
-#define VGM_NIBBLE_INVALID 0xF
+#define VGM_BYTE_VALID      0
+#define VGM_BYTE_INVALID    0xFF
 
-#define VGM_BYTE_VALID     0
-#define VGM_BYTE_INVALID   0xFF
+#define VGM_WORD32_VALID    0
+#define VGM_WORD32_INVALID  0xFFFFFFFF
 
-#define VGM_WORD_VALID     0
-#define VGM_WORD_INVALID   0xFFFFFFFF
+#define VGM_WORD64_VALID    0ULL
+#define VGM_WORD64_INVALID  0xFFFFFFFFFFFFFFFFULL
 
-#define VGM_WORD64_VALID     0x0ULL
-#define VGM_WORD64_INVALID   0xFFFFFFFFFFFFFFFFULL
 
 /*------------------------------------------------------------*/
 /*--- Command line options + defaults                      ---*/
@@ -408,166 +428,166 @@ extern                void MAC_(new_mem_stack) ( Addr a, SizeT len);
 
    Note that this code is executed very frequently and must be highly
    optimised, which is why I resort to the preprocessor to achieve the
-   factoring, rather than eg. using function pointers.
+   factoring, rather than eg. using function pointers.  
 */
 
-#define ESP_UPDATE_HANDLERS(ALIGNED4_NEW,  ALIGNED4_DIE,                      \
-                            ALIGNED8_NEW,  ALIGNED8_DIE,                      \
-                            UNALIGNED_NEW, UNALIGNED_DIE)                     \
-                                                                              \
-void VGA_REGPARM(1) MAC_(new_mem_stack_4)(Addr new_ESP)                       \
-{                                                                             \
-   PROF_EVENT(110);                                                           \
-   if (VG_IS_4_ALIGNED(new_ESP)) {                                            \
-      ALIGNED4_NEW  ( new_ESP );                                              \
-   } else {                                                                   \
-      UNALIGNED_NEW ( new_ESP, 4 );                                           \
-   }                                                                          \
-}                                                                             \
-                                                                              \
-void VGA_REGPARM(1) MAC_(die_mem_stack_4)(Addr new_ESP)                       \
-{                                                                             \
-   PROF_EVENT(120);                                                           \
-   if (VG_IS_4_ALIGNED(new_ESP)) {                                            \
-      ALIGNED4_DIE  ( new_ESP-4 );                                            \
-   } else {                                                                   \
-      UNALIGNED_DIE ( new_ESP-4, 4 );                                         \
-   }                                                                          \
-}                                                                             \
-                                                                              \
-void VGA_REGPARM(1) MAC_(new_mem_stack_8)(Addr new_ESP)                       \
-{                                                                             \
-   PROF_EVENT(111);                                                           \
-   if (VG_IS_8_ALIGNED(new_ESP)) {                                            \
-      ALIGNED8_NEW  ( new_ESP );                                              \
-   } else if (VG_IS_4_ALIGNED(new_ESP)) {                                     \
-      ALIGNED4_NEW  ( new_ESP   );                                            \
-      ALIGNED4_NEW  ( new_ESP+4 );                                            \
-   } else {                                                                   \
-      UNALIGNED_NEW ( new_ESP, 8 );                                           \
-   }                                                                          \
-}                                                                             \
-                                                                              \
-void VGA_REGPARM(1) MAC_(die_mem_stack_8)(Addr new_ESP)                       \
-{                                                                             \
-   PROF_EVENT(121);                                                           \
-   if (VG_IS_8_ALIGNED(new_ESP)) {                                            \
-      ALIGNED8_DIE  ( new_ESP-8 );                                            \
-   } else if (VG_IS_4_ALIGNED(new_ESP)) {                                     \
-      ALIGNED4_DIE  ( new_ESP-8 );                                            \
-      ALIGNED4_DIE  ( new_ESP-4 );                                            \
-   } else {                                                                   \
-      UNALIGNED_DIE ( new_ESP-8, 8 );                                         \
-   }                                                                          \
-}                                                                             \
-                                                                              \
-void VGA_REGPARM(1) MAC_(new_mem_stack_12)(Addr new_ESP)                      \
-{                                                                             \
-   PROF_EVENT(112);                                                           \
-   if (VG_IS_8_ALIGNED(new_ESP)) {                                            \
-      ALIGNED8_NEW  ( new_ESP   );                                            \
-      ALIGNED4_NEW  ( new_ESP+8 );                                            \
-   } else if (VG_IS_4_ALIGNED(new_ESP)) {                                     \
-      ALIGNED4_NEW  ( new_ESP   );                                            \
-      ALIGNED8_NEW  ( new_ESP+4 );                                            \
-   } else {                                                                   \
-      UNALIGNED_NEW ( new_ESP, 12 );                                          \
-   }                                                                          \
-}                                                                             \
-                                                                              \
-void VGA_REGPARM(1) MAC_(die_mem_stack_12)(Addr new_ESP)                      \
-{                                                                             \
-   PROF_EVENT(122);                                                           \
-   /* Note the -12 in the test */                                             \
-   if (VG_IS_8_ALIGNED(new_ESP-12)) {                                         \
-      ALIGNED8_DIE  ( new_ESP-12 );                                           \
-      ALIGNED4_DIE  ( new_ESP-4  );                                           \
-   } else if (VG_IS_4_ALIGNED(new_ESP)) {                                     \
-      ALIGNED4_DIE  ( new_ESP-12 );                                           \
-      ALIGNED8_DIE  ( new_ESP-8  );                                           \
-   } else {                                                                   \
-      UNALIGNED_DIE ( new_ESP-12, 12 );                                       \
-   }                                                                          \
-}                                                                             \
-                                                                              \
-void VGA_REGPARM(1) MAC_(new_mem_stack_16)(Addr new_ESP)                      \
-{                                                                             \
-   PROF_EVENT(113);                                                           \
-   if (VG_IS_8_ALIGNED(new_ESP)) {                                            \
-      ALIGNED8_NEW  ( new_ESP   );                                            \
-      ALIGNED8_NEW  ( new_ESP+8 );                                            \
-   } else if (VG_IS_4_ALIGNED(new_ESP)) {                                     \
-      ALIGNED4_NEW  ( new_ESP    );                                           \
-      ALIGNED8_NEW  ( new_ESP+4  );                                           \
-      ALIGNED4_NEW  ( new_ESP+12 );                                           \
-   } else {                                                                   \
-      UNALIGNED_NEW ( new_ESP, 16 );                                          \
-   }                                                                          \
-}                                                                             \
-                                                                              \
-void VGA_REGPARM(1) MAC_(die_mem_stack_16)(Addr new_ESP)                      \
-{                                                                             \
-   PROF_EVENT(123);                                                           \
-   if (VG_IS_8_ALIGNED(new_ESP)) {                                            \
-      ALIGNED8_DIE  ( new_ESP-16 );                                           \
-      ALIGNED8_DIE  ( new_ESP-8  );                                           \
-   } else if (VG_IS_4_ALIGNED(new_ESP)) {                                     \
-      ALIGNED4_DIE  ( new_ESP-16 );                                           \
-      ALIGNED8_DIE  ( new_ESP-12 );                                           \
-      ALIGNED4_DIE  ( new_ESP-4  );                                           \
-   } else {                                                                   \
-      UNALIGNED_DIE ( new_ESP-16, 16 );                                       \
-   }                                                                          \
-}                                                                             \
-                                                                              \
-void VGA_REGPARM(1) MAC_(new_mem_stack_32)(Addr new_ESP)                      \
-{                                                                             \
-   PROF_EVENT(114);                                                           \
-   if (VG_IS_8_ALIGNED(new_ESP)) {                                            \
-      ALIGNED8_NEW  ( new_ESP    );                                           \
-      ALIGNED8_NEW  ( new_ESP+8  );                                           \
-      ALIGNED8_NEW  ( new_ESP+16 );                                           \
-      ALIGNED8_NEW  ( new_ESP+24 );                                           \
-   } else if (VG_IS_4_ALIGNED(new_ESP)) {                                     \
-      ALIGNED4_NEW  ( new_ESP    );                                           \
-      ALIGNED8_NEW  ( new_ESP+4  );                                           \
-      ALIGNED8_NEW  ( new_ESP+12 );                                           \
-      ALIGNED8_NEW  ( new_ESP+20 );                                           \
-      ALIGNED4_NEW  ( new_ESP+28 );                                           \
-   } else {                                                                   \
-      UNALIGNED_NEW ( new_ESP, 32 );                                          \
-   }                                                                          \
-}                                                                             \
-                                                                              \
-void VGA_REGPARM(1) MAC_(die_mem_stack_32)(Addr new_ESP)                      \
-{                                                                             \
-   PROF_EVENT(124);                                                           \
-   if (VG_IS_8_ALIGNED(new_ESP)) {                                            \
-      ALIGNED8_DIE  ( new_ESP-32 );                                           \
-      ALIGNED8_DIE  ( new_ESP-24 );                                           \
-      ALIGNED8_DIE  ( new_ESP-16 );                                           \
-      ALIGNED8_DIE  ( new_ESP- 8 );                                           \
-   } else if (VG_IS_4_ALIGNED(new_ESP)) {                                     \
-      ALIGNED4_DIE  ( new_ESP-32 );                                           \
-      ALIGNED8_DIE  ( new_ESP-28 );                                           \
-      ALIGNED8_DIE  ( new_ESP-20 );                                           \
-      ALIGNED8_DIE  ( new_ESP-12 );                                           \
-      ALIGNED4_DIE  ( new_ESP-4  );                                           \
-   } else {                                                                   \
-      UNALIGNED_DIE ( new_ESP-32, 32 );                                       \
-   }                                                                          \
-}                                                                             \
-                                                                              \
-void MAC_(new_mem_stack) ( Addr a, SizeT len )                                \
-{                                                                             \
-   PROF_EVENT(115);                                                           \
-   UNALIGNED_NEW ( a, len );                                                  \
-}                                                                             \
-                                                                              \
-void MAC_(die_mem_stack) ( Addr a, SizeT len )                                \
-{                                                                             \
-   PROF_EVENT(125);                                                           \
-   UNALIGNED_DIE ( a, len );                                                  \
+#define SP_UPDATE_HANDLERS(ALIGNED4_NEW,  ALIGNED4_DIE,       \
+                           ALIGNED8_NEW,  ALIGNED8_DIE,       \
+                           UNALIGNED_NEW, UNALIGNED_DIE)      \
+                                                              \
+void VGA_REGPARM(1) MAC_(new_mem_stack_4)(Addr new_SP)        \
+{                                                             \
+   PROF_EVENT(110);                                           \
+   if (VG_IS_4_ALIGNED(new_SP)) {                             \
+      ALIGNED4_NEW  ( new_SP );                               \
+   } else {                                                   \
+      UNALIGNED_NEW ( new_SP, 4 );                            \
+   }                                                          \
+}                                                             \
+                                                              \
+void VGA_REGPARM(1) MAC_(die_mem_stack_4)(Addr new_SP)        \
+{                                                             \
+   PROF_EVENT(120);                                           \
+   if (VG_IS_4_ALIGNED(new_SP)) {                             \
+      ALIGNED4_DIE  ( new_SP-4 );                             \
+   } else {                                                   \
+      UNALIGNED_DIE ( new_SP-4, 4 );                          \
+   }                                                          \
+}                                                             \
+                                                              \
+void VGA_REGPARM(1) MAC_(new_mem_stack_8)(Addr new_SP)        \
+{                                                             \
+   PROF_EVENT(111);                                           \
+   if (VG_IS_8_ALIGNED(new_SP)) {                             \
+      ALIGNED8_NEW  ( new_SP );                               \
+   } else if (VG_IS_4_ALIGNED(new_SP)) {                      \
+      ALIGNED4_NEW  ( new_SP   );                             \
+      ALIGNED4_NEW  ( new_SP+4 );                             \
+   } else {                                                   \
+      UNALIGNED_NEW ( new_SP, 8 );                            \
+   }                                                          \
+}                                                             \
+                                                              \
+void VGA_REGPARM(1) MAC_(die_mem_stack_8)(Addr new_SP)        \
+{                                                             \
+   PROF_EVENT(121);                                           \
+   if (VG_IS_8_ALIGNED(new_SP)) {                             \
+      ALIGNED8_DIE  ( new_SP-8 );                             \
+   } else if (VG_IS_4_ALIGNED(new_SP)) {                      \
+      ALIGNED4_DIE  ( new_SP-8 );                             \
+      ALIGNED4_DIE  ( new_SP-4 );                             \
+   } else {                                                   \
+      UNALIGNED_DIE ( new_SP-8, 8 );                          \
+   }                                                          \
+}                                                             \
+                                                              \
+void VGA_REGPARM(1) MAC_(new_mem_stack_12)(Addr new_SP)       \
+{                                                             \
+   PROF_EVENT(112);                                           \
+   if (VG_IS_8_ALIGNED(new_SP)) {                             \
+      ALIGNED8_NEW  ( new_SP   );                             \
+      ALIGNED4_NEW  ( new_SP+8 );                             \
+   } else if (VG_IS_4_ALIGNED(new_SP)) {                      \
+      ALIGNED4_NEW  ( new_SP   );                             \
+      ALIGNED8_NEW  ( new_SP+4 );                             \
+   } else {                                                   \
+      UNALIGNED_NEW ( new_SP, 12 );                           \
+   }                                                          \
+}                                                             \
+                                                              \
+void VGA_REGPARM(1) MAC_(die_mem_stack_12)(Addr new_SP)       \
+{                                                             \
+   PROF_EVENT(122);                                           \
+   /* Note the -12 in the test */                             \
+   if (VG_IS_8_ALIGNED(new_SP-12)) {                          \
+      ALIGNED8_DIE  ( new_SP-12 );                            \
+      ALIGNED4_DIE  ( new_SP-4  );                            \
+   } else if (VG_IS_4_ALIGNED(new_SP)) {                      \
+      ALIGNED4_DIE  ( new_SP-12 );                            \
+      ALIGNED8_DIE  ( new_SP-8  );                            \
+   } else {                                                   \
+      UNALIGNED_DIE ( new_SP-12, 12 );                        \
+   }                                                          \
+}                                                             \
+                                                              \
+void VGA_REGPARM(1) MAC_(new_mem_stack_16)(Addr new_SP)       \
+{                                                             \
+   PROF_EVENT(113);                                           \
+   if (VG_IS_8_ALIGNED(new_SP)) {                             \
+      ALIGNED8_NEW  ( new_SP   );                             \
+      ALIGNED8_NEW  ( new_SP+8 );                             \
+   } else if (VG_IS_4_ALIGNED(new_SP)) {                      \
+      ALIGNED4_NEW  ( new_SP    );                            \
+      ALIGNED8_NEW  ( new_SP+4  );                            \
+      ALIGNED4_NEW  ( new_SP+12 );                            \
+   } else {                                                   \
+      UNALIGNED_NEW ( new_SP, 16 );                           \
+   }                                                          \
+}                                                             \
+                                                              \
+void VGA_REGPARM(1) MAC_(die_mem_stack_16)(Addr new_SP)       \
+{                                                             \
+   PROF_EVENT(123);                                           \
+   if (VG_IS_8_ALIGNED(new_SP)) {                             \
+      ALIGNED8_DIE  ( new_SP-16 );                            \
+      ALIGNED8_DIE  ( new_SP-8  );                            \
+   } else if (VG_IS_4_ALIGNED(new_SP)) {                      \
+      ALIGNED4_DIE  ( new_SP-16 );                            \
+      ALIGNED8_DIE  ( new_SP-12 );                            \
+      ALIGNED4_DIE  ( new_SP-4  );                            \
+   } else {                                                   \
+      UNALIGNED_DIE ( new_SP-16, 16 );                        \
+   }                                                          \
+}                                                             \
+                                                              \
+void VGA_REGPARM(1) MAC_(new_mem_stack_32)(Addr new_SP)       \
+{                                                             \
+   PROF_EVENT(114);                                           \
+   if (VG_IS_8_ALIGNED(new_SP)) {                             \
+      ALIGNED8_NEW  ( new_SP    );                            \
+      ALIGNED8_NEW  ( new_SP+8  );                            \
+      ALIGNED8_NEW  ( new_SP+16 );                            \
+      ALIGNED8_NEW  ( new_SP+24 );                            \
+   } else if (VG_IS_4_ALIGNED(new_SP)) {                      \
+      ALIGNED4_NEW  ( new_SP    );                            \
+      ALIGNED8_NEW  ( new_SP+4  );                            \
+      ALIGNED8_NEW  ( new_SP+12 );                            \
+      ALIGNED8_NEW  ( new_SP+20 );                            \
+      ALIGNED4_NEW  ( new_SP+28 );                            \
+   } else {                                                   \
+      UNALIGNED_NEW ( new_SP, 32 );                           \
+   }                                                          \
+}                                                             \
+                                                              \
+void VGA_REGPARM(1) MAC_(die_mem_stack_32)(Addr new_SP)       \
+{                                                             \
+   PROF_EVENT(124);                                           \
+   if (VG_IS_8_ALIGNED(new_SP)) {                             \
+      ALIGNED8_DIE  ( new_SP-32 );                            \
+      ALIGNED8_DIE  ( new_SP-24 );                            \
+      ALIGNED8_DIE  ( new_SP-16 );                            \
+      ALIGNED8_DIE  ( new_SP- 8 );                            \
+   } else if (VG_IS_4_ALIGNED(new_SP)) {                      \
+      ALIGNED4_DIE  ( new_SP-32 );                            \
+      ALIGNED8_DIE  ( new_SP-28 );                            \
+      ALIGNED8_DIE  ( new_SP-20 );                            \
+      ALIGNED8_DIE  ( new_SP-12 );                            \
+      ALIGNED4_DIE  ( new_SP-4  );                            \
+   } else {                                                   \
+      UNALIGNED_DIE ( new_SP-32, 32 );                        \
+   }                                                          \
+}                                                             \
+                                                              \
+void MAC_(new_mem_stack) ( Addr a, SizeT len )                \
+{                                                             \
+   PROF_EVENT(115);                                           \
+   UNALIGNED_NEW ( a, len );                                  \
+}                                                             \
+                                                              \
+void MAC_(die_mem_stack) ( Addr a, SizeT len )                \
+{                                                             \
+   PROF_EVENT(125);                                           \
+   UNALIGNED_DIE ( a, len );                                  \
 }
 
 #endif   /* __MAC_SHARED_H */
index c90513de71068abd61fdd5ee68694f2793b93319..f7b873309bc62f8999eada00f621b12cb53a4792 100644 (file)
    The GNU General Public License is contained in the file COPYING.
 */
 
+/* TODO urgently
+
+   sanity check: 
+      auxmap only covers address space that the primary doesn't
+      auxmap entries non-duplicated (expensive)
+
+   types of helper functions
+
+   set_address_range_perms to notice when a distinguished secondary
+   will work, and use that (viz, re-implement compression scheme)
+
+   profile
+
+   reinstate fast-path cases
+*/
+
+
 #include "mc_include.h"
 #include "memcheck.h"   /* for client requests */
 //#include "vg_profile.c"
 
-/* Define to debug the mem audit system. */
-/* #define VG_DEBUG_MEMORY */
+
+typedef enum {
+   MC_Ok = 5, MC_AddrErr = 6, MC_ValueErr = 7
+} MC_ReadResult;
 
 #define DEBUG(fmt, args...) //VG_(printf)(fmt, ## args)
 
+
 /*------------------------------------------------------------*/
-/*--- Low-level support for memory checking.               ---*/
+/*--- Basic A/V bitmap representation.                     ---*/
 /*------------------------------------------------------------*/
 
-/* All reads and writes are checked against a memory map, which
-   records the state of all memory in the process.  The memory map is
-   organised like this:
-
-   The top 16 bits of an address are used to index into a top-level
-   map table, containing 65536 entries.  Each entry is a pointer to a
-   second-level map, which records the accesibililty and validity
-   permissions for the 65536 bytes indexed by the lower 16 bits of the
-   address.  Each byte is represented by nine bits, one indicating
-   accessibility, the other eight validity.  So each second-level map
-   contains 73728 bytes.  This two-level arrangement conveniently
-   divides the 4G address space into 64k lumps, each size 64k bytes.
-
-   All entries in the primary (top-level) map must point to a valid
-   secondary (second-level) map.  Since most of the 4G of address
-   space will not be in use -- ie, not mapped at all -- there is a
-   distinguished secondary map, which indicates `not addressible and
-   not valid' writeable for all bytes.  Entries in the primary map for
-   which the entire 64k is not in use at all point at this
-   distinguished map.
-
-   There are actually 4 distinguished secondaries.  These are used to
-   represent a memory range which is either not addressable (validity
-   doesn't matter), addressable+not valid, addressable+valid.
-
-   [...] lots of stuff deleted due to out of date-ness
-
-   As a final optimisation, the alignment and address checks for
-   4-byte loads and stores are combined in a neat way.  The primary
-   map is extended to have 262144 entries (2^18), rather than 2^16.
-   The top 3/4 of these entries are permanently set to the
-   distinguished secondary map.  For a 4-byte load/store, the
-   top-level map is indexed not with (addr >> 16) but instead f(addr),
-   where
-
-    f( XXXX XXXX XXXX XXXX ____ ____ ____ __YZ )
-        = ____ ____ ____ __YZ XXXX XXXX XXXX XXXX  or 
-        = ____ ____ ____ __ZY XXXX XXXX XXXX XXXX
-
-   ie the lowest two bits are placed above the 16 high address bits.
-   If either of these two bits are nonzero, the address is misaligned;
-   this will select a secondary map from the upper 3/4 of the primary
-   map.  Because this is always the distinguished secondary map, a
-   (bogus) address check failure will result.  The failure handling
-   code can then figure out whether this is a genuine addr check
-   failure or whether it is a possibly-legitimate access at a
-   misaligned address.  
-*/
+/* --------------- Basic configuration --------------- */
 
-/*------------------------------------------------------------*/
-/*--- Function declarations.                               ---*/
-/*------------------------------------------------------------*/
+/* The number of entries in the primary map can be altered.  However
+   we hardwire the assumption that each secondary map covers precisely
+   64k of address space. */
 
-static ULong mc_rd_V8_SLOWLY ( Addr a );
-static UInt  mc_rd_V4_SLOWLY ( Addr a );
-static UInt  mc_rd_V2_SLOWLY ( Addr a );
-static UInt  mc_rd_V1_SLOWLY ( Addr a );
+#define N_PRIMARY_BITS  16
+#define N_PRIMARY_MAPS  ((1 << N_PRIMARY_BITS)-1)
 
-static void mc_wr_V8_SLOWLY ( Addr a, ULong vbytes );
-static void mc_wr_V4_SLOWLY ( Addr a, UInt vbytes );
-static void mc_wr_V2_SLOWLY ( Addr a, UInt vbytes );
-static void mc_wr_V1_SLOWLY ( Addr a, UInt vbytes );
+#define MAX_PRIMARY_ADDRESS (Addr)(((Addr)65536) * N_PRIMARY_MAPS)
 
-/*------------------------------------------------------------*/
-/*--- Data defns.                                          ---*/
-/*------------------------------------------------------------*/
+
+/* --------------- Secondary maps --------------- */
 
 typedef 
    struct {
-      UChar abits[SECONDARY_SIZE/8];
-      UChar vbyte[SECONDARY_SIZE];
+      UChar abits[8192];
+      UChar vbyte[65536];
    }
    SecMap;
 
+/* 3 distinguished secondary maps, one for no-access, one for
+   accessible but undefined, and one for accessible and defined.
+   Distinguished secondaries may never be modified.
+*/
+#define SM_DIST_NOACCESS          0
+#define SM_DIST_ACCESS_UNDEFINED  1
+#define SM_DIST_ACCESS_DEFINED    2
+
+static SecMap sm_distinguished[3];
 
-static SecMap* primary_map[ /*PRIMARY_SIZE*/ PRIMARY_SIZE*4 ];
+static inline Bool is_distinguished_sm ( SecMap* sm ) {
+   return sm >= &sm_distinguished[0] && sm <= &sm_distinguished[2];
+}
 
-#define DSM_IDX(a, v)  ((((a)&1) << 1) + ((v)&1))
+/* dist_sm points to one of our three distinguished secondaries.  Make
+   a copy of it so that we can write to it.
+*/
+static SecMap* copy_for_writing ( SecMap* dist_sm )
+{
+   SecMap* new_sm;
+   tl_assert(dist_sm == &sm_distinguished[0]
+             || dist_sm == &sm_distinguished[1]
+            || dist_sm == &sm_distinguished[2]);
 
-/* 4 secondary maps, but one is redundant (because the !addressable &&
-   valid state is meaningless) */
-static const SecMap  distinguished_secondary_maps[4] = {
-#define INIT(a, v)                                                     \
-   [ DSM_IDX(a, v) ] = { { [0 ... (SECONDARY_SIZE/8)-1] = BIT_EXPAND(a) }, \
-                        { [0 ... SECONDARY_SIZE-1]     = BIT_EXPAND(a|v) } }
-   INIT(VGM_BIT_VALID,   VGM_BIT_VALID),
-   INIT(VGM_BIT_VALID,   VGM_BIT_INVALID),
-   INIT(VGM_BIT_INVALID, VGM_BIT_VALID),
-   INIT(VGM_BIT_INVALID, VGM_BIT_INVALID),
-#undef INIT
-};
-#define N_SECONDARY_MAPS       (sizeof(distinguished_secondary_maps)/sizeof(*distinguished_secondary_maps))
+   new_sm = VG_(shadow_alloc)(sizeof(SecMap));
+   VG_(memcpy)(new_sm, dist_sm, sizeof(SecMap));
+   return new_sm;
+}
 
-#define DSM(a,v)               ((SecMap *)&distinguished_secondary_maps[DSM_IDX(a, v)])
 
-#define DSM_NOTADDR            DSM(VGM_BIT_INVALID, VGM_BIT_INVALID)
-#define DSM_ADDR_NOTVALID      DSM(VGM_BIT_VALID, VGM_BIT_INVALID)
-#define DSM_ADDR_VALID         DSM(VGM_BIT_VALID, VGM_BIT_VALID)
+/* --------------- Primary maps --------------- */
 
-static void init_shadow_memory ( void )
+/* The main primary map.  This covers some initial part of the address
+   space, addresses 0 .. (N_PRIMARY_MAPS << 16)-1.  The rest of it is
+   handled using the auxiliary primary map.  
+*/
+static SecMap* primary_map[N_PRIMARY_MAPS];
+
+
+/* An entry in the auxiliary primary map.  base must be a 64k-aligned
+   value, and sm points at the relevant secondary map.  As with the
+   main primary map, the secondary may be either a real secondary, or
+   one of the three distinguished secondaries.
+*/
+typedef
+   struct { 
+      Addr base;
+      SecMap* sm;
+   }
+   AuxMapEnt;
+
+/* An expanding array of AuxMapEnts. */
+#define N_AUXMAPS 500 /* HACK */
+static AuxMapEnt  hacky_auxmaps[N_AUXMAPS];
+static Int        auxmap_size = N_AUXMAPS;
+static Int        auxmap_used = 0;
+static AuxMapEnt* auxmap      = &hacky_auxmaps[0];
+
+/* Auxmap statistics */
+static ULong n_auxmap_searches = 0;
+static ULong n_auxmap_cmps     = 0;
+
+
+/* Find an entry in the auxiliary map.  If an entry is found, move it
+   one step closer to the front of the array, then return its address.
+   If an entry is not found, allocate one.  Note carefully that
+   because a each call potentially rearranges the entries, each call
+   to this function invalidates ALL AuxMapEnt*s previously obtained by
+   calling this fn.  
+*/
+static AuxMapEnt* find_or_alloc_in_auxmap ( Addr a )
 {
-   Int i, a, v;
+   UWord i;
+   tl_assert(a > MAX_PRIMARY_ADDRESS);
 
-   /* check construction of the 4 distinguished secondaries */
-   tl_assert(VGM_BIT_INVALID == 1);
-   tl_assert(VGM_BIT_VALID == 0);
+   a &= ~(Addr)0xFFFF;
 
-   for (a = 0; a <= 1; a++) {
-      for (v = 0; v <= 1; v++) {
-        if (DSM(a,v)->abits[0] != BIT_EXPAND(a))
-           VG_(printf)("DSM(%d,%d)[%d]->abits[0] == %x not %x\n",
-                       a,v,DSM_IDX(a,v),DSM(a,v)->abits[0], BIT_EXPAND(a));
-        if (DSM(a,v)->vbyte[0] != BIT_EXPAND(a|v))
-           VG_(printf)("DSM(%d,%d)[%d]->vbyte[0] == %x not %x\n",
-                       a,v,DSM_IDX(a,v),DSM(a,v)->vbyte[0], BIT_EXPAND(a|v));
-
-        tl_assert(DSM(a,v)->abits[0] == BIT_EXPAND(a));
-        tl_assert(DSM(a,v)->vbyte[0] == BIT_EXPAND(v|a));
+   /* Search .. */
+   n_auxmap_searches++;
+   for (i = 0; i < auxmap_used; i++) {
+      if (auxmap[i].base == a)
+         break;
+   }
+   n_auxmap_cmps += (ULong)(i+1);
+
+   if (i < auxmap_used) {
+      /* Found it.  Nudge it a bit closer to the front. */
+      if (i > 0) {
+         AuxMapEnt tmp = auxmap[i-1];
+         auxmap[i-1] = auxmap[i];
+         auxmap[i] = tmp;
+         i--;
       }
+      return &auxmap[i];
    }
-   /* These entries gradually get overwritten as the used address
-      space expands. */
-   for (i = 0; i < PRIMARY_SIZE; i++)
-      primary_map[i] = DSM_NOTADDR;
 
-   /* These ones should never change; it's a bug in Valgrind if they do. */
-   for (i = PRIMARY_SIZE; i < PRIMARY_SIZE*4; i++)
-      primary_map[i] = DSM_NOTADDR;
+   /* We didn't find it.  Hmm.  This is a new piece of address space.
+      We'll need to allocate a new AuxMap entry for it. */
+   if (auxmap_used >= auxmap_size) {
+      tl_assert(auxmap_used == auxmap_size);
+      /* Out of auxmap entries. */
+      tl_assert2(0, "failed to expand the auxmap table");
+   }
+
+   tl_assert(auxmap_used < auxmap_size);
+
+   auxmap[auxmap_used].base = a & ~(Addr)0xFFFF;
+   auxmap[auxmap_used].sm   = &sm_distinguished[SM_DIST_NOACCESS];
+
+   if (0)
+      VG_(printf)("new auxmap, base = 0x%llx\n", 
+                  (ULong)auxmap[auxmap_used].base );
+
+   auxmap_used++;
+   return &auxmap[auxmap_used-1];
 }
 
-/*------------------------------------------------------------*/
-/*--- Basic bitmap management, reading and writing.        ---*/
-/*------------------------------------------------------------*/
 
-/* Allocate and initialise a secondary map. */
+/* --------------- SecMap fundamentals --------------- */
 
-static SecMap* alloc_secondary_map ( __attribute__ ((unused)) 
-                                     Char* caller,
-                                    const SecMap *prototype)
+/* Produce the secmap for 'a', either from the primary map or by
+   ensuring there is an entry for it in the aux primary map.  The
+   secmap may be a distinguished one as the caller will only want to
+   be able to read it. 
+*/
+static SecMap* get_secmap_readable ( Addr a )
 {
-   SecMap* map;
-   PROF_EVENT(10);
+   if (a <= MAX_PRIMARY_ADDRESS) {
+      UWord pm_off = a >> 16;
+      return primary_map[ pm_off ];
+   } else {
+      AuxMapEnt* am = find_or_alloc_in_auxmap(a);
+      return am->sm;
+   }
+}
+
+/* Produce the secmap for 'a', either from the primary map or by
+   ensuring there is an entry for it in the aux primary map.  The
+   secmap may not be a distinguished one, since the caller will want
+   to be able to write it.  If it is a distinguished secondary, make a
+   writable copy of it, install it, and return the copy instead.  (COW
+   semantics).
+*/
+static SecMap* get_secmap_writable ( Addr a )
+{
+   if (a <= MAX_PRIMARY_ADDRESS) {
+      UWord pm_off = a >> 16;
+      if (is_distinguished_sm(primary_map[ pm_off ]))
+         primary_map[pm_off] = copy_for_writing(primary_map[pm_off]);
+      return primary_map[pm_off];
+   } else {
+      AuxMapEnt* am = find_or_alloc_in_auxmap(a);
+      if (is_distinguished_sm(am->sm))
+         am->sm = copy_for_writing(am->sm);
+      return am->sm;
+   }
+}
 
-   map = (SecMap *)VG_(shadow_alloc)(sizeof(SecMap));
 
-   VG_(memcpy)(map, prototype, sizeof(*map));
+/* --------------- Endianness helpers --------------- */
 
-   /* VG_(printf)("ALLOC_2MAP(%s)\n", caller ); */
-   return map;
+/* Returns the offset in memory of the byteno-th most significant byte
+   in a wordszB-sized word, given the specified endianness. */
+static inline UWord byte_offset_w ( UWord wordszB, Bool bigendian, 
+                                    UWord byteno ) {
+   return bigendian ? (wordszB-1-byteno) : byteno;
 }
 
 
-/* Basic reading/writing of the bitmaps, for byte-sized accesses. */
+/* --------------- Fundamental functions --------------- */
 
-static __inline__ UChar get_abit ( Addr a )
+static 
+void get_abit_and_vbyte ( /*OUT*/UWord* abit, 
+                          /*OUT*/UWord* vbyte,
+                          Addr a )
 {
-   SecMap* sm     = primary_map[PM_IDX(a)];
-   UInt    sm_off = SM_OFF(a);
-   PROF_EVENT(20);
-#  if 0
-      if (IS_DISTINGUISHED_SM(sm))
-         VG_(message)(Vg_DebugMsg, 
-                      "accessed distinguished 2ndary (A)map! 0x%x\n", a);
-#  endif
-   return BITARR_TEST(sm->abits, sm_off) 
-             ? VGM_BIT_INVALID : VGM_BIT_VALID;
-}
+   SecMap* sm = get_secmap_readable(a);
+   *vbyte = 0xFF & sm->vbyte[a & 0xFFFF];
+   *abit  = read_bit_array(sm->abits, a & 0xFFFF);
+} 
 
-static __inline__ UChar get_vbyte ( Addr a )
+static 
+UWord get_abit ( Addr a )
 {
-   SecMap* sm     = primary_map[PM_IDX(a)];
-   UInt    sm_off = SM_OFF(a);
-   PROF_EVENT(21);
-#  if 0
-      if (IS_DISTINGUISHED_SM(sm))
-         VG_(message)(Vg_DebugMsg, 
-                      "accessed distinguished 2ndary (V)map! 0x%x\n", a);
-#  endif
-   return sm->vbyte[sm_off];
+   SecMap* sm = get_secmap_readable(a);
+   return read_bit_array(sm->abits, a & 0xFFFF);
 }
 
-static /* __inline__ */ void set_abit ( Addr a, UChar abit )
+static
+void set_abit_and_vbyte ( Addr a, UWord abit, UWord vbyte )
 {
-   SecMap* sm;
-   UInt    sm_off;
-   PROF_EVENT(22);
-   ENSURE_MAPPABLE(a, "set_abit");
-   sm     = primary_map[PM_IDX(a)];
-   sm_off = SM_OFF(a);
-   if (abit) 
-      BITARR_SET(sm->abits, sm_off);
-   else
-      BITARR_CLEAR(sm->abits, sm_off);
+   SecMap* sm = get_secmap_writable(a);
+   sm->vbyte[a & 0xFFFF] = 0xFF & vbyte;
+   write_bit_array(sm->abits, a & 0xFFFF, abit);   
 }
 
-static __inline__ void set_vbyte ( Addr a, UChar vbyte )
+static
+void set_vbyte ( Addr a, UWord vbyte )
 {
-   SecMap* sm;
-   UInt    sm_off;
-   PROF_EVENT(23);
-   ENSURE_MAPPABLE(a, "set_vbyte");
-   sm     = primary_map[PM_IDX(a)];
-   sm_off = SM_OFF(a);
-   sm->vbyte[sm_off] = vbyte;
+   SecMap* sm = get_secmap_writable(a);
+   sm->vbyte[a & 0xFFFF] = 0xFF & vbyte;
 }
 
 
-/* Reading/writing of the bitmaps, for aligned word-sized accesses. */
+/* --------------- Load/store slow cases. --------------- */
 
-static __inline__ UChar get_abits4_ALIGNED ( Addr a )
-{
-   SecMap* sm;
-   UInt    sm_off;
-   UChar   abits8;
-   PROF_EVENT(24);
-#  ifdef VG_DEBUG_MEMORY
-   tl_assert(VG_IS_4_ALIGNED(a));
-#  endif
-   sm     = primary_map[PM_IDX(a)];
-   sm_off = SM_OFF(a);
-   abits8 = sm->abits[sm_off >> 3];
-   abits8 >>= (a & 4 /* 100b */);   /* a & 4 is either 0 or 4 */
-   abits8 &= 0x0F;
-   return abits8;
-}
+static
+ULong mc_LOADVn_slow ( Addr a, SizeT szB, Bool bigendian )
+{
+   /* Make up a result V word, which contains the loaded data for
+      valid addresses and Undefined for invalid addresses.  Iterate
+      over the bytes in the word, from the most significant down to
+      the least. */
+   ULong vw          = VGM_WORD64_INVALID;
+   SizeT i           = szB-1;
+   SizeT n_addrs_bad = 0;
+   Addr  ai;
+   Bool  aok;
+   UWord abit, vbyte;
 
-static UInt __inline__ get_vbytes4_ALIGNED ( Addr a )
-{
-   SecMap* sm     = primary_map[PM_IDX(a)];
-   UInt    sm_off = SM_OFF(a);
-   PROF_EVENT(25);
-#  ifdef VG_DEBUG_MEMORY
-   tl_assert(VG_IS_4_ALIGNED(a));
-#  endif
-   return ((UInt*)(sm->vbyte))[sm_off >> 2];
+   PROF_EVENT(70);
+   tl_assert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
+
+   while (True) {
+      ai = a+byte_offset_w(szB,bigendian,i);
+      get_abit_and_vbyte(&abit, &vbyte, ai);
+      aok = abit == VGM_BIT_VALID;
+      if (!aok)
+         n_addrs_bad++;
+      vw <<= 8; 
+      vw |= 0xFF & (aok ? vbyte : VGM_BYTE_INVALID);
+      if (i == 0) break;
+      i--;
+   }
+
+   if (n_addrs_bad > 0)
+      MAC_(record_address_error)( VG_(get_running_tid)(), a, szB, False );
+
+   //if (n_addrs_bad == n)
+   //   vw = VGM_WORD64_VALID;
+   return vw;
 }
 
 
-static void __inline__ set_vbytes4_ALIGNED ( Addr a, UInt vbytes )
+static 
+void mc_STOREVn_slow ( Addr a, SizeT szB, UWord vbytes, Bool bigendian )
 {
-   SecMap* sm;
-   UInt    sm_off;
-   ENSURE_MAPPABLE(a, "set_vbytes4_ALIGNED");
-   sm     = primary_map[PM_IDX(a)];
-   sm_off = SM_OFF(a);
-   PROF_EVENT(23);
-#  ifdef VG_DEBUG_MEMORY
-   tl_assert(VG_IS_4_ALIGNED(a));
-#  endif
-   ((UInt*)(sm->vbyte))[sm_off >> 2] = vbytes;
-}
+   SizeT i;
+   SizeT n_addrs_bad = 0;
+   UWord abit;
+   Bool  aok;
+   Addr  ai;
 
+   PROF_EVENT(71);
+   tl_assert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
+
+   /* Dump vbytes in memory, iterating from least to most significant
+      byte.  At the same time establish addressibility of the
+      location. */
+   for (i = 0; i < szB; i++) {
+      ai = a+byte_offset_w(szB,bigendian,i);
+      abit = get_abit(ai);
+      aok = abit == VGM_BIT_VALID;
+      if (!aok)
+         n_addrs_bad++;
+      set_vbyte(ai, vbytes & 0xFF ); 
+      vbytes >>= 8;
+   }
 
-/*------------------------------------------------------------*/
-/*--- Setting permissions over address ranges.             ---*/
-/*------------------------------------------------------------*/
+   /* If an address error has happened, report it. */
+   if (n_addrs_bad > 0)
+      MAC_(record_address_error)( VG_(get_running_tid)(), a, szB, True );
+}
+
+
+///////////////////////////////////////////////////////////////
+
+
+
+
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+
+//zz #if 0  /* this is the old implementation */
+//zz 
+//zz /* Define to debug the mem audit system. */
+//zz /* #define VG_DEBUG_MEMORY */
+//zz 
+//zz 
+//zz /*------------------------------------------------------------*/
+//zz /*--- Low-level support for memory checking.               ---*/
+//zz /*------------------------------------------------------------*/
+//zz 
+//zz /* All reads and writes are checked against a memory map, which
+//zz    records the state of all memory in the process.  The memory map is
+//zz    organised like this:
+//zz 
+//zz    The top 16 bits of an address are used to index into a top-level
+//zz    map table, containing 65536 entries.  Each entry is a pointer to a
+//zz    second-level map, which records the accesibililty and validity
+//zz    permissions for the 65536 bytes indexed by the lower 16 bits of the
+//zz    address.  Each byte is represented by nine bits, one indicating
+//zz    accessibility, the other eight validity.  So each second-level map
+//zz    contains 73728 bytes.  This two-level arrangement conveniently
+//zz    divides the 4G address space into 64k lumps, each size 64k bytes.
+//zz 
+//zz    All entries in the primary (top-level) map must point to a valid
+//zz    secondary (second-level) map.  Since most of the 4G of address
+//zz    space will not be in use -- ie, not mapped at all -- there is a
+//zz    distinguished secondary map, which indicates `not addressible and
+//zz    not valid' writeable for all bytes.  Entries in the primary map for
+//zz    which the entire 64k is not in use at all point at this
+//zz    distinguished map.
+//zz 
+//zz    There are actually 4 distinguished secondaries.  These are used to
+//zz    represent a memory range which is either not addressable (validity
+//zz    doesn't matter), addressable+not valid, addressable+valid.
+//zz 
+//zz    [...] lots of stuff deleted due to out of date-ness
+//zz 
+//zz    As a final optimisation, the alignment and address checks for
+//zz    4-byte loads and stores are combined in a neat way.  The primary
+//zz    map is extended to have 262144 entries (2^18), rather than 2^16.
+//zz    The top 3/4 of these entries are permanently set to the
+//zz    distinguished secondary map.  For a 4-byte load/store, the
+//zz    top-level map is indexed not with (addr >> 16) but instead f(addr),
+//zz    where
+//zz 
+//zz     f( XXXX XXXX XXXX XXXX ____ ____ ____ __YZ )
+//zz         = ____ ____ ____ __YZ XXXX XXXX XXXX XXXX  or 
+//zz         = ____ ____ ____ __ZY XXXX XXXX XXXX XXXX
+//zz 
+//zz    ie the lowest two bits are placed above the 16 high address bits.
+//zz    If either of these two bits are nonzero, the address is misaligned;
+//zz    this will select a secondary map from the upper 3/4 of the primary
+//zz    map.  Because this is always the distinguished secondary map, a
+//zz    (bogus) address check failure will result.  The failure handling
+//zz    code can then figure out whether this is a genuine addr check
+//zz    failure or whether it is a possibly-legitimate access at a
+//zz    misaligned address.  
+//zz */
+//zz 
+//zz /*------------------------------------------------------------*/
+//zz /*--- Function declarations.                               ---*/
+//zz /*------------------------------------------------------------*/
+//zz 
+//zz static ULong mc_rd_V8_SLOWLY ( Addr a );
+//zz static UInt  mc_rd_V4_SLOWLY ( Addr a );
+//zz static UInt  mc_rd_V2_SLOWLY ( Addr a );
+//zz static UInt  mc_rd_V1_SLOWLY ( Addr a );
+//zz 
+//zz static void mc_wr_V8_SLOWLY ( Addr a, ULong vbytes );
+//zz static void mc_wr_V4_SLOWLY ( Addr a, UInt vbytes );
+//zz static void mc_wr_V2_SLOWLY ( Addr a, UInt vbytes );
+//zz static void mc_wr_V1_SLOWLY ( Addr a, UInt vbytes );
+//zz 
+//zz /*------------------------------------------------------------*/
+//zz /*--- Data defns.                                          ---*/
+//zz /*------------------------------------------------------------*/
+//zz 
+//zz typedef 
+//zz    struct {
+//zz       UChar abits[SECONDARY_SIZE/8];
+//zz       UChar vbyte[SECONDARY_SIZE];
+//zz    }
+//zz    SecMap;
+//zz 
+//zz 
+//zz static SecMap* primary_map[ /*PRIMARY_SIZE*/ PRIMARY_SIZE*4 ];
+//zz 
+//zz #define DSM_IDX(a, v)     ((((a)&1) << 1) + ((v)&1))
+//zz 
+//zz /* 4 secondary maps, but one is redundant (because the !addressable &&
+//zz    valid state is meaningless) */
+//zz static const SecMap  distinguished_secondary_maps[4] = {
+//zz #define INIT(a, v)                                                        \
+//zz    [ DSM_IDX(a, v) ] = { { [0 ... (SECONDARY_SIZE/8)-1] = BIT_EXPAND(a) }, \
+//zz                    { [0 ... SECONDARY_SIZE-1]     = BIT_EXPAND(a|v) } }
+//zz    INIT(VGM_BIT_VALID,   VGM_BIT_VALID),
+//zz    INIT(VGM_BIT_VALID,   VGM_BIT_INVALID),
+//zz    INIT(VGM_BIT_INVALID, VGM_BIT_VALID),
+//zz    INIT(VGM_BIT_INVALID, VGM_BIT_INVALID),
+//zz #undef INIT
+//zz };
+//zz #define N_SECONDARY_MAPS  (sizeof(distinguished_secondary_maps)/sizeof(*distinguished_secondary_maps))
+//zz 
+//zz #define DSM(a,v)          ((SecMap *)&distinguished_secondary_maps[DSM_IDX(a, v)])
+//zz 
+//zz #define DSM_NOTADDR               DSM(VGM_BIT_INVALID, VGM_BIT_INVALID)
+//zz #define DSM_ADDR_NOTVALID DSM(VGM_BIT_VALID, VGM_BIT_INVALID)
+//zz #define DSM_ADDR_VALID            DSM(VGM_BIT_VALID, VGM_BIT_VALID)
 
-static void set_address_range_perms ( Addr a, SizeT len, 
-                                      UInt example_a_bit,
-                                      UInt example_v_bit )
+static void init_shadow_memory ( void )
 {
-   UChar   vbyte, abyte8;
-   UInt    vword4, sm_off;
+   Int     i;
    SecMap* sm;
 
-   PROF_EVENT(30);
-
-   if (len == 0)
-      return;
-
-   if (VG_(clo_verbosity) > 0) {
-      if (len > 100 * 1000 * 1000) {
-         VG_(message)(Vg_UserMsg, 
-                      "Warning: set address range perms: "
-                      "large range %u, a %d, v %d",
-                      len, example_a_bit, example_v_bit );
-      }
-   }
+   /* Build the 3 distinguished secondaries */
+   tl_assert(VGM_BIT_INVALID == 1);
+   tl_assert(VGM_BIT_VALID == 0);
+   tl_assert(VGM_BYTE_INVALID == 0xFF);
+   tl_assert(VGM_BYTE_VALID == 0);
 
-   VGP_PUSHCC(VgpSetMem);
-
-   /* Requests to change permissions of huge address ranges may
-      indicate bugs in our machinery.  30,000,000 is arbitrary, but so
-      far all legitimate requests have fallen beneath that size. */
-   /* 4 Mar 02: this is just stupid; get rid of it. */
-   /* tl_assert(len < 30000000); */
-
-   /* Check the permissions make sense. */
-   tl_assert(example_a_bit == VGM_BIT_VALID 
-             || example_a_bit == VGM_BIT_INVALID);
-   tl_assert(example_v_bit == VGM_BIT_VALID 
-             || example_v_bit == VGM_BIT_INVALID);
-   if (example_a_bit == VGM_BIT_INVALID)
-      tl_assert(example_v_bit == VGM_BIT_INVALID);
-
-   /* The validity bits to write. */
-   vbyte = example_v_bit==VGM_BIT_VALID 
-              ? VGM_BYTE_VALID : VGM_BYTE_INVALID;
-
-   /* In order that we can charge through the address space at 8
-      bytes/main-loop iteration, make up some perms. */
-   abyte8 = BIT_EXPAND(example_a_bit);
-   vword4 = (vbyte << 24) | (vbyte << 16) | (vbyte << 8) | vbyte;
-
-#  ifdef VG_DEBUG_MEMORY
-   /* Do it ... */
-   while (True) {
-      PROF_EVENT(31);
-      if (len == 0) break;
-      set_abit ( a, example_a_bit );
-      set_vbyte ( a, vbyte );
-      a++;
-      len--;
-   }
+   /* Set A invalid, V invalid. */
+   sm = &sm_distinguished[SM_DIST_NOACCESS];
+   for (i = 0; i < 65536; i++)
+      sm->vbyte[i] = VGM_BYTE_INVALID;
+   for (i = 0; i < 8192; i++)
+      sm->abits[i] = VGM_BYTE_INVALID;
 
-#  else
-   /* Slowly do parts preceding 8-byte alignment. */
-   while (True) {
-      PROF_EVENT(31);
-      if (len == 0) break;
-      if ((a % 8) == 0) break;
-      set_abit ( a, example_a_bit );
-      set_vbyte ( a, vbyte );
-      a++;
-      len--;
-   }   
+   /* Set A valid, V invalid. */
+   sm = &sm_distinguished[SM_DIST_ACCESS_UNDEFINED];
+   for (i = 0; i < 65536; i++)
+      sm->vbyte[i] = VGM_BYTE_INVALID;
+   for (i = 0; i < 8192; i++)
+      sm->abits[i] = VGM_BYTE_VALID;
 
-   if (len == 0) {
-      VGP_POPCC(VgpSetMem);
-      return;
-   }
-   tl_assert((a % 8) == 0 && len > 0);
+   /* Set A valid, V valid. */
+   sm = &sm_distinguished[SM_DIST_ACCESS_DEFINED];
+   for (i = 0; i < 65536; i++)
+      sm->vbyte[i] = VGM_BYTE_VALID;
+   for (i = 0; i < 8192; i++)
+      sm->abits[i] = VGM_BYTE_VALID;
 
-   /* Now align to the next primary_map entry */
-   for (; (a & SECONDARY_MASK) && len >= 8; a += 8, len -= 8) {
+   /* Set up the primary map. */
+   /* These entries gradually get overwritten as the used address
+      space expands. */
+   for (i = 0; i < N_PRIMARY_MAPS; i++)
+      primary_map[i] = &sm_distinguished[SM_DIST_NOACCESS];
+
+   /* auxmap_size = auxmap_used = 0; 
+      no ... these are statically initialised */
+
+   tl_assert( TL_(expensive_sanity_check)() );
+}
+
+
+//zz /*------------------------------------------------------------*/
+//zz /*--- Basic bitmap management, reading and writing.        ---*/
+//zz /*------------------------------------------------------------*/
+//zz 
+//zz /* Allocate and initialise a secondary map. */
+//zz 
+//zz static SecMap* alloc_secondary_map ( __attribute__ ((unused)) 
+//zz                                      Char* caller,
+//zz                                        const SecMap *prototype)
+//zz {
+//zz    SecMap* map;
+//zz    PROF_EVENT(10);
+//zz 
+//zz    map = (SecMap *)VG_(shadow_alloc)(sizeof(SecMap));
+//zz 
+//zz    VG_(memcpy)(map, prototype, sizeof(*map));
+//zz 
+//zz    /* VG_(printf)("ALLOC_2MAP(%s)\n", caller ); */
+//zz    return map;
+//zz }
+//zz 
+//zz 
+//zz /* Basic reading/writing of the bitmaps, for byte-sized accesses. */
+//zz 
+//zz static __inline__ UChar get_abit ( Addr a )
+//zz {
+//zz    SecMap* sm     = primary_map[PM_IDX(a)];
+//zz    UInt    sm_off = SM_OFF(a);
+//zz    PROF_EVENT(20);
+//zz #  if 0
+//zz       if (IS_DISTINGUISHED_SM(sm))
+//zz          VG_(message)(Vg_DebugMsg, 
+//zz                       "accessed distinguished 2ndary (A)map! 0x%x\n", a);
+//zz #  endif
+//zz    return BITARR_TEST(sm->abits, sm_off) 
+//zz              ? VGM_BIT_INVALID : VGM_BIT_VALID;
+//zz }
+//zz 
+//zz static __inline__ UChar get_vbyte ( Addr a )
+//zz {
+//zz    SecMap* sm     = primary_map[PM_IDX(a)];
+//zz    UInt    sm_off = SM_OFF(a);
+//zz    PROF_EVENT(21);
+//zz #  if 0
+//zz       if (IS_DISTINGUISHED_SM(sm))
+//zz          VG_(message)(Vg_DebugMsg, 
+//zz                       "accessed distinguished 2ndary (V)map! 0x%x\n", a);
+//zz #  endif
+//zz    return sm->vbyte[sm_off];
+//zz }
+//zz 
+//zz static /* __inline__ */ void set_abit ( Addr a, UChar abit )
+//zz {
+//zz    SecMap* sm;
+//zz    UInt    sm_off;
+//zz    PROF_EVENT(22);
+//zz    ENSURE_MAPPABLE(a, "set_abit");
+//zz    sm     = primary_map[PM_IDX(a)];
+//zz    sm_off = SM_OFF(a);
+//zz    if (abit) 
+//zz       BITARR_SET(sm->abits, sm_off);
+//zz    else
+//zz       BITARR_CLEAR(sm->abits, sm_off);
+//zz }
+//zz 
+//zz static __inline__ void set_vbyte ( Addr a, UChar vbyte )
+//zz {
+//zz    SecMap* sm;
+//zz    UInt    sm_off;
+//zz    PROF_EVENT(23);
+//zz    ENSURE_MAPPABLE(a, "set_vbyte");
+//zz    sm     = primary_map[PM_IDX(a)];
+//zz    sm_off = SM_OFF(a);
+//zz    sm->vbyte[sm_off] = vbyte;
+//zz }
+//zz 
+//zz 
+//zz /* Reading/writing of the bitmaps, for aligned word-sized accesses. */
+//zz 
+//zz static __inline__ UChar get_abits4_ALIGNED ( Addr a )
+//zz {
+//zz    SecMap* sm;
+//zz    UInt    sm_off;
+//zz    UChar   abits8;
+//zz    PROF_EVENT(24);
+//zz #  ifdef VG_DEBUG_MEMORY
+//zz    tl_assert(VG_IS_4_ALIGNED(a));
+//zz #  endif
+//zz    sm     = primary_map[PM_IDX(a)];
+//zz    sm_off = SM_OFF(a);
+//zz    abits8 = sm->abits[sm_off >> 3];
+//zz    abits8 >>= (a & 4 /* 100b */);   /* a & 4 is either 0 or 4 */
+//zz    abits8 &= 0x0F;
+//zz    return abits8;
+//zz }
+//zz 
+//zz static UInt __inline__ get_vbytes4_ALIGNED ( Addr a )
+//zz {
+//zz    SecMap* sm     = primary_map[PM_IDX(a)];
+//zz    UInt    sm_off = SM_OFF(a);
+//zz    PROF_EVENT(25);
+//zz #  ifdef VG_DEBUG_MEMORY
+//zz    tl_assert(VG_IS_4_ALIGNED(a));
+//zz #  endif
+//zz    return ((UInt*)(sm->vbyte))[sm_off >> 2];
+//zz }
+//zz 
+//zz 
+//zz static void __inline__ set_vbytes4_ALIGNED ( Addr a, UInt vbytes )
+//zz {
+//zz    SecMap* sm;
+//zz    UInt    sm_off;
+//zz    ENSURE_MAPPABLE(a, "set_vbytes4_ALIGNED");
+//zz    sm     = primary_map[PM_IDX(a)];
+//zz    sm_off = SM_OFF(a);
+//zz    PROF_EVENT(23);
+//zz #  ifdef VG_DEBUG_MEMORY
+//zz    tl_assert(VG_IS_4_ALIGNED(a));
+//zz #  endif
+//zz    ((UInt*)(sm->vbyte))[sm_off >> 2] = vbytes;
+//zz }
 
-      PROF_EVENT(32);
-      /* If the primary is already pointing to a distinguished map
-         with the same properties as we're trying to set, then leave
-         it that way. */
-      if (primary_map[PM_IDX(a)] == DSM(example_a_bit, example_v_bit))
-         continue;
 
-      ENSURE_MAPPABLE(a, "set_address_range_perms(fast)");
-      sm = primary_map[PM_IDX(a)];
-      sm_off = SM_OFF(a);
-      sm->abits[sm_off >> 3] = abyte8;
-      ((UInt*)(sm->vbyte))[(sm_off >> 2) + 0] = vword4;
-      ((UInt*)(sm->vbyte))[(sm_off >> 2) + 1] = vword4;
-   }
+/*------------------------------------------------------------*/
+/*--- Setting permissions over address ranges.             ---*/
+/*------------------------------------------------------------*/
 
-   /* Now set whole secondary maps to the right distinguished value.
+static void set_address_range_perms ( Addr a, SizeT len, 
+                                      UWord example_a_bit,
+                                      UWord example_v_bit )
+{
+   SizeT i;
 
-      Note that if the primary already points to a non-distinguished
-      secondary, then don't replace the reference.  That would just
-      leak memory.
-    */
-   for(; len >= SECONDARY_SIZE; a += SECONDARY_SIZE, len -= SECONDARY_SIZE) {
-      sm = primary_map[PM_IDX(a)];
+   UWord example_vbyte = 1 & example_v_bit;
+   example_vbyte |= (example_vbyte << 1);
+   example_vbyte |= (example_vbyte << 2);
+   example_vbyte |= (example_vbyte << 4);
 
-      if (IS_DISTINGUISHED_SM(sm))
-         primary_map[PM_IDX(a)] = DSM(example_a_bit, example_v_bit);
-      else {
-         VG_(memset)(sm->abits, abyte8, sizeof(sm->abits));
-         VG_(memset)(sm->vbyte, vbyte, sizeof(sm->vbyte));
-      }
-   }
+   tl_assert(sizeof(SizeT) == sizeof(Addr));
 
-   /* Now finish off any remains */
-   for (; len >= 8; a += 8, len -= 8) {
-      PROF_EVENT(32);
+   if (0 && len >= 4096)
+      VG_(printf)("s_a_r_p(0x%llx, %d, %d,%d)\n", 
+                  (ULong)a, len, example_a_bit, example_v_bit);
 
-      /* If the primary is already pointing to a distinguished map
-         with the same properties as we're trying to set, then leave
-         it that way. */
-      if (primary_map[PM_IDX(a)] == DSM(example_a_bit, example_v_bit))
-         continue;
+   if (len == 0)
+      return;
 
-      ENSURE_MAPPABLE(a, "set_address_range_perms(fast)");
-      sm = primary_map[PM_IDX(a)];
-      sm_off = SM_OFF(a);
-      sm->abits[sm_off >> 3] = abyte8;
-      ((UInt*)(sm->vbyte))[(sm_off >> 2) + 0] = vword4;
-      ((UInt*)(sm->vbyte))[(sm_off >> 2) + 1] = vword4;
+   for (i = 0; i < len; i++) {
+      set_abit_and_vbyte(a+i, example_a_bit, example_vbyte);
    }
-
-   /* Finish the upper fragment. */
-   while (True) {
-      PROF_EVENT(33);
-      if (len == 0) break;
-      set_abit ( a, example_a_bit );
-      set_vbyte ( a, vbyte );
-      a++;
-      len--;
-   }   
-#  endif
-
-   /* Check that zero page and highest page have not been written to
-      -- this could happen with buggy syscall wrappers.  Today
-      (2001-04-26) had precisely such a problem with __NR_setitimer. */
-   tl_assert(TL_(cheap_sanity_check)());
-   VGP_POPCC(VgpSetMem);
 }
 
+//zz {
+//zz    UChar   vbyte, abyte8;
+//zz    UInt    vword4, sm_off;
+//zz    SecMap* sm;
+//zz 
+//zz    PROF_EVENT(30);
+//zz 
+//zz    if (len == 0)
+//zz       return;
+//zz 
+//zz    if (VG_(clo_verbosity) > 0) {
+//zz       if (len > 100 * 1000 * 1000) {
+//zz          VG_(message)(Vg_UserMsg, 
+//zz                       "Warning: set address range perms: "
+//zz                       "large range %u, a %d, v %d",
+//zz                       len, example_a_bit, example_v_bit );
+//zz       }
+//zz    }
+//zz 
+//zz    VGP_PUSHCC(VgpSetMem);
+//zz 
+//zz    /* Requests to change permissions of huge address ranges may
+//zz       indicate bugs in our machinery.  30,000,000 is arbitrary, but so
+//zz       far all legitimate requests have fallen beneath that size. */
+//zz    /* 4 Mar 02: this is just stupid; get rid of it. */
+//zz    /* tl_assert(len < 30000000); */
+//zz 
+//zz    /* Check the permissions make sense. */
+//zz    tl_assert(example_a_bit == VGM_BIT_VALID 
+//zz              || example_a_bit == VGM_BIT_INVALID);
+//zz    tl_assert(example_v_bit == VGM_BIT_VALID 
+//zz              || example_v_bit == VGM_BIT_INVALID);
+//zz    if (example_a_bit == VGM_BIT_INVALID)
+//zz       tl_assert(example_v_bit == VGM_BIT_INVALID);
+//zz 
+//zz    /* The validity bits to write. */
+//zz    vbyte = example_v_bit==VGM_BIT_VALID 
+//zz               ? VGM_BYTE_VALID : VGM_BYTE_INVALID;
+//zz 
+//zz    /* In order that we can charge through the address space at 8
+//zz       bytes/main-loop iteration, make up some perms. */
+//zz    abyte8 = BIT_EXPAND(example_a_bit);
+//zz    vword4 = (vbyte << 24) | (vbyte << 16) | (vbyte << 8) | vbyte;
+//zz 
+//zz #  ifdef VG_DEBUG_MEMORY
+//zz    /* Do it ... */
+//zz    while (True) {
+//zz       PROF_EVENT(31);
+//zz       if (len == 0) break;
+//zz       set_abit ( a, example_a_bit );
+//zz       set_vbyte ( a, vbyte );
+//zz       a++;
+//zz       len--;
+//zz    }
+//zz 
+//zz #  else
+//zz    /* Slowly do parts preceding 8-byte alignment. */
+//zz    while (True) {
+//zz       PROF_EVENT(31);
+//zz       if (len == 0) break;
+//zz       if ((a % 8) == 0) break;
+//zz       set_abit ( a, example_a_bit );
+//zz       set_vbyte ( a, vbyte );
+//zz       a++;
+//zz       len--;
+//zz    }   
+//zz 
+//zz    if (len == 0) {
+//zz       VGP_POPCC(VgpSetMem);
+//zz       return;
+//zz    }
+//zz    tl_assert((a % 8) == 0 && len > 0);
+//zz 
+//zz    /* Now align to the next primary_map entry */
+//zz    for (; (a & SECONDARY_MASK) && len >= 8; a += 8, len -= 8) {
+//zz 
+//zz       PROF_EVENT(32);
+//zz       /* If the primary is already pointing to a distinguished map
+//zz          with the same properties as we're trying to set, then leave
+//zz          it that way. */
+//zz       if (primary_map[PM_IDX(a)] == DSM(example_a_bit, example_v_bit))
+//zz          continue;
+//zz 
+//zz       ENSURE_MAPPABLE(a, "set_address_range_perms(fast)");
+//zz       sm = primary_map[PM_IDX(a)];
+//zz       sm_off = SM_OFF(a);
+//zz       sm->abits[sm_off >> 3] = abyte8;
+//zz       ((UInt*)(sm->vbyte))[(sm_off >> 2) + 0] = vword4;
+//zz       ((UInt*)(sm->vbyte))[(sm_off >> 2) + 1] = vword4;
+//zz    }
+//zz 
+//zz    /* Now set whole secondary maps to the right distinguished value.
+//zz 
+//zz       Note that if the primary already points to a non-distinguished
+//zz       secondary, then don't replace the reference.  That would just
+//zz       leak memory.
+//zz     */
+//zz    for(; len >= SECONDARY_SIZE; a += SECONDARY_SIZE, len -= SECONDARY_SIZE) {
+//zz       sm = primary_map[PM_IDX(a)];
+//zz 
+//zz       if (IS_DISTINGUISHED_SM(sm))
+//zz          primary_map[PM_IDX(a)] = DSM(example_a_bit, example_v_bit);
+//zz       else {
+//zz          VG_(memset)(sm->abits, abyte8, sizeof(sm->abits));
+//zz          VG_(memset)(sm->vbyte, vbyte, sizeof(sm->vbyte));
+//zz       }
+//zz    }
+//zz 
+//zz    /* Now finish off any remains */
+//zz    for (; len >= 8; a += 8, len -= 8) {
+//zz       PROF_EVENT(32);
+//zz 
+//zz       /* If the primary is already pointing to a distinguished map
+//zz          with the same properties as we're trying to set, then leave
+//zz          it that way. */
+//zz       if (primary_map[PM_IDX(a)] == DSM(example_a_bit, example_v_bit))
+//zz          continue;
+//zz 
+//zz       ENSURE_MAPPABLE(a, "set_address_range_perms(fast)");
+//zz       sm = primary_map[PM_IDX(a)];
+//zz       sm_off = SM_OFF(a);
+//zz       sm->abits[sm_off >> 3] = abyte8;
+//zz       ((UInt*)(sm->vbyte))[(sm_off >> 2) + 0] = vword4;
+//zz       ((UInt*)(sm->vbyte))[(sm_off >> 2) + 1] = vword4;
+//zz    }
+//zz 
+//zz    /* Finish the upper fragment. */
+//zz    while (True) {
+//zz       PROF_EVENT(33);
+//zz       if (len == 0) break;
+//zz       set_abit ( a, example_a_bit );
+//zz       set_vbyte ( a, vbyte );
+//zz       a++;
+//zz       len--;
+//zz    }   
+//zz #  endif
+//zz 
+//zz    /* Check that zero page and highest page have not been written to
+//zz       -- this could happen with buggy syscall wrappers.  Today
+//zz       (2001-04-26) had precisely such a problem with __NR_setitimer. */
+//zz    tl_assert(TL_(cheap_sanity_check)());
+//zz    VGP_POPCC(VgpSetMem);
+//zz }
+
 /* Set permissions for address ranges ... */
 
 static void mc_make_noaccess ( Addr a, SizeT len )
@@ -472,102 +848,106 @@ static void mc_make_readable ( Addr a, SizeT len )
 }
 
 static __inline__
-void make_aligned_word_writable(Addr a)
-{
-   SecMap* sm;
-   UInt    sm_off;
-   UChar   mask;
-
-   VGP_PUSHCC(VgpESPAdj);
-   ENSURE_MAPPABLE(a, "make_aligned_word_writable");
-   sm     = primary_map[PM_IDX(a)];
-   sm_off = SM_OFF(a);
-   ((UInt*)(sm->vbyte))[sm_off >> 2] = VGM_WORD_INVALID;
-   mask = 0x0F;
-   mask <<= (a & 4 /* 100b */);   /* a & 4 is either 0 or 4 */
-   /* mask now contains 1s where we wish to make address bits invalid (0s). */
-   sm->abits[sm_off >> 3] &= ~mask;
-   VGP_POPCC(VgpESPAdj);
+void make_aligned_word32_writable(Addr a)
+{
+   mc_make_writable(a, 4);
+//zz    SecMap* sm;
+//zz    UInt    sm_off;
+//zz    UChar   mask;
+//zz 
+//zz    VGP_PUSHCC(VgpESPAdj);
+//zz    ENSURE_MAPPABLE(a, "make_aligned_word_writable");
+//zz    sm     = primary_map[PM_IDX(a)];
+//zz    sm_off = SM_OFF(a);
+//zz    ((UInt*)(sm->vbyte))[sm_off >> 2] = VGM_WORD_INVALID;
+//zz    mask = 0x0F;
+//zz    mask <<= (a & 4 /* 100b */);   /* a & 4 is either 0 or 4 */
+//zz    /* mask now contains 1s where we wish to make address bits invalid (0s). */
+//zz    sm->abits[sm_off >> 3] &= ~mask;
+//zz    VGP_POPCC(VgpESPAdj);
 }
 
 static __inline__
-void make_aligned_word_noaccess(Addr a)
-{
-   SecMap* sm;
-   UInt    sm_off;
-   UChar   mask;
-
-   VGP_PUSHCC(VgpESPAdj);
-   ENSURE_MAPPABLE(a, "make_aligned_word_noaccess");
-   sm     = primary_map[PM_IDX(a)];
-   sm_off = SM_OFF(a);
-   ((UInt*)(sm->vbyte))[sm_off >> 2] = VGM_WORD_INVALID;
-   mask = 0x0F;
-   mask <<= (a & 4 /* 100b */);   /* a & 4 is either 0 or 4 */
-   /* mask now contains 1s where we wish to make address bits invalid (1s). */
-   sm->abits[sm_off >> 3] |= mask;
-   VGP_POPCC(VgpESPAdj);
+void make_aligned_word32_noaccess(Addr a)
+{
+   mc_make_noaccess(a, 4);
+//zz    SecMap* sm;
+//zz    UInt    sm_off;
+//zz    UChar   mask;
+//zz 
+//zz    VGP_PUSHCC(VgpESPAdj);
+//zz    ENSURE_MAPPABLE(a, "make_aligned_word_noaccess");
+//zz    sm     = primary_map[PM_IDX(a)];
+//zz    sm_off = SM_OFF(a);
+//zz    ((UInt*)(sm->vbyte))[sm_off >> 2] = VGM_WORD_INVALID;
+//zz    mask = 0x0F;
+//zz    mask <<= (a & 4 /* 100b */);   /* a & 4 is either 0 or 4 */
+//zz    /* mask now contains 1s where we wish to make address bits invalid (1s). */
+//zz    sm->abits[sm_off >> 3] |= mask;
+//zz    VGP_POPCC(VgpESPAdj);
 }
 
 /* Nb: by "aligned" here we mean 8-byte aligned */
 static __inline__
-void make_aligned_doubleword_writable(Addr a)
-{
-   SecMap* sm;
-   UInt    sm_off;
-
-   VGP_PUSHCC(VgpESPAdj);
-   ENSURE_MAPPABLE(a, "make_aligned_doubleword_writable");
-   sm = primary_map[PM_IDX(a)];
-   sm_off = SM_OFF(a);
-   sm->abits[sm_off >> 3] = VGM_BYTE_VALID;
-   ((UInt*)(sm->vbyte))[(sm_off >> 2) + 0] = VGM_WORD_INVALID;
-   ((UInt*)(sm->vbyte))[(sm_off >> 2) + 1] = VGM_WORD_INVALID;
-   VGP_POPCC(VgpESPAdj);
+void make_aligned_word64_writable(Addr a)
+{
+   mc_make_writable(a, 8);
+//zz    SecMap* sm;
+//zz    UInt    sm_off;
+//zz 
+//zz    VGP_PUSHCC(VgpESPAdj);
+//zz    ENSURE_MAPPABLE(a, "make_aligned_doubleword_writable");
+//zz    sm = primary_map[PM_IDX(a)];
+//zz    sm_off = SM_OFF(a);
+//zz    sm->abits[sm_off >> 3] = VGM_BYTE_VALID;
+//zz    ((UInt*)(sm->vbyte))[(sm_off >> 2) + 0] = VGM_WORD_INVALID;
+//zz    ((UInt*)(sm->vbyte))[(sm_off >> 2) + 1] = VGM_WORD_INVALID;
+//zz    VGP_POPCC(VgpESPAdj);
 }
 
 static __inline__
-void make_aligned_doubleword_noaccess(Addr a)
-{
-   SecMap* sm;
-   UInt    sm_off;
-
-   VGP_PUSHCC(VgpESPAdj);
-   ENSURE_MAPPABLE(a, "make_aligned_doubleword_noaccess");
-   sm = primary_map[PM_IDX(a)];
-   sm_off = SM_OFF(a);
-   sm->abits[sm_off >> 3] = VGM_BYTE_INVALID;
-   ((UInt*)(sm->vbyte))[(sm_off >> 2) + 0] = VGM_WORD_INVALID;
-   ((UInt*)(sm->vbyte))[(sm_off >> 2) + 1] = VGM_WORD_INVALID;
-   VGP_POPCC(VgpESPAdj);
-}
-
-/* The %esp update handling functions */
-ESP_UPDATE_HANDLERS ( make_aligned_word_writable,
-                      make_aligned_word_noaccess,
-                      make_aligned_doubleword_writable,
-                      make_aligned_doubleword_noaccess,
-                      mc_make_writable,
-                      mc_make_noaccess 
-                    );
+void make_aligned_word64_noaccess(Addr a)
+{
+   mc_make_noaccess(a, 8);
+//zz    SecMap* sm;
+//zz    UInt    sm_off;
+//zz 
+//zz    VGP_PUSHCC(VgpESPAdj);
+//zz    ENSURE_MAPPABLE(a, "make_aligned_doubleword_noaccess");
+//zz    sm = primary_map[PM_IDX(a)];
+//zz    sm_off = SM_OFF(a);
+//zz    sm->abits[sm_off >> 3] = VGM_BYTE_INVALID;
+//zz    ((UInt*)(sm->vbyte))[(sm_off >> 2) + 0] = VGM_WORD_INVALID;
+//zz    ((UInt*)(sm->vbyte))[(sm_off >> 2) + 1] = VGM_WORD_INVALID;
+//zz    VGP_POPCC(VgpESPAdj);
+}
+
+/* The stack-pointer update handling functions */
+SP_UPDATE_HANDLERS ( make_aligned_word32_writable,
+                     make_aligned_word32_noaccess,
+                     make_aligned_word64_writable,
+                     make_aligned_word64_noaccess,
+                     mc_make_writable,
+                     mc_make_noaccess 
+                   );
 
 /* Block-copy permissions (needed for implementing realloc()). */
 static void mc_copy_address_range_state ( Addr src, Addr dst, SizeT len )
 {
    SizeT i;
+   UWord abit, vbyte;
 
    DEBUG("mc_copy_address_range_state\n");
 
    PROF_EVENT(40);
    for (i = 0; i < len; i++) {
-      UChar abit  = get_abit ( src+i );
-      UChar vbyte = get_vbyte ( src+i );
       PROF_EVENT(41);
-      set_abit ( dst+i, abit );
-      set_vbyte ( dst+i, vbyte );
+      get_abit_and_vbyte( &abit, &vbyte, src+i );
+      set_abit_and_vbyte( dst+i, abit, vbyte );
    }
 }
 
+
 /*------------------------------------------------------------*/
 /*--- Checking memory                                      ---*/
 /*------------------------------------------------------------*/
@@ -583,13 +963,14 @@ static void mc_copy_address_range_state ( Addr src, Addr dst, SizeT len )
 static Bool mc_check_noaccess ( Addr a, SizeT len, Addr* bad_addr )
 {
    SizeT i;
-   UChar abit;
+   UWord abit;
    PROF_EVENT(42);
    for (i = 0; i < len; i++) {
       PROF_EVENT(43);
       abit = get_abit(a);
       if (abit == VGM_BIT_VALID) {
-         if (bad_addr != NULL) *bad_addr = a;
+         if (bad_addr != NULL) 
+            *bad_addr = a;
          return False;
       }
       a++;
@@ -600,7 +981,7 @@ static Bool mc_check_noaccess ( Addr a, SizeT len, Addr* bad_addr )
 static Bool mc_check_writable ( Addr a, SizeT len, Addr* bad_addr )
 {
    SizeT i;
-   UChar abit;
+   UWord abit;
    PROF_EVENT(42);
    for (i = 0; i < len; i++) {
       PROF_EVENT(43);
@@ -614,30 +995,27 @@ static Bool mc_check_writable ( Addr a, SizeT len, Addr* bad_addr )
    return True;
 }
 
-typedef enum {
-   MC_Ok = 5, MC_AddrErr = 6, MC_ValueErr = 7
-} MC_ReadResult;
-
 static MC_ReadResult mc_check_readable ( Addr a, SizeT len, Addr* bad_addr )
 {
    SizeT i;
-   UChar abit;
-   UChar vbyte;
+   UWord abit;
+   UWord vbyte;
 
    PROF_EVENT(44);
    DEBUG("mc_check_readable\n");
    for (i = 0; i < len; i++) {
-      abit  = get_abit(a);
-      vbyte = get_vbyte(a);
       PROF_EVENT(45);
+      get_abit_and_vbyte(&abit, &vbyte, a);
       // Report addressability errors in preference to definedness errors
       // by checking the A bits first.
       if (abit != VGM_BIT_VALID) {
-         if (bad_addr != NULL) *bad_addr = a;
+         if (bad_addr != NULL) 
+            *bad_addr = a;
          return MC_AddrErr;
       }
       if (vbyte != VGM_BYTE_VALID) {
-         if (bad_addr != NULL) *bad_addr = a;
+         if (bad_addr != NULL) 
+            *bad_addr = a;
          return MC_ValueErr;
       }
       a++;
@@ -652,25 +1030,27 @@ static MC_ReadResult mc_check_readable ( Addr a, SizeT len, Addr* bad_addr )
 
 static Bool mc_check_readable_asciiz ( Addr a, Addr* bad_addr )
 {
-   UChar abit;
-   UChar vbyte;
+   UWord abit;
+   UWord vbyte;
    PROF_EVENT(46);
    DEBUG("mc_check_readable_asciiz\n");
    while (True) {
       PROF_EVENT(47);
-      abit  = get_abit(a);
-      vbyte = get_vbyte(a);
+      get_abit_and_vbyte(&abit, &vbyte, a);
       // As in mc_check_readable(), check A bits first
       if (abit != VGM_BIT_VALID) {
-         if (bad_addr != NULL) *bad_addr = a;
+         if (bad_addr != NULL) 
+            *bad_addr = a;
          return MC_AddrErr;
       }
       if (vbyte != VGM_BYTE_VALID) {
-         if (bad_addr != NULL) *bad_addr = a;
+         if (bad_addr != NULL) 
+            *bad_addr = a;
          return MC_ValueErr;
       }
       /* Ok, a is safe to read. */
-      if (* ((UChar*)a) == 0) return MC_Ok;
+      if (* ((UChar*)a) == 0) 
+         return MC_Ok;
       a++;
    }
 }
@@ -755,7 +1135,7 @@ void mc_check_is_readable_asciiz ( CorePart part, ThreadId tid,
                                    Char* s, Addr str )
 {
    MC_ReadResult res;
-   Addr bad_addr = 0;   // initialise to shut gcc up
+   Addr bad_addr;
    /* VG_(message)(Vg_DebugMsg,"check is readable asciiz: 0x%x",str); */
 
    VGP_PUSHCC(VgpCheckMem);
@@ -770,7 +1150,6 @@ void mc_check_is_readable_asciiz ( CorePart part, ThreadId tid,
    VGP_POPCC(VgpCheckMem);
 }
 
-
 static
 void mc_new_mem_startup( Addr a, SizeT len, Bool rr, Bool ww, Bool xx )
 {
@@ -802,142 +1181,158 @@ void mc_post_mem_write(CorePart part, ThreadId tid, Addr a, SizeT len)
    mc_make_readable(a, len);
 }
 
+
 /*------------------------------------------------------------*/
 /*--- Register event handlers                              ---*/
 /*------------------------------------------------------------*/
 
-// When a reg is written, mark the corresponding shadow reg bytes as valid.
-static void mc_post_reg_write(CorePart part, ThreadId tid, OffT offset,
-                              SizeT size)
+/* When some chunk of guest state is written, mark the corresponding
+   shadow area as valid.  This is used to initialise arbitrarily large
+   chunks of guest state, hence the (somewhat arbitrary) 512 limit.
+*/
+static void mc_post_reg_write ( CorePart part, ThreadId tid, 
+                                OffT offset, SizeT size)
 {
-   UChar area[size];
+   UChar area[512];
+   tl_assert(size <= 512);
    VG_(memset)(area, VGM_BYTE_VALID, size);
    VG_(set_shadow_regs_area)( tid, offset, size, area );
 }
 
-static void mc_post_reg_write_clientcall(ThreadId tid, OffT offset, SizeT size,
-                                         Addr f)
+static 
+void mc_post_reg_write_clientcall ( ThreadId tid, 
+                                    OffT offset, SizeT size,
+                                    Addr f)
 {
    mc_post_reg_write(/*dummy*/0, tid, offset, size);
 }
 
-static void mc_pre_reg_read(CorePart part, ThreadId tid, Char* s, OffT offset,
-                            SizeT size)
+/* Look at the definedness of the guest's shadow state for 
+   [offset, offset+len).  If any part of that is undefined, record 
+   a parameter error.
+*/
+static void mc_pre_reg_read ( CorePart part, ThreadId tid, Char* s, 
+                              OffT offset, SizeT size)
 {
-   UWord mask;
-   UWord sh_reg_contents;
-   
-   // XXX: the only one at the moment
-   tl_assert(Vg_CoreSysCall == part);
-   
-   switch (size) {
-   case 4:  mask = 0xffffffff; break;
-   case 2:  mask = 0xffff;     break;
-   case 1:  mask = 0xff;       break;
-   default: VG_(tool_panic)("Unhandled size in mc_pre_reg_read");
-   }
-
-   VG_(get_shadow_regs_area)( tid, offset, size, (UChar*)&sh_reg_contents );
-   if ( VGM_WORD_VALID != (mask & sh_reg_contents) )
-      MAC_(record_param_error) ( tid, 0, /*isReg*/True, /*isUnaddr*/False, s );
-}
+   Int   i;
+   Bool  bad;
 
-/*------------------------------------------------------------*/
-/*--- Functions called directly from generated code.       ---*/
-/*------------------------------------------------------------*/
+   UChar area[16];
+   tl_assert(size <= 16);
 
-static __inline__ UInt rotateRight16 ( UInt x )
-{
-   /* Amazingly, gcc turns this into a single rotate insn. */
-   return (x >> 16) | (x << 16);
-}
+   VG_(get_shadow_regs_area)( tid, offset, size, area );
 
+   bad = False;
+   for (i = 0; i < size; i++) {
+      if (area[i] != VGM_BYTE_VALID) {
+         bad = False;
+         break;
+      }
+   }
 
-static __inline__ UInt shiftRight16 ( UInt x )
-{
-   return x >> 16;
+   if (bad)
+      MAC_(record_param_error) ( tid, 0, /*isReg*/True, /*isUnaddr*/False, s );
 }
 
 
-/* Read/write 1/2/4/8 sized V bytes, and emit an address error if
-   needed. */
-
-/* MC_(helperc_{LD,ST}V{1,2,4,8}) handle the common case fast.
-   Under all other circumstances, it defers to the relevant _SLOWLY
-   function, which can handle all situations.
-*/
+//zz /*------------------------------------------------------------*/
+//zz /*--- Functions called directly from generated code.       ---*/
+//zz /*------------------------------------------------------------*/
+//zz 
+//zz static __inline__ UInt rotateRight16 ( UInt x )
+//zz {
+//zz    /* Amazingly, gcc turns this into a single rotate insn. */
+//zz    return (x >> 16) | (x << 16);
+//zz }
+//zz 
+//zz 
+//zz static __inline__ UInt shiftRight16 ( UInt x )
+//zz {
+//zz    return x >> 16;
+//zz }
+//zz 
+//zz 
+//zz /* Read/write 1/2/4/8 sized V bytes, and emit an address error if
+//zz    needed. */
+//zz 
+//zz /* MC_(helperc_{LD,ST}V{1,2,4,8}) handle the common case fast.
+//zz    Under all other circumstances, it defers to the relevant _SLOWLY
+//zz    function, which can handle all situations.
+//zz */
 
 /* ------------------------ Size = 8 ------------------------ */
 
 VGA_REGPARM(1)
 ULong MC_(helperc_LOADV8) ( Addr a )
 {
-#  ifdef VG_DEBUG_MEMORY
-   return mc_rd_V8_SLOWLY(a);
-#  else
-   if (VG_IS_8_ALIGNED(a)) {
-      UInt    sec_no = shiftRight16(a) & 0xFFFF;
-      SecMap* sm     = primary_map[sec_no];
-      UInt    a_off  = (SM_OFF(a)) >> 3;
-      UChar   abits  = sm->abits[a_off];
-      if (abits == VGM_BYTE_VALID) {
-         /* a is 8-aligned, mapped, and addressible. */
-         UInt v_off = SM_OFF(a);
-         /* LITTLE-ENDIAN */
-         UInt vLo   = ((UInt*)(sm->vbyte))[ (v_off >> 2) ];
-         UInt vHi   = ((UInt*)(sm->vbyte))[ (v_off >> 2) + 1 ];
-         return ( ((ULong)vHi) << 32 ) | ((ULong)vLo);
-      } else {
-         return mc_rd_V8_SLOWLY(a);
-      }
-   }
-   else
-   if (VG_IS_4_ALIGNED(a)) {
-      /* LITTLE-ENDIAN */
-      UInt vLo =  MC_(helperc_LOADV4)(a+0);
-      UInt vHi =  MC_(helperc_LOADV4)(a+4);
-      return ( ((ULong)vHi) << 32 ) | ((ULong)vLo);
-   }
-   else
-      return mc_rd_V8_SLOWLY(a);
-#  endif
+   return mc_LOADVn_slow( a, 8, False/*littleendian*/ );
+//zz #  ifdef VG_DEBUG_MEMORY
+//zz    return mc_rd_V8_SLOWLY(a);
+//zz #  else
+//zz    if (VG_IS_8_ALIGNED(a)) {
+//zz       UInt    sec_no = shiftRight16(a) & 0xFFFF;
+//zz       SecMap* sm     = primary_map[sec_no];
+//zz       UInt    a_off  = (SM_OFF(a)) >> 3;
+//zz       UChar   abits  = sm->abits[a_off];
+//zz       if (abits == VGM_BYTE_VALID) {
+//zz          /* a is 8-aligned, mapped, and addressible. */
+//zz          UInt v_off = SM_OFF(a);
+//zz          /* LITTLE-ENDIAN */
+//zz          UInt vLo   = ((UInt*)(sm->vbyte))[ (v_off >> 2) ];
+//zz          UInt vHi   = ((UInt*)(sm->vbyte))[ (v_off >> 2) + 1 ];
+//zz          return ( ((ULong)vHi) << 32 ) | ((ULong)vLo);
+//zz       } else {
+//zz          return mc_rd_V8_SLOWLY(a);
+//zz       }
+//zz    }
+//zz    else
+//zz    if (VG_IS_4_ALIGNED(a)) {
+//zz       /* LITTLE-ENDIAN */
+//zz       UInt vLo =  MC_(helperc_LOADV4)(a+0);
+//zz       UInt vHi =  MC_(helperc_LOADV4)(a+4);
+//zz       return ( ((ULong)vHi) << 32 ) | ((ULong)vLo);
+//zz    }
+//zz    else
+//zz       return mc_rd_V8_SLOWLY(a);
+//zz #  endif
 }
 
 VGA_REGPARM(1)
 void MC_(helperc_STOREV8) ( Addr a, ULong vbytes )
 {
-#  ifdef VG_DEBUG_MEMORY
-   mc_wr_V8_SLOWLY(a, vbytes);
-#  else
-   if (VG_IS_8_ALIGNED(a)) {
-      UInt    sec_no = shiftRight16(a) & 0xFFFF;
-      SecMap* sm     = primary_map[sec_no];
-      UInt    a_off  = (SM_OFF(a)) >> 3;
-      if (!IS_DISTINGUISHED_SM(sm) && sm->abits[a_off] == VGM_BYTE_VALID) {
-         /* a is 8-aligned, mapped, and addressible. */
-         UInt v_off = SM_OFF(a);
-         UInt vHi = (UInt)(vbytes >> 32);
-         UInt vLo = (UInt)vbytes;
-         /* LITTLE-ENDIAN */
-         ((UInt*)(sm->vbyte))[ (v_off >> 2) ]     = vLo;
-         ((UInt*)(sm->vbyte))[ (v_off >> 2) + 1 ] = vHi;
-      } else {
-         mc_wr_V8_SLOWLY(a, vbytes);
-      }
-      return;
-   }
-   else
-   if (VG_IS_4_ALIGNED(a)) {
-      UInt vHi = (UInt)(vbytes >> 32);
-      UInt vLo = (UInt)vbytes;
-      /* LITTLE-ENDIAN */
-      MC_(helperc_STOREV4)(a+0, vLo);
-      MC_(helperc_STOREV4)(a+4, vHi);
-      return;
-   }
-   else
-      mc_wr_V8_SLOWLY(a, vbytes);
-#  endif
+   mc_STOREVn_slow( a, 8, vbytes, False/*littleendian*/ );
+//zz #  ifdef VG_DEBUG_MEMORY
+//zz    mc_wr_V8_SLOWLY(a, vbytes);
+//zz #  else
+//zz    if (VG_IS_8_ALIGNED(a)) {
+//zz       UInt    sec_no = shiftRight16(a) & 0xFFFF;
+//zz       SecMap* sm     = primary_map[sec_no];
+//zz       UInt    a_off  = (SM_OFF(a)) >> 3;
+//zz       if (!IS_DISTINGUISHED_SM(sm) && sm->abits[a_off] == VGM_BYTE_VALID) {
+//zz          /* a is 8-aligned, mapped, and addressible. */
+//zz          UInt v_off = SM_OFF(a);
+//zz          UInt vHi = (UInt)(vbytes >> 32);
+//zz          UInt vLo = (UInt)vbytes;
+//zz          /* LITTLE-ENDIAN */
+//zz          ((UInt*)(sm->vbyte))[ (v_off >> 2) ]     = vLo;
+//zz          ((UInt*)(sm->vbyte))[ (v_off >> 2) + 1 ] = vHi;
+//zz       } else {
+//zz          mc_wr_V8_SLOWLY(a, vbytes);
+//zz       }
+//zz       return;
+//zz    }
+//zz    else
+//zz    if (VG_IS_4_ALIGNED(a)) {
+//zz       UInt vHi = (UInt)(vbytes >> 32);
+//zz       UInt vLo = (UInt)vbytes;
+//zz       /* LITTLE-ENDIAN */
+//zz       MC_(helperc_STOREV4)(a+0, vLo);
+//zz       MC_(helperc_STOREV4)(a+4, vHi);
+//zz       return;
+//zz    }
+//zz    else
+//zz       mc_wr_V8_SLOWLY(a, vbytes);
+//zz #  endif
 }
 
 /* ------------------------ Size = 4 ------------------------ */
@@ -945,51 +1340,53 @@ void MC_(helperc_STOREV8) ( Addr a, ULong vbytes )
 VGA_REGPARM(1)
 UInt MC_(helperc_LOADV4) ( Addr a )
 {
-#  ifdef VG_DEBUG_MEMORY
-   return mc_rd_V4_SLOWLY(a);
-#  else
-   UInt    sec_no = rotateRight16(a) & 0x3FFFF;
-   SecMap* sm     = primary_map[sec_no];
-   UInt    a_off  = (SM_OFF(a)) >> 3;
-   UChar   abits  = sm->abits[a_off];
-   abits >>= (a & 4);
-   abits &= 15;
-   PROF_EVENT(60);
-   if (abits == VGM_NIBBLE_VALID) {
-      /* Handle common case quickly: a is suitably aligned, is mapped,
-         and is addressible. */
-      UInt v_off = SM_OFF(a);
-      return ((UInt*)(sm->vbyte))[ v_off >> 2 ];
-   } else {
-      /* Slow but general case. */
-      return mc_rd_V4_SLOWLY(a);
-   }
-#  endif
+   return (UInt)mc_LOADVn_slow( a, 4, False/*littleendian*/ );
+//zz #  ifdef VG_DEBUG_MEMORY
+//zz    return mc_rd_V4_SLOWLY(a);
+//zz #  else
+//zz    UInt    sec_no = rotateRight16(a) & 0x3FFFF;
+//zz    SecMap* sm     = primary_map[sec_no];
+//zz    UInt    a_off  = (SM_OFF(a)) >> 3;
+//zz    UChar   abits  = sm->abits[a_off];
+//zz    abits >>= (a & 4);
+//zz    abits &= 15;
+//zz    PROF_EVENT(60);
+//zz    if (abits == VGM_NIBBLE_VALID) {
+//zz       /* Handle common case quickly: a is suitably aligned, is mapped,
+//zz          and is addressible. */
+//zz       UInt v_off = SM_OFF(a);
+//zz       return ((UInt*)(sm->vbyte))[ v_off >> 2 ];
+//zz    } else {
+//zz       /* Slow but general case. */
+//zz       return mc_rd_V4_SLOWLY(a);
+//zz    }
+//zz #  endif
 }
 
 VGA_REGPARM(2)
 void MC_(helperc_STOREV4) ( Addr a, UInt vbytes )
 {
-#  ifdef VG_DEBUG_MEMORY
-   mc_wr_V4_SLOWLY(a, vbytes);
-#  else
-   UInt    sec_no = rotateRight16(a) & 0x3FFFF;
-   SecMap* sm     = primary_map[sec_no];
-   UInt    a_off  = (SM_OFF(a)) >> 3;
-   UChar   abits  = sm->abits[a_off];
-   abits >>= (a & 4);
-   abits &= 15;
-   PROF_EVENT(61);
-   if (!IS_DISTINGUISHED_SM(sm) && abits == VGM_NIBBLE_VALID) {
-      /* Handle common case quickly: a is suitably aligned, is mapped,
-         and is addressible. */
-      UInt v_off = SM_OFF(a);
-      ((UInt*)(sm->vbyte))[ v_off >> 2 ] = vbytes;
-   } else {
-      /* Slow but general case. */
-      mc_wr_V4_SLOWLY(a, vbytes);
-   }
-#  endif
+   mc_STOREVn_slow( a, 4, vbytes, False/*littleendian*/ );
+//zz #  ifdef VG_DEBUG_MEMORY
+//zz    mc_wr_V4_SLOWLY(a, vbytes);
+//zz #  else
+//zz    UInt    sec_no = rotateRight16(a) & 0x3FFFF;
+//zz    SecMap* sm     = primary_map[sec_no];
+//zz    UInt    a_off  = (SM_OFF(a)) >> 3;
+//zz    UChar   abits  = sm->abits[a_off];
+//zz    abits >>= (a & 4);
+//zz    abits &= 15;
+//zz    PROF_EVENT(61);
+//zz    if (!IS_DISTINGUISHED_SM(sm) && abits == VGM_NIBBLE_VALID) {
+//zz       /* Handle common case quickly: a is suitably aligned, is mapped,
+//zz          and is addressible. */
+//zz       UInt v_off = SM_OFF(a);
+//zz       ((UInt*)(sm->vbyte))[ v_off >> 2 ] = vbytes;
+//zz    } else {
+//zz       /* Slow but general case. */
+//zz       mc_wr_V4_SLOWLY(a, vbytes);
+//zz    }
+//zz #  endif
 }
 
 /* ------------------------ Size = 2 ------------------------ */
@@ -997,45 +1394,47 @@ void MC_(helperc_STOREV4) ( Addr a, UInt vbytes )
 VGA_REGPARM(1)
 UInt MC_(helperc_LOADV2) ( Addr a )
 {
-#  ifdef VG_DEBUG_MEMORY
-   return mc_rd_V2_SLOWLY(a);
-#  else
-   UInt    sec_no = rotateRight16(a) & 0x1FFFF;
-   SecMap* sm     = primary_map[sec_no];
-   UInt    a_off  = (SM_OFF(a)) >> 3;
-   PROF_EVENT(62);
-   if (sm->abits[a_off] == VGM_BYTE_VALID) {
-      /* Handle common case quickly. */
-      UInt v_off = SM_OFF(a);
-      return 0xFFFF0000 
-             |  
-             (UInt)( ((UShort*)(sm->vbyte))[ v_off >> 1 ] );
-   } else {
-      /* Slow but general case. */
-      return mc_rd_V2_SLOWLY(a);
-   }
-#  endif
+   return (UInt)mc_LOADVn_slow( a, 2, False/*littleendian*/ );
+//zz #  ifdef VG_DEBUG_MEMORY
+//zz    return mc_rd_V2_SLOWLY(a);
+//zz #  else
+//zz    UInt    sec_no = rotateRight16(a) & 0x1FFFF;
+//zz    SecMap* sm     = primary_map[sec_no];
+//zz    UInt    a_off  = (SM_OFF(a)) >> 3;
+//zz    PROF_EVENT(62);
+//zz    if (sm->abits[a_off] == VGM_BYTE_VALID) {
+//zz       /* Handle common case quickly. */
+//zz       UInt v_off = SM_OFF(a);
+//zz       return 0xFFFF0000 
+//zz              |  
+//zz              (UInt)( ((UShort*)(sm->vbyte))[ v_off >> 1 ] );
+//zz    } else {
+//zz       /* Slow but general case. */
+//zz       return mc_rd_V2_SLOWLY(a);
+//zz    }
+//zz #  endif
 }
 
 VGA_REGPARM(2)
 void MC_(helperc_STOREV2) ( Addr a, UInt vbytes )
 {
-#  ifdef VG_DEBUG_MEMORY
-   mc_wr_V2_SLOWLY(a, vbytes);
-#  else
-   UInt    sec_no = rotateRight16(a) & 0x1FFFF;
-   SecMap* sm     = primary_map[sec_no];
-   UInt    a_off  = (SM_OFF(a)) >> 3;
-   PROF_EVENT(63);
-   if (!IS_DISTINGUISHED_SM(sm) && sm->abits[a_off] == VGM_BYTE_VALID) {
-      /* Handle common case quickly. */
-      UInt v_off = SM_OFF(a);
-      ((UShort*)(sm->vbyte))[ v_off >> 1 ] = vbytes & 0x0000FFFF;
-   } else {
-      /* Slow but general case. */
-      mc_wr_V2_SLOWLY(a, vbytes);
-   }
-#  endif
+   mc_STOREVn_slow( a, 2, vbytes, False/*littleendian*/ );
+//zz #  ifdef VG_DEBUG_MEMORY
+//zz    mc_wr_V2_SLOWLY(a, vbytes);
+//zz #  else
+//zz    UInt    sec_no = rotateRight16(a) & 0x1FFFF;
+//zz    SecMap* sm     = primary_map[sec_no];
+//zz    UInt    a_off  = (SM_OFF(a)) >> 3;
+//zz    PROF_EVENT(63);
+//zz    if (!IS_DISTINGUISHED_SM(sm) && sm->abits[a_off] == VGM_BYTE_VALID) {
+//zz       /* Handle common case quickly. */
+//zz       UInt v_off = SM_OFF(a);
+//zz       ((UShort*)(sm->vbyte))[ v_off >> 1 ] = vbytes & 0x0000FFFF;
+//zz    } else {
+//zz       /* Slow but general case. */
+//zz       mc_wr_V2_SLOWLY(a, vbytes);
+//zz    }
+//zz #  endif
 }
 
 /* ------------------------ Size = 1 ------------------------ */
@@ -1043,346 +1442,348 @@ void MC_(helperc_STOREV2) ( Addr a, UInt vbytes )
 VGA_REGPARM(1)
 UInt MC_(helperc_LOADV1) ( Addr a )
 {
-#  ifdef VG_DEBUG_MEMORY
-   return mc_rd_V1_SLOWLY(a);
-#  else
-   UInt    sec_no = shiftRight16(a);
-   SecMap* sm     = primary_map[sec_no];
-   UInt    a_off  = (SM_OFF(a)) >> 3;
-   PROF_EVENT(64);
-   if (sm->abits[a_off] == VGM_BYTE_VALID) {
-      /* Handle common case quickly. */
-      UInt v_off = SM_OFF(a);
-      return 0xFFFFFF00
-             |
-             (UInt)( ((UChar*)(sm->vbyte))[ v_off ] );
-   } else {
-      /* Slow but general case. */
-      return mc_rd_V1_SLOWLY(a);
-   }
-#  endif
+   return (UInt)mc_LOADVn_slow( a, 1, False/*littleendian*/ );
+//zz #  ifdef VG_DEBUG_MEMORY
+//zz    return mc_rd_V1_SLOWLY(a);
+//zz #  else
+//zz    UInt    sec_no = shiftRight16(a);
+//zz    SecMap* sm     = primary_map[sec_no];
+//zz    UInt    a_off  = (SM_OFF(a)) >> 3;
+//zz    PROF_EVENT(64);
+//zz    if (sm->abits[a_off] == VGM_BYTE_VALID) {
+//zz       /* Handle common case quickly. */
+//zz       UInt v_off = SM_OFF(a);
+//zz       return 0xFFFFFF00
+//zz              |
+//zz              (UInt)( ((UChar*)(sm->vbyte))[ v_off ] );
+//zz    } else {
+//zz       /* Slow but general case. */
+//zz       return mc_rd_V1_SLOWLY(a);
+//zz    }
+//zz #  endif
 }
 
 VGA_REGPARM(2)
 void MC_(helperc_STOREV1) ( Addr a, UInt vbytes )
 {
-#  ifdef VG_DEBUG_MEMORY
-   mc_wr_V1_SLOWLY(a, vbytes);
-#  else
-   UInt    sec_no = shiftRight16(a);
-   SecMap* sm     = primary_map[sec_no];
-   UInt    a_off  = (SM_OFF(a)) >> 3;
-   PROF_EVENT(65);
-   if (!IS_DISTINGUISHED_SM(sm) && sm->abits[a_off] == VGM_BYTE_VALID) {
-      /* Handle common case quickly. */
-      UInt v_off = SM_OFF(a);
-      ((UChar*)(sm->vbyte))[ v_off ] = vbytes & 0x000000FF;
-   } else {
-      /* Slow but general case. */
-      mc_wr_V1_SLOWLY(a, vbytes);
-   }
-#  endif
-}
-
-
-/*------------------------------------------------------------*/
-/*--- Fallback functions to handle cases that the above    ---*/
-/*--- VG_(helperc_{LD,ST}V{1,2,4,8}) can't manage.         ---*/
-/*------------------------------------------------------------*/
-
-/* ------------------------ Size = 8 ------------------------ */
-
-static ULong mc_rd_V8_SLOWLY ( Addr a )
-{
-   Bool a0ok, a1ok, a2ok, a3ok, a4ok, a5ok, a6ok, a7ok;
-   UInt vb0,  vb1,  vb2,  vb3,  vb4,  vb5,  vb6,  vb7;
-
-   PROF_EVENT(70);
-
-   /* First establish independently the addressibility of the 4 bytes
-      involved. */
-   a0ok = get_abit(a+0) == VGM_BIT_VALID;
-   a1ok = get_abit(a+1) == VGM_BIT_VALID;
-   a2ok = get_abit(a+2) == VGM_BIT_VALID;
-   a3ok = get_abit(a+3) == VGM_BIT_VALID;
-   a4ok = get_abit(a+4) == VGM_BIT_VALID;
-   a5ok = get_abit(a+5) == VGM_BIT_VALID;
-   a6ok = get_abit(a+6) == VGM_BIT_VALID;
-   a7ok = get_abit(a+7) == VGM_BIT_VALID;
-
-   /* Also get the validity bytes for the address. */
-   vb0 = (UInt)get_vbyte(a+0);
-   vb1 = (UInt)get_vbyte(a+1);
-   vb2 = (UInt)get_vbyte(a+2);
-   vb3 = (UInt)get_vbyte(a+3);
-   vb4 = (UInt)get_vbyte(a+4);
-   vb5 = (UInt)get_vbyte(a+5);
-   vb6 = (UInt)get_vbyte(a+6);
-   vb7 = (UInt)get_vbyte(a+7);
-
-   /* Now distinguish 3 cases */
-
-   /* Case 1: the address is completely valid, so:
-      - no addressing error
-      - return V bytes as read from memory
-   */
-   if (a0ok && a1ok && a2ok && a3ok && a4ok && a5ok && a6ok && a7ok) {
-      ULong vw = VGM_WORD64_INVALID;
-      vw <<= 8; vw |= vb7;
-      vw <<= 8; vw |= vb6;
-      vw <<= 8; vw |= vb5;
-      vw <<= 8; vw |= vb4;
-      vw <<= 8; vw |= vb3;
-      vw <<= 8; vw |= vb2;
-      vw <<= 8; vw |= vb1;
-      vw <<= 8; vw |= vb0;
-      return vw;
-   }
-
-   /* Case 2: the address is completely invalid.  
-      - emit addressing error
-      - return V word indicating validity.  
-      This sounds strange, but if we make loads from invalid addresses 
-      give invalid data, we also risk producing a number of confusing
-      undefined-value errors later, which confuses the fact that the
-      error arose in the first place from an invalid address. 
-   */
-   /* VG_(printf)("%p (%d %d %d %d)\n", a, a0ok, a1ok, a2ok, a3ok); */
-   if (!MAC_(clo_partial_loads_ok) 
-       || ((a & 7) != 0)
-       || (!a0ok && !a1ok && !a2ok && !a3ok && !a4ok && !a5ok && !a6ok && !a7ok)) {
-      MAC_(record_address_error)( VG_(get_running_tid)(), a, 8, False );
-      return VGM_WORD64_VALID;
-   }
-
-   /* Case 3: the address is partially valid.  
-      - no addressing error
-      - returned V word is invalid where the address is invalid, 
-        and contains V bytes from memory otherwise. 
-      Case 3 is only allowed if MC_(clo_partial_loads_ok) is True
-      (which is the default), and the address is 4-aligned.  
-      If not, Case 2 will have applied.
-   */
-   tl_assert(MAC_(clo_partial_loads_ok));
-   {
-      ULong vw = VGM_WORD64_INVALID;
-      vw <<= 8; vw |= (a7ok ? vb7 : VGM_BYTE_INVALID);
-      vw <<= 8; vw |= (a6ok ? vb6 : VGM_BYTE_INVALID);
-      vw <<= 8; vw |= (a5ok ? vb5 : VGM_BYTE_INVALID);
-      vw <<= 8; vw |= (a4ok ? vb4 : VGM_BYTE_INVALID);
-      vw <<= 8; vw |= (a3ok ? vb3 : VGM_BYTE_INVALID);
-      vw <<= 8; vw |= (a2ok ? vb2 : VGM_BYTE_INVALID);
-      vw <<= 8; vw |= (a1ok ? vb1 : VGM_BYTE_INVALID);
-      vw <<= 8; vw |= (a0ok ? vb0 : VGM_BYTE_INVALID);
-      return vw;
-   }
-}
-
-static void mc_wr_V8_SLOWLY ( Addr a, ULong vbytes )
-{
-   /* Check the address for validity. */
-   Bool aerr = False;
-   PROF_EVENT(71);
-
-   if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
-   if (get_abit(a+1) != VGM_BIT_VALID) aerr = True;
-   if (get_abit(a+2) != VGM_BIT_VALID) aerr = True;
-   if (get_abit(a+3) != VGM_BIT_VALID) aerr = True;
-   if (get_abit(a+4) != VGM_BIT_VALID) aerr = True;
-   if (get_abit(a+5) != VGM_BIT_VALID) aerr = True;
-   if (get_abit(a+6) != VGM_BIT_VALID) aerr = True;
-   if (get_abit(a+7) != VGM_BIT_VALID) aerr = True;
-
-   /* Store the V bytes, remembering to do it little-endian-ly. */
-   set_vbyte( a+0, vbytes & 0x000000FF ); vbytes >>= 8;
-   set_vbyte( a+1, vbytes & 0x000000FF ); vbytes >>= 8;
-   set_vbyte( a+2, vbytes & 0x000000FF ); vbytes >>= 8;
-   set_vbyte( a+3, vbytes & 0x000000FF ); vbytes >>= 8;
-   set_vbyte( a+4, vbytes & 0x000000FF ); vbytes >>= 8;
-   set_vbyte( a+5, vbytes & 0x000000FF ); vbytes >>= 8;
-   set_vbyte( a+6, vbytes & 0x000000FF ); vbytes >>= 8;
-   set_vbyte( a+7, vbytes & 0x000000FF );
-
-   /* If an address error has happened, report it. */
-   if (aerr)
-      MAC_(record_address_error)( VG_(get_running_tid)(), a, 8, True );
-}
-
-/* ------------------------ Size = 4 ------------------------ */
-
-static UInt mc_rd_V4_SLOWLY ( Addr a )
-{
-   Bool a0ok, a1ok, a2ok, a3ok;
-   UInt vb0, vb1, vb2, vb3;
-
-   PROF_EVENT(70);
-
-   /* First establish independently the addressibility of the 4 bytes
-      involved. */
-   a0ok = get_abit(a+0) == VGM_BIT_VALID;
-   a1ok = get_abit(a+1) == VGM_BIT_VALID;
-   a2ok = get_abit(a+2) == VGM_BIT_VALID;
-   a3ok = get_abit(a+3) == VGM_BIT_VALID;
-
-   /* Also get the validity bytes for the address. */
-   vb0 = (UInt)get_vbyte(a+0);
-   vb1 = (UInt)get_vbyte(a+1);
-   vb2 = (UInt)get_vbyte(a+2);
-   vb3 = (UInt)get_vbyte(a+3);
-
-   /* Now distinguish 3 cases */
-
-   /* Case 1: the address is completely valid, so:
-      - no addressing error
-      - return V bytes as read from memory
-   */
-   if (a0ok && a1ok && a2ok && a3ok) {
-      UInt vw = VGM_WORD_INVALID;
-      vw <<= 8; vw |= vb3;
-      vw <<= 8; vw |= vb2;
-      vw <<= 8; vw |= vb1;
-      vw <<= 8; vw |= vb0;
-      return vw;
-   }
-
-   /* Case 2: the address is completely invalid.  
-      - emit addressing error
-      - return V word indicating validity.  
-      This sounds strange, but if we make loads from invalid addresses 
-      give invalid data, we also risk producing a number of confusing
-      undefined-value errors later, which confuses the fact that the
-      error arose in the first place from an invalid address. 
-   */
-   /* VG_(printf)("%p (%d %d %d %d)\n", a, a0ok, a1ok, a2ok, a3ok); */
-   if (!MAC_(clo_partial_loads_ok) 
-       || ((a & 3) != 0)
-       || (!a0ok && !a1ok && !a2ok && !a3ok)) {
-      MAC_(record_address_error)( VG_(get_running_tid)(), a, 4, False );
-      return (VGM_BYTE_VALID << 24) | (VGM_BYTE_VALID << 16) 
-             | (VGM_BYTE_VALID << 8) | VGM_BYTE_VALID;
-   }
-
-   /* Case 3: the address is partially valid.  
-      - no addressing error
-      - returned V word is invalid where the address is invalid, 
-        and contains V bytes from memory otherwise. 
-      Case 3 is only allowed if MC_(clo_partial_loads_ok) is True
-      (which is the default), and the address is 4-aligned.  
-      If not, Case 2 will have applied.
-   */
-   tl_assert(MAC_(clo_partial_loads_ok));
-   {
-      UInt vw = VGM_WORD_INVALID;
-      vw <<= 8; vw |= (a3ok ? vb3 : VGM_BYTE_INVALID);
-      vw <<= 8; vw |= (a2ok ? vb2 : VGM_BYTE_INVALID);
-      vw <<= 8; vw |= (a1ok ? vb1 : VGM_BYTE_INVALID);
-      vw <<= 8; vw |= (a0ok ? vb0 : VGM_BYTE_INVALID);
-      return vw;
-   }
-}
-
-static void mc_wr_V4_SLOWLY ( Addr a, UInt vbytes )
-{
-   /* Check the address for validity. */
-   Bool aerr = False;
-   PROF_EVENT(71);
-
-   if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
-   if (get_abit(a+1) != VGM_BIT_VALID) aerr = True;
-   if (get_abit(a+2) != VGM_BIT_VALID) aerr = True;
-   if (get_abit(a+3) != VGM_BIT_VALID) aerr = True;
-
-   /* Store the V bytes, remembering to do it little-endian-ly. */
-   set_vbyte( a+0, vbytes & 0x000000FF ); vbytes >>= 8;
-   set_vbyte( a+1, vbytes & 0x000000FF ); vbytes >>= 8;
-   set_vbyte( a+2, vbytes & 0x000000FF ); vbytes >>= 8;
-   set_vbyte( a+3, vbytes & 0x000000FF );
-
-   /* If an address error has happened, report it. */
-   if (aerr)
-      MAC_(record_address_error)( VG_(get_running_tid)(), a, 4, True );
-}
-
-/* ------------------------ Size = 2 ------------------------ */
-
-static UInt mc_rd_V2_SLOWLY ( Addr a )
-{
-   /* Check the address for validity. */
-   UInt vw   = VGM_WORD_INVALID;
-   Bool aerr = False;
-   PROF_EVENT(72);
-
-   if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
-   if (get_abit(a+1) != VGM_BIT_VALID) aerr = True;
-
-   /* Fetch the V bytes, remembering to do it little-endian-ly. */
-   vw <<= 8; vw |= (UInt)get_vbyte(a+1);
-   vw <<= 8; vw |= (UInt)get_vbyte(a+0);
-
-   /* If an address error has happened, report it. */
-   if (aerr) {
-      MAC_(record_address_error)( VG_(get_running_tid)(), a, 2, False );
-      vw = (VGM_BYTE_INVALID << 24) | (VGM_BYTE_INVALID << 16) 
-           | (VGM_BYTE_VALID << 8) | (VGM_BYTE_VALID);
-   }
-   return vw;   
-}
-
-static void mc_wr_V2_SLOWLY ( Addr a, UInt vbytes )
-{
-   /* Check the address for validity. */
-   Bool aerr = False;
-   PROF_EVENT(73);
-
-   if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
-   if (get_abit(a+1) != VGM_BIT_VALID) aerr = True;
-
-   /* Store the V bytes, remembering to do it little-endian-ly. */
-   set_vbyte( a+0, vbytes & 0x000000FF ); vbytes >>= 8;
-   set_vbyte( a+1, vbytes & 0x000000FF );
-
-   /* If an address error has happened, report it. */
-   if (aerr)
-      MAC_(record_address_error)( VG_(get_running_tid)(), a, 2, True );
-}
-
-/* ------------------------ Size = 1 ------------------------ */
-
-static UInt mc_rd_V1_SLOWLY ( Addr a )
-{
-   /* Check the address for validity. */
-   UInt vw   = VGM_WORD_INVALID;
-   Bool aerr = False;
-   PROF_EVENT(74);
-
-   if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
-
-   /* Fetch the V byte. */
-   vw <<= 8; vw |= (UInt)get_vbyte(a+0);
-
-   /* If an address error has happened, report it. */
-   if (aerr) {
-      MAC_(record_address_error)( VG_(get_running_tid)(), a, 1, False );
-      vw = (VGM_BYTE_INVALID << 24) | (VGM_BYTE_INVALID << 16) 
-           | (VGM_BYTE_INVALID << 8) | (VGM_BYTE_VALID);
-   }
-   return vw;   
-}
-
-static void mc_wr_V1_SLOWLY ( Addr a, UInt vbytes )
-{
-   /* Check the address for validity. */
-   Bool aerr = False;
-   PROF_EVENT(75);
-   if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
-
-   /* Store the V bytes, remembering to do it little-endian-ly. */
-   set_vbyte( a+0, vbytes & 0x000000FF );
-
-   /* If an address error has happened, report it. */
-   if (aerr)
-      MAC_(record_address_error)( VG_(get_running_tid)(), a, 1, True );
-}
+   mc_STOREVn_slow( a, 1, vbytes, False/*littleendian*/ );
+//zz #  ifdef VG_DEBUG_MEMORY
+//zz    mc_wr_V1_SLOWLY(a, vbytes);
+//zz #  else
+//zz    UInt    sec_no = shiftRight16(a);
+//zz    SecMap* sm     = primary_map[sec_no];
+//zz    UInt    a_off  = (SM_OFF(a)) >> 3;
+//zz    PROF_EVENT(65);
+//zz    if (!IS_DISTINGUISHED_SM(sm) && sm->abits[a_off] == VGM_BYTE_VALID) {
+//zz       /* Handle common case quickly. */
+//zz       UInt v_off = SM_OFF(a);
+//zz       ((UChar*)(sm->vbyte))[ v_off ] = vbytes & 0x000000FF;
+//zz    } else {
+//zz       /* Slow but general case. */
+//zz       mc_wr_V1_SLOWLY(a, vbytes);
+//zz    }
+//zz #  endif
+}
+
+
+//zz /*------------------------------------------------------------*/
+//zz /*--- Fallback functions to handle cases that the above    ---*/
+//zz /*--- VG_(helperc_{LD,ST}V{1,2,4,8}) can't manage.         ---*/
+//zz /*------------------------------------------------------------*/
+//zz 
+//zz /* ------------------------ Size = 8 ------------------------ */
+//zz 
+//zz static ULong mc_rd_V8_SLOWLY ( Addr a )
+//zz {
+//zz    Bool a0ok, a1ok, a2ok, a3ok, a4ok, a5ok, a6ok, a7ok;
+//zz    UInt vb0,  vb1,  vb2,  vb3,  vb4,  vb5,  vb6,  vb7;
+//zz 
+//zz    PROF_EVENT(70);
+//zz 
+//zz    /* First establish independently the addressibility of the 4 bytes
+//zz       involved. */
+//zz    a0ok = get_abit(a+0) == VGM_BIT_VALID;
+//zz    a1ok = get_abit(a+1) == VGM_BIT_VALID;
+//zz    a2ok = get_abit(a+2) == VGM_BIT_VALID;
+//zz    a3ok = get_abit(a+3) == VGM_BIT_VALID;
+//zz    a4ok = get_abit(a+4) == VGM_BIT_VALID;
+//zz    a5ok = get_abit(a+5) == VGM_BIT_VALID;
+//zz    a6ok = get_abit(a+6) == VGM_BIT_VALID;
+//zz    a7ok = get_abit(a+7) == VGM_BIT_VALID;
+//zz 
+//zz    /* Also get the validity bytes for the address. */
+//zz    vb0 = (UInt)get_vbyte(a+0);
+//zz    vb1 = (UInt)get_vbyte(a+1);
+//zz    vb2 = (UInt)get_vbyte(a+2);
+//zz    vb3 = (UInt)get_vbyte(a+3);
+//zz    vb4 = (UInt)get_vbyte(a+4);
+//zz    vb5 = (UInt)get_vbyte(a+5);
+//zz    vb6 = (UInt)get_vbyte(a+6);
+//zz    vb7 = (UInt)get_vbyte(a+7);
+//zz 
+//zz    /* Now distinguish 3 cases */
+//zz 
+//zz    /* Case 1: the address is completely valid, so:
+//zz       - no addressing error
+//zz       - return V bytes as read from memory
+//zz    */
+//zz    if (a0ok && a1ok && a2ok && a3ok && a4ok && a5ok && a6ok && a7ok) {
+//zz       ULong vw = VGM_WORD64_INVALID;
+//zz       vw <<= 8; vw |= vb7;
+//zz       vw <<= 8; vw |= vb6;
+//zz       vw <<= 8; vw |= vb5;
+//zz       vw <<= 8; vw |= vb4;
+//zz       vw <<= 8; vw |= vb3;
+//zz       vw <<= 8; vw |= vb2;
+//zz       vw <<= 8; vw |= vb1;
+//zz       vw <<= 8; vw |= vb0;
+//zz       return vw;
+//zz    }
+//zz 
+//zz    /* Case 2: the address is completely invalid.  
+//zz       - emit addressing error
+//zz       - return V word indicating validity.  
+//zz       This sounds strange, but if we make loads from invalid addresses 
+//zz       give invalid data, we also risk producing a number of confusing
+//zz       undefined-value errors later, which confuses the fact that the
+//zz       error arose in the first place from an invalid address. 
+//zz    */
+//zz    /* VG_(printf)("%p (%d %d %d %d)\n", a, a0ok, a1ok, a2ok, a3ok); */
+//zz    if (!MAC_(clo_partial_loads_ok) 
+//zz        || ((a & 7) != 0)
+//zz        || (!a0ok && !a1ok && !a2ok && !a3ok && !a4ok && !a5ok && !a6ok && !a7ok)) {
+//zz       MAC_(record_address_error)( VG_(get_running_tid)(), a, 8, False );
+//zz       return VGM_WORD64_VALID;
+//zz    }
+//zz 
+//zz    /* Case 3: the address is partially valid.  
+//zz       - no addressing error
+//zz       - returned V word is invalid where the address is invalid, 
+//zz         and contains V bytes from memory otherwise. 
+//zz       Case 3 is only allowed if MC_(clo_partial_loads_ok) is True
+//zz       (which is the default), and the address is 4-aligned.  
+//zz       If not, Case 2 will have applied.
+//zz    */
+//zz    tl_assert(MAC_(clo_partial_loads_ok));
+//zz    {
+//zz       ULong vw = VGM_WORD64_INVALID;
+//zz       vw <<= 8; vw |= (a7ok ? vb7 : VGM_BYTE_INVALID);
+//zz       vw <<= 8; vw |= (a6ok ? vb6 : VGM_BYTE_INVALID);
+//zz       vw <<= 8; vw |= (a5ok ? vb5 : VGM_BYTE_INVALID);
+//zz       vw <<= 8; vw |= (a4ok ? vb4 : VGM_BYTE_INVALID);
+//zz       vw <<= 8; vw |= (a3ok ? vb3 : VGM_BYTE_INVALID);
+//zz       vw <<= 8; vw |= (a2ok ? vb2 : VGM_BYTE_INVALID);
+//zz       vw <<= 8; vw |= (a1ok ? vb1 : VGM_BYTE_INVALID);
+//zz       vw <<= 8; vw |= (a0ok ? vb0 : VGM_BYTE_INVALID);
+//zz       return vw;
+//zz    }
+//zz }
+//zz 
+//zz static void mc_wr_V8_SLOWLY ( Addr a, ULong vbytes )
+//zz {
+//zz    /* Check the address for validity. */
+//zz    Bool aerr = False;
+//zz    PROF_EVENT(71);
+//zz 
+//zz    if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
+//zz    if (get_abit(a+1) != VGM_BIT_VALID) aerr = True;
+//zz    if (get_abit(a+2) != VGM_BIT_VALID) aerr = True;
+//zz    if (get_abit(a+3) != VGM_BIT_VALID) aerr = True;
+//zz    if (get_abit(a+4) != VGM_BIT_VALID) aerr = True;
+//zz    if (get_abit(a+5) != VGM_BIT_VALID) aerr = True;
+//zz    if (get_abit(a+6) != VGM_BIT_VALID) aerr = True;
+//zz    if (get_abit(a+7) != VGM_BIT_VALID) aerr = True;
+//zz 
+//zz    /* Store the V bytes, remembering to do it little-endian-ly. */
+//zz    set_vbyte( a+0, vbytes & 0x000000FF ); vbytes >>= 8;
+//zz    set_vbyte( a+1, vbytes & 0x000000FF ); vbytes >>= 8;
+//zz    set_vbyte( a+2, vbytes & 0x000000FF ); vbytes >>= 8;
+//zz    set_vbyte( a+3, vbytes & 0x000000FF ); vbytes >>= 8;
+//zz    set_vbyte( a+4, vbytes & 0x000000FF ); vbytes >>= 8;
+//zz    set_vbyte( a+5, vbytes & 0x000000FF ); vbytes >>= 8;
+//zz    set_vbyte( a+6, vbytes & 0x000000FF ); vbytes >>= 8;
+//zz    set_vbyte( a+7, vbytes & 0x000000FF );
+//zz 
+//zz    /* If an address error has happened, report it. */
+//zz    if (aerr)
+//zz       MAC_(record_address_error)( VG_(get_running_tid)(), a, 8, True );
+//zz }
+//zz 
+//zz /* ------------------------ Size = 4 ------------------------ */
+//zz 
+//zz static UInt mc_rd_V4_SLOWLY ( Addr a )
+//zz {
+//zz    Bool a0ok, a1ok, a2ok, a3ok;
+//zz    UInt vb0, vb1, vb2, vb3;
+//zz 
+//zz    PROF_EVENT(70);
+//zz 
+//zz    /* First establish independently the addressibility of the 4 bytes
+//zz       involved. */
+//zz    a0ok = get_abit(a+0) == VGM_BIT_VALID;
+//zz    a1ok = get_abit(a+1) == VGM_BIT_VALID;
+//zz    a2ok = get_abit(a+2) == VGM_BIT_VALID;
+//zz    a3ok = get_abit(a+3) == VGM_BIT_VALID;
+//zz 
+//zz    /* Also get the validity bytes for the address. */
+//zz    vb0 = (UInt)get_vbyte(a+0);
+//zz    vb1 = (UInt)get_vbyte(a+1);
+//zz    vb2 = (UInt)get_vbyte(a+2);
+//zz    vb3 = (UInt)get_vbyte(a+3);
+//zz 
+//zz    /* Now distinguish 3 cases */
+//zz 
+//zz    /* Case 1: the address is completely valid, so:
+//zz       - no addressing error
+//zz       - return V bytes as read from memory
+//zz    */
+//zz    if (a0ok && a1ok && a2ok && a3ok) {
+//zz       UInt vw = VGM_WORD_INVALID;
+//zz       vw <<= 8; vw |= vb3;
+//zz       vw <<= 8; vw |= vb2;
+//zz       vw <<= 8; vw |= vb1;
+//zz       vw <<= 8; vw |= vb0;
+//zz       return vw;
+//zz    }
+//zz 
+//zz    /* Case 2: the address is completely invalid.  
+//zz       - emit addressing error
+//zz       - return V word indicating validity.  
+//zz       This sounds strange, but if we make loads from invalid addresses 
+//zz       give invalid data, we also risk producing a number of confusing
+//zz       undefined-value errors later, which confuses the fact that the
+//zz       error arose in the first place from an invalid address. 
+//zz    */
+//zz    /* VG_(printf)("%p (%d %d %d %d)\n", a, a0ok, a1ok, a2ok, a3ok); */
+//zz    if (!MAC_(clo_partial_loads_ok) 
+//zz        || ((a & 3) != 0)
+//zz        || (!a0ok && !a1ok && !a2ok && !a3ok)) {
+//zz       MAC_(record_address_error)( VG_(get_running_tid)(), a, 4, False );
+//zz       return (VGM_BYTE_VALID << 24) | (VGM_BYTE_VALID << 16) 
+//zz              | (VGM_BYTE_VALID << 8) | VGM_BYTE_VALID;
+//zz    }
+//zz 
+//zz    /* Case 3: the address is partially valid.  
+//zz       - no addressing error
+//zz       - returned V word is invalid where the address is invalid, 
+//zz         and contains V bytes from memory otherwise. 
+//zz       Case 3 is only allowed if MC_(clo_partial_loads_ok) is True
+//zz       (which is the default), and the address is 4-aligned.  
+//zz       If not, Case 2 will have applied.
+//zz    */
+//zz    tl_assert(MAC_(clo_partial_loads_ok));
+//zz    {
+//zz       UInt vw = VGM_WORD_INVALID;
+//zz       vw <<= 8; vw |= (a3ok ? vb3 : VGM_BYTE_INVALID);
+//zz       vw <<= 8; vw |= (a2ok ? vb2 : VGM_BYTE_INVALID);
+//zz       vw <<= 8; vw |= (a1ok ? vb1 : VGM_BYTE_INVALID);
+//zz       vw <<= 8; vw |= (a0ok ? vb0 : VGM_BYTE_INVALID);
+//zz       return vw;
+//zz    }
+//zz }
+//zz 
+//zz static void mc_wr_V4_SLOWLY ( Addr a, UInt vbytes )
+//zz {
+//zz    /* Check the address for validity. */
+//zz    Bool aerr = False;
+//zz    PROF_EVENT(71);
+//zz 
+//zz    if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
+//zz    if (get_abit(a+1) != VGM_BIT_VALID) aerr = True;
+//zz    if (get_abit(a+2) != VGM_BIT_VALID) aerr = True;
+//zz    if (get_abit(a+3) != VGM_BIT_VALID) aerr = True;
+//zz 
+//zz    /* Store the V bytes, remembering to do it little-endian-ly. */
+//zz    set_vbyte( a+0, vbytes & 0x000000FF ); vbytes >>= 8;
+//zz    set_vbyte( a+1, vbytes & 0x000000FF ); vbytes >>= 8;
+//zz    set_vbyte( a+2, vbytes & 0x000000FF ); vbytes >>= 8;
+//zz    set_vbyte( a+3, vbytes & 0x000000FF );
+//zz 
+//zz    /* If an address error has happened, report it. */
+//zz    if (aerr)
+//zz       MAC_(record_address_error)( VG_(get_running_tid)(), a, 4, True );
+//zz }
+//zz 
+//zz /* ------------------------ Size = 2 ------------------------ */
+//zz 
+//zz static UInt mc_rd_V2_SLOWLY ( Addr a )
+//zz {
+//zz    /* Check the address for validity. */
+//zz    UInt vw   = VGM_WORD_INVALID;
+//zz    Bool aerr = False;
+//zz    PROF_EVENT(72);
+//zz 
+//zz    if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
+//zz    if (get_abit(a+1) != VGM_BIT_VALID) aerr = True;
+//zz 
+//zz    /* Fetch the V bytes, remembering to do it little-endian-ly. */
+//zz    vw <<= 8; vw |= (UInt)get_vbyte(a+1);
+//zz    vw <<= 8; vw |= (UInt)get_vbyte(a+0);
+//zz 
+//zz    /* If an address error has happened, report it. */
+//zz    if (aerr) {
+//zz       MAC_(record_address_error)( VG_(get_running_tid)(), a, 2, False );
+//zz       vw = (VGM_BYTE_INVALID << 24) | (VGM_BYTE_INVALID << 16) 
+//zz            | (VGM_BYTE_VALID << 8) | (VGM_BYTE_VALID);
+//zz    }
+//zz    return vw;   
+//zz }
+//zz 
+//zz static void mc_wr_V2_SLOWLY ( Addr a, UInt vbytes )
+//zz {
+//zz    /* Check the address for validity. */
+//zz    Bool aerr = False;
+//zz    PROF_EVENT(73);
+//zz 
+//zz    if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
+//zz    if (get_abit(a+1) != VGM_BIT_VALID) aerr = True;
+//zz 
+//zz    /* Store the V bytes, remembering to do it little-endian-ly. */
+//zz    set_vbyte( a+0, vbytes & 0x000000FF ); vbytes >>= 8;
+//zz    set_vbyte( a+1, vbytes & 0x000000FF );
+//zz 
+//zz    /* If an address error has happened, report it. */
+//zz    if (aerr)
+//zz       MAC_(record_address_error)( VG_(get_running_tid)(), a, 2, True );
+//zz }
+//zz 
+//zz /* ------------------------ Size = 1 ------------------------ */
+//zz 
+//zz static UInt mc_rd_V1_SLOWLY ( Addr a )
+//zz {
+//zz    /* Check the address for validity. */
+//zz    UInt vw   = VGM_WORD_INVALID;
+//zz    Bool aerr = False;
+//zz    PROF_EVENT(74);
+//zz 
+//zz    if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
+//zz 
+//zz    /* Fetch the V byte. */
+//zz    vw <<= 8; vw |= (UInt)get_vbyte(a+0);
+//zz 
+//zz    /* If an address error has happened, report it. */
+//zz    if (aerr) {
+//zz       MAC_(record_address_error)( VG_(get_running_tid)(), a, 1, False );
+//zz       vw = (VGM_BYTE_INVALID << 24) | (VGM_BYTE_INVALID << 16) 
+//zz            | (VGM_BYTE_INVALID << 8) | (VGM_BYTE_VALID);
+//zz    }
+//zz    return vw;   
+//zz }
+//zz 
+//zz static void mc_wr_V1_SLOWLY ( Addr a, UInt vbytes )
+//zz {
+//zz    /* Check the address for validity. */
+//zz    Bool aerr = False;
+//zz    PROF_EVENT(75);
+//zz    if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
+//zz 
+//zz    /* Store the V bytes, remembering to do it little-endian-ly. */
+//zz    set_vbyte( a+0, vbytes & 0x000000FF );
+//zz 
+//zz    /* If an address error has happened, report it. */
+//zz    if (aerr)
+//zz       MAC_(record_address_error)( VG_(get_running_tid)(), a, 1, True );
+//zz }
 
 
 /* ---------------------------------------------------------------------
@@ -1400,10 +1801,10 @@ void MC_(helperc_value_check1_fail) ( void )
    MC_(record_value_error) ( VG_(get_running_tid)(), 1 );
 }
 
-void MC_(helperc_value_check2_fail) ( void )
-{
-   MC_(record_value_error) ( VG_(get_running_tid)(), 2 );
-}
+//zz void MC_(helperc_value_check2_fail) ( void )
+//zz {
+//zz    MC_(record_value_error) ( VG_(get_running_tid)(), 2 );
+//zz }
 
 void MC_(helperc_value_check4_fail) ( void )
 {
@@ -1416,116 +1817,116 @@ VGA_REGPARM(1) void MC_(helperc_complain_undef) ( HWord sz )
 }
 
 
-/*------------------------------------------------------------*/
-/*--- Metadata get/set functions, for client requests.     ---*/
-/*------------------------------------------------------------*/
-
-/* Copy Vbits for src into vbits. Returns: 1 == OK, 2 == alignment
-   error, 3 == addressing error. */
-static Int mc_get_or_set_vbits_for_client ( 
-   ThreadId tid,
-   Addr dataV, 
-   Addr vbitsV, 
-   SizeT size, 
-   Bool setting /* True <=> set vbits,  False <=> get vbits */ 
-)
-{
-   Bool addressibleD = True;
-   Bool addressibleV = True;
-   UInt* data  = (UInt*)dataV;
-   UInt* vbits = (UInt*)vbitsV;
-   SizeT szW   = size / 4; /* sigh */
-   SizeT i;
-   UInt* dataP  = NULL; /* bogus init to keep gcc happy */
-   UInt* vbitsP = NULL; /* ditto */
-
-   /* Check alignment of args. */
-   if (!(VG_IS_4_ALIGNED(data) && VG_IS_4_ALIGNED(vbits)))
-      return 2;
-   if ((size & 3) != 0)
-      return 2;
-  
-   /* Check that arrays are addressible. */
-   for (i = 0; i < szW; i++) {
-      dataP  = &data[i];
-      vbitsP = &vbits[i];
-      if (get_abits4_ALIGNED((Addr)dataP) != VGM_NIBBLE_VALID) {
-         addressibleD = False;
-         break;
-      }
-      if (get_abits4_ALIGNED((Addr)vbitsP) != VGM_NIBBLE_VALID) {
-         addressibleV = False;
-         break;
-      }
-   }
-   if (!addressibleD) {
-      MAC_(record_address_error)( tid, (Addr)dataP, 4, 
-                                  setting ? True : False );
-      return 3;
-   }
-   if (!addressibleV) {
-      MAC_(record_address_error)( tid, (Addr)vbitsP, 4, 
-                                  setting ? False : True );
-      return 3;
-   }
-   /* Do the copy */
-   if (setting) {
-      /* setting */
-      for (i = 0; i < szW; i++) {
-         if (get_vbytes4_ALIGNED( (Addr)&vbits[i] ) != VGM_WORD_VALID)
-            MC_(record_value_error)(tid, 4);
-         set_vbytes4_ALIGNED( (Addr)&data[i], vbits[i] );
-      }
-   } else {
-      /* getting */
-      for (i = 0; i < szW; i++) {
-         vbits[i] = get_vbytes4_ALIGNED( (Addr)&data[i] );
-         set_vbytes4_ALIGNED( (Addr)&vbits[i], VGM_WORD_VALID );
-      }
-   }
-
-   return 1;
-}
-
-
-/*------------------------------------------------------------*/
-/*--- Detecting leaked (unreachable) malloc'd blocks.      ---*/
-/*------------------------------------------------------------*/
-
-/* For the memory leak detector, say whether an entire 64k chunk of
-   address space is possibly in use, or not.  If in doubt return
-   True.
-*/
-static
-Bool mc_is_valid_64k_chunk ( UInt chunk_number )
-{
-   tl_assert(chunk_number >= 0 && chunk_number < PRIMARY_SIZE);
-   if (primary_map[chunk_number] == DSM_NOTADDR) {
-      /* Definitely not in use. */
-      return False;
-   } else {
-      return True;
-   }
-}
-
-
-/* For the memory leak detector, say whether or not a given word
-   address is to be regarded as valid. */
-static
-Bool mc_is_valid_address ( Addr a )
-{
-   UInt vbytes;
-   UChar abits;
-   tl_assert(VG_IS_4_ALIGNED(a));
-   abits  = get_abits4_ALIGNED(a);
-   vbytes = get_vbytes4_ALIGNED(a);
-   if (abits == VGM_NIBBLE_VALID && vbytes == VGM_WORD_VALID) {
-      return True;
-   } else {
-      return False;
-   }
-}
+//zz /*------------------------------------------------------------*/
+//zz /*--- Metadata get/set functions, for client requests.     ---*/
+//zz /*------------------------------------------------------------*/
+//zz 
+//zz /* Copy Vbits for src into vbits. Returns: 1 == OK, 2 == alignment
+//zz    error, 3 == addressing error. */
+//zz static Int mc_get_or_set_vbits_for_client ( 
+//zz    ThreadId tid,
+//zz    Addr dataV, 
+//zz    Addr vbitsV, 
+//zz    SizeT size, 
+//zz    Bool setting /* True <=> set vbits,  False <=> get vbits */ 
+//zz )
+//zz {
+//zz    Bool addressibleD = True;
+//zz    Bool addressibleV = True;
+//zz    UInt* data  = (UInt*)dataV;
+//zz    UInt* vbits = (UInt*)vbitsV;
+//zz    SizeT szW   = size / 4; /* sigh */
+//zz    SizeT i;
+//zz    UInt* dataP  = NULL; /* bogus init to keep gcc happy */
+//zz    UInt* vbitsP = NULL; /* ditto */
+//zz 
+//zz    /* Check alignment of args. */
+//zz    if (!(VG_IS_4_ALIGNED(data) && VG_IS_4_ALIGNED(vbits)))
+//zz       return 2;
+//zz    if ((size & 3) != 0)
+//zz       return 2;
+//zz   
+//zz    /* Check that arrays are addressible. */
+//zz    for (i = 0; i < szW; i++) {
+//zz       dataP  = &data[i];
+//zz       vbitsP = &vbits[i];
+//zz       if (get_abits4_ALIGNED((Addr)dataP) != VGM_NIBBLE_VALID) {
+//zz          addressibleD = False;
+//zz          break;
+//zz       }
+//zz       if (get_abits4_ALIGNED((Addr)vbitsP) != VGM_NIBBLE_VALID) {
+//zz          addressibleV = False;
+//zz          break;
+//zz       }
+//zz    }
+//zz    if (!addressibleD) {
+//zz       MAC_(record_address_error)( tid, (Addr)dataP, 4, 
+//zz                                   setting ? True : False );
+//zz       return 3;
+//zz    }
+//zz    if (!addressibleV) {
+//zz       MAC_(record_address_error)( tid, (Addr)vbitsP, 4, 
+//zz                                   setting ? False : True );
+//zz       return 3;
+//zz    }
+//zz  
+//zz    /* Do the copy */
+//zz    if (setting) {
+//zz       /* setting */
+//zz       for (i = 0; i < szW; i++) {
+//zz          if (get_vbytes4_ALIGNED( (Addr)&vbits[i] ) != VGM_WORD_VALID)
+//zz             MC_(record_value_error)(tid, 4);
+//zz          set_vbytes4_ALIGNED( (Addr)&data[i], vbits[i] );
+//zz       }
+//zz    } else {
+//zz       /* getting */
+//zz       for (i = 0; i < szW; i++) {
+//zz          vbits[i] = get_vbytes4_ALIGNED( (Addr)&data[i] );
+//zz          set_vbytes4_ALIGNED( (Addr)&vbits[i], VGM_WORD_VALID );
+//zz       }
+//zz    }
+//zz 
+//zz    return 1;
+//zz }
+//zz 
+//zz 
+//zz /*------------------------------------------------------------*/
+//zz /*--- Detecting leaked (unreachable) malloc'd blocks.      ---*/
+//zz /*------------------------------------------------------------*/
+//zz 
+//zz /* For the memory leak detector, say whether an entire 64k chunk of
+//zz    address space is possibly in use, or not.  If in doubt return
+//zz    True.
+//zz */
+//zz static
+//zz Bool mc_is_valid_64k_chunk ( UInt chunk_number )
+//zz {
+//zz    tl_assert(chunk_number >= 0 && chunk_number < PRIMARY_SIZE);
+//zz    if (primary_map[chunk_number] == DSM_NOTADDR) {
+//zz       /* Definitely not in use. */
+//zz       return False;
+//zz    } else {
+//zz       return True;
+//zz    }
+//zz }
+//zz 
+//zz 
+//zz /* For the memory leak detector, say whether or not a given word
+//zz    address is to be regarded as valid. */
+//zz static
+//zz Bool mc_is_valid_address ( Addr a )
+//zz {
+//zz    UInt vbytes;
+//zz    UChar abits;
+//zz    tl_assert(VG_IS_4_ALIGNED(a));
+//zz    abits  = get_abits4_ALIGNED(a);
+//zz    vbytes = get_vbytes4_ALIGNED(a);
+//zz    if (abits == VGM_NIBBLE_VALID && vbytes == VGM_WORD_VALID) {
+//zz       return True;
+//zz    } else {
+//zz       return False;
+//zz    }
+//zz }
 
 
 /* Leak detector for this tool.  We don't actually do anything, merely
@@ -1533,8 +1934,9 @@ Bool mc_is_valid_address ( Addr a )
    tool. */
 static void mc_detect_memory_leaks ( ThreadId tid, LeakCheckMode mode )
 {
-   MAC_(do_detect_memory_leaks) ( 
-      tid, mode, mc_is_valid_64k_chunk, mc_is_valid_address );
+   VG_(printf)("memcheck: leak detection currently disabled\n");
+   //   MAC_(do_detect_memory_leaks) ( 
+   //      tid, mode, mc_is_valid_64k_chunk, mc_is_valid_address );
 }
 
 
@@ -1550,30 +1952,55 @@ Bool TL_(cheap_sanity_check) ( void )
 
 Bool TL_(expensive_sanity_check) ( void )
 {
-   Int i;
+   Int     i;
+   SecMap* sm;
+
+   /* Check the 3 distinguished SMs. */
 
-   /* Make sure nobody changed the distinguished secondary.
-      They're in read-only memory, so that would be hard.
-    */
-#if 0
+   /* Check A invalid, V invalid. */
+   sm = &sm_distinguished[SM_DIST_NOACCESS];
+   for (i = 0; i < 65536; i++)
+      if (!(sm->vbyte[i] == VGM_BYTE_INVALID))
+         return False;
    for (i = 0; i < 8192; i++)
-      if (distinguished_secondary_map.abits[i] != VGM_BYTE_INVALID)
+      if (!(sm->abits[i] == VGM_BYTE_INVALID))
          return False;
 
+   /* Check A valid, V invalid. */
+   sm = &sm_distinguished[SM_DIST_ACCESS_UNDEFINED];
    for (i = 0; i < 65536; i++)
-      if (distinguished_secondary_map.vbyte[i] != VGM_BYTE_INVALID)
+      if (!(sm->vbyte[i] == VGM_BYTE_INVALID))
+         return False;
+   for (i = 0; i < 8192; i++)
+      if (!(sm->abits[i] == VGM_BYTE_VALID))
          return False;
-#endif
 
-   /* Make sure that the upper 3/4 of the primary map hasn't
-      been messed with. */
-   for (i = PRIMARY_SIZE; i < PRIMARY_SIZE*4; i++)
-      if (primary_map[i] != DSM_NOTADDR)
+   /* Check A valid, V valid. */
+   sm = &sm_distinguished[SM_DIST_ACCESS_DEFINED];
+   for (i = 0; i < 65536; i++)
+      if (!(sm->vbyte[i] == VGM_BYTE_VALID))
          return False;
+   for (i = 0; i < 8192; i++)
+      if (!(sm->abits[i] == VGM_BYTE_VALID))
+         return False;
+
+   if (auxmap_used > auxmap_size)
+       return False;
 
    return True;
 }
+
       
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////
+
 /*------------------------------------------------------------*/
 /*--- Command line args                                    ---*/
 /*------------------------------------------------------------*/
@@ -1829,21 +2256,21 @@ Bool TL_(handle_client_request) ( ThreadId tid, UWord* arg, UWord* ret )
         }
         break;
 
-      case VG_USERREQ__GET_VBITS:
-         /* Returns: 1 == OK, 2 == alignment error, 3 == addressing
-            error. */
-         /* VG_(printf)("get_vbits %p %p %d\n", arg[1], arg[2], arg[3] ); */
-         *ret = mc_get_or_set_vbits_for_client
-                   ( tid, arg[1], arg[2], arg[3], False /* get them */ );
-         break;
-
-      case VG_USERREQ__SET_VBITS:
-         /* Returns: 1 == OK, 2 == alignment error, 3 == addressing
-            error. */
-         /* VG_(printf)("set_vbits %p %p %d\n", arg[1], arg[2], arg[3] ); */
-         *ret = mc_get_or_set_vbits_for_client
-                   ( tid, arg[1], arg[2], arg[3], True /* set them */ );
-         break;
+//zz       case VG_USERREQ__GET_VBITS:
+//zz          /* Returns: 1 == OK, 2 == alignment error, 3 == addressing
+//zz             error. */
+//zz          /* VG_(printf)("get_vbits %p %p %d\n", arg[1], arg[2], arg[3] ); */
+//zz          *ret = mc_get_or_set_vbits_for_client
+//zz                    ( tid, arg[1], arg[2], arg[3], False /* get them */ );
+//zz          break;
+//zz 
+//zz       case VG_USERREQ__SET_VBITS:
+//zz          /* Returns: 1 == OK, 2 == alignment error, 3 == addressing
+//zz             error. */
+//zz          /* VG_(printf)("set_vbits %p %p %d\n", arg[1], arg[2], arg[3] ); */
+//zz          *ret = mc_get_or_set_vbits_for_client
+//zz                    ( tid, arg[1], arg[2], arg[3], True /* set them */ );
+//zz          break;
 
       default:
          if (MAC_(handle_common_client_requests)(tid, arg, ret )) {
@@ -1858,7 +2285,6 @@ Bool TL_(handle_client_request) ( ThreadId tid, UWord* arg, UWord* ret )
    return True;
 }
 
-
 /*------------------------------------------------------------*/
 /*--- Setup                                                ---*/
 /*------------------------------------------------------------*/
@@ -1967,7 +2393,17 @@ void TL_(post_clo_init) ( void )
 void TL_(fini) ( Int exitcode )
 {
    MAC_(common_fini)( mc_detect_memory_leaks );
-   
+
+   if (VG_(clo_verbosity) > 1) {
+      VG_(message)(Vg_DebugMsg,
+         "memcheck: auxmaps: %d auxmap entries (%dk, %dM) in use",
+         auxmap_used, 
+         64 * auxmap_used, auxmap_used / 16 );
+      VG_(message)(Vg_DebugMsg,
+         "memcheck: auxmaps: %lld searches, %lld comparisons",
+         n_auxmap_searches, n_auxmap_cmps );   
+   }
+
    if (0) {
       VG_(message)(Vg_DebugMsg, 
         "------ Valgrind's client block stats follow ---------------" );