2 /*--------------------------------------------------------------------*/
3 /*--- begin guest_generic_bb_to_IR.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2004-2010 OpenWorks LLP
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.
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.
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
28 The GNU General Public License is contained in the file COPYING.
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.
36 #include "libvex_basictypes.h"
37 #include "libvex_ir.h"
39 #include "main_util.h"
40 #include "main_globals.h"
41 #include "guest_generic_bb_to_IR.h"
46 static UInt genericg_compute_checksum_4al ( HWord first_w32, HWord n_w32s );
48 static UInt genericg_compute_checksum_4al_1 ( HWord first_w32 );
50 static UInt genericg_compute_checksum_4al_2 ( HWord first_w32 );
52 static UInt genericg_compute_checksum_4al_3 ( HWord first_w32 );
54 static UInt genericg_compute_checksum_4al_4 ( HWord first_w32 );
56 static UInt genericg_compute_checksum_4al_5 ( HWord first_w32 );
58 static UInt genericg_compute_checksum_4al_6 ( HWord first_w32 );
60 static UInt genericg_compute_checksum_4al_7 ( HWord first_w32 );
62 static UInt genericg_compute_checksum_4al_8 ( HWord first_w32 );
64 static UInt genericg_compute_checksum_4al_9 ( HWord first_w32 );
66 static UInt genericg_compute_checksum_4al_10 ( HWord first_w32 );
68 static UInt genericg_compute_checksum_4al_11 ( HWord first_w32 );
70 static UInt genericg_compute_checksum_4al_12 ( HWord first_w32 );
73 static ULong genericg_compute_checksum_8al ( HWord first_w64, HWord n_w64s );
75 static ULong genericg_compute_checksum_8al_1 ( HWord first_w64 );
77 static ULong genericg_compute_checksum_8al_2 ( HWord first_w64 );
79 static ULong genericg_compute_checksum_8al_3 ( HWord first_w64 );
81 static ULong genericg_compute_checksum_8al_4 ( HWord first_w64 );
83 static ULong genericg_compute_checksum_8al_5 ( HWord first_w64 );
85 static ULong genericg_compute_checksum_8al_6 ( HWord first_w64 );
87 static ULong genericg_compute_checksum_8al_7 ( HWord first_w64 );
89 static ULong genericg_compute_checksum_8al_8 ( HWord first_w64 );
91 static ULong genericg_compute_checksum_8al_9 ( HWord first_w64 );
93 static ULong genericg_compute_checksum_8al_10 ( HWord first_w64 );
95 static ULong genericg_compute_checksum_8al_11 ( HWord first_w64 );
97 static ULong genericg_compute_checksum_8al_12 ( HWord first_w64 );
100 static Bool const_False ( void* callback_opaque, Addr64 a ) {
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
112 dis_instr_fn is the arch-specific fn to disassemble on function; it
113 is this that does the real work.
115 do_self_check indicates that the caller needs a self-checking
118 preamble_function is a callback which allows the caller to add
119 its own IR preamble (following the self-check, if any). May be
120 NULL. If non-NULL, the IRSB under construction is handed to
121 this function, which presumably adds IR statements to it. The
122 callback may optionally complete the block and direct bb_to_IR
123 not to disassemble any instructions into it; this is indicated
124 by the callback returning True.
126 offB_TIADDR and offB_TILEN are the offsets of guest_TIADDR and
127 guest_TILEN. Since this routine has to work for any guest state,
128 without knowing what it is, those offsets have to passed in.
130 callback_opaque is a caller-supplied pointer to data which the
131 callbacks may want to see. Vex has no idea what it is.
132 (In fact it's a VgInstrumentClosure.)
135 IRSB* bb_to_IR ( /*OUT*/VexGuestExtents* vge,
136 /*IN*/ void* callback_opaque,
137 /*IN*/ DisOneInstrFn dis_instr_fn,
138 /*IN*/ UChar* guest_code,
139 /*IN*/ Addr64 guest_IP_bbstart,
140 /*IN*/ Bool (*chase_into_ok)(void*,Addr64),
141 /*IN*/ Bool host_bigendian,
142 /*IN*/ VexArch arch_guest,
143 /*IN*/ VexArchInfo* archinfo_guest,
144 /*IN*/ VexAbiInfo* abiinfo_both,
145 /*IN*/ IRType guest_word_type,
146 /*IN*/ Bool do_self_check,
147 /*IN*/ Bool (*preamble_function)(void*,IRSB*),
148 /*IN*/ Int offB_TISTART,
149 /*IN*/ Int offB_TILEN )
152 Int i, n_instrs, first_stmt_idx;
153 Bool resteerOK, need_to_put_IP, debug_print;
156 static Int n_resteers = 0;
158 Int selfcheck_idx = 0;
160 Addr64 guest_IP_curr_instr;
161 IRConst* guest_IP_bbstart_IRConst = NULL;
162 Int n_cond_resteers_allowed = 2;
164 Bool (*resteerOKfn)(void*,Addr64) = NULL;
166 debug_print = toBool(vex_traceflags & VEX_TRACE_FE);
168 /* Note: for adler32 to work without % operation for the self
169 check, need to limit length of stuff it scans to 5552 bytes.
170 Therefore limiting the max bb len to 100 insns seems generously
173 /* check sanity .. */
174 vassert(sizeof(HWord) == sizeof(void*));
175 vassert(vex_control.guest_max_insns >= 1);
176 vassert(vex_control.guest_max_insns < 100);
177 vassert(vex_control.guest_chase_thresh >= 0);
178 vassert(vex_control.guest_chase_thresh < vex_control.guest_max_insns);
179 vassert(guest_word_type == Ity_I32 || guest_word_type == Ity_I64);
181 /* Start a new, empty extent. */
183 vge->base[0] = guest_IP_bbstart;
186 /* And a new IR superblock to dump the result into. */
189 /* Delta keeps track of how far along the guest_code array we have
194 /* Guest addresses as IRConsts. Used in the two self-checks
197 guest_IP_bbstart_IRConst
198 = guest_word_type==Ity_I32
199 ? IRConst_U32(toUInt(guest_IP_bbstart))
200 : IRConst_U64(guest_IP_bbstart);
203 /* If asked to make a self-checking translation, leave 15 spaces in
204 which to put the check statements (up to 3 extents, and 5 stmts
205 required for each). We'll fill them in later when we know the
206 extents and checksums of the areas to check. */
208 selfcheck_idx = irsb->stmts_used;
209 for (i = 0; i < 3 * 5; i++)
210 addStmtToIRSB( irsb, IRStmt_NoOp() );
213 /* If the caller supplied a function to add its own preamble, use
215 if (preamble_function) {
216 Bool stopNow = preamble_function( callback_opaque, irsb );
218 /* The callback has completed the IR block without any guest
219 insns being disassembled into it, so just return it at
220 this point, even if a self-check was requested - as there
221 is nothing to self-check. The five self-check no-ops will
222 still be in place, but they are harmless. */
227 /* Process instructions. */
229 vassert(n_instrs < vex_control.guest_max_insns);
231 /* Regardless of what chase_into_ok says, is chasing permissible
232 at all right now? Set resteerOKfn accordingly. */
235 n_instrs < vex_control.guest_chase_thresh
236 /* we can't afford to have a resteer once we're on the
242 = resteerOK ? chase_into_ok : const_False;
244 /* n_cond_resteers_allowed keeps track of whether we're still
245 allowing dis_instr_fn to chase conditional branches. It
246 starts (at 2) and gets decremented each time dis_instr_fn
247 tells us it has chased a conditional branch. We then
248 decrement it, and use it to tell later calls to dis_instr_fn
249 whether or not it is allowed to chase conditional
251 vassert(n_cond_resteers_allowed >= 0 && n_cond_resteers_allowed <= 2);
253 /* This is the IP of the instruction we're just about to deal
255 guest_IP_curr_instr = guest_IP_bbstart + delta;
257 /* This is the irsb statement array index of the first stmt in
258 this insn. That will always be the instruction-mark
260 first_stmt_idx = irsb->stmts_used;
262 /* Add an instruction-mark statement. We won't know until after
263 disassembling the instruction how long it instruction is, so
264 just put in a zero length and we'll fix it up later.
266 On ARM, the least significant bit of the instr address
267 distinguishes ARM vs Thumb instructions. All instructions
268 actually start on at least 2-aligned addresses. So we need
269 to ignore the bottom bit of the insn address when forming the
270 IMark. For more details of this convention, see comments on
271 definition of guest_R15 in libvex_guest_arm.h. */
273 IRStmt_IMark( arch_guest == VexArchARM
274 ? (guest_IP_curr_instr & ~(Addr64)1)
275 : guest_IP_curr_instr,
280 /* for the first insn, the dispatch loop will have set
281 %IP, but for all the others we have to do it ourselves. */
282 need_to_put_IP = toBool(n_instrs > 0);
284 /* Finally, actually disassemble an instruction. */
285 dres = dis_instr_fn ( irsb,
288 toBool(n_cond_resteers_allowed > 0),
299 vassert(dres.whatNext == Dis_StopHere
300 || dres.whatNext == Dis_Continue
301 || dres.whatNext == Dis_ResteerU
302 || dres.whatNext == Dis_ResteerC);
303 /* ... disassembled insn length is sane ... */
304 vassert(dres.len >= 0 && dres.len <= 20);
305 /* ... continueAt is zero if no resteer requested ... */
306 if (dres.whatNext != Dis_ResteerU && dres.whatNext != Dis_ResteerC)
307 vassert(dres.continueAt == 0);
308 /* ... if we disallowed conditional resteers, check that one
309 didn't actually happen anyway ... */
310 if (n_cond_resteers_allowed == 0)
311 vassert(dres.whatNext != Dis_ResteerC);
313 /* Fill in the insn-mark length field. */
314 vassert(first_stmt_idx >= 0 && first_stmt_idx < irsb->stmts_used);
315 imark = irsb->stmts[first_stmt_idx];
317 vassert(imark->tag == Ist_IMark);
318 vassert(imark->Ist.IMark.len == 0);
319 imark->Ist.IMark.len = toUInt(dres.len);
321 /* Print the resulting IR, if needed. */
322 if (vex_traceflags & VEX_TRACE_FE) {
323 for (i = first_stmt_idx; i < irsb->stmts_used; i++) {
325 ppIRStmt(irsb->stmts[i]);
330 /* If dis_instr_fn terminated the BB at this point, check it
331 also filled in the irsb->next field. */
332 if (dres.whatNext == Dis_StopHere) {
333 vassert(irsb->next != NULL);
336 vex_printf( "goto {");
337 ppIRJumpKind(irsb->jumpkind);
339 ppIRExpr( irsb->next );
344 /* Update the VexGuestExtents we are constructing. */
345 /* If vex_control.guest_max_insns is required to be < 100 and
346 each insn is at max 20 bytes long, this limit of 5000 then
347 seems reasonable since the max possible extent length will be
349 vassert(vge->len[vge->n_used-1] < 5000);
350 vge->len[vge->n_used-1]
351 = toUShort(toUInt( vge->len[vge->n_used-1] + dres.len ));
356 /* Advance delta (inconspicuous but very important :-) */
357 delta += (Long)dres.len;
359 switch (dres.whatNext) {
361 vassert(irsb->next == NULL);
362 if (n_instrs < vex_control.guest_max_insns) {
365 /* We have to stop. */
368 guest_word_type == Ity_I32
369 ? IRConst_U32(toUInt(guest_IP_bbstart+delta))
370 : IRConst_U64(guest_IP_bbstart+delta)
376 vassert(irsb->next != NULL);
380 /* Check that we actually allowed a resteer .. */
382 vassert(irsb->next == NULL);
383 if (dres.whatNext == Dis_ResteerC) {
384 vassert(n_cond_resteers_allowed > 0);
385 n_cond_resteers_allowed--;
387 /* figure out a new delta to continue at. */
388 vassert(resteerOKfn(callback_opaque,dres.continueAt));
389 delta = dres.continueAt - guest_IP_bbstart;
390 /* we now have to start a new extent slot. */
392 vassert(vge->n_used <= 3);
393 vge->base[vge->n_used-1] = dres.continueAt;
394 vge->len[vge->n_used-1] = 0;
397 if (0 && (n_resteers & 0xFF) == 0)
398 vex_printf("resteer[%d,%d] to 0x%llx (delta = %lld)\n",
399 n_resteers, d_resteers,
400 dres.continueAt, delta);
410 /* We're done. The only thing that might need attending to is that
411 a self-checking preamble may need to be created.
413 The scheme is to compute a rather crude checksum of the code
414 we're making a translation of, and add to the IR a call to a
415 helper routine which recomputes the checksum every time the
416 translation is run, and requests a retranslation if it doesn't
417 match. This is obviously very expensive and considerable
418 efforts are made to speed it up:
420 * the checksum is computed from all the 32-bit words that
421 overlap the translated code. That means it could depend on up
422 to 3 bytes before and 3 bytes after which aren't part of the
423 translated area, and so if those change then we'll
424 unnecessarily have to discard and retranslate. This seems
425 like a pretty remote possibility and it seems as if the
426 benefit of not having to deal with the ends of the range at
427 byte precision far outweigh any possible extra translations
430 * there's a generic routine and 12 specialised cases, which
431 handle the cases of 1 through 12-word lengths respectively.
432 They seem to cover about 90% of the cases that occur in
440 IRTemp tistart_tmp, tilen_tmp;
441 HWord VEX_REGPARM(2) (*fn_generic)(HWord, HWord);
442 HWord VEX_REGPARM(1) (*fn_spec)(HWord);
445 HWord fn_generic_entry = 0;
446 HWord fn_spec_entry = 0;
447 UInt host_word_szB = sizeof(HWord);
448 IRType host_word_type = Ity_INVALID;
450 if (host_word_szB == 4) host_word_type = Ity_I32;
451 if (host_word_szB == 8) host_word_type = Ity_I64;
452 vassert(host_word_type != Ity_INVALID);
454 vassert(vge->n_used >= 1 && vge->n_used <= 3);
455 for (i = 0; i < vge->n_used; i++) {
457 /* the extent we're generating a check for */
458 base2check = vge->base[i];
459 len2check = vge->len[i];
462 vassert(len2check >= 0 && len2check < 1000/*arbitrary*/);
464 /* Skip the check if the translation involved zero bytes */
468 HWord first_hW = ((HWord)base2check)
469 & ~(HWord)(host_word_szB-1);
470 HWord last_hW = (((HWord)base2check) + len2check - 1)
471 & ~(HWord)(host_word_szB-1);
472 vassert(first_hW <= last_hW);
473 HWord hW_diff = last_hW - first_hW;
474 vassert(0 == (hW_diff & (host_word_szB-1)));
475 HWord hWs_to_check = (hW_diff + host_word_szB) / host_word_szB;
476 vassert(hWs_to_check > 0
477 && hWs_to_check < 1004/*arbitrary*/ / host_word_szB);
479 /* vex_printf("%lx %lx %ld\n", first_w32, last_w32, w32s_to_check); */
481 if (host_word_szB == 8) {
482 fn_generic = (VEX_REGPARM(2) HWord(*)(HWord, HWord))
483 genericg_compute_checksum_8al;
484 nm_generic = "genericg_compute_checksum_8al";
486 fn_generic = (VEX_REGPARM(2) HWord(*)(HWord, HWord))
487 genericg_compute_checksum_4al;
488 nm_generic = "genericg_compute_checksum_4al";
494 if (host_word_szB == 8) {
496 ULong VEX_REGPARM(1) (*fn)(HWord) = NULL;
497 switch (hWs_to_check) {
498 case 1: fn = genericg_compute_checksum_8al_1;
499 nm = "genericg_compute_checksum_8al_1"; break;
500 case 2: fn = genericg_compute_checksum_8al_2;
501 nm = "genericg_compute_checksum_8al_2"; break;
502 case 3: fn = genericg_compute_checksum_8al_3;
503 nm = "genericg_compute_checksum_8al_3"; break;
504 case 4: fn = genericg_compute_checksum_8al_4;
505 nm = "genericg_compute_checksum_8al_4"; break;
506 case 5: fn = genericg_compute_checksum_8al_5;
507 nm = "genericg_compute_checksum_8al_5"; break;
508 case 6: fn = genericg_compute_checksum_8al_6;
509 nm = "genericg_compute_checksum_8al_6"; break;
510 case 7: fn = genericg_compute_checksum_8al_7;
511 nm = "genericg_compute_checksum_8al_7"; break;
512 case 8: fn = genericg_compute_checksum_8al_8;
513 nm = "genericg_compute_checksum_8al_8"; break;
514 case 9: fn = genericg_compute_checksum_8al_9;
515 nm = "genericg_compute_checksum_8al_9"; break;
516 case 10: fn = genericg_compute_checksum_8al_10;
517 nm = "genericg_compute_checksum_8al_10"; break;
518 case 11: fn = genericg_compute_checksum_8al_11;
519 nm = "genericg_compute_checksum_8al_11"; break;
520 case 12: fn = genericg_compute_checksum_8al_12;
521 nm = "genericg_compute_checksum_8al_12"; break;
524 fn_spec = (VEX_REGPARM(1) HWord(*)(HWord)) fn;
528 UInt VEX_REGPARM(1) (*fn)(HWord) = NULL;
529 switch (hWs_to_check) {
530 case 1: fn = genericg_compute_checksum_4al_1;
531 nm = "genericg_compute_checksum_4al_1"; break;
532 case 2: fn = genericg_compute_checksum_4al_2;
533 nm = "genericg_compute_checksum_4al_2"; break;
534 case 3: fn = genericg_compute_checksum_4al_3;
535 nm = "genericg_compute_checksum_4al_3"; break;
536 case 4: fn = genericg_compute_checksum_4al_4;
537 nm = "genericg_compute_checksum_4al_4"; break;
538 case 5: fn = genericg_compute_checksum_4al_5;
539 nm = "genericg_compute_checksum_4al_5"; break;
540 case 6: fn = genericg_compute_checksum_4al_6;
541 nm = "genericg_compute_checksum_4al_6"; break;
542 case 7: fn = genericg_compute_checksum_4al_7;
543 nm = "genericg_compute_checksum_4al_7"; break;
544 case 8: fn = genericg_compute_checksum_4al_8;
545 nm = "genericg_compute_checksum_4al_8"; break;
546 case 9: fn = genericg_compute_checksum_4al_9;
547 nm = "genericg_compute_checksum_4al_9"; break;
548 case 10: fn = genericg_compute_checksum_4al_10;
549 nm = "genericg_compute_checksum_4al_10"; break;
550 case 11: fn = genericg_compute_checksum_4al_11;
551 nm = "genericg_compute_checksum_4al_11"; break;
552 case 12: fn = genericg_compute_checksum_4al_12;
553 nm = "genericg_compute_checksum_4al_12"; break;
556 fn_spec = (VEX_REGPARM(1) HWord(*)(HWord))fn;
560 expectedhW = fn_generic( first_hW, hWs_to_check );
561 /* If we got a specialised version, check it produces the same
562 result as the generic version! */
565 vassert(expectedhW == fn_spec( first_hW ));
570 /* Set TISTART and TILEN. These will describe to the despatcher
571 the area of guest code to invalidate should we exit with a
572 self-check failure. */
574 tistart_tmp = newIRTemp(irsb->tyenv, guest_word_type);
575 tilen_tmp = newIRTemp(irsb->tyenv, guest_word_type);
577 IRConst* base2check_IRConst
578 = guest_word_type==Ity_I32 ? IRConst_U32(toUInt(base2check))
579 : IRConst_U64(base2check);
580 IRConst* len2check_IRConst
581 = guest_word_type==Ity_I32 ? IRConst_U32(len2check)
582 : IRConst_U64(len2check);
584 irsb->stmts[selfcheck_idx + i * 5 + 0]
585 = IRStmt_WrTmp(tistart_tmp, IRExpr_Const(base2check_IRConst) );
587 irsb->stmts[selfcheck_idx + i * 5 + 1]
588 = IRStmt_WrTmp(tilen_tmp, IRExpr_Const(len2check_IRConst) );
590 irsb->stmts[selfcheck_idx + i * 5 + 2]
591 = IRStmt_Put( offB_TISTART, IRExpr_RdTmp(tistart_tmp) );
593 irsb->stmts[selfcheck_idx + i * 5 + 3]
594 = IRStmt_Put( offB_TILEN, IRExpr_RdTmp(tilen_tmp) );
596 /* Generate the entry point descriptors */
597 if (abiinfo_both->host_ppc_calls_use_fndescrs) {
598 HWord* descr = (HWord*)fn_generic;
599 fn_generic_entry = descr[0];
601 descr = (HWord*)fn_spec;
602 fn_spec_entry = descr[0];
604 fn_spec_entry = (HWord)NULL;
607 fn_generic_entry = (HWord)fn_generic;
609 fn_spec_entry = (HWord)fn_spec;
611 fn_spec_entry = (HWord)NULL;
615 IRExpr* callexpr = NULL;
617 callexpr = mkIRExprCCall(
618 host_word_type, 1/*regparms*/,
619 nm_spec, (void*)fn_spec_entry,
621 mkIRExpr_HWord( (HWord)first_hW )
625 callexpr = mkIRExprCCall(
626 host_word_type, 2/*regparms*/,
627 nm_generic, (void*)fn_generic_entry,
629 mkIRExpr_HWord( (HWord)first_hW ),
630 mkIRExpr_HWord( (HWord)hWs_to_check )
635 irsb->stmts[selfcheck_idx + i * 5 + 4]
638 host_word_type==Ity_I64 ? Iop_CmpNE64 : Iop_CmpNE32,
640 host_word_type==Ity_I64
641 ? IRExpr_Const(IRConst_U64(expectedhW))
642 : IRExpr_Const(IRConst_U32(expectedhW))
645 /* Where we must restart if there's a failure: at the
646 first extent, regardless of which extent the
647 failure actually happened in. */
648 guest_IP_bbstart_IRConst
657 /*-------------------------------------------------------------
658 A support routine for doing self-checking translations.
659 -------------------------------------------------------------*/
662 /* CALLED FROM GENERATED CODE */
664 /* Compute a checksum of host memory at [addr .. addr+len-1], as fast
665 as possible. All _4al versions assume that the supplied address is
666 4 aligned. All length values are in 4-byte chunks. These fns
667 arecalled once for every use of a self-checking translation, so
668 they needs to be as fast as possible. */
670 /* --- 32-bit versions, used only on 32-bit hosts --- */
672 static inline UInt ROL32 ( UInt w, Int n ) {
673 w = (w << n) | (w >> (32-n));
678 static UInt genericg_compute_checksum_4al ( HWord first_w32, HWord n_w32s )
680 UInt sum1 = 0, sum2 = 0;
681 UInt* p = (UInt*)first_w32;
683 while (n_w32s >= 4) {
685 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
686 w = p[1]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
687 w = p[2]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
688 w = p[3]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
693 while (n_w32s >= 1) {
695 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
703 /* Specialised versions of the above function */
706 static UInt genericg_compute_checksum_4al_1 ( HWord first_w32 )
708 UInt sum1 = 0, sum2 = 0;
709 UInt* p = (UInt*)first_w32;
711 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
717 static UInt genericg_compute_checksum_4al_2 ( HWord first_w32 )
719 UInt sum1 = 0, sum2 = 0;
720 UInt* p = (UInt*)first_w32;
722 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
724 w = p[1]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
730 static UInt genericg_compute_checksum_4al_3 ( HWord first_w32 )
732 UInt sum1 = 0, sum2 = 0;
733 UInt* p = (UInt*)first_w32;
735 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
737 w = p[1]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
739 w = p[2]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
745 static UInt genericg_compute_checksum_4al_4 ( HWord first_w32 )
747 UInt sum1 = 0, sum2 = 0;
748 UInt* p = (UInt*)first_w32;
750 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
751 w = p[1]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
752 w = p[2]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
753 w = p[3]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
759 static UInt genericg_compute_checksum_4al_5 ( HWord first_w32 )
761 UInt sum1 = 0, sum2 = 0;
762 UInt* p = (UInt*)first_w32;
764 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
765 w = p[1]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
766 w = p[2]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
767 w = p[3]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
769 w = p[4]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
775 static UInt genericg_compute_checksum_4al_6 ( HWord first_w32 )
777 UInt sum1 = 0, sum2 = 0;
778 UInt* p = (UInt*)first_w32;
780 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
781 w = p[1]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
782 w = p[2]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
783 w = p[3]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
785 w = p[4]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
787 w = p[5]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
793 static UInt genericg_compute_checksum_4al_7 ( HWord first_w32 )
795 UInt sum1 = 0, sum2 = 0;
796 UInt* p = (UInt*)first_w32;
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;
803 w = p[4]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
805 w = p[5]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
807 w = p[6]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
813 static UInt genericg_compute_checksum_4al_8 ( HWord first_w32 )
815 UInt sum1 = 0, sum2 = 0;
816 UInt* p = (UInt*)first_w32;
818 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
819 w = p[1]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
820 w = p[2]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
821 w = p[3]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
823 w = p[4]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
824 w = p[5]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
825 w = p[6]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
826 w = p[7]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
832 static UInt genericg_compute_checksum_4al_9 ( HWord first_w32 )
834 UInt sum1 = 0, sum2 = 0;
835 UInt* p = (UInt*)first_w32;
837 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
838 w = p[1]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
839 w = p[2]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
840 w = p[3]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
842 w = p[4]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
843 w = p[5]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
844 w = p[6]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
845 w = p[7]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
847 w = p[8]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
853 static UInt genericg_compute_checksum_4al_10 ( HWord first_w32 )
855 UInt sum1 = 0, sum2 = 0;
856 UInt* p = (UInt*)first_w32;
858 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
859 w = p[1]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
860 w = p[2]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
861 w = p[3]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
863 w = p[4]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
864 w = p[5]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
865 w = p[6]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
866 w = p[7]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
868 w = p[8]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
870 w = p[9]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
876 static UInt genericg_compute_checksum_4al_11 ( HWord first_w32 )
878 UInt sum1 = 0, sum2 = 0;
879 UInt* p = (UInt*)first_w32;
881 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
882 w = p[1]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
883 w = p[2]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
884 w = p[3]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
886 w = p[4]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
887 w = p[5]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
888 w = p[6]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
889 w = p[7]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
891 w = p[8]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
893 w = p[9]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
895 w = p[10]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
901 static UInt genericg_compute_checksum_4al_12 ( HWord first_w32 )
903 UInt sum1 = 0, sum2 = 0;
904 UInt* p = (UInt*)first_w32;
906 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
907 w = p[1]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
908 w = p[2]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
909 w = p[3]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
911 w = p[4]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
912 w = p[5]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
913 w = p[6]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
914 w = p[7]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
916 w = p[8]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
917 w = p[9]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
918 w = p[10]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
919 w = p[11]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
925 /* --- 64-bit versions, used only on 64-bit hosts --- */
927 static inline ULong ROL64 ( ULong w, Int n ) {
928 w = (w << n) | (w >> (64-n));
933 static ULong genericg_compute_checksum_8al ( HWord first_w64, HWord n_w64s )
935 ULong sum1 = 0, sum2 = 0;
936 ULong* p = (ULong*)first_w64;
938 while (n_w64s >= 4) {
940 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
941 w = p[1]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
942 w = p[2]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
943 w = p[3]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
948 while (n_w64s >= 1) {
950 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
958 /* Specialised versions of the above function */
961 static ULong genericg_compute_checksum_8al_1 ( HWord first_w64 )
963 ULong sum1 = 0, sum2 = 0;
964 ULong* p = (ULong*)first_w64;
966 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
972 static ULong genericg_compute_checksum_8al_2 ( HWord first_w64 )
974 ULong sum1 = 0, sum2 = 0;
975 ULong* p = (ULong*)first_w64;
977 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
979 w = p[1]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
985 static ULong genericg_compute_checksum_8al_3 ( HWord first_w64 )
987 ULong sum1 = 0, sum2 = 0;
988 ULong* p = (ULong*)first_w64;
990 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
992 w = p[1]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
994 w = p[2]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1000 static ULong genericg_compute_checksum_8al_4 ( HWord first_w64 )
1002 ULong sum1 = 0, sum2 = 0;
1003 ULong* p = (ULong*)first_w64;
1005 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1006 w = p[1]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1007 w = p[2]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1008 w = p[3]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1014 static ULong genericg_compute_checksum_8al_5 ( HWord first_w64 )
1016 ULong sum1 = 0, sum2 = 0;
1017 ULong* p = (ULong*)first_w64;
1019 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1020 w = p[1]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1021 w = p[2]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1022 w = p[3]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1024 w = p[4]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1030 static ULong genericg_compute_checksum_8al_6 ( HWord first_w64 )
1032 ULong sum1 = 0, sum2 = 0;
1033 ULong* p = (ULong*)first_w64;
1035 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1036 w = p[1]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1037 w = p[2]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1038 w = p[3]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1040 w = p[4]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1042 w = p[5]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1048 static ULong genericg_compute_checksum_8al_7 ( HWord first_w64 )
1050 ULong sum1 = 0, sum2 = 0;
1051 ULong* p = (ULong*)first_w64;
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;
1058 w = p[4]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1060 w = p[5]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1062 w = p[6]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1068 static ULong genericg_compute_checksum_8al_8 ( HWord first_w64 )
1070 ULong sum1 = 0, sum2 = 0;
1071 ULong* p = (ULong*)first_w64;
1073 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1074 w = p[1]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1075 w = p[2]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1076 w = p[3]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1078 w = p[4]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1079 w = p[5]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1080 w = p[6]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1081 w = p[7]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1087 static ULong genericg_compute_checksum_8al_9 ( HWord first_w64 )
1089 ULong sum1 = 0, sum2 = 0;
1090 ULong* p = (ULong*)first_w64;
1092 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1093 w = p[1]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1094 w = p[2]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1095 w = p[3]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1097 w = p[4]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1098 w = p[5]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1099 w = p[6]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1100 w = p[7]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1102 w = p[8]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1108 static ULong genericg_compute_checksum_8al_10 ( HWord first_w64 )
1110 ULong sum1 = 0, sum2 = 0;
1111 ULong* p = (ULong*)first_w64;
1113 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1114 w = p[1]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1115 w = p[2]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1116 w = p[3]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1118 w = p[4]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1119 w = p[5]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1120 w = p[6]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1121 w = p[7]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1123 w = p[8]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1125 w = p[9]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1131 static ULong genericg_compute_checksum_8al_11 ( HWord first_w64 )
1133 ULong sum1 = 0, sum2 = 0;
1134 ULong* p = (ULong*)first_w64;
1136 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1137 w = p[1]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1138 w = p[2]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1139 w = p[3]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1141 w = p[4]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1142 w = p[5]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1143 w = p[6]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1144 w = p[7]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1146 w = p[8]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1148 w = p[9]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1150 w = p[10]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1156 static ULong genericg_compute_checksum_8al_12 ( HWord first_w64 )
1158 ULong sum1 = 0, sum2 = 0;
1159 ULong* p = (ULong*)first_w64;
1161 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1162 w = p[1]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1163 w = p[2]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1164 w = p[3]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1166 w = p[4]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1167 w = p[5]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1168 w = p[6]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1169 w = p[7]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1171 w = p[8]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1172 w = p[9]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1173 w = p[10]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1174 w = p[11]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1179 /*--------------------------------------------------------------------*/
1180 /*--- end guest_generic_bb_to_IR.c ---*/
1181 /*--------------------------------------------------------------------*/