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