]> rtime.felk.cvut.cz Git - l4.git/blobdiff - l4/pkg/valgrind/src/valgrind-3.6.0-svn/VEX/priv/guest_generic_bb_to_IR.c
update
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / VEX / priv / guest_generic_bb_to_IR.c
index c2be377dbc4c6bb8957d33bd8657cd970bdfc496..1e59c70e0d1d978b91aaf8f1cd1d2b6bc62c104d 100644 (file)
 
 
 /* Forwards .. */
-__attribute__((regparm(2)))
+VEX_REGPARM(2)
 static UInt genericg_compute_checksum_4al ( HWord first_w32, HWord n_w32s );
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_1 ( HWord first_w32 );
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_2 ( HWord first_w32 );
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_3 ( HWord first_w32 );
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_4 ( HWord first_w32 );
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_5 ( HWord first_w32 );
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_6 ( HWord first_w32 );
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_7 ( HWord first_w32 );
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_8 ( HWord first_w32 );
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_9 ( HWord first_w32 );
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_10 ( HWord first_w32 );
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_11 ( HWord first_w32 );
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_12 ( HWord first_w32 );
 
+VEX_REGPARM(2)
+static ULong genericg_compute_checksum_8al ( HWord first_w64, HWord n_w64s );
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_1 ( HWord first_w64 );
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_2 ( HWord first_w64 );
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_3 ( HWord first_w64 );
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_4 ( HWord first_w64 );
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_5 ( HWord first_w64 );
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_6 ( HWord first_w64 );
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_7 ( HWord first_w64 );
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_8 ( HWord first_w64 );
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_9 ( HWord first_w64 );
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_10 ( HWord first_w64 );
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_11 ( HWord first_w64 );
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_12 ( HWord first_w64 );
+
 /* Small helpers */
 static Bool const_False ( void* callback_opaque, Addr64 a ) { 
    return False; 
@@ -173,16 +200,14 @@ IRSB* bb_to_IR ( /*OUT*/VexGuestExtents* vge,
               : IRConst_U64(guest_IP_bbstart);
    }
 
-   /* If asked to make a self-checking translation, leave 5 spaces
-      in which to put the check statements.  We'll fill them in later
-      when we know the length and adler32 of the area to check. */
+   /* If asked to make a self-checking translation, leave 15 spaces in
+      which to put the check statements (up to 3 extents, and 5 stmts
+      required for each).  We'll fill them in later when we know the
+      extents and checksums of the areas to check. */
    if (do_self_check) {
       selfcheck_idx = irsb->stmts_used;
-      addStmtToIRSB( irsb, IRStmt_NoOp() );
-      addStmtToIRSB( irsb, IRStmt_NoOp() );
-      addStmtToIRSB( irsb, IRStmt_NoOp() );
-      addStmtToIRSB( irsb, IRStmt_NoOp() );
-      addStmtToIRSB( irsb, IRStmt_NoOp() );
+      for (i = 0; i < 3 * 5; i++)
+         addStmtToIRSB( irsb, IRStmt_NoOp() );
    }
 
    /* If the caller supplied a function to add its own preamble, use
@@ -208,11 +233,6 @@ IRSB* bb_to_IR ( /*OUT*/VexGuestExtents* vge,
       resteerOK 
          = toBool(
               n_instrs < vex_control.guest_chase_thresh
-              /* If making self-checking translations, don't chase
-                 .. it makes the checks too complicated.  We only want
-                 to scan just one sequence of bytes in the check, not
-                 a whole bunch. */
-              && !do_self_check
               /* we can't afford to have a resteer once we're on the
                  last extent slot. */
               && vge->n_used < 3
@@ -241,8 +261,21 @@ IRSB* bb_to_IR ( /*OUT*/VexGuestExtents* vge,
 
       /* Add an instruction-mark statement.  We won't know until after
          disassembling the instruction how long it instruction is, so
-         just put in a zero length and we'll fix it up later. */
-      addStmtToIRSB( irsb, IRStmt_IMark( guest_IP_curr_instr, 0 ));
+         just put in a zero length and we'll fix it up later.
+
+         On ARM, the least significant bit of the instr address
+         distinguishes ARM vs Thumb instructions.  All instructions
+         actually start on at least 2-aligned addresses.  So we need
+         to ignore the bottom bit of the insn address when forming the
+         IMark.  For more details of this convention, see comments on
+         definition of guest_R15 in libvex_guest_arm.h. */
+      addStmtToIRSB( irsb,
+                     IRStmt_IMark( arch_guest == VexArchARM
+                                      ? (guest_IP_curr_instr & ~(Addr64)1)
+                                      : guest_IP_curr_instr,
+                                   0
+                     )
+      );
 
       /* for the first insn, the dispatch loop will have set
          %IP, but for all the others we have to do it ourselves. */
@@ -401,101 +434,167 @@ IRSB* bb_to_IR ( /*OUT*/VexGuestExtents* vge,
    */
    if (do_self_check) {
 
-      UInt     len2check, expected32;
+      Addr64   base2check;
+      UInt     len2check;
+      HWord    expectedhW;
       IRTemp   tistart_tmp, tilen_tmp;
-      UInt     (*fn_generic)(HWord, HWord) __attribute__((regparm(2)));
-      UInt     (*fn_spec)(HWord) __attribute__((regparm(1)));
+      HWord    VEX_REGPARM(2) (*fn_generic)(HWord, HWord);
+      HWord    VEX_REGPARM(1) (*fn_spec)(HWord);
       HChar*   nm_generic;
       HChar*   nm_spec;
       HWord    fn_generic_entry = 0;
       HWord    fn_spec_entry = 0;
-
-      vassert(vge->n_used == 1);
-      len2check = vge->len[0];
-
-      /* stay sane */
-      vassert(len2check >= 0 && len2check < 1000/*arbitrary*/);
-
-      /* Skip the check if the translation involved zero bytes */
-      if (len2check > 0) {
-         HWord first_w32 = ((HWord)guest_code) & ~(HWord)3;
-         HWord last_w32  = (((HWord)guest_code) + len2check - 1) & ~(HWord)3;
-         vassert(first_w32 <= last_w32);
-         HWord w32_diff = last_w32 - first_w32;
-         vassert(0 == (w32_diff & 3));
-         HWord w32s_to_check = (w32_diff + 4) / 4;
-         vassert(w32s_to_check > 0 && w32s_to_check < 1004/*arbitrary*//4);
+      UInt     host_word_szB = sizeof(HWord);
+      IRType   host_word_type = Ity_INVALID;
+
+      if (host_word_szB == 4) host_word_type = Ity_I32;
+      if (host_word_szB == 8) host_word_type = Ity_I64;
+      vassert(host_word_type != Ity_INVALID);
+
+      vassert(vge->n_used >= 1 && vge->n_used <= 3);
+      for (i = 0; i < vge->n_used; i++) {
+
+         /* the extent we're generating a check for */
+         base2check = vge->base[i];
+         len2check  = vge->len[i];
+
+         /* stay sane */
+         vassert(len2check >= 0 && len2check < 1000/*arbitrary*/);
+
+         /* Skip the check if the translation involved zero bytes */
+         if (len2check == 0)
+            continue;
+
+         HWord first_hW = ((HWord)base2check)
+                          & ~(HWord)(host_word_szB-1);
+         HWord last_hW  = (((HWord)base2check) + len2check - 1)
+                          & ~(HWord)(host_word_szB-1);
+         vassert(first_hW <= last_hW);
+         HWord hW_diff = last_hW - first_hW;
+         vassert(0 == (hW_diff & (host_word_szB-1)));
+         HWord hWs_to_check = (hW_diff + host_word_szB) / host_word_szB;
+         vassert(hWs_to_check > 0
+                 && hWs_to_check < 1004/*arbitrary*/ / host_word_szB);
 
          /* vex_printf("%lx %lx  %ld\n", first_w32, last_w32, w32s_to_check); */
 
-         fn_generic =  genericg_compute_checksum_4al;
-         nm_generic = "genericg_compute_checksum_4al";
+         if (host_word_szB == 8) {
+            fn_generic =  (VEX_REGPARM(2) HWord(*)(HWord, HWord))
+                          genericg_compute_checksum_8al;
+            nm_generic = "genericg_compute_checksum_8al";
+         } else {
+            fn_generic =  (VEX_REGPARM(2) HWord(*)(HWord, HWord))
+                          genericg_compute_checksum_4al;
+            nm_generic = "genericg_compute_checksum_4al";
+         }
+
          fn_spec = NULL;
          nm_spec = NULL;
 
-         switch (w32s_to_check) {
-             case 1:  fn_spec =  genericg_compute_checksum_4al_1;
-                      nm_spec = "genericg_compute_checksum_4al_1"; break;
-             case 2:  fn_spec =  genericg_compute_checksum_4al_2;
-                      nm_spec = "genericg_compute_checksum_4al_2"; break;
-             case 3:  fn_spec =  genericg_compute_checksum_4al_3;
-                      nm_spec = "genericg_compute_checksum_4al_3"; break;
-             case 4:  fn_spec =  genericg_compute_checksum_4al_4;
-                      nm_spec = "genericg_compute_checksum_4al_4"; break;
-             case 5:  fn_spec =  genericg_compute_checksum_4al_5;
-                      nm_spec = "genericg_compute_checksum_4al_5"; break;
-             case 6:  fn_spec =  genericg_compute_checksum_4al_6;
-                      nm_spec = "genericg_compute_checksum_4al_6"; break;
-             case 7:  fn_spec =  genericg_compute_checksum_4al_7;
-                      nm_spec = "genericg_compute_checksum_4al_7"; break;
-             case 8:  fn_spec =  genericg_compute_checksum_4al_8;
-                      nm_spec = "genericg_compute_checksum_4al_8"; break;
-             case 9:  fn_spec =  genericg_compute_checksum_4al_9;
-                      nm_spec = "genericg_compute_checksum_4al_9"; break;
-             case 10: fn_spec =  genericg_compute_checksum_4al_10;
-                      nm_spec = "genericg_compute_checksum_4al_10"; break;
-             case 11: fn_spec =  genericg_compute_checksum_4al_11;
-                      nm_spec = "genericg_compute_checksum_4al_11"; break;
-             case 12: fn_spec =  genericg_compute_checksum_4al_12;
-                      nm_spec = "genericg_compute_checksum_4al_12"; break;
-             default: break;
+         if (host_word_szB == 8) {
+            HChar* nm = NULL;
+            ULong  VEX_REGPARM(1) (*fn)(HWord)  = NULL;
+            switch (hWs_to_check) {
+               case 1:  fn =  genericg_compute_checksum_8al_1;
+                        nm = "genericg_compute_checksum_8al_1"; break;
+               case 2:  fn =  genericg_compute_checksum_8al_2;
+                        nm = "genericg_compute_checksum_8al_2"; break;
+               case 3:  fn =  genericg_compute_checksum_8al_3;
+                        nm = "genericg_compute_checksum_8al_3"; break;
+               case 4:  fn =  genericg_compute_checksum_8al_4;
+                        nm = "genericg_compute_checksum_8al_4"; break;
+               case 5:  fn =  genericg_compute_checksum_8al_5;
+                        nm = "genericg_compute_checksum_8al_5"; break;
+               case 6:  fn =  genericg_compute_checksum_8al_6;
+                        nm = "genericg_compute_checksum_8al_6"; break;
+               case 7:  fn =  genericg_compute_checksum_8al_7;
+                        nm = "genericg_compute_checksum_8al_7"; break;
+               case 8:  fn =  genericg_compute_checksum_8al_8;
+                        nm = "genericg_compute_checksum_8al_8"; break;
+               case 9:  fn =  genericg_compute_checksum_8al_9;
+                        nm = "genericg_compute_checksum_8al_9"; break;
+               case 10: fn =  genericg_compute_checksum_8al_10;
+                        nm = "genericg_compute_checksum_8al_10"; break;
+               case 11: fn =  genericg_compute_checksum_8al_11;
+                        nm = "genericg_compute_checksum_8al_11"; break;
+               case 12: fn =  genericg_compute_checksum_8al_12;
+                        nm = "genericg_compute_checksum_8al_12"; break;
+               default: break;
+            }
+            fn_spec = (VEX_REGPARM(1) HWord(*)(HWord)) fn;
+            nm_spec = nm;
+         } else {
+            HChar* nm = NULL;
+            UInt   VEX_REGPARM(1) (*fn)(HWord) = NULL;
+            switch (hWs_to_check) {
+               case 1:  fn =  genericg_compute_checksum_4al_1;
+                        nm = "genericg_compute_checksum_4al_1"; break;
+               case 2:  fn =  genericg_compute_checksum_4al_2;
+                        nm = "genericg_compute_checksum_4al_2"; break;
+               case 3:  fn =  genericg_compute_checksum_4al_3;
+                        nm = "genericg_compute_checksum_4al_3"; break;
+               case 4:  fn =  genericg_compute_checksum_4al_4;
+                        nm = "genericg_compute_checksum_4al_4"; break;
+               case 5:  fn =  genericg_compute_checksum_4al_5;
+                        nm = "genericg_compute_checksum_4al_5"; break;
+               case 6:  fn =  genericg_compute_checksum_4al_6;
+                        nm = "genericg_compute_checksum_4al_6"; break;
+               case 7:  fn =  genericg_compute_checksum_4al_7;
+                        nm = "genericg_compute_checksum_4al_7"; break;
+               case 8:  fn =  genericg_compute_checksum_4al_8;
+                        nm = "genericg_compute_checksum_4al_8"; break;
+               case 9:  fn =  genericg_compute_checksum_4al_9;
+                        nm = "genericg_compute_checksum_4al_9"; break;
+               case 10: fn =  genericg_compute_checksum_4al_10;
+                        nm = "genericg_compute_checksum_4al_10"; break;
+               case 11: fn =  genericg_compute_checksum_4al_11;
+                        nm = "genericg_compute_checksum_4al_11"; break;
+               case 12: fn =  genericg_compute_checksum_4al_12;
+                        nm = "genericg_compute_checksum_4al_12"; break;
+               default: break;
+            }
+            fn_spec = (VEX_REGPARM(1) HWord(*)(HWord))fn;
+            nm_spec = nm;
          }
 
-         expected32 = fn_generic( first_w32, w32s_to_check );
+         expectedhW = fn_generic( first_hW, hWs_to_check );
          /* If we got a specialised version, check it produces the same
             result as the generic version! */
          if (fn_spec) {
             vassert(nm_spec);
-            vassert(expected32 == fn_spec( first_w32 ));
-      } else {
+            vassert(expectedhW == fn_spec( first_hW ));
+         } else {
             vassert(!nm_spec);
-      }
+         }
 
-      /* Set TISTART and TILEN.  These will describe to the despatcher
-         the area of guest code to invalidate should we exit with a
-         self-check failure. */
+         /* Set TISTART and TILEN.  These will describe to the despatcher
+            the area of guest code to invalidate should we exit with a
+            self-check failure. */
 
-      tistart_tmp = newIRTemp(irsb->tyenv, guest_word_type);
-      tilen_tmp   = newIRTemp(irsb->tyenv, guest_word_type);
+         tistart_tmp = newIRTemp(irsb->tyenv, guest_word_type);
+         tilen_tmp   = newIRTemp(irsb->tyenv, guest_word_type);
 
-      irsb->stmts[selfcheck_idx+0]
-         = IRStmt_WrTmp(tistart_tmp, IRExpr_Const(guest_IP_bbstart_IRConst) );
+         IRConst* base2check_IRConst
+            = guest_word_type==Ity_I32 ? IRConst_U32(toUInt(base2check))
+                                       : IRConst_U64(base2check);
+         IRConst* len2check_IRConst
+            = guest_word_type==Ity_I32 ? IRConst_U32(len2check)
+                                       : IRConst_U64(len2check);
 
-      irsb->stmts[selfcheck_idx+1]
-         = IRStmt_WrTmp(tilen_tmp,
-                        guest_word_type==Ity_I32 
-                           ? IRExpr_Const(IRConst_U32(len2check)) 
-                           : IRExpr_Const(IRConst_U64(len2check))
-           );
+         irsb->stmts[selfcheck_idx + i * 5 + 0]
+            = IRStmt_WrTmp(tistart_tmp, IRExpr_Const(base2check_IRConst) );
+
+         irsb->stmts[selfcheck_idx + i * 5 + 1]
+            = IRStmt_WrTmp(tilen_tmp, IRExpr_Const(len2check_IRConst) );
 
-      irsb->stmts[selfcheck_idx+2]
-         = IRStmt_Put( offB_TISTART, IRExpr_RdTmp(tistart_tmp) );
+         irsb->stmts[selfcheck_idx + i * 5 + 2]
+            = IRStmt_Put( offB_TISTART, IRExpr_RdTmp(tistart_tmp) );
 
-      irsb->stmts[selfcheck_idx+3]
-         = IRStmt_Put( offB_TILEN, IRExpr_RdTmp(tilen_tmp) );
+         irsb->stmts[selfcheck_idx + i * 5 + 3]
+            = IRStmt_Put( offB_TILEN, IRExpr_RdTmp(tilen_tmp) );
 
          /* Generate the entry point descriptors */
-      if (abiinfo_both->host_ppc_calls_use_fndescrs) {
+         if (abiinfo_both->host_ppc_calls_use_fndescrs) {
             HWord* descr = (HWord*)fn_generic;
             fn_generic_entry = descr[0];
             if (fn_spec) {
@@ -508,7 +607,7 @@ IRSB* bb_to_IR ( /*OUT*/VexGuestExtents* vge,
             fn_generic_entry = (HWord)fn_generic;
             if (fn_spec) {
                fn_spec_entry = (HWord)fn_spec;
-      } else {
+            } else {
                fn_spec_entry = (HWord)NULL;
             }
          }
@@ -516,34 +615,39 @@ IRSB* bb_to_IR ( /*OUT*/VexGuestExtents* vge,
          IRExpr* callexpr = NULL;
          if (fn_spec) {
             callexpr = mkIRExprCCall( 
-                          Ity_I32, 1/*regparms*/, 
+                          host_word_type, 1/*regparms*/, 
                           nm_spec, (void*)fn_spec_entry,
                           mkIRExprVec_1(
-                             mkIRExpr_HWord( (HWord)first_w32 )
+                             mkIRExpr_HWord( (HWord)first_hW )
                           )
                        );
          } else {
             callexpr = mkIRExprCCall( 
-                          Ity_I32, 2/*regparms*/, 
+                          host_word_type, 2/*regparms*/, 
                           nm_generic, (void*)fn_generic_entry,
                           mkIRExprVec_2(
-                             mkIRExpr_HWord( (HWord)first_w32 ),
-                             mkIRExpr_HWord( (HWord)w32s_to_check )
+                             mkIRExpr_HWord( (HWord)first_hW ),
+                             mkIRExpr_HWord( (HWord)hWs_to_check )
                           )
                        );
-      }
+         }
 
-      irsb->stmts[selfcheck_idx+4]
-         = IRStmt_Exit( 
-              IRExpr_Binop( 
-                 Iop_CmpNE32, 
+         irsb->stmts[selfcheck_idx + i * 5 + 4]
+            = IRStmt_Exit( 
+                 IRExpr_Binop( 
+                    host_word_type==Ity_I64 ? Iop_CmpNE64 : Iop_CmpNE32,
                     callexpr,
-                 IRExpr_Const(IRConst_U32(expected32))
-              ),
-              Ijk_TInval,
-              guest_IP_bbstart_IRConst
-           );
-   }
+                       host_word_type==Ity_I64
+                          ? IRExpr_Const(IRConst_U64(expectedhW))
+                          : IRExpr_Const(IRConst_U32(expectedhW))
+                 ),
+                 Ijk_TInval,
+                 /* Where we must restart if there's a failure: at the
+                    first extent, regardless of which extent the
+                    failure actually happened in. */
+                 guest_IP_bbstart_IRConst
+              );
+      }
    }
 
    return irsb;
@@ -558,22 +662,22 @@ IRSB* bb_to_IR ( /*OUT*/VexGuestExtents* vge,
 /* CALLED FROM GENERATED CODE */
 
 /* Compute a checksum of host memory at [addr .. addr+len-1], as fast
-   as possible.  The _4al_4plus version is assured that the request is
-   for 4-aligned memory and for a block of 4 or more long, whilst the
-   _generic version must be able to handle any alignment, and lengths
-   down to zero too.  This fn is called once for every use of a
-   self-checking translation, so it needs to be as fast as
-   possible. */
+   as possible.  All _4al versions assume that the supplied address is
+   4 aligned.  All length values are in 4-byte chunks.  These fns
+   arecalled once for every use of a self-checking translation, so
+   they needs to be as fast as possible. */
+
+/* --- 32-bit versions, used only on 32-bit hosts --- */
 
 static inline UInt ROL32 ( UInt w, Int n ) {
    w = (w << n) | (w >> (32-n));
    return w;
 }
 
-__attribute((regparm(2)))
+VEX_REGPARM(2)
 static UInt genericg_compute_checksum_4al ( HWord first_w32, HWord n_w32s )
 {
-   UInt sum1 = 0, sum2 = 0;
+   UInt  sum1 = 0, sum2 = 0;
    UInt* p = (UInt*)first_w32;
    /* unrolled */
    while (n_w32s >= 4) {
@@ -598,7 +702,7 @@ static UInt genericg_compute_checksum_4al ( HWord first_w32, HWord n_w32s )
 
 /* Specialised versions of the above function */
 
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_1 ( HWord first_w32 )
 {
    UInt  sum1 = 0, sum2 = 0;
@@ -609,10 +713,10 @@ static UInt genericg_compute_checksum_4al_1 ( HWord first_w32 )
    return sum1 + sum2;
 }
 
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_2 ( HWord first_w32 )
 {
-   UInt sum1 = 0, sum2 = 0;
+   UInt  sum1 = 0, sum2 = 0;
    UInt* p = (UInt*)first_w32;
    UInt  w;
    w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
@@ -622,7 +726,7 @@ static UInt genericg_compute_checksum_4al_2 ( HWord first_w32 )
    return sum1 + sum2;
 }
 
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_3 ( HWord first_w32 )
 {
    UInt  sum1 = 0, sum2 = 0;
@@ -637,21 +741,21 @@ static UInt genericg_compute_checksum_4al_3 ( HWord first_w32 )
    return sum1 + sum2;
 }
 
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_4 ( HWord first_w32 )
 {
    UInt  sum1 = 0, sum2 = 0;
    UInt* p = (UInt*)first_w32;
-      UInt  w;
-      w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
-      w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
-      w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
-      w = p[3];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
-      sum1 ^= sum2;
+   UInt  w;
+   w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
+   w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
+   w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
+   w = p[3];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
+   sum1 ^= sum2;
    return sum1 + sum2;
 }
 
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_5 ( HWord first_w32 )
 {
    UInt  sum1 = 0, sum2 = 0;
@@ -667,7 +771,7 @@ static UInt genericg_compute_checksum_4al_5 ( HWord first_w32 )
    return sum1 + sum2;
 }
 
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_6 ( HWord first_w32 )
 {
    UInt  sum1 = 0, sum2 = 0;
@@ -685,7 +789,7 @@ static UInt genericg_compute_checksum_4al_6 ( HWord first_w32 )
    return sum1 + sum2;
 }
 
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_7 ( HWord first_w32 )
 {
    UInt  sum1 = 0, sum2 = 0;
@@ -705,7 +809,7 @@ static UInt genericg_compute_checksum_4al_7 ( HWord first_w32 )
    return sum1 + sum2;
 }
 
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_8 ( HWord first_w32 )
 {
    UInt  sum1 = 0, sum2 = 0;
@@ -724,7 +828,7 @@ static UInt genericg_compute_checksum_4al_8 ( HWord first_w32 )
    return sum1 + sum2;
 }
 
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_9 ( HWord first_w32 )
 {
    UInt  sum1 = 0, sum2 = 0;
@@ -745,7 +849,7 @@ static UInt genericg_compute_checksum_4al_9 ( HWord first_w32 )
    return sum1 + sum2;
 }
 
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_10 ( HWord first_w32 )
 {
    UInt  sum1 = 0, sum2 = 0;
@@ -768,7 +872,7 @@ static UInt genericg_compute_checksum_4al_10 ( HWord first_w32 )
    return sum1 + sum2;
 }
 
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_11 ( HWord first_w32 )
 {
    UInt  sum1 = 0, sum2 = 0;
@@ -793,7 +897,7 @@ static UInt genericg_compute_checksum_4al_11 ( HWord first_w32 )
    return sum1 + sum2;
 }
 
-__attribute__((regparm(1)))
+VEX_REGPARM(1)
 static UInt genericg_compute_checksum_4al_12 ( HWord first_w32 )
 {
    UInt  sum1 = 0, sum2 = 0;
@@ -817,6 +921,261 @@ static UInt genericg_compute_checksum_4al_12 ( HWord first_w32 )
    return sum1 + sum2;
 }
 
+
+/* --- 64-bit versions, used only on 64-bit hosts --- */
+
+static inline ULong ROL64 ( ULong w, Int n ) {
+   w = (w << n) | (w >> (64-n));
+   return w;
+}
+
+VEX_REGPARM(2)
+static ULong genericg_compute_checksum_8al ( HWord first_w64, HWord n_w64s )
+{
+   ULong  sum1 = 0, sum2 = 0;
+   ULong* p = (ULong*)first_w64;
+   /* unrolled */
+   while (n_w64s >= 4) {
+      ULong  w;
+      w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+      w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+      w = p[2];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+      w = p[3];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+      p += 4;
+      n_w64s -= 4;
+      sum1 ^= sum2;
+   }
+   while (n_w64s >= 1) {
+      ULong  w;
+      w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+      p += 1;
+      n_w64s -= 1;
+      sum1 ^= sum2;
+   }
+   return sum1 + sum2;
+}
+
+/* Specialised versions of the above function */
+
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_1 ( HWord first_w64 )
+{
+   ULong  sum1 = 0, sum2 = 0;
+   ULong* p = (ULong*)first_w64;
+   ULong  w;
+   w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   return sum1 + sum2;
+}
+
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_2 ( HWord first_w64 )
+{
+   ULong  sum1 = 0, sum2 = 0;
+   ULong* p = (ULong*)first_w64;
+   ULong  w;
+   w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   return sum1 + sum2;
+}
+
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_3 ( HWord first_w64 )
+{
+   ULong  sum1 = 0, sum2 = 0;
+   ULong* p = (ULong*)first_w64;
+   ULong  w;
+   w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   w = p[2];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   return sum1 + sum2;
+}
+
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_4 ( HWord first_w64 )
+{
+   ULong  sum1 = 0, sum2 = 0;
+   ULong* p = (ULong*)first_w64;
+   ULong  w;
+   w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[2];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[3];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   return sum1 + sum2;
+}
+
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_5 ( HWord first_w64 )
+{
+   ULong  sum1 = 0, sum2 = 0;
+   ULong* p = (ULong*)first_w64;
+   ULong  w;
+   w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[2];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[3];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   w = p[4];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   return sum1 + sum2;
+}
+
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_6 ( HWord first_w64 )
+{
+   ULong  sum1 = 0, sum2 = 0;
+   ULong* p = (ULong*)first_w64;
+   ULong  w;
+   w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[2];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[3];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   w = p[4];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   w = p[5];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   return sum1 + sum2;
+}
+
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_7 ( HWord first_w64 )
+{
+   ULong  sum1 = 0, sum2 = 0;
+   ULong* p = (ULong*)first_w64;
+   ULong  w;
+   w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[2];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[3];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   w = p[4];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   w = p[5];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   w = p[6];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   return sum1 + sum2;
+}
+
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_8 ( HWord first_w64 )
+{
+   ULong  sum1 = 0, sum2 = 0;
+   ULong* p = (ULong*)first_w64;
+   ULong  w;
+   w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[2];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[3];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   w = p[4];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[5];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[6];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[7];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   return sum1 + sum2;
+}
+
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_9 ( HWord first_w64 )
+{
+   ULong  sum1 = 0, sum2 = 0;
+   ULong* p = (ULong*)first_w64;
+   ULong  w;
+   w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[2];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[3];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   w = p[4];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[5];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[6];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[7];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   w = p[8];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   return sum1 + sum2;
+}
+
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_10 ( HWord first_w64 )
+{
+   ULong  sum1 = 0, sum2 = 0;
+   ULong* p = (ULong*)first_w64;
+   ULong  w;
+   w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[2];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[3];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   w = p[4];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[5];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[6];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[7];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   w = p[8];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   w = p[9];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   return sum1 + sum2;
+}
+
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_11 ( HWord first_w64 )
+{
+   ULong  sum1 = 0, sum2 = 0;
+   ULong* p = (ULong*)first_w64;
+   ULong  w;
+   w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[2];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[3];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   w = p[4];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[5];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[6];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[7];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   w = p[8];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   w = p[9];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   w = p[10]; sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   return sum1 + sum2;
+}
+
+VEX_REGPARM(1)
+static ULong genericg_compute_checksum_8al_12 ( HWord first_w64 )
+{
+   ULong  sum1 = 0, sum2 = 0;
+   ULong* p = (ULong*)first_w64;
+   ULong  w;
+   w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[2];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[3];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   w = p[4];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[5];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[6];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[7];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   w = p[8];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[9];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[10]; sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   w = p[11]; sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
+   sum1 ^= sum2;
+   return sum1 + sum2;
+}
+
 /*--------------------------------------------------------------------*/
 /*--- end                                 guest_generic_bb_to_IR.c ---*/
 /*--------------------------------------------------------------------*/