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