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