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