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