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-2017 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
, Addr 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 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.
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.
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.
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.
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.)
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.
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).
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)
160 PUT(guest_IP) [implicitly] = GET(guest_IP) [explicit expr on ::next]
162 which looks pretty strange at first. Eg so unconditional branch
163 to some address 0x123456 looks like this:
165 PUT(guest_IP) = 0x123456; // dis_instr_fn generates this
167 PUT(guest_IP) [implicitly] = GET(guest_IP); exit-Boring
169 after redundant-GET and -PUT removal by iropt, we get what we want:
172 PUT(guest_IP) [implicitly] = 0x123456; exit-Boring
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.
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
207 Int i
, n_instrs
, first_stmt_idx
;
208 Bool resteerOK
, debug_print
;
212 static Int n_resteers
= 0;
214 Int selfcheck_idx
= 0;
216 Addr guest_IP_curr_instr
;
217 IRConst
* guest_IP_bbstart_IRConst
= NULL
;
218 Int n_cond_resteers_allowed
= 2;
220 Bool (*resteerOKfn
)(void*,Addr
) = NULL
;
222 debug_print
= toBool(vex_traceflags
& VEX_TRACE_FE
);
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
);
232 if (guest_word_type
== Ity_I32
) {
233 vassert(szB_GUEST_IP
== 4);
234 vassert((offB_GUEST_IP
% 4) == 0);
236 vassert(szB_GUEST_IP
== 8);
237 vassert((offB_GUEST_IP
% 8) == 0);
240 /* Although we will try to disassemble up to vex_control.guest_max_insns
241 insns into the block, the individual insn assemblers may hint to us that a
242 disassembled instruction is verbose. In that case we will lower the limit
243 so as to ensure that the JIT doesn't run out of space. See bug 375839 for
244 the motivating example. */
245 Int guest_max_insns_really
= vex_control
.guest_max_insns
;
247 /* Start a new, empty extent. */
249 vge
->base
[0] = guest_IP_bbstart
;
253 /* And a new IR superblock to dump the result into. */
256 /* Delta keeps track of how far along the guest_code array we have
262 /* Guest addresses as IRConsts. Used in self-checks to specify the
263 restart-after-discard point. */
264 guest_IP_bbstart_IRConst
265 = guest_word_type
==Ity_I32
266 ? IRConst_U32(toUInt(guest_IP_bbstart
))
267 : IRConst_U64(guest_IP_bbstart
);
269 /* Leave 15 spaces in which to put the check statements for a self
270 checking translation (up to 3 extents, and 5 stmts required for
271 each). We won't know until later the extents and checksums of
272 the areas, if any, that need to be checked. */
274 selfcheck_idx
= irsb
->stmts_used
;
275 for (i
= 0; i
< 3 * 5; i
++)
276 addStmtToIRSB( irsb
, nop
);
278 /* If the caller supplied a function to add its own preamble, use
280 if (preamble_function
) {
281 Bool stopNow
= preamble_function( callback_opaque
, irsb
);
283 /* The callback has completed the IR block without any guest
284 insns being disassembled into it, so just return it at
285 this point, even if a self-check was requested - as there
286 is nothing to self-check. The 15 self-check no-ops will
287 still be in place, but they are harmless. */
292 /* Process instructions. */
294 vassert(n_instrs
< guest_max_insns_really
);
296 /* Regardless of what chase_into_ok says, is chasing permissible
297 at all right now? Set resteerOKfn accordingly. */
300 n_instrs
< vex_control
.guest_chase_thresh
301 /* we can't afford to have a resteer once we're on the
307 = resteerOK
? chase_into_ok
: const_False
;
309 /* n_cond_resteers_allowed keeps track of whether we're still
310 allowing dis_instr_fn to chase conditional branches. It
311 starts (at 2) and gets decremented each time dis_instr_fn
312 tells us it has chased a conditional branch. We then
313 decrement it, and use it to tell later calls to dis_instr_fn
314 whether or not it is allowed to chase conditional
316 vassert(n_cond_resteers_allowed
>= 0 && n_cond_resteers_allowed
<= 2);
318 /* This is the IP of the instruction we're just about to deal
320 guest_IP_curr_instr
= guest_IP_bbstart
+ delta
;
322 /* This is the irsb statement array index of the first stmt in
323 this insn. That will always be the instruction-mark
325 first_stmt_idx
= irsb
->stmts_used
;
327 /* Add an instruction-mark statement. We won't know until after
328 disassembling the instruction how long it instruction is, so
329 just put in a zero length and we'll fix it up later.
331 On ARM, the least significant bit of the instr address
332 distinguishes ARM vs Thumb instructions. All instructions
333 actually start on at least 2-aligned addresses. So we need
334 to ignore the bottom bit of the insn address when forming the
335 IMark's address field, but put that bottom bit in the delta
336 field, so that comparisons against guest_R15T for Thumb can
337 be done correctly. By inspecting the delta field,
338 instruction processors can determine whether the instruction
339 was originally Thumb or ARM. For more details of this
340 convention, see comments on definition of guest_R15T in
341 libvex_guest_arm.h. */
342 if (arch_guest
== VexArchARM
&& (guest_IP_curr_instr
& 1)) {
343 /* Thumb insn => mask out the T bit, but put it in delta */
345 IRStmt_IMark(guest_IP_curr_instr
& ~(Addr
)1,
351 /* All other targets: store IP as-is, and set delta to zero. */
353 IRStmt_IMark(guest_IP_curr_instr
,
360 if (debug_print
&& n_instrs
> 0)
363 /* Finally, actually disassemble an instruction. */
364 vassert(irsb
->next
== NULL
);
365 dres
= dis_instr_fn ( irsb
,
367 toBool(n_cond_resteers_allowed
> 0),
379 vassert(dres
.whatNext
== Dis_StopHere
380 || dres
.whatNext
== Dis_Continue
381 || dres
.whatNext
== Dis_ResteerU
382 || dres
.whatNext
== Dis_ResteerC
);
383 /* ... disassembled insn length is sane ... */
384 vassert(dres
.len
>= 0 && dres
.len
<= 24);
385 /* ... continueAt is zero if no resteer requested ... */
386 if (dres
.whatNext
!= Dis_ResteerU
&& dres
.whatNext
!= Dis_ResteerC
)
387 vassert(dres
.continueAt
== 0);
388 /* ... if we disallowed conditional resteers, check that one
389 didn't actually happen anyway ... */
390 if (n_cond_resteers_allowed
== 0)
391 vassert(dres
.whatNext
!= Dis_ResteerC
);
393 /* If the disassembly function passed us a hint, take note of it. */
394 if (LIKELY(dres
.hint
== Dis_HintNone
)) {
397 vassert(dres
.hint
== Dis_HintVerbose
);
398 /* The current insn is known to be verbose. Lower the max insns limit
399 if necessary so as to avoid running the JIT out of space in the
400 event that we've encountered the start of a long sequence of them.
401 This is expected to be a very rare event. In any case the remaining
402 limit (30 insns) is still so high that most blocks will terminate
403 anyway before then. So this is very unlikely to give a perf hit in
404 practice. See bug 375839 for the motivating example. */
405 if (guest_max_insns_really
> 30) {
406 guest_max_insns_really
= 30;
410 /* Fill in the insn-mark length field. */
411 vassert(first_stmt_idx
>= 0 && first_stmt_idx
< irsb
->stmts_used
);
412 imark
= irsb
->stmts
[first_stmt_idx
];
414 vassert(imark
->tag
== Ist_IMark
);
415 vassert(imark
->Ist
.IMark
.len
== 0);
416 imark
->Ist
.IMark
.len
= dres
.len
;
418 /* Print the resulting IR, if needed. */
419 if (vex_traceflags
& VEX_TRACE_FE
) {
420 for (i
= first_stmt_idx
; i
< irsb
->stmts_used
; i
++) {
422 ppIRStmt(irsb
->stmts
[i
]);
427 /* Individual insn disassembly may not mess with irsb->next.
428 This function is the only place where it can be set. */
429 vassert(irsb
->next
== NULL
);
430 vassert(irsb
->jumpkind
== Ijk_Boring
);
431 vassert(irsb
->offsIP
== 0);
433 /* Individual insn disassembly must finish the IR for each
434 instruction with an assignment to the guest PC. */
435 vassert(first_stmt_idx
< irsb
->stmts_used
);
436 /* it follows that irsb->stmts_used must be > 0 */
437 { IRStmt
* st
= irsb
->stmts
[irsb
->stmts_used
-1];
439 vassert(st
->tag
== Ist_Put
);
440 vassert(st
->Ist
.Put
.offset
== offB_GUEST_IP
);
441 /* Really we should also check that the type of the Put'd data
442 == guest_word_type, but that's a bit expensive. */
445 /* Update the VexGuestExtents we are constructing. */
446 /* If vex_control.guest_max_insns is required to be < 100 and
447 each insn is at max 20 bytes long, this limit of 5000 then
448 seems reasonable since the max possible extent length will be
450 vassert(vge
->len
[vge
->n_used
-1] < 5000);
451 vge
->len
[vge
->n_used
-1]
452 = toUShort(toUInt( vge
->len
[vge
->n_used
-1] + dres
.len
));
455 /* Advance delta (inconspicuous but very important :-) */
456 delta
+= (Long
)dres
.len
;
458 switch (dres
.whatNext
) {
460 vassert(dres
.continueAt
== 0);
461 vassert(dres
.jk_StopHere
== Ijk_INVALID
);
462 if (n_instrs
< guest_max_insns_really
) {
465 /* We have to stop. See comment above re irsb field
467 irsb
->next
= IRExpr_Get(offB_GUEST_IP
, guest_word_type
);
468 /* irsb->jumpkind must already by Ijk_Boring */
469 irsb
->offsIP
= offB_GUEST_IP
;
474 vassert(dres
.continueAt
== 0);
475 vassert(dres
.jk_StopHere
!= Ijk_INVALID
);
476 /* See comment above re irsb field settings here. */
477 irsb
->next
= IRExpr_Get(offB_GUEST_IP
, guest_word_type
);
478 irsb
->jumpkind
= dres
.jk_StopHere
;
479 irsb
->offsIP
= offB_GUEST_IP
;
484 /* Check that we actually allowed a resteer .. */
486 if (dres
.whatNext
== Dis_ResteerC
) {
487 vassert(n_cond_resteers_allowed
> 0);
488 n_cond_resteers_allowed
--;
490 /* figure out a new delta to continue at. */
491 vassert(resteerOKfn(callback_opaque
,dres
.continueAt
));
492 delta
= dres
.continueAt
- guest_IP_bbstart
;
493 /* we now have to start a new extent slot. */
495 vassert(vge
->n_used
<= 3);
496 vge
->base
[vge
->n_used
-1] = dres
.continueAt
;
497 vge
->len
[vge
->n_used
-1] = 0;
500 if (0 && (n_resteers
& 0xFF) == 0)
501 vex_printf("resteer[%d,%d] to 0x%lx (delta = %lld)\n",
502 n_resteers
, d_resteers
,
503 dres
.continueAt
, delta
);
513 /* We're done. The only thing that might need attending to is that
514 a self-checking preamble may need to be created. If so it gets
515 placed in the 15 slots reserved above.
517 The scheme is to compute a rather crude checksum of the code
518 we're making a translation of, and add to the IR a call to a
519 helper routine which recomputes the checksum every time the
520 translation is run, and requests a retranslation if it doesn't
521 match. This is obviously very expensive and considerable
522 efforts are made to speed it up:
524 * the checksum is computed from all the naturally aligned
525 host-sized words that overlap the translated code. That means
526 it could depend on up to 7 bytes before and 7 bytes after
527 which aren't part of the translated area, and so if those
528 change then we'll unnecessarily have to discard and
529 retranslate. This seems like a pretty remote possibility and
530 it seems as if the benefit of not having to deal with the ends
531 of the range at byte precision far outweigh any possible extra
534 * there's a generic routine and 12 specialised cases, which
535 handle the cases of 1 through 12-word lengths respectively.
536 They seem to cover about 90% of the cases that occur in
539 We ask the caller, via needs_self_check, which of the 3 vge
540 extents needs a check, and only generate check code for those
547 IRTemp tistart_tmp
, tilen_tmp
;
548 HWord
VEX_REGPARM(2) (*fn_generic
)(HWord
, HWord
);
549 HWord
VEX_REGPARM(1) (*fn_spec
)(HWord
);
550 const HChar
* nm_generic
;
551 const HChar
* nm_spec
;
552 HWord fn_generic_entry
= 0;
553 HWord fn_spec_entry
= 0;
554 UInt host_word_szB
= sizeof(HWord
);
555 IRType host_word_type
= Ity_INVALID
;
557 UInt extents_needing_check
558 = needs_self_check(callback_opaque
, pxControl
, vge
);
560 if (host_word_szB
== 4) host_word_type
= Ity_I32
;
561 if (host_word_szB
== 8) host_word_type
= Ity_I64
;
562 vassert(host_word_type
!= Ity_INVALID
);
564 vassert(vge
->n_used
>= 1 && vge
->n_used
<= 3);
566 /* Caller shouldn't claim that nonexistent extents need a
568 vassert((extents_needing_check
>> vge
->n_used
) == 0);
570 for (i
= 0; i
< vge
->n_used
; i
++) {
572 /* Do we need to generate a check for this extent? */
573 if ((extents_needing_check
& (1 << i
)) == 0)
576 /* Tell the caller */
579 /* the extent we're generating a check for */
580 base2check
= vge
->base
[i
];
581 len2check
= vge
->len
[i
];
584 vassert(len2check
>= 0 && len2check
< 1000/*arbitrary*/);
586 /* Skip the check if the translation involved zero bytes */
590 HWord first_hW
= ((HWord
)base2check
)
591 & ~(HWord
)(host_word_szB
-1);
592 HWord last_hW
= (((HWord
)base2check
) + len2check
- 1)
593 & ~(HWord
)(host_word_szB
-1);
594 vassert(first_hW
<= last_hW
);
595 HWord hW_diff
= last_hW
- first_hW
;
596 vassert(0 == (hW_diff
& (host_word_szB
-1)));
597 HWord hWs_to_check
= (hW_diff
+ host_word_szB
) / host_word_szB
;
598 vassert(hWs_to_check
> 0
599 && hWs_to_check
< 1004/*arbitrary*/ / host_word_szB
);
601 /* vex_printf("%lx %lx %ld\n", first_hW, last_hW, hWs_to_check); */
603 if (host_word_szB
== 8) {
604 fn_generic
= (VEX_REGPARM(2) HWord(*)(HWord
, HWord
))
605 genericg_compute_checksum_8al
;
606 nm_generic
= "genericg_compute_checksum_8al";
608 fn_generic
= (VEX_REGPARM(2) HWord(*)(HWord
, HWord
))
609 genericg_compute_checksum_4al
;
610 nm_generic
= "genericg_compute_checksum_4al";
616 if (host_word_szB
== 8) {
617 const HChar
* nm
= NULL
;
618 ULong
VEX_REGPARM(1) (*fn
)(HWord
) = NULL
;
619 switch (hWs_to_check
) {
620 case 1: fn
= genericg_compute_checksum_8al_1
;
621 nm
= "genericg_compute_checksum_8al_1"; break;
622 case 2: fn
= genericg_compute_checksum_8al_2
;
623 nm
= "genericg_compute_checksum_8al_2"; break;
624 case 3: fn
= genericg_compute_checksum_8al_3
;
625 nm
= "genericg_compute_checksum_8al_3"; break;
626 case 4: fn
= genericg_compute_checksum_8al_4
;
627 nm
= "genericg_compute_checksum_8al_4"; break;
628 case 5: fn
= genericg_compute_checksum_8al_5
;
629 nm
= "genericg_compute_checksum_8al_5"; break;
630 case 6: fn
= genericg_compute_checksum_8al_6
;
631 nm
= "genericg_compute_checksum_8al_6"; break;
632 case 7: fn
= genericg_compute_checksum_8al_7
;
633 nm
= "genericg_compute_checksum_8al_7"; break;
634 case 8: fn
= genericg_compute_checksum_8al_8
;
635 nm
= "genericg_compute_checksum_8al_8"; break;
636 case 9: fn
= genericg_compute_checksum_8al_9
;
637 nm
= "genericg_compute_checksum_8al_9"; break;
638 case 10: fn
= genericg_compute_checksum_8al_10
;
639 nm
= "genericg_compute_checksum_8al_10"; break;
640 case 11: fn
= genericg_compute_checksum_8al_11
;
641 nm
= "genericg_compute_checksum_8al_11"; break;
642 case 12: fn
= genericg_compute_checksum_8al_12
;
643 nm
= "genericg_compute_checksum_8al_12"; break;
646 fn_spec
= (VEX_REGPARM(1) HWord(*)(HWord
)) fn
;
649 const HChar
* nm
= NULL
;
650 UInt
VEX_REGPARM(1) (*fn
)(HWord
) = NULL
;
651 switch (hWs_to_check
) {
652 case 1: fn
= genericg_compute_checksum_4al_1
;
653 nm
= "genericg_compute_checksum_4al_1"; break;
654 case 2: fn
= genericg_compute_checksum_4al_2
;
655 nm
= "genericg_compute_checksum_4al_2"; break;
656 case 3: fn
= genericg_compute_checksum_4al_3
;
657 nm
= "genericg_compute_checksum_4al_3"; break;
658 case 4: fn
= genericg_compute_checksum_4al_4
;
659 nm
= "genericg_compute_checksum_4al_4"; break;
660 case 5: fn
= genericg_compute_checksum_4al_5
;
661 nm
= "genericg_compute_checksum_4al_5"; break;
662 case 6: fn
= genericg_compute_checksum_4al_6
;
663 nm
= "genericg_compute_checksum_4al_6"; break;
664 case 7: fn
= genericg_compute_checksum_4al_7
;
665 nm
= "genericg_compute_checksum_4al_7"; break;
666 case 8: fn
= genericg_compute_checksum_4al_8
;
667 nm
= "genericg_compute_checksum_4al_8"; break;
668 case 9: fn
= genericg_compute_checksum_4al_9
;
669 nm
= "genericg_compute_checksum_4al_9"; break;
670 case 10: fn
= genericg_compute_checksum_4al_10
;
671 nm
= "genericg_compute_checksum_4al_10"; break;
672 case 11: fn
= genericg_compute_checksum_4al_11
;
673 nm
= "genericg_compute_checksum_4al_11"; break;
674 case 12: fn
= genericg_compute_checksum_4al_12
;
675 nm
= "genericg_compute_checksum_4al_12"; break;
678 fn_spec
= (VEX_REGPARM(1) HWord(*)(HWord
))fn
;
682 expectedhW
= fn_generic( first_hW
, hWs_to_check
);
683 /* If we got a specialised version, check it produces the same
684 result as the generic version! */
687 vassert(expectedhW
== fn_spec( first_hW
));
692 /* Set CMSTART and CMLEN. These will describe to the despatcher
693 the area of guest code to invalidate should we exit with a
694 self-check failure. */
696 tistart_tmp
= newIRTemp(irsb
->tyenv
, guest_word_type
);
697 tilen_tmp
= newIRTemp(irsb
->tyenv
, guest_word_type
);
699 IRConst
* base2check_IRConst
700 = guest_word_type
==Ity_I32
? IRConst_U32(toUInt(base2check
))
701 : IRConst_U64(base2check
);
702 IRConst
* len2check_IRConst
703 = guest_word_type
==Ity_I32
? IRConst_U32(len2check
)
704 : IRConst_U64(len2check
);
706 irsb
->stmts
[selfcheck_idx
+ i
* 5 + 0]
707 = IRStmt_WrTmp(tistart_tmp
, IRExpr_Const(base2check_IRConst
) );
709 irsb
->stmts
[selfcheck_idx
+ i
* 5 + 1]
710 = IRStmt_WrTmp(tilen_tmp
, IRExpr_Const(len2check_IRConst
) );
712 irsb
->stmts
[selfcheck_idx
+ i
* 5 + 2]
713 = IRStmt_Put( offB_GUEST_CMSTART
, IRExpr_RdTmp(tistart_tmp
) );
715 irsb
->stmts
[selfcheck_idx
+ i
* 5 + 3]
716 = IRStmt_Put( offB_GUEST_CMLEN
, IRExpr_RdTmp(tilen_tmp
) );
718 /* Generate the entry point descriptors */
719 if (abiinfo_both
->host_ppc_calls_use_fndescrs
) {
720 HWord
* descr
= (HWord
*)fn_generic
;
721 fn_generic_entry
= descr
[0];
723 descr
= (HWord
*)fn_spec
;
724 fn_spec_entry
= descr
[0];
726 fn_spec_entry
= (HWord
)NULL
;
729 fn_generic_entry
= (HWord
)fn_generic
;
731 fn_spec_entry
= (HWord
)fn_spec
;
733 fn_spec_entry
= (HWord
)NULL
;
737 IRExpr
* callexpr
= NULL
;
739 callexpr
= mkIRExprCCall(
740 host_word_type
, 1/*regparms*/,
741 nm_spec
, (void*)fn_spec_entry
,
743 mkIRExpr_HWord( (HWord
)first_hW
)
747 callexpr
= mkIRExprCCall(
748 host_word_type
, 2/*regparms*/,
749 nm_generic
, (void*)fn_generic_entry
,
751 mkIRExpr_HWord( (HWord
)first_hW
),
752 mkIRExpr_HWord( (HWord
)hWs_to_check
)
757 irsb
->stmts
[selfcheck_idx
+ i
* 5 + 4]
760 host_word_type
==Ity_I64
? Iop_CmpNE64
: Iop_CmpNE32
,
762 host_word_type
==Ity_I64
763 ? IRExpr_Const(IRConst_U64(expectedhW
))
764 : IRExpr_Const(IRConst_U32(expectedhW
))
767 /* Where we must restart if there's a failure: at the
768 first extent, regardless of which extent the
769 failure actually happened in. */
770 guest_IP_bbstart_IRConst
,
773 } /* for (i = 0; i < vge->n_used; i++) */
776 /* irsb->next must now be set, since we've finished the block.
777 Print it if necessary.*/
778 vassert(irsb
->next
!= NULL
);
781 vex_printf( "PUT(%d) = ", irsb
->offsIP
);
782 ppIRExpr( irsb
->next
);
783 vex_printf( "; exit-");
784 ppIRJumpKind(irsb
->jumpkind
);
789 *n_guest_instrs
= n_instrs
;
794 /*-------------------------------------------------------------
795 A support routine for doing self-checking translations.
796 -------------------------------------------------------------*/
799 /* CALLED FROM GENERATED CODE */
801 /* Compute a checksum of host memory at [addr .. addr+len-1], as fast
802 as possible. All _4al versions assume that the supplied address is
803 4 aligned. All length values are in 4-byte chunks. These fns
804 arecalled once for every use of a self-checking translation, so
805 they needs to be as fast as possible. */
807 /* --- 32-bit versions, used only on 32-bit hosts --- */
809 static inline UInt
ROL32 ( UInt w
, Int n
) {
810 w
= (w
<< n
) | (w
>> (32-n
));
815 static UInt
genericg_compute_checksum_4al ( HWord first_w32
, HWord n_w32s
)
817 UInt sum1
= 0, sum2
= 0;
818 UInt
* p
= (UInt
*)first_w32
;
820 while (n_w32s
>= 4) {
822 w
= p
[0]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
823 w
= p
[1]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
824 w
= p
[2]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
825 w
= p
[3]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
830 while (n_w32s
>= 1) {
832 w
= p
[0]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
840 /* Specialised versions of the above function */
843 static UInt
genericg_compute_checksum_4al_1 ( HWord first_w32
)
845 UInt sum1
= 0, sum2
= 0;
846 UInt
* p
= (UInt
*)first_w32
;
848 w
= p
[0]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
854 static UInt
genericg_compute_checksum_4al_2 ( HWord first_w32
)
856 UInt sum1
= 0, sum2
= 0;
857 UInt
* p
= (UInt
*)first_w32
;
859 w
= p
[0]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
861 w
= p
[1]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
867 static UInt
genericg_compute_checksum_4al_3 ( HWord first_w32
)
869 UInt sum1
= 0, sum2
= 0;
870 UInt
* p
= (UInt
*)first_w32
;
872 w
= p
[0]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
874 w
= p
[1]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
876 w
= p
[2]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
882 static UInt
genericg_compute_checksum_4al_4 ( HWord first_w32
)
884 UInt sum1
= 0, sum2
= 0;
885 UInt
* p
= (UInt
*)first_w32
;
887 w
= p
[0]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
888 w
= p
[1]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
889 w
= p
[2]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
890 w
= p
[3]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
896 static UInt
genericg_compute_checksum_4al_5 ( HWord first_w32
)
898 UInt sum1
= 0, sum2
= 0;
899 UInt
* p
= (UInt
*)first_w32
;
901 w
= p
[0]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
902 w
= p
[1]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
903 w
= p
[2]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
904 w
= p
[3]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
906 w
= p
[4]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
912 static UInt
genericg_compute_checksum_4al_6 ( HWord first_w32
)
914 UInt sum1
= 0, sum2
= 0;
915 UInt
* p
= (UInt
*)first_w32
;
917 w
= p
[0]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
918 w
= p
[1]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
919 w
= p
[2]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
920 w
= p
[3]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
922 w
= p
[4]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
924 w
= p
[5]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
930 static UInt
genericg_compute_checksum_4al_7 ( HWord first_w32
)
932 UInt sum1
= 0, sum2
= 0;
933 UInt
* p
= (UInt
*)first_w32
;
935 w
= p
[0]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
936 w
= p
[1]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
937 w
= p
[2]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
938 w
= p
[3]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
940 w
= p
[4]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
942 w
= p
[5]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
944 w
= p
[6]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
950 static UInt
genericg_compute_checksum_4al_8 ( HWord first_w32
)
952 UInt sum1
= 0, sum2
= 0;
953 UInt
* p
= (UInt
*)first_w32
;
955 w
= p
[0]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
956 w
= p
[1]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
957 w
= p
[2]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
958 w
= p
[3]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
960 w
= p
[4]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
961 w
= p
[5]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
962 w
= p
[6]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
963 w
= p
[7]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
969 static UInt
genericg_compute_checksum_4al_9 ( HWord first_w32
)
971 UInt sum1
= 0, sum2
= 0;
972 UInt
* p
= (UInt
*)first_w32
;
974 w
= p
[0]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
975 w
= p
[1]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
976 w
= p
[2]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
977 w
= p
[3]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
979 w
= p
[4]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
980 w
= p
[5]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
981 w
= p
[6]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
982 w
= p
[7]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
984 w
= p
[8]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
990 static UInt
genericg_compute_checksum_4al_10 ( HWord first_w32
)
992 UInt sum1
= 0, sum2
= 0;
993 UInt
* p
= (UInt
*)first_w32
;
995 w
= p
[0]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
996 w
= p
[1]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
997 w
= p
[2]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
998 w
= p
[3]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1000 w
= p
[4]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1001 w
= p
[5]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1002 w
= p
[6]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1003 w
= p
[7]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1005 w
= p
[8]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1007 w
= p
[9]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1013 static UInt
genericg_compute_checksum_4al_11 ( HWord first_w32
)
1015 UInt sum1
= 0, sum2
= 0;
1016 UInt
* p
= (UInt
*)first_w32
;
1018 w
= p
[0]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1019 w
= p
[1]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1020 w
= p
[2]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1021 w
= p
[3]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1023 w
= p
[4]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1024 w
= p
[5]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1025 w
= p
[6]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1026 w
= p
[7]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1028 w
= p
[8]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1030 w
= p
[9]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1032 w
= p
[10]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1038 static UInt
genericg_compute_checksum_4al_12 ( HWord first_w32
)
1040 UInt sum1
= 0, sum2
= 0;
1041 UInt
* p
= (UInt
*)first_w32
;
1043 w
= p
[0]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1044 w
= p
[1]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1045 w
= p
[2]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1046 w
= p
[3]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1048 w
= p
[4]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1049 w
= p
[5]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1050 w
= p
[6]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1051 w
= p
[7]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1053 w
= p
[8]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1054 w
= p
[9]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1055 w
= p
[10]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1056 w
= p
[11]; sum1
= ROL32(sum1
^ w
, 31); sum2
+= w
;
1062 /* --- 64-bit versions, used only on 64-bit hosts --- */
1064 static inline ULong
ROL64 ( ULong w
, Int n
) {
1065 w
= (w
<< n
) | (w
>> (64-n
));
1070 static ULong
genericg_compute_checksum_8al ( HWord first_w64
, HWord n_w64s
)
1072 ULong sum1
= 0, sum2
= 0;
1073 ULong
* p
= (ULong
*)first_w64
;
1075 while (n_w64s
>= 4) {
1077 w
= p
[0]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1078 w
= p
[1]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1079 w
= p
[2]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1080 w
= p
[3]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1085 while (n_w64s
>= 1) {
1087 w
= p
[0]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1095 /* Specialised versions of the above function */
1098 static ULong
genericg_compute_checksum_8al_1 ( HWord first_w64
)
1100 ULong sum1
= 0, sum2
= 0;
1101 ULong
* p
= (ULong
*)first_w64
;
1103 w
= p
[0]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1109 static ULong
genericg_compute_checksum_8al_2 ( HWord first_w64
)
1111 ULong sum1
= 0, sum2
= 0;
1112 ULong
* p
= (ULong
*)first_w64
;
1114 w
= p
[0]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1116 w
= p
[1]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1122 static ULong
genericg_compute_checksum_8al_3 ( HWord first_w64
)
1124 ULong sum1
= 0, sum2
= 0;
1125 ULong
* p
= (ULong
*)first_w64
;
1127 w
= p
[0]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1129 w
= p
[1]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1131 w
= p
[2]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1137 static ULong
genericg_compute_checksum_8al_4 ( HWord first_w64
)
1139 ULong sum1
= 0, sum2
= 0;
1140 ULong
* p
= (ULong
*)first_w64
;
1142 w
= p
[0]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1143 w
= p
[1]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1144 w
= p
[2]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1145 w
= p
[3]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1151 static ULong
genericg_compute_checksum_8al_5 ( HWord first_w64
)
1153 ULong sum1
= 0, sum2
= 0;
1154 ULong
* p
= (ULong
*)first_w64
;
1156 w
= p
[0]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1157 w
= p
[1]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1158 w
= p
[2]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1159 w
= p
[3]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1161 w
= p
[4]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1167 static ULong
genericg_compute_checksum_8al_6 ( HWord first_w64
)
1169 ULong sum1
= 0, sum2
= 0;
1170 ULong
* p
= (ULong
*)first_w64
;
1172 w
= p
[0]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1173 w
= p
[1]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1174 w
= p
[2]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1175 w
= p
[3]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1177 w
= p
[4]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1179 w
= p
[5]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1185 static ULong
genericg_compute_checksum_8al_7 ( HWord first_w64
)
1187 ULong sum1
= 0, sum2
= 0;
1188 ULong
* p
= (ULong
*)first_w64
;
1190 w
= p
[0]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1191 w
= p
[1]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1192 w
= p
[2]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1193 w
= p
[3]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1195 w
= p
[4]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1197 w
= p
[5]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1199 w
= p
[6]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1205 static ULong
genericg_compute_checksum_8al_8 ( HWord first_w64
)
1207 ULong sum1
= 0, sum2
= 0;
1208 ULong
* p
= (ULong
*)first_w64
;
1210 w
= p
[0]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1211 w
= p
[1]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1212 w
= p
[2]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1213 w
= p
[3]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1215 w
= p
[4]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1216 w
= p
[5]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1217 w
= p
[6]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1218 w
= p
[7]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1224 static ULong
genericg_compute_checksum_8al_9 ( HWord first_w64
)
1226 ULong sum1
= 0, sum2
= 0;
1227 ULong
* p
= (ULong
*)first_w64
;
1229 w
= p
[0]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1230 w
= p
[1]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1231 w
= p
[2]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1232 w
= p
[3]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1234 w
= p
[4]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1235 w
= p
[5]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1236 w
= p
[6]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1237 w
= p
[7]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1239 w
= p
[8]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1245 static ULong
genericg_compute_checksum_8al_10 ( HWord first_w64
)
1247 ULong sum1
= 0, sum2
= 0;
1248 ULong
* p
= (ULong
*)first_w64
;
1250 w
= p
[0]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1251 w
= p
[1]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1252 w
= p
[2]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1253 w
= p
[3]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1255 w
= p
[4]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1256 w
= p
[5]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1257 w
= p
[6]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1258 w
= p
[7]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1260 w
= p
[8]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1262 w
= p
[9]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1268 static ULong
genericg_compute_checksum_8al_11 ( HWord first_w64
)
1270 ULong sum1
= 0, sum2
= 0;
1271 ULong
* p
= (ULong
*)first_w64
;
1273 w
= p
[0]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1274 w
= p
[1]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1275 w
= p
[2]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1276 w
= p
[3]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1278 w
= p
[4]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1279 w
= p
[5]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1280 w
= p
[6]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1281 w
= p
[7]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1283 w
= p
[8]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1285 w
= p
[9]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1287 w
= p
[10]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1293 static ULong
genericg_compute_checksum_8al_12 ( HWord first_w64
)
1295 ULong sum1
= 0, sum2
= 0;
1296 ULong
* p
= (ULong
*)first_w64
;
1298 w
= p
[0]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1299 w
= p
[1]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1300 w
= p
[2]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1301 w
= p
[3]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1303 w
= p
[4]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1304 w
= p
[5]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1305 w
= p
[6]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1306 w
= p
[7]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1308 w
= p
[8]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1309 w
= p
[9]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1310 w
= p
[10]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1311 w
= p
[11]; sum1
= ROL64(sum1
^ w
, 63); sum2
+= w
;
1316 /*--------------------------------------------------------------------*/
1317 /*--- end guest_generic_bb_to_IR.c ---*/
1318 /*--------------------------------------------------------------------*/