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