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