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