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