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