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