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