1 2 /*---------------------------------------------------------------*/ 3 /*--- begin main_main.c ---*/ 4 /*---------------------------------------------------------------*/ 5 6 /* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2004-2010 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.h" 37 #include "libvex_emwarn.h" 38 #include "libvex_guest_x86.h" 39 #include "libvex_guest_amd64.h" 40 #include "libvex_guest_arm.h" 41 #include "libvex_guest_ppc32.h" 42 #include "libvex_guest_ppc64.h" 43 44 #include "main_globals.h" 45 #include "main_util.h" 46 #include "host_generic_regs.h" 47 #include "ir_opt.h" 48 49 #include "host_x86_defs.h" 50 #include "host_amd64_defs.h" 51 #include "host_ppc_defs.h" 52 #include "host_arm_defs.h" 53 54 #include "guest_generic_bb_to_IR.h" 55 #include "guest_x86_defs.h" 56 #include "guest_amd64_defs.h" 57 #include "guest_arm_defs.h" 58 #include "guest_ppc_defs.h" 59 60 #include "host_generic_simd128.h" 61 62 63 /* This file contains the top level interface to the library. */ 64 65 /* --------- fwds ... --------- */ 66 67 static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps ); 68 static HChar* show_hwcaps ( VexArch arch, UInt hwcaps ); 69 70 71 /* --------- Initialise the library. --------- */ 72 73 /* Exported to library client. */ 74 75 void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon ) 76 { 77 vcon->iropt_verbosity = 0; 78 vcon->iropt_level = 2; 79 vcon->iropt_precise_memory_exns = False; 80 vcon->iropt_unroll_thresh = 120; 81 vcon->guest_max_insns = 60; 82 vcon->guest_chase_thresh = 10; 83 vcon->guest_chase_cond = False; 84 } 85 86 87 /* Exported to library client. */ 88 89 void LibVEX_Init ( 90 /* failure exit function */ 91 __attribute__ ((noreturn)) 92 void (*failure_exit) ( void ), 93 /* logging output function */ 94 void (*log_bytes) ( HChar*, Int nbytes ), 95 /* debug paranoia level */ 96 Int debuglevel, 97 /* Are we supporting valgrind checking? */ 98 Bool valgrind_support, 99 /* Control ... */ 100 /*READONLY*/VexControl* vcon 101 ) 102 { 103 /* First off, do enough minimal setup so that the following 104 assertions can fail in a sane fashion, if need be. */ 105 vex_failure_exit = failure_exit; 106 vex_log_bytes = log_bytes; 107 108 /* Now it's safe to check parameters for sanity. */ 109 vassert(!vex_initdone); 110 vassert(failure_exit); 111 vassert(log_bytes); 112 vassert(debuglevel >= 0); 113 114 vassert(vcon->iropt_verbosity >= 0); 115 vassert(vcon->iropt_level >= 0); 116 vassert(vcon->iropt_level <= 2); 117 vassert(vcon->iropt_unroll_thresh >= 0); 118 vassert(vcon->iropt_unroll_thresh <= 400); 119 vassert(vcon->guest_max_insns >= 1); 120 vassert(vcon->guest_max_insns <= 100); 121 vassert(vcon->guest_chase_thresh >= 0); 122 vassert(vcon->guest_chase_thresh < vcon->guest_max_insns); 123 vassert(vcon->guest_chase_cond == True 124 || vcon->guest_chase_cond == False); 125 126 /* Check that Vex has been built with sizes of basic types as 127 stated in priv/libvex_basictypes.h. Failure of any of these is 128 a serious configuration error and should be corrected 129 immediately. If any of these assertions fail you can fully 130 expect Vex not to work properly, if at all. */ 131 132 vassert(1 == sizeof(UChar)); 133 vassert(1 == sizeof(Char)); 134 vassert(2 == sizeof(UShort)); 135 vassert(2 == sizeof(Short)); 136 vassert(4 == sizeof(UInt)); 137 vassert(4 == sizeof(Int)); 138 vassert(8 == sizeof(ULong)); 139 vassert(8 == sizeof(Long)); 140 vassert(4 == sizeof(Float)); 141 vassert(8 == sizeof(Double)); 142 vassert(1 == sizeof(Bool)); 143 vassert(4 == sizeof(Addr32)); 144 vassert(8 == sizeof(Addr64)); 145 vassert(16 == sizeof(U128)); 146 vassert(16 == sizeof(V128)); 147 148 vassert(sizeof(void*) == 4 || sizeof(void*) == 8); 149 vassert(sizeof(void*) == sizeof(int*)); 150 vassert(sizeof(void*) == sizeof(HWord)); 151 152 vassert(VEX_HOST_WORDSIZE == sizeof(void*)); 153 vassert(VEX_HOST_WORDSIZE == sizeof(HWord)); 154 155 /* Really start up .. */ 156 vex_debuglevel = debuglevel; 157 vex_valgrind_support = valgrind_support; 158 vex_control = *vcon; 159 vex_initdone = True; 160 vexSetAllocMode ( VexAllocModeTEMP ); 161 } 162 163 164 /* --------- Make a translation. --------- */ 165 166 /* Exported to library client. */ 167 168 VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta ) 169 { 170 /* This the bundle of functions we need to do the back-end stuff 171 (insn selection, reg-alloc, assembly) whilst being insulated 172 from the target instruction set. */ 173 HReg* available_real_regs; 174 Int n_available_real_regs; 175 Bool (*isMove) ( HInstr*, HReg*, HReg* ); 176 void (*getRegUsage) ( HRegUsage*, HInstr*, Bool ); 177 void (*mapRegs) ( HRegRemap*, HInstr*, Bool ); 178 void (*genSpill) ( HInstr**, HInstr**, HReg, Int, Bool ); 179 void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool ); 180 HInstr* (*directReload) ( HInstr*, HReg, Short ); 181 void (*ppInstr) ( HInstr*, Bool ); 182 void (*ppReg) ( HReg ); 183 HInstrArray* (*iselSB) ( IRSB*, VexArch, VexArchInfo*, 184 VexAbiInfo* ); 185 Int (*emit) ( UChar*, Int, HInstr*, Bool, void* ); 186 IRExpr* (*specHelper) ( HChar*, IRExpr**, IRStmt**, Int ); 187 Bool (*preciseMemExnsFn) ( Int, Int ); 188 189 DisOneInstrFn disInstrFn; 190 191 VexGuestLayout* guest_layout; 192 Bool host_is_bigendian = False; 193 IRSB* irsb; 194 HInstrArray* vcode; 195 HInstrArray* rcode; 196 Int i, j, k, out_used, guest_sizeB; 197 Int offB_TISTART, offB_TILEN; 198 UChar insn_bytes[32]; 199 IRType guest_word_type; 200 IRType host_word_type; 201 Bool mode64; 202 203 guest_layout = NULL; 204 available_real_regs = NULL; 205 n_available_real_regs = 0; 206 isMove = NULL; 207 getRegUsage = NULL; 208 mapRegs = NULL; 209 genSpill = NULL; 210 genReload = NULL; 211 directReload = NULL; 212 ppInstr = NULL; 213 ppReg = NULL; 214 iselSB = NULL; 215 emit = NULL; 216 specHelper = NULL; 217 preciseMemExnsFn = NULL; 218 disInstrFn = NULL; 219 guest_word_type = Ity_INVALID; 220 host_word_type = Ity_INVALID; 221 offB_TISTART = 0; 222 offB_TILEN = 0; 223 mode64 = False; 224 225 vex_traceflags = vta->traceflags; 226 227 vassert(vex_initdone); 228 vexSetAllocModeTEMP_and_clear(); 229 vexAllocSanityCheck(); 230 231 /* First off, check that the guest and host insn sets 232 are supported. */ 233 234 switch (vta->arch_host) { 235 236 case VexArchX86: 237 mode64 = False; 238 getAllocableRegs_X86 ( &n_available_real_regs, 239 &available_real_regs ); 240 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr; 241 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) 242 getRegUsage_X86Instr; 243 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_X86Instr; 244 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) 245 genSpill_X86; 246 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) 247 genReload_X86; 248 directReload = (HInstr*(*)(HInstr*,HReg,Short)) directReload_X86; 249 ppInstr = (void(*)(HInstr*, Bool)) ppX86Instr; 250 ppReg = (void(*)(HReg)) ppHRegX86; 251 iselSB = iselSB_X86; 252 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_X86Instr; 253 host_is_bigendian = False; 254 host_word_type = Ity_I32; 255 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_host.hwcaps)); 256 vassert(vta->dispatch != NULL); /* jump-to-dispatcher scheme */ 257 break; 258 259 case VexArchAMD64: 260 mode64 = True; 261 getAllocableRegs_AMD64 ( &n_available_real_regs, 262 &available_real_regs ); 263 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr; 264 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) 265 getRegUsage_AMD64Instr; 266 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_AMD64Instr; 267 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) 268 genSpill_AMD64; 269 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) 270 genReload_AMD64; 271 ppInstr = (void(*)(HInstr*, Bool)) ppAMD64Instr; 272 ppReg = (void(*)(HReg)) ppHRegAMD64; 273 iselSB = iselSB_AMD64; 274 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_AMD64Instr; 275 host_is_bigendian = False; 276 host_word_type = Ity_I64; 277 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_host.hwcaps)); 278 vassert(vta->dispatch != NULL); /* jump-to-dispatcher scheme */ 279 break; 280 281 case VexArchPPC32: 282 mode64 = False; 283 getAllocableRegs_PPC ( &n_available_real_regs, 284 &available_real_regs, mode64 ); 285 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr; 286 getRegUsage = (void(*)(HRegUsage*,HInstr*,Bool)) getRegUsage_PPCInstr; 287 mapRegs = (void(*)(HRegRemap*,HInstr*,Bool)) mapRegs_PPCInstr; 288 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC; 289 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC; 290 ppInstr = (void(*)(HInstr*,Bool)) ppPPCInstr; 291 ppReg = (void(*)(HReg)) ppHRegPPC; 292 iselSB = iselSB_PPC; 293 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_PPCInstr; 294 host_is_bigendian = True; 295 host_word_type = Ity_I32; 296 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_host.hwcaps)); 297 vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */ 298 break; 299 300 case VexArchPPC64: 301 mode64 = True; 302 getAllocableRegs_PPC ( &n_available_real_regs, 303 &available_real_regs, mode64 ); 304 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr; 305 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_PPCInstr; 306 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_PPCInstr; 307 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC; 308 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC; 309 ppInstr = (void(*)(HInstr*, Bool)) ppPPCInstr; 310 ppReg = (void(*)(HReg)) ppHRegPPC; 311 iselSB = iselSB_PPC; 312 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_PPCInstr; 313 host_is_bigendian = True; 314 host_word_type = Ity_I64; 315 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_host.hwcaps)); 316 vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */ 317 break; 318 319 case VexArchARM: 320 mode64 = False; 321 getAllocableRegs_ARM ( &n_available_real_regs, 322 &available_real_regs ); 323 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARMInstr; 324 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_ARMInstr; 325 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_ARMInstr; 326 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_ARM; 327 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_ARM; 328 ppInstr = (void(*)(HInstr*, Bool)) ppARMInstr; 329 ppReg = (void(*)(HReg)) ppHRegARM; 330 iselSB = iselSB_ARM; 331 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_ARMInstr; 332 host_is_bigendian = False; 333 host_word_type = Ity_I32; 334 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_host.hwcaps)); 335 vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */ 336 break; 337 338 default: 339 vpanic("LibVEX_Translate: unsupported host insn set"); 340 } 341 342 343 switch (vta->arch_guest) { 344 345 case VexArchX86: 346 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns; 347 disInstrFn = disInstr_X86; 348 specHelper = guest_x86_spechelper; 349 guest_sizeB = sizeof(VexGuestX86State); 350 guest_word_type = Ity_I32; 351 guest_layout = &x86guest_layout; 352 offB_TISTART = offsetof(VexGuestX86State,guest_TISTART); 353 offB_TILEN = offsetof(VexGuestX86State,guest_TILEN); 354 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_guest.hwcaps)); 355 vassert(0 == sizeof(VexGuestX86State) % 16); 356 vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART) == 4); 357 vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4); 358 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4); 359 break; 360 361 case VexArchAMD64: 362 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns; 363 disInstrFn = disInstr_AMD64; 364 specHelper = guest_amd64_spechelper; 365 guest_sizeB = sizeof(VexGuestAMD64State); 366 guest_word_type = Ity_I64; 367 guest_layout = &amd64guest_layout; 368 offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART); 369 offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN); 370 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_guest.hwcaps)); 371 vassert(0 == sizeof(VexGuestAMD64State) % 16); 372 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8); 373 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8); 374 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8); 375 break; 376 377 case VexArchPPC32: 378 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns; 379 disInstrFn = disInstr_PPC; 380 specHelper = guest_ppc32_spechelper; 381 guest_sizeB = sizeof(VexGuestPPC32State); 382 guest_word_type = Ity_I32; 383 guest_layout = &ppc32Guest_layout; 384 offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART); 385 offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN); 386 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_guest.hwcaps)); 387 vassert(0 == sizeof(VexGuestPPC32State) % 16); 388 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4); 389 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4); 390 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4); 391 break; 392 393 case VexArchPPC64: 394 preciseMemExnsFn = guest_ppc64_state_requires_precise_mem_exns; 395 disInstrFn = disInstr_PPC; 396 specHelper = guest_ppc64_spechelper; 397 guest_sizeB = sizeof(VexGuestPPC64State); 398 guest_word_type = Ity_I64; 399 guest_layout = &ppc64Guest_layout; 400 offB_TISTART = offsetof(VexGuestPPC64State,guest_TISTART); 401 offB_TILEN = offsetof(VexGuestPPC64State,guest_TILEN); 402 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_guest.hwcaps)); 403 vassert(0 == sizeof(VexGuestPPC64State) % 16); 404 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TISTART ) == 8); 405 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TILEN ) == 8); 406 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8); 407 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8); 408 break; 409 410 case VexArchARM: 411 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns; 412 disInstrFn = disInstr_ARM; 413 specHelper = guest_arm_spechelper; 414 guest_sizeB = sizeof(VexGuestARMState); 415 guest_word_type = Ity_I32; 416 guest_layout = &armGuest_layout; 417 offB_TISTART = offsetof(VexGuestARMState,guest_TISTART); 418 offB_TILEN = offsetof(VexGuestARMState,guest_TILEN); 419 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_guest.hwcaps)); 420 vassert(0 == sizeof(VexGuestARMState) % 16); 421 vassert(sizeof( ((VexGuestARMState*)0)->guest_TISTART) == 4); 422 vassert(sizeof( ((VexGuestARMState*)0)->guest_TILEN ) == 4); 423 vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4); 424 break; 425 426 default: 427 vpanic("LibVEX_Translate: unsupported guest insn set"); 428 } 429 430 /* yet more sanity checks ... */ 431 if (vta->arch_guest == vta->arch_host) { 432 /* doesn't necessarily have to be true, but if it isn't it means 433 we are simulating one flavour of an architecture a different 434 flavour of the same architecture, which is pretty strange. */ 435 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps); 436 } 437 438 vexAllocSanityCheck(); 439 440 if (vex_traceflags & VEX_TRACE_FE) 441 vex_printf("\n------------------------" 442 " Front end " 443 "------------------------\n\n"); 444 445 irsb = bb_to_IR ( vta->guest_extents, 446 vta->callback_opaque, 447 disInstrFn, 448 vta->guest_bytes, 449 vta->guest_bytes_addr, 450 vta->chase_into_ok, 451 host_is_bigendian, 452 vta->arch_guest, 453 &vta->archinfo_guest, 454 &vta->abiinfo_both, 455 guest_word_type, 456 vta->do_self_check, 457 vta->preamble_function, 458 offB_TISTART, 459 offB_TILEN ); 460 461 vexAllocSanityCheck(); 462 463 if (irsb == NULL) { 464 /* Access failure. */ 465 vexSetAllocModeTEMP_and_clear(); 466 vex_traceflags = 0; 467 return VexTransAccessFail; 468 } 469 470 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3); 471 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr); 472 for (i = 0; i < vta->guest_extents->n_used; i++) { 473 vassert(vta->guest_extents->len[i] < 10000); /* sanity */ 474 } 475 476 /* If debugging, show the raw guest bytes for this bb. */ 477 if (0 || (vex_traceflags & VEX_TRACE_FE)) { 478 if (vta->guest_extents->n_used > 1) { 479 vex_printf("can't show code due to extents > 1\n"); 480 } else { 481 /* HACK */ 482 UChar* p = (UChar*)vta->guest_bytes; 483 UInt sum = 0; 484 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0]; 485 vex_printf("GuestBytes %llx %u ", vta->guest_bytes_addr, 486 guest_bytes_read ); 487 for (i = 0; i < guest_bytes_read; i++) { 488 UInt b = (UInt)p[i]; 489 vex_printf(" %02x", b ); 490 sum = (sum << 1) ^ b; 491 } 492 vex_printf(" %08x\n\n", sum); 493 } 494 } 495 496 /* Sanity check the initial IR. */ 497 sanityCheckIRSB( irsb, "initial IR", 498 False/*can be non-flat*/, guest_word_type ); 499 500 vexAllocSanityCheck(); 501 502 /* Clean it up, hopefully a lot. */ 503 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn, 504 vta->guest_bytes_addr, 505 vta->arch_guest ); 506 sanityCheckIRSB( irsb, "after initial iropt", 507 True/*must be flat*/, guest_word_type ); 508 509 if (vex_traceflags & VEX_TRACE_OPT1) { 510 vex_printf("\n------------------------" 511 " After pre-instr IR optimisation " 512 "------------------------\n\n"); 513 ppIRSB ( irsb ); 514 vex_printf("\n"); 515 } 516 517 vexAllocSanityCheck(); 518 519 /* Get the thing instrumented. */ 520 if (vta->instrument1) 521 irsb = vta->instrument1(vta->callback_opaque, 522 irsb, guest_layout, 523 vta->guest_extents, 524 guest_word_type, host_word_type); 525 vexAllocSanityCheck(); 526 527 if (vta->instrument2) 528 irsb = vta->instrument2(vta->callback_opaque, 529 irsb, guest_layout, 530 vta->guest_extents, 531 guest_word_type, host_word_type); 532 533 if (vex_traceflags & VEX_TRACE_INST) { 534 vex_printf("\n------------------------" 535 " After instrumentation " 536 "------------------------\n\n"); 537 ppIRSB ( irsb ); 538 vex_printf("\n"); 539 } 540 541 if (vta->instrument1 || vta->instrument2) 542 sanityCheckIRSB( irsb, "after instrumentation", 543 True/*must be flat*/, guest_word_type ); 544 545 /* Do a post-instrumentation cleanup pass. */ 546 if (vta->instrument1 || vta->instrument2) { 547 do_deadcode_BB( irsb ); 548 irsb = cprop_BB( irsb ); 549 do_deadcode_BB( irsb ); 550 sanityCheckIRSB( irsb, "after post-instrumentation cleanup", 551 True/*must be flat*/, guest_word_type ); 552 } 553 554 vexAllocSanityCheck(); 555 556 if (vex_traceflags & VEX_TRACE_OPT2) { 557 vex_printf("\n------------------------" 558 " After post-instr IR optimisation " 559 "------------------------\n\n"); 560 ppIRSB ( irsb ); 561 vex_printf("\n"); 562 } 563 564 /* Turn it into virtual-registerised code. Build trees -- this 565 also throws away any dead bindings. */ 566 ado_treebuild_BB( irsb ); 567 568 if (vta->finaltidy) { 569 irsb = vta->finaltidy(irsb); 570 } 571 572 vexAllocSanityCheck(); 573 574 if (vex_traceflags & VEX_TRACE_TREES) { 575 vex_printf("\n------------------------" 576 " After tree-building " 577 "------------------------\n\n"); 578 ppIRSB ( irsb ); 579 vex_printf("\n"); 580 } 581 582 /* HACK */ 583 if (0) { *(vta->host_bytes_used) = 0; return VexTransOK; } 584 /* end HACK */ 585 586 if (vex_traceflags & VEX_TRACE_VCODE) 587 vex_printf("\n------------------------" 588 " Instruction selection " 589 "------------------------\n"); 590 591 vcode = iselSB ( irsb, vta->arch_host, &vta->archinfo_host, 592 &vta->abiinfo_both ); 593 594 vexAllocSanityCheck(); 595 596 if (vex_traceflags & VEX_TRACE_VCODE) 597 vex_printf("\n"); 598 599 if (vex_traceflags & VEX_TRACE_VCODE) { 600 for (i = 0; i < vcode->arr_used; i++) { 601 vex_printf("%3d ", i); 602 ppInstr(vcode->arr[i], mode64); 603 vex_printf("\n"); 604 } 605 vex_printf("\n"); 606 } 607 608 /* Register allocate. */ 609 rcode = doRegisterAllocation ( vcode, available_real_regs, 610 n_available_real_regs, 611 isMove, getRegUsage, mapRegs, 612 genSpill, genReload, directReload, 613 guest_sizeB, 614 ppInstr, ppReg, mode64 ); 615 616 vexAllocSanityCheck(); 617 618 if (vex_traceflags & VEX_TRACE_RCODE) { 619 vex_printf("\n------------------------" 620 " Register-allocated code " 621 "------------------------\n\n"); 622 for (i = 0; i < rcode->arr_used; i++) { 623 vex_printf("%3d ", i); 624 ppInstr(rcode->arr[i], mode64); 625 vex_printf("\n"); 626 } 627 vex_printf("\n"); 628 } 629 630 /* HACK */ 631 if (0) { *(vta->host_bytes_used) = 0; return VexTransOK; } 632 /* end HACK */ 633 634 /* Assemble */ 635 if (vex_traceflags & VEX_TRACE_ASM) { 636 vex_printf("\n------------------------" 637 " Assembly " 638 "------------------------\n\n"); 639 } 640 641 out_used = 0; /* tracks along the host_bytes array */ 642 for (i = 0; i < rcode->arr_used; i++) { 643 if (vex_traceflags & VEX_TRACE_ASM) { 644 ppInstr(rcode->arr[i], mode64); 645 vex_printf("\n"); 646 } 647 j = (*emit)( insn_bytes, 32, rcode->arr[i], mode64, vta->dispatch ); 648 if (vex_traceflags & VEX_TRACE_ASM) { 649 for (k = 0; k < j; k++) 650 if (insn_bytes[k] < 16) 651 vex_printf("0%x ", (UInt)insn_bytes[k]); 652 else 653 vex_printf("%x ", (UInt)insn_bytes[k]); 654 vex_printf("\n\n"); 655 } 656 if (out_used + j > vta->host_bytes_size) { 657 vexSetAllocModeTEMP_and_clear(); 658 vex_traceflags = 0; 659 return VexTransOutputFull; 660 } 661 for (k = 0; k < j; k++) { 662 vta->host_bytes[out_used] = insn_bytes[k]; 663 out_used++; 664 } 665 vassert(out_used <= vta->host_bytes_size); 666 } 667 *(vta->host_bytes_used) = out_used; 668 669 vexAllocSanityCheck(); 670 671 vexSetAllocModeTEMP_and_clear(); 672 673 vex_traceflags = 0; 674 return VexTransOK; 675 } 676 677 678 /* --------- Emulation warnings. --------- */ 679 680 HChar* LibVEX_EmWarn_string ( VexEmWarn ew ) 681 { 682 switch (ew) { 683 case EmWarn_NONE: 684 return "none"; 685 case EmWarn_X86_x87exns: 686 return "Unmasking x87 FP exceptions"; 687 case EmWarn_X86_x87precision: 688 return "Selection of non-80-bit x87 FP precision"; 689 case EmWarn_X86_sseExns: 690 return "Unmasking SSE FP exceptions"; 691 case EmWarn_X86_fz: 692 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)"; 693 case EmWarn_X86_daz: 694 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)"; 695 case EmWarn_X86_acFlag: 696 return "Setting %eflags.ac (setting noted but ignored)"; 697 case EmWarn_PPCexns: 698 return "Unmasking PPC32/64 FP exceptions"; 699 case EmWarn_PPC64_redir_overflow: 700 return "PPC64 function redirection stack overflow"; 701 case EmWarn_PPC64_redir_underflow: 702 return "PPC64 function redirection stack underflow"; 703 default: 704 vpanic("LibVEX_EmWarn_string: unknown warning"); 705 } 706 } 707 708 /* ------------------ Arch/HwCaps stuff. ------------------ */ 709 710 const HChar* LibVEX_ppVexArch ( VexArch arch ) 711 { 712 switch (arch) { 713 case VexArch_INVALID: return "INVALID"; 714 case VexArchX86: return "X86"; 715 case VexArchAMD64: return "AMD64"; 716 case VexArchARM: return "ARM"; 717 case VexArchPPC32: return "PPC32"; 718 case VexArchPPC64: return "PPC64"; 719 default: return "VexArch???"; 720 } 721 } 722 723 const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps ) 724 { 725 HChar* str = show_hwcaps(arch,hwcaps); 726 return str ? str : "INVALID"; 727 } 728 729 730 /* Write default settings info *vai. */ 731 void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai ) 732 { 733 vai->hwcaps = 0; 734 vai->ppc_cache_line_szB = 0; 735 vai->ppc_dcbz_szB = 0; 736 vai->ppc_dcbzl_szB = 0; 737 738 } 739 740 /* Write default settings info *vbi. */ 741 void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi ) 742 { 743 vbi->guest_stack_redzone_size = 0; 744 vbi->guest_amd64_assume_fs_is_zero = False; 745 vbi->guest_amd64_assume_gs_is_0x60 = False; 746 vbi->guest_ppc_zap_RZ_at_blr = False; 747 vbi->guest_ppc_zap_RZ_at_bl = NULL; 748 vbi->guest_ppc_sc_continues_at_LR = False; 749 vbi->host_ppc_calls_use_fndescrs = False; 750 vbi->host_ppc32_regalign_int64_args = False; 751 } 752 753 754 /* Return a string showing the hwcaps in a nice way. The string will 755 be NULL for invalid combinations of flags, so these functions also 756 serve as a way to validate hwcaps values. */ 757 758 static HChar* show_hwcaps_x86 ( UInt hwcaps ) 759 { 760 /* Monotonic, SSE3 > SSE2 > SSE1 > baseline. */ 761 switch (hwcaps) { 762 case 0: 763 return "x86-sse0"; 764 case VEX_HWCAPS_X86_SSE1: 765 return "x86-sse1"; 766 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2: 767 return "x86-sse1-sse2"; 768 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2 769 | VEX_HWCAPS_X86_LZCNT: 770 return "x86-sse1-sse2-lzcnt"; 771 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2 772 | VEX_HWCAPS_X86_SSE3: 773 return "x86-sse1-sse2-sse3"; 774 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2 775 | VEX_HWCAPS_X86_SSE3 | VEX_HWCAPS_X86_LZCNT: 776 return "x86-sse1-sse2-sse3-lzcnt"; 777 default: 778 return NULL; 779 } 780 } 781 782 static HChar* show_hwcaps_amd64 ( UInt hwcaps ) 783 { 784 /* SSE3 and CX16 are orthogonal and > baseline, although we really 785 don't expect to come across anything which can do SSE3 but can't 786 do CX16. Still, we can handle that case. LZCNT is similarly 787 orthogonal. */ 788 switch (hwcaps) { 789 case 0: 790 return "amd64-sse2"; 791 case VEX_HWCAPS_AMD64_SSE3: 792 return "amd64-sse3"; 793 case VEX_HWCAPS_AMD64_CX16: 794 return "amd64-sse2-cx16"; 795 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16: 796 return "amd64-sse3-cx16"; 797 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_LZCNT: 798 return "amd64-sse3-lzcnt"; 799 case VEX_HWCAPS_AMD64_CX16 | VEX_HWCAPS_AMD64_LZCNT: 800 return "amd64-sse2-cx16-lzcnt"; 801 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16 802 | VEX_HWCAPS_AMD64_LZCNT: 803 return "amd64-sse3-cx16-lzcnt"; 804 805 default: 806 return NULL; 807 } 808 } 809 810 static HChar* show_hwcaps_ppc32 ( UInt hwcaps ) 811 { 812 /* Monotonic with complications. Basically V > F > baseline, 813 but once you have F then you can have FX or GX too. */ 814 const UInt F = VEX_HWCAPS_PPC32_F; 815 const UInt V = VEX_HWCAPS_PPC32_V; 816 const UInt FX = VEX_HWCAPS_PPC32_FX; 817 const UInt GX = VEX_HWCAPS_PPC32_GX; 818 UInt c = hwcaps; 819 if (c == 0) return "ppc32-int"; 820 if (c == F) return "ppc32-int-flt"; 821 if (c == (F|FX)) return "ppc32-int-flt-FX"; 822 if (c == (F|GX)) return "ppc32-int-flt-GX"; 823 if (c == (F|FX|GX)) return "ppc32-int-flt-FX-GX"; 824 if (c == (F|V)) return "ppc32-int-flt-vmx"; 825 if (c == (F|V|FX)) return "ppc32-int-flt-vmx-FX"; 826 if (c == (F|V|GX)) return "ppc32-int-flt-vmx-GX"; 827 if (c == (F|V|FX|GX)) return "ppc32-int-flt-vmx-FX-GX"; 828 return NULL; 829 } 830 831 static HChar* show_hwcaps_ppc64 ( UInt hwcaps ) 832 { 833 /* Monotonic with complications. Basically V > baseline(==F), 834 but once you have F then you can have FX or GX too. */ 835 const UInt V = VEX_HWCAPS_PPC64_V; 836 const UInt FX = VEX_HWCAPS_PPC64_FX; 837 const UInt GX = VEX_HWCAPS_PPC64_GX; 838 UInt c = hwcaps; 839 if (c == 0) return "ppc64-int-flt"; 840 if (c == FX) return "ppc64-int-flt-FX"; 841 if (c == GX) return "ppc64-int-flt-GX"; 842 if (c == (FX|GX)) return "ppc64-int-flt-FX-GX"; 843 if (c == V) return "ppc64-int-flt-vmx"; 844 if (c == (V|FX)) return "ppc64-int-flt-vmx-FX"; 845 if (c == (V|GX)) return "ppc64-int-flt-vmx-GX"; 846 if (c == (V|FX|GX)) return "ppc64-int-flt-vmx-FX-GX"; 847 return NULL; 848 } 849 850 static HChar* show_hwcaps_arm ( UInt hwcaps ) 851 { 852 Bool N = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0); 853 Bool vfp = ((hwcaps & (VEX_HWCAPS_ARM_VFP | 854 VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3)) != 0); 855 switch (VEX_ARM_ARCHLEVEL(hwcaps)) { 856 case 5: 857 if (N) 858 return NULL; 859 if (vfp) 860 return "ARMv5-vfp"; 861 else 862 return "ARMv5"; 863 return NULL; 864 case 6: 865 if (N) 866 return NULL; 867 if (vfp) 868 return "ARMv6-vfp"; 869 else 870 return "ARMv6"; 871 return NULL; 872 case 7: 873 if (vfp) { 874 if (N) 875 return "ARMv7-vfp-neon"; 876 else 877 return "ARMv7-vfp"; 878 } else { 879 if (N) 880 return "ARMv7-neon"; 881 else 882 return "ARMv7"; 883 } 884 default: 885 return NULL; 886 } 887 return NULL; 888 } 889 890 /* ---- */ 891 static HChar* show_hwcaps ( VexArch arch, UInt hwcaps ) 892 { 893 switch (arch) { 894 case VexArchX86: return show_hwcaps_x86(hwcaps); 895 case VexArchAMD64: return show_hwcaps_amd64(hwcaps); 896 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps); 897 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps); 898 case VexArchARM: return show_hwcaps_arm(hwcaps); 899 default: return NULL; 900 } 901 } 902 903 static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps ) 904 { 905 return show_hwcaps(arch,hwcaps) != NULL; 906 } 907 908 909 /*---------------------------------------------------------------*/ 910 /*--- end main_main.c ---*/ 911 /*---------------------------------------------------------------*/ 912