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