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 (at) 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 */ 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 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 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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