Home | History | Annotate | Download | only in priv
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- begin                               guest_generic_bb_to_IR.c ---*/
      4 /*--------------------------------------------------------------------*/
      5 
      6 /*
      7    This file is part of Valgrind, a dynamic binary instrumentation
      8    framework.
      9 
     10    Copyright (C) 2004-2013 OpenWorks LLP
     11       info (at) open-works.net
     12 
     13    This program is free software; you can redistribute it and/or
     14    modify it under the terms of the GNU General Public License as
     15    published by the Free Software Foundation; either version 2 of the
     16    License, or (at your option) any later version.
     17 
     18    This program is distributed in the hope that it will be useful, but
     19    WITHOUT ANY WARRANTY; without even the implied warranty of
     20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     21    General Public License for more details.
     22 
     23    You should have received a copy of the GNU General Public License
     24    along with this program; if not, write to the Free Software
     25    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
     26    02110-1301, USA.
     27 
     28    The GNU General Public License is contained in the file COPYING.
     29 
     30    Neither the names of the U.S. Department of Energy nor the
     31    University of California nor the names of its contributors may be
     32    used to endorse or promote products derived from this software
     33    without prior written permission.
     34 */
     35 
     36 #include "libvex_basictypes.h"
     37 #include "libvex_ir.h"
     38 #include "libvex.h"
     39 #include "main_util.h"
     40 #include "main_globals.h"
     41 #include "guest_generic_bb_to_IR.h"
     42 
     43 
     44 /* Forwards .. */
     45 VEX_REGPARM(2)
     46 static UInt genericg_compute_checksum_4al ( HWord first_w32, HWord n_w32s );
     47 VEX_REGPARM(1)
     48 static UInt genericg_compute_checksum_4al_1 ( HWord first_w32 );
     49 VEX_REGPARM(1)
     50 static UInt genericg_compute_checksum_4al_2 ( HWord first_w32 );
     51 VEX_REGPARM(1)
     52 static UInt genericg_compute_checksum_4al_3 ( HWord first_w32 );
     53 VEX_REGPARM(1)
     54 static UInt genericg_compute_checksum_4al_4 ( HWord first_w32 );
     55 VEX_REGPARM(1)
     56 static UInt genericg_compute_checksum_4al_5 ( HWord first_w32 );
     57 VEX_REGPARM(1)
     58 static UInt genericg_compute_checksum_4al_6 ( HWord first_w32 );
     59 VEX_REGPARM(1)
     60 static UInt genericg_compute_checksum_4al_7 ( HWord first_w32 );
     61 VEX_REGPARM(1)
     62 static UInt genericg_compute_checksum_4al_8 ( HWord first_w32 );
     63 VEX_REGPARM(1)
     64 static UInt genericg_compute_checksum_4al_9 ( HWord first_w32 );
     65 VEX_REGPARM(1)
     66 static UInt genericg_compute_checksum_4al_10 ( HWord first_w32 );
     67 VEX_REGPARM(1)
     68 static UInt genericg_compute_checksum_4al_11 ( HWord first_w32 );
     69 VEX_REGPARM(1)
     70 static UInt genericg_compute_checksum_4al_12 ( HWord first_w32 );
     71 
     72 VEX_REGPARM(2)
     73 static ULong genericg_compute_checksum_8al ( HWord first_w64, HWord n_w64s );
     74 VEX_REGPARM(1)
     75 static ULong genericg_compute_checksum_8al_1 ( HWord first_w64 );
     76 VEX_REGPARM(1)
     77 static ULong genericg_compute_checksum_8al_2 ( HWord first_w64 );
     78 VEX_REGPARM(1)
     79 static ULong genericg_compute_checksum_8al_3 ( HWord first_w64 );
     80 VEX_REGPARM(1)
     81 static ULong genericg_compute_checksum_8al_4 ( HWord first_w64 );
     82 VEX_REGPARM(1)
     83 static ULong genericg_compute_checksum_8al_5 ( HWord first_w64 );
     84 VEX_REGPARM(1)
     85 static ULong genericg_compute_checksum_8al_6 ( HWord first_w64 );
     86 VEX_REGPARM(1)
     87 static ULong genericg_compute_checksum_8al_7 ( HWord first_w64 );
     88 VEX_REGPARM(1)
     89 static ULong genericg_compute_checksum_8al_8 ( HWord first_w64 );
     90 VEX_REGPARM(1)
     91 static ULong genericg_compute_checksum_8al_9 ( HWord first_w64 );
     92 VEX_REGPARM(1)
     93 static ULong genericg_compute_checksum_8al_10 ( HWord first_w64 );
     94 VEX_REGPARM(1)
     95 static ULong genericg_compute_checksum_8al_11 ( HWord first_w64 );
     96 VEX_REGPARM(1)
     97 static ULong genericg_compute_checksum_8al_12 ( HWord first_w64 );
     98 
     99 /* Small helpers */
    100 static Bool const_False ( void* callback_opaque, Addr64 a ) {
    101    return False;
    102 }
    103 
    104 /* Disassemble a complete basic block, starting at guest_IP_start,
    105    returning a new IRSB.  The disassembler may chase across basic
    106    block boundaries if it wishes and if chase_into_ok allows it.
    107    The precise guest address ranges from which code has been taken
    108    are written into vge.  guest_IP_bbstart is taken to be the IP in
    109    the guest's address space corresponding to the instruction at
    110    &guest_code[0].
    111 
    112    dis_instr_fn is the arch-specific fn to disassemble on function; it
    113    is this that does the real work.
    114 
    115    needs_self_check is a callback used to ask the caller which of the
    116    extents, if any, a self check is required for.  The returned value
    117    is a bitmask with a 1 in position i indicating that the i'th extent
    118    needs a check.  Since there can be at most 3 extents, the returned
    119    values must be between 0 and 7.
    120 
    121    The number of extents which did get a self check (0 to 3) is put in
    122    n_sc_extents.  The caller already knows this because it told us
    123    which extents to add checks for, via the needs_self_check callback,
    124    but we ship the number back out here for the caller's convenience.
    125 
    126    preamble_function is a callback which allows the caller to add
    127    its own IR preamble (following the self-check, if any).  May be
    128    NULL.  If non-NULL, the IRSB under construction is handed to
    129    this function, which presumably adds IR statements to it.  The
    130    callback may optionally complete the block and direct bb_to_IR
    131    not to disassemble any instructions into it; this is indicated
    132    by the callback returning True.
    133 
    134    offB_CMADDR and offB_CMLEN are the offsets of guest_CMADDR and
    135    guest_CMLEN.  Since this routine has to work for any guest state,
    136    without knowing what it is, those offsets have to passed in.
    137 
    138    callback_opaque is a caller-supplied pointer to data which the
    139    callbacks may want to see.  Vex has no idea what it is.
    140    (In fact it's a VgInstrumentClosure.)
    141 */
    142 
    143 /* Regarding IP updating.  dis_instr_fn (that does the guest specific
    144    work of disassembling an individual instruction) must finish the
    145    resulting IR with "PUT(guest_IP) = ".  Hence in all cases it must
    146    state the next instruction address.
    147 
    148    If the block is to be ended at that point, then this routine
    149    (bb_to_IR) will set up the next/jumpkind/offsIP fields so as to
    150    make a transfer (of the right kind) to "GET(guest_IP)".  Hence if
    151    dis_instr_fn generates incorrect IP updates we will see it
    152    immediately (due to jumping to the wrong next guest address).
    153 
    154    However it is also necessary to set this up so it can be optimised
    155    nicely.  The IRSB exit is defined to update the guest IP, so that
    156    chaining works -- since the chain_me stubs expect the chain-to
    157    address to be in the guest state.  Hence what the IRSB next fields
    158    will contain initially is (implicitly)
    159 
    160    PUT(guest_IP) [implicitly] = GET(guest_IP) [explicit expr on ::next]
    161 
    162    which looks pretty strange at first.  Eg so unconditional branch
    163    to some address 0x123456 looks like this:
    164 
    165    PUT(guest_IP) = 0x123456;  // dis_instr_fn generates this
    166    // the exit
    167    PUT(guest_IP) [implicitly] = GET(guest_IP); exit-Boring
    168 
    169    after redundant-GET and -PUT removal by iropt, we get what we want:
    170 
    171    // the exit
    172    PUT(guest_IP) [implicitly] = 0x123456; exit-Boring
    173 
    174    This makes the IRSB-end case the same as the side-exit case: update
    175    IP, then transfer.  There is no redundancy of representation for
    176    the destination, and we use the destination specified by
    177    dis_instr_fn, so any errors it makes show up sooner.
    178 */
    179 
    180 IRSB* bb_to_IR (
    181          /*OUT*/VexGuestExtents* vge,
    182          /*OUT*/UInt*            n_sc_extents,
    183          /*OUT*/UInt*            n_guest_instrs, /* stats only */
    184          /*IN*/ void*            callback_opaque,
    185          /*IN*/ DisOneInstrFn    dis_instr_fn,
    186          /*IN*/ UChar*           guest_code,
    187          /*IN*/ Addr64           guest_IP_bbstart,
    188          /*IN*/ Bool             (*chase_into_ok)(void*,Addr64),
    189          /*IN*/ Bool             host_bigendian,
    190          /*IN*/ Bool             sigill_diag,
    191          /*IN*/ VexArch          arch_guest,
    192          /*IN*/ VexArchInfo*     archinfo_guest,
    193          /*IN*/ VexAbiInfo*      abiinfo_both,
    194          /*IN*/ IRType           guest_word_type,
    195          /*IN*/ UInt             (*needs_self_check)(void*,VexGuestExtents*),
    196          /*IN*/ Bool             (*preamble_function)(void*,IRSB*),
    197          /*IN*/ Int              offB_GUEST_CMSTART,
    198          /*IN*/ Int              offB_GUEST_CMLEN,
    199          /*IN*/ Int              offB_GUEST_IP,
    200          /*IN*/ Int              szB_GUEST_IP
    201       )
    202 {
    203    Long       delta;
    204    Int        i, n_instrs, first_stmt_idx;
    205    Bool       resteerOK, debug_print;
    206    DisResult  dres;
    207    IRStmt*    imark;
    208    IRStmt*    nop;
    209    static Int n_resteers = 0;
    210    Int        d_resteers = 0;
    211    Int        selfcheck_idx = 0;
    212    IRSB*      irsb;
    213    Addr64     guest_IP_curr_instr;
    214    IRConst*   guest_IP_bbstart_IRConst = NULL;
    215    Int        n_cond_resteers_allowed = 2;
    216 
    217    Bool (*resteerOKfn)(void*,Addr64) = NULL;
    218 
    219    debug_print = toBool(vex_traceflags & VEX_TRACE_FE);
    220 
    221    /* check sanity .. */
    222    vassert(sizeof(HWord) == sizeof(void*));
    223    vassert(vex_control.guest_max_insns >= 1);
    224    vassert(vex_control.guest_max_insns < 100);
    225    vassert(vex_control.guest_chase_thresh >= 0);
    226    vassert(vex_control.guest_chase_thresh < vex_control.guest_max_insns);
    227    vassert(guest_word_type == Ity_I32 || guest_word_type == Ity_I64);
    228 
    229    if (guest_word_type == Ity_I32) {
    230       vassert(szB_GUEST_IP == 4);
    231       vassert((offB_GUEST_IP % 4) == 0);
    232    } else {
    233       vassert(szB_GUEST_IP == 8);
    234       vassert((offB_GUEST_IP % 8) == 0);
    235    }
    236 
    237    /* Start a new, empty extent. */
    238    vge->n_used  = 1;
    239    vge->base[0] = guest_IP_bbstart;
    240    vge->len[0]  = 0;
    241    *n_sc_extents = 0;
    242 
    243    /* And a new IR superblock to dump the result into. */
    244    irsb = emptyIRSB();
    245 
    246    /* Delta keeps track of how far along the guest_code array we have
    247       so far gone. */
    248    delta    = 0;
    249    n_instrs = 0;
    250    *n_guest_instrs = 0;
    251 
    252    /* Guest addresses as IRConsts.  Used in self-checks to specify the
    253       restart-after-discard point. */
    254    guest_IP_bbstart_IRConst
    255       = guest_word_type==Ity_I32
    256            ? IRConst_U32(toUInt(guest_IP_bbstart))
    257            : IRConst_U64(guest_IP_bbstart);
    258 
    259    /* Leave 15 spaces in which to put the check statements for a self
    260       checking translation (up to 3 extents, and 5 stmts required for
    261       each).  We won't know until later the extents and checksums of
    262       the areas, if any, that need to be checked. */
    263    nop = IRStmt_NoOp();
    264    selfcheck_idx = irsb->stmts_used;
    265    for (i = 0; i < 3 * 5; i++)
    266       addStmtToIRSB( irsb, nop );
    267 
    268    /* If the caller supplied a function to add its own preamble, use
    269       it now. */
    270    if (preamble_function) {
    271       Bool stopNow = preamble_function( callback_opaque, irsb );
    272       if (stopNow) {
    273          /* The callback has completed the IR block without any guest
    274             insns being disassembled into it, so just return it at
    275             this point, even if a self-check was requested - as there
    276             is nothing to self-check.  The 15 self-check no-ops will
    277             still be in place, but they are harmless. */
    278          return irsb;
    279       }
    280    }
    281 
    282    /* Process instructions. */
    283    while (True) {
    284       vassert(n_instrs < vex_control.guest_max_insns);
    285 
    286       /* Regardless of what chase_into_ok says, is chasing permissible
    287          at all right now?  Set resteerOKfn accordingly. */
    288       resteerOK
    289          = toBool(
    290               n_instrs < vex_control.guest_chase_thresh
    291               /* we can't afford to have a resteer once we're on the
    292                  last extent slot. */
    293               && vge->n_used < 3
    294            );
    295 
    296       resteerOKfn
    297          = resteerOK ? chase_into_ok : const_False;
    298 
    299       /* n_cond_resteers_allowed keeps track of whether we're still
    300          allowing dis_instr_fn to chase conditional branches.  It
    301          starts (at 2) and gets decremented each time dis_instr_fn
    302          tells us it has chased a conditional branch.  We then
    303          decrement it, and use it to tell later calls to dis_instr_fn
    304          whether or not it is allowed to chase conditional
    305          branches. */
    306       vassert(n_cond_resteers_allowed >= 0 && n_cond_resteers_allowed <= 2);
    307 
    308       /* This is the IP of the instruction we're just about to deal
    309          with. */
    310       guest_IP_curr_instr = guest_IP_bbstart + delta;
    311 
    312       /* This is the irsb statement array index of the first stmt in
    313          this insn.  That will always be the instruction-mark
    314          descriptor. */
    315       first_stmt_idx = irsb->stmts_used;
    316 
    317       /* Add an instruction-mark statement.  We won't know until after
    318          disassembling the instruction how long it instruction is, so
    319          just put in a zero length and we'll fix it up later.
    320 
    321          On ARM, the least significant bit of the instr address
    322          distinguishes ARM vs Thumb instructions.  All instructions
    323          actually start on at least 2-aligned addresses.  So we need
    324          to ignore the bottom bit of the insn address when forming the
    325          IMark's address field, but put that bottom bit in the delta
    326          field, so that comparisons against guest_R15T for Thumb can
    327          be done correctly.  By inspecting the delta field,
    328          instruction processors can determine whether the instruction
    329          was originally Thumb or ARM.  For more details of this
    330          convention, see comments on definition of guest_R15T in
    331          libvex_guest_arm.h. */
    332       if (arch_guest == VexArchARM && (guest_IP_curr_instr & (Addr64)1)) {
    333          /* Thumb insn => mask out the T bit, but put it in delta */
    334          addStmtToIRSB( irsb,
    335                         IRStmt_IMark(guest_IP_curr_instr & ~(Addr64)1,
    336                                      0, /* len */
    337                                      1  /* delta */
    338                         )
    339          );
    340       } else {
    341          /* All other targets: store IP as-is, and set delta to zero. */
    342          addStmtToIRSB( irsb,
    343                         IRStmt_IMark(guest_IP_curr_instr,
    344                                      0, /* len */
    345                                      0  /* delta */
    346                         )
    347          );
    348       }
    349 
    350       if (debug_print && n_instrs > 0)
    351          vex_printf("\n");
    352 
    353       /* Finally, actually disassemble an instruction. */
    354       vassert(irsb->next == NULL);
    355       dres = dis_instr_fn ( irsb,
    356                             resteerOKfn,
    357                             toBool(n_cond_resteers_allowed > 0),
    358                             callback_opaque,
    359                             guest_code,
    360                             delta,
    361                             guest_IP_curr_instr,
    362                             arch_guest,
    363                             archinfo_guest,
    364                             abiinfo_both,
    365                             host_bigendian,
    366                             sigill_diag );
    367 
    368       /* stay sane ... */
    369       vassert(dres.whatNext == Dis_StopHere
    370               || dres.whatNext == Dis_Continue
    371               || dres.whatNext == Dis_ResteerU
    372               || dres.whatNext == Dis_ResteerC);
    373       /* ... disassembled insn length is sane ... */
    374       vassert(dres.len >= 0 && dres.len <= 20);
    375       /* ... continueAt is zero if no resteer requested ... */
    376       if (dres.whatNext != Dis_ResteerU && dres.whatNext != Dis_ResteerC)
    377          vassert(dres.continueAt == 0);
    378       /* ... if we disallowed conditional resteers, check that one
    379              didn't actually happen anyway ... */
    380       if (n_cond_resteers_allowed == 0)
    381          vassert(dres.whatNext != Dis_ResteerC);
    382 
    383       /* Fill in the insn-mark length field. */
    384       vassert(first_stmt_idx >= 0 && first_stmt_idx < irsb->stmts_used);
    385       imark = irsb->stmts[first_stmt_idx];
    386       vassert(imark);
    387       vassert(imark->tag == Ist_IMark);
    388       vassert(imark->Ist.IMark.len == 0);
    389       imark->Ist.IMark.len = toUInt(dres.len);
    390 
    391       /* Print the resulting IR, if needed. */
    392       if (vex_traceflags & VEX_TRACE_FE) {
    393          for (i = first_stmt_idx; i < irsb->stmts_used; i++) {
    394             vex_printf("              ");
    395             ppIRStmt(irsb->stmts[i]);
    396             vex_printf("\n");
    397          }
    398       }
    399 
    400       /* Individual insn disassembly may not mess with irsb->next.
    401          This function is the only place where it can be set. */
    402       vassert(irsb->next == NULL);
    403       vassert(irsb->jumpkind == Ijk_Boring);
    404       vassert(irsb->offsIP == 0);
    405 
    406       /* Individual insn disassembly must finish the IR for each
    407          instruction with an assignment to the guest PC. */
    408       vassert(first_stmt_idx < irsb->stmts_used);
    409       /* it follows that irsb->stmts_used must be > 0 */
    410       { IRStmt* st = irsb->stmts[irsb->stmts_used-1];
    411         vassert(st);
    412         vassert(st->tag == Ist_Put);
    413         vassert(st->Ist.Put.offset == offB_GUEST_IP);
    414         /* Really we should also check that the type of the Put'd data
    415            == guest_word_type, but that's a bit expensive. */
    416       }
    417 
    418       /* Update the VexGuestExtents we are constructing. */
    419       /* If vex_control.guest_max_insns is required to be < 100 and
    420          each insn is at max 20 bytes long, this limit of 5000 then
    421          seems reasonable since the max possible extent length will be
    422          100 * 20 == 2000. */
    423       vassert(vge->len[vge->n_used-1] < 5000);
    424       vge->len[vge->n_used-1]
    425          = toUShort(toUInt( vge->len[vge->n_used-1] + dres.len ));
    426       n_instrs++;
    427 
    428       /* Advance delta (inconspicuous but very important :-) */
    429       delta += (Long)dres.len;
    430 
    431       switch (dres.whatNext) {
    432          case Dis_Continue:
    433             vassert(dres.continueAt == 0);
    434             vassert(dres.jk_StopHere == Ijk_INVALID);
    435             if (n_instrs < vex_control.guest_max_insns) {
    436                /* keep going */
    437             } else {
    438                /* We have to stop.  See comment above re irsb field
    439                   settings here. */
    440                irsb->next = IRExpr_Get(offB_GUEST_IP, guest_word_type);
    441                /* irsb->jumpkind must already by Ijk_Boring */
    442                irsb->offsIP = offB_GUEST_IP;
    443                goto done;
    444             }
    445             break;
    446          case Dis_StopHere:
    447             vassert(dres.continueAt == 0);
    448             vassert(dres.jk_StopHere != Ijk_INVALID);
    449             /* See comment above re irsb field settings here. */
    450             irsb->next = IRExpr_Get(offB_GUEST_IP, guest_word_type);
    451             irsb->jumpkind = dres.jk_StopHere;
    452             irsb->offsIP = offB_GUEST_IP;
    453             goto done;
    454 
    455          case Dis_ResteerU:
    456          case Dis_ResteerC:
    457             /* Check that we actually allowed a resteer .. */
    458             vassert(resteerOK);
    459             if (dres.whatNext == Dis_ResteerC) {
    460                vassert(n_cond_resteers_allowed > 0);
    461                n_cond_resteers_allowed--;
    462             }
    463             /* figure out a new delta to continue at. */
    464             vassert(resteerOKfn(callback_opaque,dres.continueAt));
    465             delta = dres.continueAt - guest_IP_bbstart;
    466             /* we now have to start a new extent slot. */
    467             vge->n_used++;
    468             vassert(vge->n_used <= 3);
    469             vge->base[vge->n_used-1] = dres.continueAt;
    470             vge->len[vge->n_used-1] = 0;
    471             n_resteers++;
    472             d_resteers++;
    473             if (0 && (n_resteers & 0xFF) == 0)
    474             vex_printf("resteer[%d,%d] to 0x%llx (delta = %lld)\n",
    475                        n_resteers, d_resteers,
    476                        dres.continueAt, delta);
    477             break;
    478          default:
    479             vpanic("bb_to_IR");
    480       }
    481    }
    482    /*NOTREACHED*/
    483    vassert(0);
    484 
    485   done:
    486    /* We're done.  The only thing that might need attending to is that
    487       a self-checking preamble may need to be created.  If so it gets
    488       placed in the 15 slots reserved above.
    489 
    490       The scheme is to compute a rather crude checksum of the code
    491       we're making a translation of, and add to the IR a call to a
    492       helper routine which recomputes the checksum every time the
    493       translation is run, and requests a retranslation if it doesn't
    494       match.  This is obviously very expensive and considerable
    495       efforts are made to speed it up:
    496 
    497       * the checksum is computed from all the naturally aligned
    498         host-sized words that overlap the translated code.  That means
    499         it could depend on up to 7 bytes before and 7 bytes after
    500         which aren't part of the translated area, and so if those
    501         change then we'll unnecessarily have to discard and
    502         retranslate.  This seems like a pretty remote possibility and
    503         it seems as if the benefit of not having to deal with the ends
    504         of the range at byte precision far outweigh any possible extra
    505         translations needed.
    506 
    507       * there's a generic routine and 12 specialised cases, which
    508         handle the cases of 1 through 12-word lengths respectively.
    509         They seem to cover about 90% of the cases that occur in
    510         practice.
    511 
    512       We ask the caller, via needs_self_check, which of the 3 vge
    513       extents needs a check, and only generate check code for those
    514       that do.
    515    */
    516    {
    517       Addr64   base2check;
    518       UInt     len2check;
    519       HWord    expectedhW;
    520       IRTemp   tistart_tmp, tilen_tmp;
    521       HWord    VEX_REGPARM(2) (*fn_generic)(HWord, HWord);
    522       HWord    VEX_REGPARM(1) (*fn_spec)(HWord);
    523       const HChar* nm_generic;
    524       const HChar* nm_spec;
    525       HWord    fn_generic_entry = 0;
    526       HWord    fn_spec_entry = 0;
    527       UInt     host_word_szB = sizeof(HWord);
    528       IRType   host_word_type = Ity_INVALID;
    529 
    530       VexGuestExtents vge_tmp = *vge;
    531       UInt extents_needing_check
    532          = needs_self_check(callback_opaque, &vge_tmp);
    533 
    534       if (host_word_szB == 4) host_word_type = Ity_I32;
    535       if (host_word_szB == 8) host_word_type = Ity_I64;
    536       vassert(host_word_type != Ity_INVALID);
    537 
    538       vassert(vge->n_used >= 1 && vge->n_used <= 3);
    539 
    540       /* Caller shouldn't claim that nonexistent extents need a
    541          check. */
    542       vassert((extents_needing_check >> vge->n_used) == 0);
    543 
    544       for (i = 0; i < vge->n_used; i++) {
    545 
    546          /* Do we need to generate a check for this extent? */
    547          if ((extents_needing_check & (1 << i)) == 0)
    548             continue;
    549 
    550          /* Tell the caller */
    551          (*n_sc_extents)++;
    552 
    553          /* the extent we're generating a check for */
    554          base2check = vge->base[i];
    555          len2check  = vge->len[i];
    556 
    557          /* stay sane */
    558          vassert(len2check >= 0 && len2check < 1000/*arbitrary*/);
    559 
    560          /* Skip the check if the translation involved zero bytes */
    561          if (len2check == 0)
    562             continue;
    563 
    564          HWord first_hW = ((HWord)base2check)
    565                           & ~(HWord)(host_word_szB-1);
    566          HWord last_hW  = (((HWord)base2check) + len2check - 1)
    567                           & ~(HWord)(host_word_szB-1);
    568          vassert(first_hW <= last_hW);
    569          HWord hW_diff = last_hW - first_hW;
    570          vassert(0 == (hW_diff & (host_word_szB-1)));
    571          HWord hWs_to_check = (hW_diff + host_word_szB) / host_word_szB;
    572          vassert(hWs_to_check > 0
    573                  && hWs_to_check < 1004/*arbitrary*/ / host_word_szB);
    574 
    575          /* vex_printf("%lx %lx  %ld\n", first_hW, last_hW, hWs_to_check); */
    576 
    577          if (host_word_szB == 8) {
    578             fn_generic =  (VEX_REGPARM(2) HWord(*)(HWord, HWord))
    579                           genericg_compute_checksum_8al;
    580             nm_generic = "genericg_compute_checksum_8al";
    581          } else {
    582             fn_generic =  (VEX_REGPARM(2) HWord(*)(HWord, HWord))
    583                           genericg_compute_checksum_4al;
    584             nm_generic = "genericg_compute_checksum_4al";
    585          }
    586 
    587          fn_spec = NULL;
    588          nm_spec = NULL;
    589 
    590          if (host_word_szB == 8) {
    591             const HChar* nm = NULL;
    592             ULong  VEX_REGPARM(1) (*fn)(HWord)  = NULL;
    593             switch (hWs_to_check) {
    594                case 1:  fn =  genericg_compute_checksum_8al_1;
    595                         nm = "genericg_compute_checksum_8al_1"; break;
    596                case 2:  fn =  genericg_compute_checksum_8al_2;
    597                         nm = "genericg_compute_checksum_8al_2"; break;
    598                case 3:  fn =  genericg_compute_checksum_8al_3;
    599                         nm = "genericg_compute_checksum_8al_3"; break;
    600                case 4:  fn =  genericg_compute_checksum_8al_4;
    601                         nm = "genericg_compute_checksum_8al_4"; break;
    602                case 5:  fn =  genericg_compute_checksum_8al_5;
    603                         nm = "genericg_compute_checksum_8al_5"; break;
    604                case 6:  fn =  genericg_compute_checksum_8al_6;
    605                         nm = "genericg_compute_checksum_8al_6"; break;
    606                case 7:  fn =  genericg_compute_checksum_8al_7;
    607                         nm = "genericg_compute_checksum_8al_7"; break;
    608                case 8:  fn =  genericg_compute_checksum_8al_8;
    609                         nm = "genericg_compute_checksum_8al_8"; break;
    610                case 9:  fn =  genericg_compute_checksum_8al_9;
    611                         nm = "genericg_compute_checksum_8al_9"; break;
    612                case 10: fn =  genericg_compute_checksum_8al_10;
    613                         nm = "genericg_compute_checksum_8al_10"; break;
    614                case 11: fn =  genericg_compute_checksum_8al_11;
    615                         nm = "genericg_compute_checksum_8al_11"; break;
    616                case 12: fn =  genericg_compute_checksum_8al_12;
    617                         nm = "genericg_compute_checksum_8al_12"; break;
    618                default: break;
    619             }
    620             fn_spec = (VEX_REGPARM(1) HWord(*)(HWord)) fn;
    621             nm_spec = nm;
    622          } else {
    623             const HChar* nm = NULL;
    624             UInt   VEX_REGPARM(1) (*fn)(HWord) = NULL;
    625             switch (hWs_to_check) {
    626                case 1:  fn =  genericg_compute_checksum_4al_1;
    627                         nm = "genericg_compute_checksum_4al_1"; break;
    628                case 2:  fn =  genericg_compute_checksum_4al_2;
    629                         nm = "genericg_compute_checksum_4al_2"; break;
    630                case 3:  fn =  genericg_compute_checksum_4al_3;
    631                         nm = "genericg_compute_checksum_4al_3"; break;
    632                case 4:  fn =  genericg_compute_checksum_4al_4;
    633                         nm = "genericg_compute_checksum_4al_4"; break;
    634                case 5:  fn =  genericg_compute_checksum_4al_5;
    635                         nm = "genericg_compute_checksum_4al_5"; break;
    636                case 6:  fn =  genericg_compute_checksum_4al_6;
    637                         nm = "genericg_compute_checksum_4al_6"; break;
    638                case 7:  fn =  genericg_compute_checksum_4al_7;
    639                         nm = "genericg_compute_checksum_4al_7"; break;
    640                case 8:  fn =  genericg_compute_checksum_4al_8;
    641                         nm = "genericg_compute_checksum_4al_8"; break;
    642                case 9:  fn =  genericg_compute_checksum_4al_9;
    643                         nm = "genericg_compute_checksum_4al_9"; break;
    644                case 10: fn =  genericg_compute_checksum_4al_10;
    645                         nm = "genericg_compute_checksum_4al_10"; break;
    646                case 11: fn =  genericg_compute_checksum_4al_11;
    647                         nm = "genericg_compute_checksum_4al_11"; break;
    648                case 12: fn =  genericg_compute_checksum_4al_12;
    649                         nm = "genericg_compute_checksum_4al_12"; break;
    650                default: break;
    651             }
    652             fn_spec = (VEX_REGPARM(1) HWord(*)(HWord))fn;
    653             nm_spec = nm;
    654          }
    655 
    656          expectedhW = fn_generic( first_hW, hWs_to_check );
    657          /* If we got a specialised version, check it produces the same
    658             result as the generic version! */
    659          if (fn_spec) {
    660             vassert(nm_spec);
    661             vassert(expectedhW == fn_spec( first_hW ));
    662          } else {
    663             vassert(!nm_spec);
    664          }
    665 
    666          /* Set CMSTART and CMLEN.  These will describe to the despatcher
    667             the area of guest code to invalidate should we exit with a
    668             self-check failure. */
    669 
    670          tistart_tmp = newIRTemp(irsb->tyenv, guest_word_type);
    671          tilen_tmp   = newIRTemp(irsb->tyenv, guest_word_type);
    672 
    673          IRConst* base2check_IRConst
    674             = guest_word_type==Ity_I32 ? IRConst_U32(toUInt(base2check))
    675                                        : IRConst_U64(base2check);
    676          IRConst* len2check_IRConst
    677             = guest_word_type==Ity_I32 ? IRConst_U32(len2check)
    678                                        : IRConst_U64(len2check);
    679 
    680          irsb->stmts[selfcheck_idx + i * 5 + 0]
    681             = IRStmt_WrTmp(tistart_tmp, IRExpr_Const(base2check_IRConst) );
    682 
    683          irsb->stmts[selfcheck_idx + i * 5 + 1]
    684             = IRStmt_WrTmp(tilen_tmp, IRExpr_Const(len2check_IRConst) );
    685 
    686          irsb->stmts[selfcheck_idx + i * 5 + 2]
    687             = IRStmt_Put( offB_GUEST_CMSTART, IRExpr_RdTmp(tistart_tmp) );
    688 
    689          irsb->stmts[selfcheck_idx + i * 5 + 3]
    690             = IRStmt_Put( offB_GUEST_CMLEN, IRExpr_RdTmp(tilen_tmp) );
    691 
    692          /* Generate the entry point descriptors */
    693          if (abiinfo_both->host_ppc_calls_use_fndescrs) {
    694             HWord* descr = (HWord*)fn_generic;
    695             fn_generic_entry = descr[0];
    696             if (fn_spec) {
    697                descr = (HWord*)fn_spec;
    698                fn_spec_entry = descr[0];
    699             } else {
    700                fn_spec_entry = (HWord)NULL;
    701             }
    702          } else {
    703             fn_generic_entry = (HWord)fn_generic;
    704             if (fn_spec) {
    705                fn_spec_entry = (HWord)fn_spec;
    706             } else {
    707                fn_spec_entry = (HWord)NULL;
    708             }
    709          }
    710 
    711          IRExpr* callexpr = NULL;
    712          if (fn_spec) {
    713             callexpr = mkIRExprCCall(
    714                           host_word_type, 1/*regparms*/,
    715                           nm_spec, (void*)fn_spec_entry,
    716                           mkIRExprVec_1(
    717                              mkIRExpr_HWord( (HWord)first_hW )
    718                           )
    719                        );
    720          } else {
    721             callexpr = mkIRExprCCall(
    722                           host_word_type, 2/*regparms*/,
    723                           nm_generic, (void*)fn_generic_entry,
    724                           mkIRExprVec_2(
    725                              mkIRExpr_HWord( (HWord)first_hW ),
    726                              mkIRExpr_HWord( (HWord)hWs_to_check )
    727                           )
    728                        );
    729          }
    730 
    731          irsb->stmts[selfcheck_idx + i * 5 + 4]
    732             = IRStmt_Exit(
    733                  IRExpr_Binop(
    734                     host_word_type==Ity_I64 ? Iop_CmpNE64 : Iop_CmpNE32,
    735                     callexpr,
    736                        host_word_type==Ity_I64
    737                           ? IRExpr_Const(IRConst_U64(expectedhW))
    738                           : IRExpr_Const(IRConst_U32(expectedhW))
    739                  ),
    740                  Ijk_InvalICache,
    741                  /* Where we must restart if there's a failure: at the
    742                     first extent, regardless of which extent the
    743                     failure actually happened in. */
    744                  guest_IP_bbstart_IRConst,
    745                  offB_GUEST_IP
    746               );
    747       } /* for (i = 0; i < vge->n_used; i++) */
    748    }
    749 
    750    /* irsb->next must now be set, since we've finished the block.
    751       Print it if necessary.*/
    752    vassert(irsb->next != NULL);
    753    if (debug_print) {
    754       vex_printf("              ");
    755       vex_printf( "PUT(%d) = ", irsb->offsIP);
    756       ppIRExpr( irsb->next );
    757       vex_printf( "; exit-");
    758       ppIRJumpKind(irsb->jumpkind);
    759       vex_printf( "\n");
    760       vex_printf( "\n");
    761    }
    762 
    763    *n_guest_instrs = n_instrs;
    764    return irsb;
    765 }
    766 
    767 
    768 /*-------------------------------------------------------------
    769   A support routine for doing self-checking translations.
    770   -------------------------------------------------------------*/
    771 
    772 /* CLEAN HELPER */
    773 /* CALLED FROM GENERATED CODE */
    774 
    775 /* Compute a checksum of host memory at [addr .. addr+len-1], as fast
    776    as possible.  All _4al versions assume that the supplied address is
    777    4 aligned.  All length values are in 4-byte chunks.  These fns
    778    arecalled once for every use of a self-checking translation, so
    779    they needs to be as fast as possible. */
    780 
    781 /* --- 32-bit versions, used only on 32-bit hosts --- */
    782 
    783 static inline UInt ROL32 ( UInt w, Int n ) {
    784    w = (w << n) | (w >> (32-n));
    785    return w;
    786 }
    787 
    788 VEX_REGPARM(2)
    789 static UInt genericg_compute_checksum_4al ( HWord first_w32, HWord n_w32s )
    790 {
    791    UInt  sum1 = 0, sum2 = 0;
    792    UInt* p = (UInt*)first_w32;
    793    /* unrolled */
    794    while (n_w32s >= 4) {
    795       UInt  w;
    796       w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    797       w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    798       w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    799       w = p[3];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    800       p += 4;
    801       n_w32s -= 4;
    802       sum1 ^= sum2;
    803    }
    804    while (n_w32s >= 1) {
    805       UInt  w;
    806       w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    807       p += 1;
    808       n_w32s -= 1;
    809       sum1 ^= sum2;
    810    }
    811    return sum1 + sum2;
    812 }
    813 
    814 /* Specialised versions of the above function */
    815 
    816 VEX_REGPARM(1)
    817 static UInt genericg_compute_checksum_4al_1 ( HWord first_w32 )
    818 {
    819    UInt  sum1 = 0, sum2 = 0;
    820    UInt* p = (UInt*)first_w32;
    821    UInt  w;
    822    w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    823    sum1 ^= sum2;
    824    return sum1 + sum2;
    825 }
    826 
    827 VEX_REGPARM(1)
    828 static UInt genericg_compute_checksum_4al_2 ( HWord first_w32 )
    829 {
    830    UInt  sum1 = 0, sum2 = 0;
    831    UInt* p = (UInt*)first_w32;
    832    UInt  w;
    833    w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    834    sum1 ^= sum2;
    835    w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    836    sum1 ^= sum2;
    837    return sum1 + sum2;
    838 }
    839 
    840 VEX_REGPARM(1)
    841 static UInt genericg_compute_checksum_4al_3 ( HWord first_w32 )
    842 {
    843    UInt  sum1 = 0, sum2 = 0;
    844    UInt* p = (UInt*)first_w32;
    845    UInt  w;
    846    w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    847    sum1 ^= sum2;
    848    w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    849    sum1 ^= sum2;
    850    w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    851    sum1 ^= sum2;
    852    return sum1 + sum2;
    853 }
    854 
    855 VEX_REGPARM(1)
    856 static UInt genericg_compute_checksum_4al_4 ( HWord first_w32 )
    857 {
    858    UInt  sum1 = 0, sum2 = 0;
    859    UInt* p = (UInt*)first_w32;
    860    UInt  w;
    861    w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    862    w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    863    w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    864    w = p[3];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    865    sum1 ^= sum2;
    866    return sum1 + sum2;
    867 }
    868 
    869 VEX_REGPARM(1)
    870 static UInt genericg_compute_checksum_4al_5 ( HWord first_w32 )
    871 {
    872    UInt  sum1 = 0, sum2 = 0;
    873    UInt* p = (UInt*)first_w32;
    874    UInt  w;
    875    w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    876    w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    877    w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    878    w = p[3];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    879    sum1 ^= sum2;
    880    w = p[4];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    881    sum1 ^= sum2;
    882    return sum1 + sum2;
    883 }
    884 
    885 VEX_REGPARM(1)
    886 static UInt genericg_compute_checksum_4al_6 ( HWord first_w32 )
    887 {
    888    UInt  sum1 = 0, sum2 = 0;
    889    UInt* p = (UInt*)first_w32;
    890    UInt  w;
    891    w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    892    w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    893    w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    894    w = p[3];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    895    sum1 ^= sum2;
    896    w = p[4];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    897    sum1 ^= sum2;
    898    w = p[5];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    899    sum1 ^= sum2;
    900    return sum1 + sum2;
    901 }
    902 
    903 VEX_REGPARM(1)
    904 static UInt genericg_compute_checksum_4al_7 ( HWord first_w32 )
    905 {
    906    UInt  sum1 = 0, sum2 = 0;
    907    UInt* p = (UInt*)first_w32;
    908    UInt  w;
    909    w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    910    w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    911    w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    912    w = p[3];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    913    sum1 ^= sum2;
    914    w = p[4];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    915    sum1 ^= sum2;
    916    w = p[5];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    917    sum1 ^= sum2;
    918    w = p[6];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    919    sum1 ^= sum2;
    920    return sum1 + sum2;
    921 }
    922 
    923 VEX_REGPARM(1)
    924 static UInt genericg_compute_checksum_4al_8 ( HWord first_w32 )
    925 {
    926    UInt  sum1 = 0, sum2 = 0;
    927    UInt* p = (UInt*)first_w32;
    928    UInt  w;
    929    w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    930    w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    931    w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    932    w = p[3];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    933    sum1 ^= sum2;
    934    w = p[4];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    935    w = p[5];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    936    w = p[6];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    937    w = p[7];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    938    sum1 ^= sum2;
    939    return sum1 + sum2;
    940 }
    941 
    942 VEX_REGPARM(1)
    943 static UInt genericg_compute_checksum_4al_9 ( HWord first_w32 )
    944 {
    945    UInt  sum1 = 0, sum2 = 0;
    946    UInt* p = (UInt*)first_w32;
    947    UInt  w;
    948    w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    949    w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    950    w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    951    w = p[3];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    952    sum1 ^= sum2;
    953    w = p[4];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    954    w = p[5];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    955    w = p[6];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    956    w = p[7];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    957    sum1 ^= sum2;
    958    w = p[8];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    959    sum1 ^= sum2;
    960    return sum1 + sum2;
    961 }
    962 
    963 VEX_REGPARM(1)
    964 static UInt genericg_compute_checksum_4al_10 ( HWord first_w32 )
    965 {
    966    UInt  sum1 = 0, sum2 = 0;
    967    UInt* p = (UInt*)first_w32;
    968    UInt  w;
    969    w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    970    w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    971    w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    972    w = p[3];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    973    sum1 ^= sum2;
    974    w = p[4];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    975    w = p[5];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    976    w = p[6];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    977    w = p[7];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    978    sum1 ^= sum2;
    979    w = p[8];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    980    sum1 ^= sum2;
    981    w = p[9];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    982    sum1 ^= sum2;
    983    return sum1 + sum2;
    984 }
    985 
    986 VEX_REGPARM(1)
    987 static UInt genericg_compute_checksum_4al_11 ( HWord first_w32 )
    988 {
    989    UInt  sum1 = 0, sum2 = 0;
    990    UInt* p = (UInt*)first_w32;
    991    UInt  w;
    992    w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    993    w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    994    w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    995    w = p[3];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    996    sum1 ^= sum2;
    997    w = p[4];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    998    w = p[5];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
    999    w = p[6];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
   1000    w = p[7];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
   1001    sum1 ^= sum2;
   1002    w = p[8];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
   1003    sum1 ^= sum2;
   1004    w = p[9];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
   1005    sum1 ^= sum2;
   1006    w = p[10]; sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
   1007    sum1 ^= sum2;
   1008    return sum1 + sum2;
   1009 }
   1010 
   1011 VEX_REGPARM(1)
   1012 static UInt genericg_compute_checksum_4al_12 ( HWord first_w32 )
   1013 {
   1014    UInt  sum1 = 0, sum2 = 0;
   1015    UInt* p = (UInt*)first_w32;
   1016    UInt  w;
   1017    w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
   1018    w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
   1019    w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
   1020    w = p[3];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
   1021    sum1 ^= sum2;
   1022    w = p[4];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
   1023    w = p[5];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
   1024    w = p[6];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
   1025    w = p[7];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
   1026    sum1 ^= sum2;
   1027    w = p[8];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
   1028    w = p[9];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
   1029    w = p[10]; sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
   1030    w = p[11]; sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
   1031    sum1 ^= sum2;
   1032    return sum1 + sum2;
   1033 }
   1034 
   1035 
   1036 /* --- 64-bit versions, used only on 64-bit hosts --- */
   1037 
   1038 static inline ULong ROL64 ( ULong w, Int n ) {
   1039    w = (w << n) | (w >> (64-n));
   1040    return w;
   1041 }
   1042 
   1043 VEX_REGPARM(2)
   1044 static ULong genericg_compute_checksum_8al ( HWord first_w64, HWord n_w64s )
   1045 {
   1046    ULong  sum1 = 0, sum2 = 0;
   1047    ULong* p = (ULong*)first_w64;
   1048    /* unrolled */
   1049    while (n_w64s >= 4) {
   1050       ULong  w;
   1051       w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1052       w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1053       w = p[2];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1054       w = p[3];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1055       p += 4;
   1056       n_w64s -= 4;
   1057       sum1 ^= sum2;
   1058    }
   1059    while (n_w64s >= 1) {
   1060       ULong  w;
   1061       w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1062       p += 1;
   1063       n_w64s -= 1;
   1064       sum1 ^= sum2;
   1065    }
   1066    return sum1 + sum2;
   1067 }
   1068 
   1069 /* Specialised versions of the above function */
   1070 
   1071 VEX_REGPARM(1)
   1072 static ULong genericg_compute_checksum_8al_1 ( HWord first_w64 )
   1073 {
   1074    ULong  sum1 = 0, sum2 = 0;
   1075    ULong* p = (ULong*)first_w64;
   1076    ULong  w;
   1077    w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1078    sum1 ^= sum2;
   1079    return sum1 + sum2;
   1080 }
   1081 
   1082 VEX_REGPARM(1)
   1083 static ULong genericg_compute_checksum_8al_2 ( HWord first_w64 )
   1084 {
   1085    ULong  sum1 = 0, sum2 = 0;
   1086    ULong* p = (ULong*)first_w64;
   1087    ULong  w;
   1088    w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1089    sum1 ^= sum2;
   1090    w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1091    sum1 ^= sum2;
   1092    return sum1 + sum2;
   1093 }
   1094 
   1095 VEX_REGPARM(1)
   1096 static ULong genericg_compute_checksum_8al_3 ( HWord first_w64 )
   1097 {
   1098    ULong  sum1 = 0, sum2 = 0;
   1099    ULong* p = (ULong*)first_w64;
   1100    ULong  w;
   1101    w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1102    sum1 ^= sum2;
   1103    w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1104    sum1 ^= sum2;
   1105    w = p[2];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1106    sum1 ^= sum2;
   1107    return sum1 + sum2;
   1108 }
   1109 
   1110 VEX_REGPARM(1)
   1111 static ULong genericg_compute_checksum_8al_4 ( HWord first_w64 )
   1112 {
   1113    ULong  sum1 = 0, sum2 = 0;
   1114    ULong* p = (ULong*)first_w64;
   1115    ULong  w;
   1116    w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1117    w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1118    w = p[2];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1119    w = p[3];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1120    sum1 ^= sum2;
   1121    return sum1 + sum2;
   1122 }
   1123 
   1124 VEX_REGPARM(1)
   1125 static ULong genericg_compute_checksum_8al_5 ( HWord first_w64 )
   1126 {
   1127    ULong  sum1 = 0, sum2 = 0;
   1128    ULong* p = (ULong*)first_w64;
   1129    ULong  w;
   1130    w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1131    w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1132    w = p[2];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1133    w = p[3];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1134    sum1 ^= sum2;
   1135    w = p[4];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1136    sum1 ^= sum2;
   1137    return sum1 + sum2;
   1138 }
   1139 
   1140 VEX_REGPARM(1)
   1141 static ULong genericg_compute_checksum_8al_6 ( HWord first_w64 )
   1142 {
   1143    ULong  sum1 = 0, sum2 = 0;
   1144    ULong* p = (ULong*)first_w64;
   1145    ULong  w;
   1146    w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1147    w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1148    w = p[2];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1149    w = p[3];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1150    sum1 ^= sum2;
   1151    w = p[4];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1152    sum1 ^= sum2;
   1153    w = p[5];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1154    sum1 ^= sum2;
   1155    return sum1 + sum2;
   1156 }
   1157 
   1158 VEX_REGPARM(1)
   1159 static ULong genericg_compute_checksum_8al_7 ( HWord first_w64 )
   1160 {
   1161    ULong  sum1 = 0, sum2 = 0;
   1162    ULong* p = (ULong*)first_w64;
   1163    ULong  w;
   1164    w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1165    w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1166    w = p[2];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1167    w = p[3];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1168    sum1 ^= sum2;
   1169    w = p[4];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1170    sum1 ^= sum2;
   1171    w = p[5];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1172    sum1 ^= sum2;
   1173    w = p[6];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1174    sum1 ^= sum2;
   1175    return sum1 + sum2;
   1176 }
   1177 
   1178 VEX_REGPARM(1)
   1179 static ULong genericg_compute_checksum_8al_8 ( HWord first_w64 )
   1180 {
   1181    ULong  sum1 = 0, sum2 = 0;
   1182    ULong* p = (ULong*)first_w64;
   1183    ULong  w;
   1184    w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1185    w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1186    w = p[2];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1187    w = p[3];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1188    sum1 ^= sum2;
   1189    w = p[4];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1190    w = p[5];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1191    w = p[6];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1192    w = p[7];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1193    sum1 ^= sum2;
   1194    return sum1 + sum2;
   1195 }
   1196 
   1197 VEX_REGPARM(1)
   1198 static ULong genericg_compute_checksum_8al_9 ( HWord first_w64 )
   1199 {
   1200    ULong  sum1 = 0, sum2 = 0;
   1201    ULong* p = (ULong*)first_w64;
   1202    ULong  w;
   1203    w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1204    w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1205    w = p[2];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1206    w = p[3];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1207    sum1 ^= sum2;
   1208    w = p[4];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1209    w = p[5];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1210    w = p[6];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1211    w = p[7];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1212    sum1 ^= sum2;
   1213    w = p[8];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1214    sum1 ^= sum2;
   1215    return sum1 + sum2;
   1216 }
   1217 
   1218 VEX_REGPARM(1)
   1219 static ULong genericg_compute_checksum_8al_10 ( HWord first_w64 )
   1220 {
   1221    ULong  sum1 = 0, sum2 = 0;
   1222    ULong* p = (ULong*)first_w64;
   1223    ULong  w;
   1224    w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1225    w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1226    w = p[2];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1227    w = p[3];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1228    sum1 ^= sum2;
   1229    w = p[4];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1230    w = p[5];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1231    w = p[6];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1232    w = p[7];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1233    sum1 ^= sum2;
   1234    w = p[8];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1235    sum1 ^= sum2;
   1236    w = p[9];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1237    sum1 ^= sum2;
   1238    return sum1 + sum2;
   1239 }
   1240 
   1241 VEX_REGPARM(1)
   1242 static ULong genericg_compute_checksum_8al_11 ( HWord first_w64 )
   1243 {
   1244    ULong  sum1 = 0, sum2 = 0;
   1245    ULong* p = (ULong*)first_w64;
   1246    ULong  w;
   1247    w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1248    w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1249    w = p[2];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1250    w = p[3];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1251    sum1 ^= sum2;
   1252    w = p[4];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1253    w = p[5];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1254    w = p[6];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1255    w = p[7];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1256    sum1 ^= sum2;
   1257    w = p[8];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1258    sum1 ^= sum2;
   1259    w = p[9];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1260    sum1 ^= sum2;
   1261    w = p[10]; sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1262    sum1 ^= sum2;
   1263    return sum1 + sum2;
   1264 }
   1265 
   1266 VEX_REGPARM(1)
   1267 static ULong genericg_compute_checksum_8al_12 ( HWord first_w64 )
   1268 {
   1269    ULong  sum1 = 0, sum2 = 0;
   1270    ULong* p = (ULong*)first_w64;
   1271    ULong  w;
   1272    w = p[0];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1273    w = p[1];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1274    w = p[2];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1275    w = p[3];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1276    sum1 ^= sum2;
   1277    w = p[4];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1278    w = p[5];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1279    w = p[6];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1280    w = p[7];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1281    sum1 ^= sum2;
   1282    w = p[8];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1283    w = p[9];  sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1284    w = p[10]; sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1285    w = p[11]; sum1 = ROL64(sum1 ^ w, 63);  sum2 += w;
   1286    sum1 ^= sum2;
   1287    return sum1 + sum2;
   1288 }
   1289 
   1290 /*--------------------------------------------------------------------*/
   1291 /*--- end                                 guest_generic_bb_to_IR.c ---*/
   1292 /*--------------------------------------------------------------------*/
   1293