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 (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_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 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 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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