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-2013 OpenWorks LLP 11 info (at) open-works.net 12 13 This program is free software; you can redistribute it and/or 14 modify it under the terms of the GNU General Public License as 15 published by the Free Software Foundation; either version 2 of the 16 License, or (at your option) any later version. 17 18 This program is distributed in the hope that it will be useful, but 19 WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 General Public License for more details. 22 23 You should have received a copy of the GNU General Public License 24 along with this program; if not, write to the Free Software 25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 26 02110-1301, USA. 27 28 The GNU General Public License is contained in the file COPYING. 29 30 Neither the names of the U.S. Department of Energy nor the 31 University of California nor the names of its contributors may be 32 used to endorse or promote products derived from this software 33 without prior written permission. 34 */ 35 36 #include "libvex.h" 37 #include "libvex_emnote.h" 38 #include "libvex_guest_x86.h" 39 #include "libvex_guest_amd64.h" 40 #include "libvex_guest_arm.h" 41 #include "libvex_guest_arm64.h" 42 #include "libvex_guest_ppc32.h" 43 #include "libvex_guest_ppc64.h" 44 #include "libvex_guest_s390x.h" 45 #include "libvex_guest_mips32.h" 46 #include "libvex_guest_mips64.h" 47 48 #include "main_globals.h" 49 #include "main_util.h" 50 #include "host_generic_regs.h" 51 #include "ir_opt.h" 52 53 #include "host_x86_defs.h" 54 #include "host_amd64_defs.h" 55 #include "host_ppc_defs.h" 56 #include "host_arm_defs.h" 57 #include "host_arm64_defs.h" 58 #include "host_s390_defs.h" 59 #include "host_mips_defs.h" 60 61 #include "guest_generic_bb_to_IR.h" 62 #include "guest_x86_defs.h" 63 #include "guest_amd64_defs.h" 64 #include "guest_arm_defs.h" 65 #include "guest_arm64_defs.h" 66 #include "guest_ppc_defs.h" 67 #include "guest_s390_defs.h" 68 #include "guest_mips_defs.h" 69 70 #include "host_generic_simd128.h" 71 72 73 /* This file contains the top level interface to the library. */ 74 75 /* --------- fwds ... --------- */ 76 77 static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps ); 78 static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps ); 79 80 81 /* --------- helpers --------- */ 82 83 __attribute__((noinline)) 84 static UInt udiv32 ( UInt x, UInt y ) { return x/y; } 85 __attribute__((noinline)) 86 static Int sdiv32 ( Int x, Int y ) { return x/y; } 87 88 89 /* --------- Initialise the library. --------- */ 90 91 /* Exported to library client. */ 92 93 void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon ) 94 { 95 vex_bzero(vcon, sizeof(*vcon)); 96 vcon->iropt_verbosity = 0; 97 vcon->iropt_level = 2; 98 vcon->iropt_register_updates = VexRegUpdUnwindregsAtMemAccess; 99 vcon->iropt_unroll_thresh = 120; 100 vcon->guest_max_insns = 60; 101 vcon->guest_chase_thresh = 10; 102 vcon->guest_chase_cond = False; 103 } 104 105 106 /* Exported to library client. */ 107 108 void LibVEX_Init ( 109 /* failure exit function */ 110 __attribute__ ((noreturn)) 111 void (*failure_exit) ( void ), 112 /* logging output function */ 113 void (*log_bytes) ( HChar*, Int nbytes ), 114 /* debug paranoia level */ 115 Int debuglevel, 116 /* Are we supporting valgrind checking? */ 117 Bool valgrind_support, 118 /* Control ... */ 119 /*READONLY*/VexControl* vcon 120 ) 121 { 122 /* First off, do enough minimal setup so that the following 123 assertions can fail in a sane fashion, if need be. */ 124 vex_failure_exit = failure_exit; 125 vex_log_bytes = log_bytes; 126 127 /* Now it's safe to check parameters for sanity. */ 128 vassert(!vex_initdone); 129 vassert(failure_exit); 130 vassert(log_bytes); 131 vassert(debuglevel >= 0); 132 133 vassert(vcon->iropt_verbosity >= 0); 134 vassert(vcon->iropt_level >= 0); 135 vassert(vcon->iropt_level <= 2); 136 vassert(vcon->iropt_unroll_thresh >= 0); 137 vassert(vcon->iropt_unroll_thresh <= 400); 138 vassert(vcon->guest_max_insns >= 1); 139 vassert(vcon->guest_max_insns <= 100); 140 vassert(vcon->guest_chase_thresh >= 0); 141 vassert(vcon->guest_chase_thresh < vcon->guest_max_insns); 142 vassert(vcon->guest_chase_cond == True 143 || vcon->guest_chase_cond == False); 144 145 /* Check that Vex has been built with sizes of basic types as 146 stated in priv/libvex_basictypes.h. Failure of any of these is 147 a serious configuration error and should be corrected 148 immediately. If any of these assertions fail you can fully 149 expect Vex not to work properly, if at all. */ 150 151 vassert(1 == sizeof(UChar)); 152 vassert(1 == sizeof(Char)); 153 vassert(2 == sizeof(UShort)); 154 vassert(2 == sizeof(Short)); 155 vassert(4 == sizeof(UInt)); 156 vassert(4 == sizeof(Int)); 157 vassert(8 == sizeof(ULong)); 158 vassert(8 == sizeof(Long)); 159 vassert(4 == sizeof(Float)); 160 vassert(8 == sizeof(Double)); 161 vassert(1 == sizeof(Bool)); 162 vassert(4 == sizeof(Addr32)); 163 vassert(8 == sizeof(Addr64)); 164 vassert(16 == sizeof(U128)); 165 vassert(16 == sizeof(V128)); 166 vassert(32 == sizeof(U256)); 167 168 vassert(sizeof(void*) == 4 || sizeof(void*) == 8); 169 vassert(sizeof(void*) == sizeof(int*)); 170 vassert(sizeof(void*) == sizeof(HWord)); 171 172 vassert(VEX_HOST_WORDSIZE == sizeof(void*)); 173 vassert(VEX_HOST_WORDSIZE == sizeof(HWord)); 174 175 /* These take a lot of space, so make sure we don't have 176 any unnoticed size regressions. */ 177 if (VEX_HOST_WORDSIZE == 4) { 178 vassert(sizeof(IRExpr) == 16); 179 vassert(sizeof(IRStmt) == 20 /* x86 */ 180 || sizeof(IRStmt) == 24 /* arm */); 181 } else { 182 vassert(sizeof(IRExpr) == 32); 183 vassert(sizeof(IRStmt) == 32); 184 } 185 186 /* Check that signed integer division on the host rounds towards 187 zero. If not, h_calc_sdiv32_w_arm_semantics() won't work 188 correctly. */ 189 /* 100.0 / 7.0 == 14.2857 */ 190 vassert(udiv32(100, 7) == 14); 191 vassert(sdiv32(100, 7) == 14); 192 vassert(sdiv32(-100, 7) == -14); /* and not -15 */ 193 vassert(sdiv32(100, -7) == -14); /* ditto */ 194 vassert(sdiv32(-100, -7) == 14); /* not sure what this proves */ 195 196 /* Really start up .. */ 197 vex_debuglevel = debuglevel; 198 vex_valgrind_support = valgrind_support; 199 vex_control = *vcon; 200 vex_initdone = True; 201 vexSetAllocMode ( VexAllocModeTEMP ); 202 } 203 204 205 /* --------- Make a translation. --------- */ 206 207 /* Exported to library client. */ 208 209 VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta ) 210 { 211 /* This the bundle of functions we need to do the back-end stuff 212 (insn selection, reg-alloc, assembly) whilst being insulated 213 from the target instruction set. */ 214 HReg* available_real_regs; 215 Int n_available_real_regs; 216 Bool (*isMove) ( HInstr*, HReg*, HReg* ); 217 void (*getRegUsage) ( HRegUsage*, HInstr*, Bool ); 218 void (*mapRegs) ( HRegRemap*, HInstr*, Bool ); 219 void (*genSpill) ( HInstr**, HInstr**, HReg, Int, Bool ); 220 void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool ); 221 HInstr* (*directReload) ( HInstr*, HReg, Short ); 222 void (*ppInstr) ( HInstr*, Bool ); 223 void (*ppReg) ( HReg ); 224 HInstrArray* (*iselSB) ( IRSB*, VexArch, VexArchInfo*, VexAbiInfo*, 225 Int, Int, Bool, Bool, Addr64 ); 226 Int (*emit) ( /*MB_MOD*/Bool*, 227 UChar*, Int, HInstr*, Bool, 228 void*, void*, void*, void* ); 229 IRExpr* (*specHelper) ( const HChar*, IRExpr**, IRStmt**, Int ); 230 Bool (*preciseMemExnsFn) ( Int, Int ); 231 232 DisOneInstrFn disInstrFn; 233 234 VexGuestLayout* guest_layout; 235 Bool host_is_bigendian = False; 236 IRSB* irsb; 237 HInstrArray* vcode; 238 HInstrArray* rcode; 239 Int i, j, k, out_used, guest_sizeB; 240 Int offB_CMSTART, offB_CMLEN, offB_GUEST_IP, szB_GUEST_IP; 241 Int offB_HOST_EvC_COUNTER, offB_HOST_EvC_FAILADDR; 242 UChar insn_bytes[128]; 243 IRType guest_word_type; 244 IRType host_word_type; 245 Bool mode64, chainingAllowed; 246 Addr64 max_ga; 247 248 guest_layout = NULL; 249 available_real_regs = NULL; 250 n_available_real_regs = 0; 251 isMove = NULL; 252 getRegUsage = NULL; 253 mapRegs = NULL; 254 genSpill = NULL; 255 genReload = NULL; 256 directReload = NULL; 257 ppInstr = NULL; 258 ppReg = NULL; 259 iselSB = NULL; 260 emit = NULL; 261 specHelper = NULL; 262 preciseMemExnsFn = NULL; 263 disInstrFn = NULL; 264 guest_word_type = Ity_INVALID; 265 host_word_type = Ity_INVALID; 266 offB_CMSTART = 0; 267 offB_CMLEN = 0; 268 offB_GUEST_IP = 0; 269 szB_GUEST_IP = 0; 270 offB_HOST_EvC_COUNTER = 0; 271 offB_HOST_EvC_FAILADDR = 0; 272 mode64 = False; 273 chainingAllowed = False; 274 275 vex_traceflags = vta->traceflags; 276 277 vassert(vex_initdone); 278 vassert(vta->needs_self_check != NULL); 279 vassert(vta->disp_cp_xassisted != NULL); 280 /* Both the chainers and the indir are either NULL or non-NULL. */ 281 if (vta->disp_cp_chain_me_to_slowEP != NULL) { 282 vassert(vta->disp_cp_chain_me_to_fastEP != NULL); 283 vassert(vta->disp_cp_xindir != NULL); 284 chainingAllowed = True; 285 } else { 286 vassert(vta->disp_cp_chain_me_to_fastEP == NULL); 287 vassert(vta->disp_cp_xindir == NULL); 288 } 289 290 vexSetAllocModeTEMP_and_clear(); 291 vexAllocSanityCheck(); 292 293 /* First off, check that the guest and host insn sets 294 are supported. */ 295 296 switch (vta->arch_host) { 297 298 case VexArchX86: 299 mode64 = False; 300 getAllocableRegs_X86 ( &n_available_real_regs, 301 &available_real_regs ); 302 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr; 303 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) 304 getRegUsage_X86Instr; 305 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_X86Instr; 306 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) 307 genSpill_X86; 308 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) 309 genReload_X86; 310 directReload = (HInstr*(*)(HInstr*,HReg,Short)) directReload_X86; 311 ppInstr = (void(*)(HInstr*, Bool)) ppX86Instr; 312 ppReg = (void(*)(HReg)) ppHRegX86; 313 iselSB = iselSB_X86; 314 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool, 315 void*,void*,void*,void*)) 316 emit_X86Instr; 317 host_is_bigendian = False; 318 host_word_type = Ity_I32; 319 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_host.hwcaps)); 320 break; 321 322 case VexArchAMD64: 323 mode64 = True; 324 getAllocableRegs_AMD64 ( &n_available_real_regs, 325 &available_real_regs ); 326 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr; 327 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) 328 getRegUsage_AMD64Instr; 329 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_AMD64Instr; 330 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) 331 genSpill_AMD64; 332 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) 333 genReload_AMD64; 334 ppInstr = (void(*)(HInstr*, Bool)) ppAMD64Instr; 335 ppReg = (void(*)(HReg)) ppHRegAMD64; 336 iselSB = iselSB_AMD64; 337 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool, 338 void*,void*,void*,void*)) 339 emit_AMD64Instr; 340 host_is_bigendian = False; 341 host_word_type = Ity_I64; 342 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_host.hwcaps)); 343 break; 344 345 case VexArchPPC32: 346 mode64 = False; 347 getAllocableRegs_PPC ( &n_available_real_regs, 348 &available_real_regs, mode64 ); 349 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr; 350 getRegUsage = (void(*)(HRegUsage*,HInstr*,Bool)) getRegUsage_PPCInstr; 351 mapRegs = (void(*)(HRegRemap*,HInstr*,Bool)) mapRegs_PPCInstr; 352 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC; 353 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC; 354 ppInstr = (void(*)(HInstr*,Bool)) ppPPCInstr; 355 ppReg = (void(*)(HReg)) ppHRegPPC; 356 iselSB = iselSB_PPC; 357 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool, 358 void*,void*,void*,void*)) 359 emit_PPCInstr; 360 host_is_bigendian = True; 361 host_word_type = Ity_I32; 362 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_host.hwcaps)); 363 break; 364 365 case VexArchPPC64: 366 mode64 = True; 367 getAllocableRegs_PPC ( &n_available_real_regs, 368 &available_real_regs, mode64 ); 369 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr; 370 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_PPCInstr; 371 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_PPCInstr; 372 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC; 373 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC; 374 ppInstr = (void(*)(HInstr*, Bool)) ppPPCInstr; 375 ppReg = (void(*)(HReg)) ppHRegPPC; 376 iselSB = iselSB_PPC; 377 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool, 378 void*,void*,void*,void*)) 379 emit_PPCInstr; 380 host_is_bigendian = True; 381 host_word_type = Ity_I64; 382 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_host.hwcaps)); 383 break; 384 385 case VexArchS390X: 386 mode64 = True; 387 getAllocableRegs_S390 ( &n_available_real_regs, 388 &available_real_regs, mode64 ); 389 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_S390Instr; 390 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_S390Instr; 391 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_S390Instr; 392 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_S390; 393 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_S390; 394 ppInstr = (void(*)(HInstr*, Bool)) ppS390Instr; 395 ppReg = (void(*)(HReg)) ppHRegS390; 396 iselSB = iselSB_S390; 397 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool, 398 void*,void*,void*,void*)) emit_S390Instr; 399 host_is_bigendian = True; 400 host_word_type = Ity_I64; 401 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_host.hwcaps)); 402 break; 403 404 case VexArchARM: 405 mode64 = False; 406 getAllocableRegs_ARM ( &n_available_real_regs, 407 &available_real_regs ); 408 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARMInstr; 409 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_ARMInstr; 410 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_ARMInstr; 411 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_ARM; 412 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_ARM; 413 ppInstr = (void(*)(HInstr*, Bool)) ppARMInstr; 414 ppReg = (void(*)(HReg)) ppHRegARM; 415 iselSB = iselSB_ARM; 416 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool, 417 void*,void*,void*,void*)) 418 emit_ARMInstr; 419 host_is_bigendian = False; 420 host_word_type = Ity_I32; 421 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_host.hwcaps)); 422 break; 423 424 case VexArchARM64: 425 mode64 = True; 426 getAllocableRegs_ARM64 ( &n_available_real_regs, 427 &available_real_regs ); 428 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARM64Instr; 429 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) 430 getRegUsage_ARM64Instr; 431 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) 432 mapRegs_ARM64Instr; 433 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) 434 genSpill_ARM64; 435 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) 436 genReload_ARM64; 437 ppInstr = (void(*)(HInstr*, Bool)) ppARM64Instr; 438 ppReg = (void(*)(HReg)) ppHRegARM64; 439 iselSB = iselSB_ARM64; 440 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool, 441 void*,void*,void*,void*)) 442 emit_ARM64Instr; 443 host_is_bigendian = False; 444 host_word_type = Ity_I64; 445 vassert(are_valid_hwcaps(VexArchARM64, vta->archinfo_host.hwcaps)); 446 break; 447 448 case VexArchMIPS32: 449 mode64 = False; 450 getAllocableRegs_MIPS ( &n_available_real_regs, 451 &available_real_regs, mode64 ); 452 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_MIPSInstr; 453 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_MIPSInstr; 454 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_MIPSInstr; 455 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_MIPS; 456 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_MIPS; 457 ppInstr = (void(*)(HInstr*, Bool)) ppMIPSInstr; 458 ppReg = (void(*)(HReg)) ppHRegMIPS; 459 iselSB = iselSB_MIPS; 460 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool, 461 void*,void*,void*,void*)) 462 emit_MIPSInstr; 463 # if defined(VKI_LITTLE_ENDIAN) 464 host_is_bigendian = False; 465 # elif defined(VKI_BIG_ENDIAN) 466 host_is_bigendian = True; 467 # endif 468 host_word_type = Ity_I32; 469 vassert(are_valid_hwcaps(VexArchMIPS32, vta->archinfo_host.hwcaps)); 470 break; 471 472 case VexArchMIPS64: 473 mode64 = True; 474 getAllocableRegs_MIPS ( &n_available_real_regs, 475 &available_real_regs, mode64 ); 476 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_MIPSInstr; 477 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_MIPSInstr; 478 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_MIPSInstr; 479 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_MIPS; 480 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_MIPS; 481 ppInstr = (void(*)(HInstr*, Bool)) ppMIPSInstr; 482 ppReg = (void(*)(HReg)) ppHRegMIPS; 483 iselSB = iselSB_MIPS; 484 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool, 485 void*,void*,void*,void*)) 486 emit_MIPSInstr; 487 # if defined(VKI_LITTLE_ENDIAN) 488 host_is_bigendian = False; 489 # elif defined(VKI_BIG_ENDIAN) 490 host_is_bigendian = True; 491 # endif 492 host_word_type = Ity_I64; 493 vassert(are_valid_hwcaps(VexArchMIPS64, vta->archinfo_host.hwcaps)); 494 break; 495 496 default: 497 vpanic("LibVEX_Translate: unsupported host insn set"); 498 } 499 500 501 switch (vta->arch_guest) { 502 503 case VexArchX86: 504 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns; 505 disInstrFn = disInstr_X86; 506 specHelper = guest_x86_spechelper; 507 guest_sizeB = sizeof(VexGuestX86State); 508 guest_word_type = Ity_I32; 509 guest_layout = &x86guest_layout; 510 offB_CMSTART = offsetof(VexGuestX86State,guest_CMSTART); 511 offB_CMLEN = offsetof(VexGuestX86State,guest_CMLEN); 512 offB_GUEST_IP = offsetof(VexGuestX86State,guest_EIP); 513 szB_GUEST_IP = sizeof( ((VexGuestX86State*)0)->guest_EIP ); 514 offB_HOST_EvC_COUNTER = offsetof(VexGuestX86State,host_EvC_COUNTER); 515 offB_HOST_EvC_FAILADDR = offsetof(VexGuestX86State,host_EvC_FAILADDR); 516 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_guest.hwcaps)); 517 vassert(0 == sizeof(VexGuestX86State) % 16); 518 vassert(sizeof( ((VexGuestX86State*)0)->guest_CMSTART) == 4); 519 vassert(sizeof( ((VexGuestX86State*)0)->guest_CMLEN ) == 4); 520 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4); 521 break; 522 523 case VexArchAMD64: 524 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns; 525 disInstrFn = disInstr_AMD64; 526 specHelper = guest_amd64_spechelper; 527 guest_sizeB = sizeof(VexGuestAMD64State); 528 guest_word_type = Ity_I64; 529 guest_layout = &amd64guest_layout; 530 offB_CMSTART = offsetof(VexGuestAMD64State,guest_CMSTART); 531 offB_CMLEN = offsetof(VexGuestAMD64State,guest_CMLEN); 532 offB_GUEST_IP = offsetof(VexGuestAMD64State,guest_RIP); 533 szB_GUEST_IP = sizeof( ((VexGuestAMD64State*)0)->guest_RIP ); 534 offB_HOST_EvC_COUNTER = offsetof(VexGuestAMD64State,host_EvC_COUNTER); 535 offB_HOST_EvC_FAILADDR = offsetof(VexGuestAMD64State,host_EvC_FAILADDR); 536 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_guest.hwcaps)); 537 vassert(0 == sizeof(VexGuestAMD64State) % 16); 538 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_CMSTART ) == 8); 539 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_CMLEN ) == 8); 540 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8); 541 break; 542 543 case VexArchPPC32: 544 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns; 545 disInstrFn = disInstr_PPC; 546 specHelper = guest_ppc32_spechelper; 547 guest_sizeB = sizeof(VexGuestPPC32State); 548 guest_word_type = Ity_I32; 549 guest_layout = &ppc32Guest_layout; 550 offB_CMSTART = offsetof(VexGuestPPC32State,guest_CMSTART); 551 offB_CMLEN = offsetof(VexGuestPPC32State,guest_CMLEN); 552 offB_GUEST_IP = offsetof(VexGuestPPC32State,guest_CIA); 553 szB_GUEST_IP = sizeof( ((VexGuestPPC32State*)0)->guest_CIA ); 554 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC32State,host_EvC_COUNTER); 555 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC32State,host_EvC_FAILADDR); 556 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_guest.hwcaps)); 557 vassert(0 == sizeof(VexGuestPPC32State) % 16); 558 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_CMSTART ) == 4); 559 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_CMLEN ) == 4); 560 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4); 561 break; 562 563 case VexArchPPC64: 564 preciseMemExnsFn = guest_ppc64_state_requires_precise_mem_exns; 565 disInstrFn = disInstr_PPC; 566 specHelper = guest_ppc64_spechelper; 567 guest_sizeB = sizeof(VexGuestPPC64State); 568 guest_word_type = Ity_I64; 569 guest_layout = &ppc64Guest_layout; 570 offB_CMSTART = offsetof(VexGuestPPC64State,guest_CMSTART); 571 offB_CMLEN = offsetof(VexGuestPPC64State,guest_CMLEN); 572 offB_GUEST_IP = offsetof(VexGuestPPC64State,guest_CIA); 573 szB_GUEST_IP = sizeof( ((VexGuestPPC64State*)0)->guest_CIA ); 574 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC64State,host_EvC_COUNTER); 575 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC64State,host_EvC_FAILADDR); 576 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_guest.hwcaps)); 577 vassert(0 == sizeof(VexGuestPPC64State) % 16); 578 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_CMSTART ) == 8); 579 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_CMLEN ) == 8); 580 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8); 581 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8); 582 break; 583 584 case VexArchS390X: 585 preciseMemExnsFn = guest_s390x_state_requires_precise_mem_exns; 586 disInstrFn = disInstr_S390; 587 specHelper = guest_s390x_spechelper; 588 guest_sizeB = sizeof(VexGuestS390XState); 589 guest_word_type = Ity_I64; 590 guest_layout = &s390xGuest_layout; 591 offB_CMSTART = offsetof(VexGuestS390XState,guest_CMSTART); 592 offB_CMLEN = offsetof(VexGuestS390XState,guest_CMLEN); 593 offB_GUEST_IP = offsetof(VexGuestS390XState,guest_IA); 594 szB_GUEST_IP = sizeof( ((VexGuestS390XState*)0)->guest_IA); 595 offB_HOST_EvC_COUNTER = offsetof(VexGuestS390XState,host_EvC_COUNTER); 596 offB_HOST_EvC_FAILADDR = offsetof(VexGuestS390XState,host_EvC_FAILADDR); 597 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_guest.hwcaps)); 598 vassert(0 == sizeof(VexGuestS390XState) % 16); 599 vassert(sizeof( ((VexGuestS390XState*)0)->guest_CMSTART ) == 8); 600 vassert(sizeof( ((VexGuestS390XState*)0)->guest_CMLEN ) == 8); 601 vassert(sizeof( ((VexGuestS390XState*)0)->guest_NRADDR ) == 8); 602 break; 603 604 case VexArchARM: 605 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns; 606 disInstrFn = disInstr_ARM; 607 specHelper = guest_arm_spechelper; 608 guest_sizeB = sizeof(VexGuestARMState); 609 guest_word_type = Ity_I32; 610 guest_layout = &armGuest_layout; 611 offB_CMSTART = offsetof(VexGuestARMState,guest_CMSTART); 612 offB_CMLEN = offsetof(VexGuestARMState,guest_CMLEN); 613 offB_GUEST_IP = offsetof(VexGuestARMState,guest_R15T); 614 szB_GUEST_IP = sizeof( ((VexGuestARMState*)0)->guest_R15T ); 615 offB_HOST_EvC_COUNTER = offsetof(VexGuestARMState,host_EvC_COUNTER); 616 offB_HOST_EvC_FAILADDR = offsetof(VexGuestARMState,host_EvC_FAILADDR); 617 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_guest.hwcaps)); 618 vassert(0 == sizeof(VexGuestARMState) % 16); 619 vassert(sizeof( ((VexGuestARMState*)0)->guest_CMSTART) == 4); 620 vassert(sizeof( ((VexGuestARMState*)0)->guest_CMLEN ) == 4); 621 vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4); 622 break; 623 624 case VexArchARM64: 625 preciseMemExnsFn = guest_arm64_state_requires_precise_mem_exns; 626 disInstrFn = disInstr_ARM64; 627 specHelper = guest_arm64_spechelper; 628 guest_sizeB = sizeof(VexGuestARM64State); 629 guest_word_type = Ity_I64; 630 guest_layout = &arm64Guest_layout; 631 offB_CMSTART = offsetof(VexGuestARM64State,guest_CMSTART); 632 offB_CMLEN = offsetof(VexGuestARM64State,guest_CMLEN); 633 offB_GUEST_IP = offsetof(VexGuestARM64State,guest_PC); 634 szB_GUEST_IP = sizeof( ((VexGuestARM64State*)0)->guest_PC ); 635 offB_HOST_EvC_COUNTER = offsetof(VexGuestARM64State,host_EvC_COUNTER); 636 offB_HOST_EvC_FAILADDR = offsetof(VexGuestARM64State,host_EvC_FAILADDR); 637 vassert(are_valid_hwcaps(VexArchARM64, vta->archinfo_guest.hwcaps)); 638 vassert(0 == sizeof(VexGuestARM64State) % 16); 639 vassert(sizeof( ((VexGuestARM64State*)0)->guest_CMSTART) == 8); 640 vassert(sizeof( ((VexGuestARM64State*)0)->guest_CMLEN ) == 8); 641 vassert(sizeof( ((VexGuestARM64State*)0)->guest_NRADDR ) == 8); 642 break; 643 644 case VexArchMIPS32: 645 preciseMemExnsFn = guest_mips32_state_requires_precise_mem_exns; 646 disInstrFn = disInstr_MIPS; 647 specHelper = guest_mips32_spechelper; 648 guest_sizeB = sizeof(VexGuestMIPS32State); 649 guest_word_type = Ity_I32; 650 guest_layout = &mips32Guest_layout; 651 offB_CMSTART = offsetof(VexGuestMIPS32State,guest_CMSTART); 652 offB_CMLEN = offsetof(VexGuestMIPS32State,guest_CMLEN); 653 offB_GUEST_IP = offsetof(VexGuestMIPS32State,guest_PC); 654 szB_GUEST_IP = sizeof( ((VexGuestMIPS32State*)0)->guest_PC ); 655 offB_HOST_EvC_COUNTER = offsetof(VexGuestMIPS32State,host_EvC_COUNTER); 656 offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS32State,host_EvC_FAILADDR); 657 vassert(are_valid_hwcaps(VexArchMIPS32, vta->archinfo_guest.hwcaps)); 658 vassert(0 == sizeof(VexGuestMIPS32State) % 16); 659 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_CMSTART) == 4); 660 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_CMLEN ) == 4); 661 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_NRADDR ) == 4); 662 break; 663 664 case VexArchMIPS64: 665 preciseMemExnsFn = guest_mips64_state_requires_precise_mem_exns; 666 disInstrFn = disInstr_MIPS; 667 specHelper = guest_mips64_spechelper; 668 guest_sizeB = sizeof(VexGuestMIPS64State); 669 guest_word_type = Ity_I64; 670 guest_layout = &mips64Guest_layout; 671 offB_CMSTART = offsetof(VexGuestMIPS64State,guest_CMSTART); 672 offB_CMLEN = offsetof(VexGuestMIPS64State,guest_CMLEN); 673 offB_GUEST_IP = offsetof(VexGuestMIPS64State,guest_PC); 674 szB_GUEST_IP = sizeof( ((VexGuestMIPS64State*)0)->guest_PC ); 675 offB_HOST_EvC_COUNTER = offsetof(VexGuestMIPS64State,host_EvC_COUNTER); 676 offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS64State,host_EvC_FAILADDR); 677 vassert(are_valid_hwcaps(VexArchMIPS64, vta->archinfo_guest.hwcaps)); 678 vassert(0 == sizeof(VexGuestMIPS64State) % 16); 679 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_CMSTART) == 8); 680 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_CMLEN ) == 8); 681 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_NRADDR ) == 8); 682 break; 683 684 default: 685 vpanic("LibVEX_Translate: unsupported guest insn set"); 686 } 687 688 /* Set up result struct. */ 689 VexTranslateResult res; 690 res.status = VexTransOK; 691 res.n_sc_extents = 0; 692 res.offs_profInc = -1; 693 res.n_guest_instrs = 0; 694 695 /* yet more sanity checks ... */ 696 if (vta->arch_guest == vta->arch_host) { 697 /* doesn't necessarily have to be true, but if it isn't it means 698 we are simulating one flavour of an architecture a different 699 flavour of the same architecture, which is pretty strange. */ 700 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps); 701 } 702 703 vexAllocSanityCheck(); 704 705 if (vex_traceflags & VEX_TRACE_FE) 706 vex_printf("\n------------------------" 707 " Front end " 708 "------------------------\n\n"); 709 710 irsb = bb_to_IR ( vta->guest_extents, 711 &res.n_sc_extents, 712 &res.n_guest_instrs, 713 vta->callback_opaque, 714 disInstrFn, 715 vta->guest_bytes, 716 vta->guest_bytes_addr, 717 vta->chase_into_ok, 718 host_is_bigendian, 719 vta->sigill_diag, 720 vta->arch_guest, 721 &vta->archinfo_guest, 722 &vta->abiinfo_both, 723 guest_word_type, 724 vta->needs_self_check, 725 vta->preamble_function, 726 offB_CMSTART, 727 offB_CMLEN, 728 offB_GUEST_IP, 729 szB_GUEST_IP ); 730 731 vexAllocSanityCheck(); 732 733 if (irsb == NULL) { 734 /* Access failure. */ 735 vexSetAllocModeTEMP_and_clear(); 736 vex_traceflags = 0; 737 res.status = VexTransAccessFail; return res; 738 } 739 740 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3); 741 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr); 742 for (i = 0; i < vta->guest_extents->n_used; i++) { 743 vassert(vta->guest_extents->len[i] < 10000); /* sanity */ 744 } 745 746 /* If debugging, show the raw guest bytes for this bb. */ 747 if (0 || (vex_traceflags & VEX_TRACE_FE)) { 748 if (vta->guest_extents->n_used > 1) { 749 vex_printf("can't show code due to extents > 1\n"); 750 } else { 751 /* HACK */ 752 UChar* p = (UChar*)vta->guest_bytes; 753 UInt sum = 0; 754 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0]; 755 vex_printf("GuestBytes %llx %u ", vta->guest_bytes_addr, 756 guest_bytes_read ); 757 for (i = 0; i < guest_bytes_read; i++) { 758 UInt b = (UInt)p[i]; 759 vex_printf(" %02x", b ); 760 sum = (sum << 1) ^ b; 761 } 762 vex_printf(" %08x\n\n", sum); 763 } 764 } 765 766 /* Sanity check the initial IR. */ 767 sanityCheckIRSB( irsb, "initial IR", 768 False/*can be non-flat*/, guest_word_type ); 769 770 vexAllocSanityCheck(); 771 772 /* Clean it up, hopefully a lot. */ 773 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn, 774 vta->guest_bytes_addr, 775 vta->arch_guest ); 776 sanityCheckIRSB( irsb, "after initial iropt", 777 True/*must be flat*/, guest_word_type ); 778 779 if (vex_traceflags & VEX_TRACE_OPT1) { 780 vex_printf("\n------------------------" 781 " After pre-instr IR optimisation " 782 "------------------------\n\n"); 783 ppIRSB ( irsb ); 784 vex_printf("\n"); 785 } 786 787 vexAllocSanityCheck(); 788 789 /* Get the thing instrumented. */ 790 if (vta->instrument1) 791 irsb = vta->instrument1(vta->callback_opaque, 792 irsb, guest_layout, 793 vta->guest_extents, 794 &vta->archinfo_host, 795 guest_word_type, host_word_type); 796 vexAllocSanityCheck(); 797 798 if (vta->instrument2) 799 irsb = vta->instrument2(vta->callback_opaque, 800 irsb, guest_layout, 801 vta->guest_extents, 802 &vta->archinfo_host, 803 guest_word_type, host_word_type); 804 805 if (vex_traceflags & VEX_TRACE_INST) { 806 vex_printf("\n------------------------" 807 " After instrumentation " 808 "------------------------\n\n"); 809 ppIRSB ( irsb ); 810 vex_printf("\n"); 811 } 812 813 if (vta->instrument1 || vta->instrument2) 814 sanityCheckIRSB( irsb, "after instrumentation", 815 True/*must be flat*/, guest_word_type ); 816 817 /* Do a post-instrumentation cleanup pass. */ 818 if (vta->instrument1 || vta->instrument2) { 819 do_deadcode_BB( irsb ); 820 irsb = cprop_BB( irsb ); 821 do_deadcode_BB( irsb ); 822 sanityCheckIRSB( irsb, "after post-instrumentation cleanup", 823 True/*must be flat*/, guest_word_type ); 824 } 825 826 vexAllocSanityCheck(); 827 828 if (vex_traceflags & VEX_TRACE_OPT2) { 829 vex_printf("\n------------------------" 830 " After post-instr IR optimisation " 831 "------------------------\n\n"); 832 ppIRSB ( irsb ); 833 vex_printf("\n"); 834 } 835 836 /* Turn it into virtual-registerised code. Build trees -- this 837 also throws away any dead bindings. */ 838 max_ga = ado_treebuild_BB( irsb, preciseMemExnsFn ); 839 840 if (vta->finaltidy) { 841 irsb = vta->finaltidy(irsb); 842 } 843 844 vexAllocSanityCheck(); 845 846 if (vex_traceflags & VEX_TRACE_TREES) { 847 vex_printf("\n------------------------" 848 " After tree-building " 849 "------------------------\n\n"); 850 ppIRSB ( irsb ); 851 vex_printf("\n"); 852 } 853 854 /* HACK */ 855 if (0) { 856 *(vta->host_bytes_used) = 0; 857 res.status = VexTransOK; return res; 858 } 859 /* end HACK */ 860 861 if (vex_traceflags & VEX_TRACE_VCODE) 862 vex_printf("\n------------------------" 863 " Instruction selection " 864 "------------------------\n"); 865 866 /* No guest has its IP field at offset zero. If this fails it 867 means some transformation pass somewhere failed to update/copy 868 irsb->offsIP properly. */ 869 vassert(irsb->offsIP >= 16); 870 871 vcode = iselSB ( irsb, vta->arch_host, 872 &vta->archinfo_host, 873 &vta->abiinfo_both, 874 offB_HOST_EvC_COUNTER, 875 offB_HOST_EvC_FAILADDR, 876 chainingAllowed, 877 vta->addProfInc, 878 max_ga ); 879 880 vexAllocSanityCheck(); 881 882 if (vex_traceflags & VEX_TRACE_VCODE) 883 vex_printf("\n"); 884 885 if (vex_traceflags & VEX_TRACE_VCODE) { 886 for (i = 0; i < vcode->arr_used; i++) { 887 vex_printf("%3d ", i); 888 ppInstr(vcode->arr[i], mode64); 889 vex_printf("\n"); 890 } 891 vex_printf("\n"); 892 } 893 894 /* Register allocate. */ 895 rcode = doRegisterAllocation ( vcode, available_real_regs, 896 n_available_real_regs, 897 isMove, getRegUsage, mapRegs, 898 genSpill, genReload, directReload, 899 guest_sizeB, 900 ppInstr, ppReg, mode64 ); 901 902 vexAllocSanityCheck(); 903 904 if (vex_traceflags & VEX_TRACE_RCODE) { 905 vex_printf("\n------------------------" 906 " Register-allocated code " 907 "------------------------\n\n"); 908 for (i = 0; i < rcode->arr_used; i++) { 909 vex_printf("%3d ", i); 910 ppInstr(rcode->arr[i], mode64); 911 vex_printf("\n"); 912 } 913 vex_printf("\n"); 914 } 915 916 /* HACK */ 917 if (0) { 918 *(vta->host_bytes_used) = 0; 919 res.status = VexTransOK; return res; 920 } 921 /* end HACK */ 922 923 /* Assemble */ 924 if (vex_traceflags & VEX_TRACE_ASM) { 925 vex_printf("\n------------------------" 926 " Assembly " 927 "------------------------\n\n"); 928 } 929 930 out_used = 0; /* tracks along the host_bytes array */ 931 for (i = 0; i < rcode->arr_used; i++) { 932 HInstr* hi = rcode->arr[i]; 933 Bool hi_isProfInc = False; 934 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { 935 ppInstr(hi, mode64); 936 vex_printf("\n"); 937 } 938 j = emit( &hi_isProfInc, 939 insn_bytes, sizeof insn_bytes, hi, mode64, 940 vta->disp_cp_chain_me_to_slowEP, 941 vta->disp_cp_chain_me_to_fastEP, 942 vta->disp_cp_xindir, 943 vta->disp_cp_xassisted ); 944 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { 945 for (k = 0; k < j; k++) 946 if (insn_bytes[k] < 16) 947 vex_printf("0%x ", (UInt)insn_bytes[k]); 948 else 949 vex_printf("%x ", (UInt)insn_bytes[k]); 950 vex_printf("\n\n"); 951 } 952 if (UNLIKELY(out_used + j > vta->host_bytes_size)) { 953 vexSetAllocModeTEMP_and_clear(); 954 vex_traceflags = 0; 955 res.status = VexTransOutputFull; 956 return res; 957 } 958 if (UNLIKELY(hi_isProfInc)) { 959 vassert(vta->addProfInc); /* else where did it come from? */ 960 vassert(res.offs_profInc == -1); /* there can be only one (tm) */ 961 vassert(out_used >= 0); 962 res.offs_profInc = out_used; 963 } 964 { UChar* dst = &vta->host_bytes[out_used]; 965 for (k = 0; k < j; k++) { 966 dst[k] = insn_bytes[k]; 967 } 968 out_used += j; 969 } 970 vassert(out_used <= vta->host_bytes_size); 971 } 972 *(vta->host_bytes_used) = out_used; 973 974 vexAllocSanityCheck(); 975 976 vexSetAllocModeTEMP_and_clear(); 977 978 if (vex_traceflags) { 979 /* Print the expansion ratio for this SB. */ 980 j = 0; /* total guest bytes */ 981 for (i = 0; i < vta->guest_extents->n_used; i++) { 982 j += vta->guest_extents->len[i]; 983 } 984 if (1) vex_printf("VexExpansionRatio %d %d %d :10\n\n", 985 j, out_used, (10 * out_used) / (j == 0 ? 1 : j)); 986 } 987 988 vex_traceflags = 0; 989 res.status = VexTransOK; 990 return res; 991 } 992 993 994 /* --------- Chain/Unchain XDirects. --------- */ 995 996 VexInvalRange LibVEX_Chain ( VexArch arch_host, 997 void* place_to_chain, 998 void* disp_cp_chain_me_EXPECTED, 999 void* place_to_jump_to ) 1000 { 1001 VexInvalRange (*chainXDirect)(void*, void*, void*) = NULL; 1002 switch (arch_host) { 1003 case VexArchX86: 1004 chainXDirect = chainXDirect_X86; break; 1005 case VexArchAMD64: 1006 chainXDirect = chainXDirect_AMD64; break; 1007 case VexArchARM: 1008 chainXDirect = chainXDirect_ARM; break; 1009 case VexArchARM64: 1010 chainXDirect = chainXDirect_ARM64; break; 1011 case VexArchS390X: 1012 chainXDirect = chainXDirect_S390; break; 1013 case VexArchPPC32: 1014 return chainXDirect_PPC(place_to_chain, 1015 disp_cp_chain_me_EXPECTED, 1016 place_to_jump_to, False/*!mode64*/); 1017 case VexArchPPC64: 1018 return chainXDirect_PPC(place_to_chain, 1019 disp_cp_chain_me_EXPECTED, 1020 place_to_jump_to, True/*mode64*/); 1021 case VexArchMIPS32: 1022 return chainXDirect_MIPS(place_to_chain, 1023 disp_cp_chain_me_EXPECTED, 1024 place_to_jump_to, False/*!mode64*/); 1025 case VexArchMIPS64: 1026 return chainXDirect_MIPS(place_to_chain, 1027 disp_cp_chain_me_EXPECTED, 1028 place_to_jump_to, True/*!mode64*/); 1029 default: 1030 vassert(0); 1031 } 1032 vassert(chainXDirect); 1033 VexInvalRange vir 1034 = chainXDirect(place_to_chain, disp_cp_chain_me_EXPECTED, 1035 place_to_jump_to); 1036 return vir; 1037 } 1038 1039 VexInvalRange LibVEX_UnChain ( VexArch arch_host, 1040 void* place_to_unchain, 1041 void* place_to_jump_to_EXPECTED, 1042 void* disp_cp_chain_me ) 1043 { 1044 VexInvalRange (*unchainXDirect)(void*, void*, void*) = NULL; 1045 switch (arch_host) { 1046 case VexArchX86: 1047 unchainXDirect = unchainXDirect_X86; break; 1048 case VexArchAMD64: 1049 unchainXDirect = unchainXDirect_AMD64; break; 1050 case VexArchARM: 1051 unchainXDirect = unchainXDirect_ARM; break; 1052 case VexArchARM64: 1053 unchainXDirect = unchainXDirect_ARM64; break; 1054 case VexArchS390X: 1055 unchainXDirect = unchainXDirect_S390; break; 1056 case VexArchPPC32: 1057 return unchainXDirect_PPC(place_to_unchain, 1058 place_to_jump_to_EXPECTED, 1059 disp_cp_chain_me, False/*!mode64*/); 1060 case VexArchPPC64: 1061 return unchainXDirect_PPC(place_to_unchain, 1062 place_to_jump_to_EXPECTED, 1063 disp_cp_chain_me, True/*mode64*/); 1064 case VexArchMIPS32: 1065 return unchainXDirect_MIPS(place_to_unchain, 1066 place_to_jump_to_EXPECTED, 1067 disp_cp_chain_me, False/*!mode64*/); 1068 case VexArchMIPS64: 1069 return unchainXDirect_MIPS(place_to_unchain, 1070 place_to_jump_to_EXPECTED, 1071 disp_cp_chain_me, True/*!mode64*/); 1072 default: 1073 vassert(0); 1074 } 1075 vassert(unchainXDirect); 1076 VexInvalRange vir 1077 = unchainXDirect(place_to_unchain, place_to_jump_to_EXPECTED, 1078 disp_cp_chain_me); 1079 return vir; 1080 } 1081 1082 Int LibVEX_evCheckSzB ( VexArch arch_host ) 1083 { 1084 static Int cached = 0; /* DO NOT MAKE NON-STATIC */ 1085 if (UNLIKELY(cached == 0)) { 1086 switch (arch_host) { 1087 case VexArchX86: 1088 cached = evCheckSzB_X86(); break; 1089 case VexArchAMD64: 1090 cached = evCheckSzB_AMD64(); break; 1091 case VexArchARM: 1092 cached = evCheckSzB_ARM(); break; 1093 case VexArchARM64: 1094 cached = evCheckSzB_ARM64(); break; 1095 case VexArchS390X: 1096 cached = evCheckSzB_S390(); break; 1097 case VexArchPPC32: 1098 case VexArchPPC64: 1099 cached = evCheckSzB_PPC(); break; 1100 case VexArchMIPS32: 1101 case VexArchMIPS64: 1102 cached = evCheckSzB_MIPS(); break; 1103 default: 1104 vassert(0); 1105 } 1106 } 1107 return cached; 1108 } 1109 1110 VexInvalRange LibVEX_PatchProfInc ( VexArch arch_host, 1111 void* place_to_patch, 1112 ULong* location_of_counter ) 1113 { 1114 VexInvalRange (*patchProfInc)(void*,ULong*) = NULL; 1115 switch (arch_host) { 1116 case VexArchX86: 1117 patchProfInc = patchProfInc_X86; break; 1118 case VexArchAMD64: 1119 patchProfInc = patchProfInc_AMD64; break; 1120 case VexArchARM: 1121 patchProfInc = patchProfInc_ARM; break; 1122 case VexArchS390X: 1123 patchProfInc = patchProfInc_S390; break; 1124 case VexArchPPC32: 1125 return patchProfInc_PPC(place_to_patch, 1126 location_of_counter, False/*!mode64*/); 1127 case VexArchPPC64: 1128 return patchProfInc_PPC(place_to_patch, 1129 location_of_counter, True/*mode64*/); 1130 case VexArchMIPS32: 1131 return patchProfInc_MIPS(place_to_patch, 1132 location_of_counter, False/*!mode64*/); 1133 case VexArchMIPS64: 1134 return patchProfInc_MIPS(place_to_patch, 1135 location_of_counter, True/*!mode64*/); 1136 default: 1137 vassert(0); 1138 } 1139 vassert(patchProfInc); 1140 VexInvalRange vir 1141 = patchProfInc(place_to_patch, location_of_counter); 1142 return vir; 1143 } 1144 1145 1146 /* --------- Emulation warnings. --------- */ 1147 1148 const HChar* LibVEX_EmNote_string ( VexEmNote ew ) 1149 { 1150 switch (ew) { 1151 case EmNote_NONE: 1152 return "none"; 1153 case EmWarn_X86_x87exns: 1154 return "Unmasking x87 FP exceptions"; 1155 case EmWarn_X86_x87precision: 1156 return "Selection of non-80-bit x87 FP precision"; 1157 case EmWarn_X86_sseExns: 1158 return "Unmasking SSE FP exceptions"; 1159 case EmWarn_X86_fz: 1160 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)"; 1161 case EmWarn_X86_daz: 1162 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)"; 1163 case EmWarn_X86_acFlag: 1164 return "Setting %eflags.ac (setting noted but ignored)"; 1165 case EmWarn_PPCexns: 1166 return "Unmasking PPC32/64 FP exceptions"; 1167 case EmWarn_PPC64_redir_overflow: 1168 return "PPC64 function redirection stack overflow"; 1169 case EmWarn_PPC64_redir_underflow: 1170 return "PPC64 function redirection stack underflow"; 1171 case EmWarn_S390X_fpext_rounding: 1172 return "The specified rounding mode cannot be supported. That\n" 1173 " feature requires the floating point extension facility.\n" 1174 " which is not available on this host. Continuing using\n" 1175 " the rounding mode from FPC. Results may differ!"; 1176 case EmWarn_S390X_invalid_rounding: 1177 return "The specified rounding mode is invalid.\n" 1178 " Continuing using 'round to nearest'. Results may differ!"; 1179 case EmFail_S390X_stfle: 1180 return "Instruction stfle is not supported on this host"; 1181 case EmFail_S390X_stckf: 1182 return "Instruction stckf is not supported on this host"; 1183 case EmFail_S390X_ecag: 1184 return "Instruction ecag is not supported on this host"; 1185 case EmFail_S390X_fpext: 1186 return "Encountered an instruction that requires the floating " 1187 "point extension facility.\n" 1188 " That facility is not available on this host"; 1189 case EmFail_S390X_invalid_PFPO_rounding_mode: 1190 return "The rounding mode specified in GPR 0 for PFPO instruction" 1191 " is invalid"; 1192 case EmFail_S390X_invalid_PFPO_function: 1193 return "The function code specified in GPR 0 for PFPO instruction" 1194 " is invalid"; 1195 default: 1196 vpanic("LibVEX_EmNote_string: unknown warning"); 1197 } 1198 } 1199 1200 /* ------------------ Arch/HwCaps stuff. ------------------ */ 1201 1202 const HChar* LibVEX_ppVexArch ( VexArch arch ) 1203 { 1204 switch (arch) { 1205 case VexArch_INVALID: return "INVALID"; 1206 case VexArchX86: return "X86"; 1207 case VexArchAMD64: return "AMD64"; 1208 case VexArchARM: return "ARM"; 1209 case VexArchARM64: return "ARM64"; 1210 case VexArchPPC32: return "PPC32"; 1211 case VexArchPPC64: return "PPC64"; 1212 case VexArchS390X: return "S390X"; 1213 case VexArchMIPS32: return "MIPS32"; 1214 case VexArchMIPS64: return "MIPS64"; 1215 default: return "VexArch???"; 1216 } 1217 } 1218 1219 const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps ) 1220 { 1221 const HChar* str = show_hwcaps(arch,hwcaps); 1222 return str ? str : "INVALID"; 1223 } 1224 1225 1226 /* Write default settings info *vai. */ 1227 void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai ) 1228 { 1229 vex_bzero(vai, sizeof(*vai)); 1230 vai->hwcaps = 0; 1231 vai->ppc_icache_line_szB = 0; 1232 vai->ppc_dcbz_szB = 0; 1233 vai->ppc_dcbzl_szB = 0; 1234 vai->arm64_dMinLine_lg2_szB = 0; 1235 vai->arm64_iMinLine_lg2_szB = 0; 1236 vai->hwcache_info.num_levels = 0; 1237 vai->hwcache_info.num_caches = 0; 1238 vai->hwcache_info.caches = NULL; 1239 vai->hwcache_info.icaches_maintain_coherence = True; // whatever 1240 } 1241 1242 /* Write default settings info *vbi. */ 1243 void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi ) 1244 { 1245 vex_bzero(vbi, sizeof(*vbi)); 1246 vbi->guest_stack_redzone_size = 0; 1247 vbi->guest_amd64_assume_fs_is_zero = False; 1248 vbi->guest_amd64_assume_gs_is_0x60 = False; 1249 vbi->guest_ppc_zap_RZ_at_blr = False; 1250 vbi->guest_ppc_zap_RZ_at_bl = NULL; 1251 vbi->guest_ppc_sc_continues_at_LR = False; 1252 vbi->host_ppc_calls_use_fndescrs = False; 1253 vbi->host_ppc32_regalign_int64_args = False; 1254 } 1255 1256 1257 /* Return a string showing the hwcaps in a nice way. The string will 1258 be NULL for invalid combinations of flags, so these functions also 1259 serve as a way to validate hwcaps values. */ 1260 1261 static const HChar* show_hwcaps_x86 ( UInt hwcaps ) 1262 { 1263 /* Monotonic, LZCNT > SSE3 > SSE2 > SSE1 > MMXEXT > baseline. */ 1264 switch (hwcaps) { 1265 case 0: 1266 return "x86-sse0"; 1267 case VEX_HWCAPS_X86_MMXEXT: 1268 return "x86-mmxext"; 1269 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1: 1270 return "x86-mmxext-sse1"; 1271 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2: 1272 return "x86-mmxext-sse1-sse2"; 1273 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2 1274 | VEX_HWCAPS_X86_LZCNT: 1275 return "x86-mmxext-sse1-sse2-lzcnt"; 1276 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2 1277 | VEX_HWCAPS_X86_SSE3: 1278 return "x86-mmxext-sse1-sse2-sse3"; 1279 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2 1280 | VEX_HWCAPS_X86_SSE3 | VEX_HWCAPS_X86_LZCNT: 1281 return "x86-mmxext-sse1-sse2-sse3-lzcnt"; 1282 default: 1283 return NULL; 1284 } 1285 } 1286 1287 static const HChar* show_hwcaps_amd64 ( UInt hwcaps ) 1288 { 1289 /* SSE3 and CX16 are orthogonal and > baseline, although we really 1290 don't expect to come across anything which can do SSE3 but can't 1291 do CX16. Still, we can handle that case. LZCNT is similarly 1292 orthogonal. */ 1293 1294 /* Throw out obviously stupid cases: */ 1295 Bool have_sse3 = (hwcaps & VEX_HWCAPS_AMD64_SSE3) != 0; 1296 Bool have_avx = (hwcaps & VEX_HWCAPS_AMD64_AVX) != 0; 1297 Bool have_bmi = (hwcaps & VEX_HWCAPS_AMD64_BMI) != 0; 1298 Bool have_avx2 = (hwcaps & VEX_HWCAPS_AMD64_AVX2) != 0; 1299 /* AVX without SSE3 */ 1300 if (have_avx && !have_sse3) 1301 return NULL; 1302 /* AVX2 or BMI without AVX */ 1303 if ((have_avx2 || have_bmi) && !have_avx) 1304 return NULL; 1305 1306 /* This isn't threadsafe. We might need to fix it at some point. */ 1307 static HChar buf[100] = { 0 }; 1308 if (buf[0] != 0) return buf; /* already constructed */ 1309 1310 vex_bzero(buf, sizeof(buf)); 1311 1312 HChar* p = &buf[0]; 1313 1314 p = p + vex_sprintf(p, "%s", "amd64"); 1315 if (hwcaps == 0) { 1316 /* special-case the baseline case */ 1317 p = p + vex_sprintf(p, "%s", "-sse2"); 1318 goto out; 1319 } 1320 if (hwcaps & VEX_HWCAPS_AMD64_CX16) { 1321 p = p + vex_sprintf(p, "%s", "-cx16"); 1322 } 1323 if (hwcaps & VEX_HWCAPS_AMD64_LZCNT) { 1324 p = p + vex_sprintf(p, "%s", "-lzcnt"); 1325 } 1326 if (hwcaps & VEX_HWCAPS_AMD64_RDTSCP) { 1327 p = p + vex_sprintf(p, "%s", "-rdtscp"); 1328 } 1329 if (hwcaps & VEX_HWCAPS_AMD64_SSE3) { 1330 p = p + vex_sprintf(p, "%s", "-sse3"); 1331 } 1332 if (hwcaps & VEX_HWCAPS_AMD64_AVX) { 1333 p = p + vex_sprintf(p, "%s", "-avx"); 1334 } 1335 if (hwcaps & VEX_HWCAPS_AMD64_AVX2) { 1336 p = p + vex_sprintf(p, "%s", "-avx2"); 1337 } 1338 if (hwcaps & VEX_HWCAPS_AMD64_BMI) { 1339 p = p + vex_sprintf(p, "%s", "-bmi"); 1340 } 1341 1342 out: 1343 vassert(buf[sizeof(buf)-1] == 0); 1344 return buf; 1345 } 1346 1347 static const HChar* show_hwcaps_ppc32 ( UInt hwcaps ) 1348 { 1349 /* Monotonic with complications. Basically V > F > baseline, 1350 but once you have F then you can have FX or GX too. */ 1351 const UInt F = VEX_HWCAPS_PPC32_F; 1352 const UInt V = VEX_HWCAPS_PPC32_V; 1353 const UInt FX = VEX_HWCAPS_PPC32_FX; 1354 const UInt GX = VEX_HWCAPS_PPC32_GX; 1355 const UInt VX = VEX_HWCAPS_PPC32_VX; 1356 const UInt DFP = VEX_HWCAPS_PPC32_DFP; 1357 const UInt ISA2_07 = VEX_HWCAPS_PPC32_ISA2_07; 1358 UInt c = hwcaps; 1359 if (c == 0) return "ppc32-int"; 1360 if (c == F) return "ppc32-int-flt"; 1361 if (c == (F|FX)) return "ppc32-int-flt-FX"; 1362 if (c == (F|GX)) return "ppc32-int-flt-GX"; 1363 if (c == (F|FX|GX)) return "ppc32-int-flt-FX-GX"; 1364 if (c == (F|V)) return "ppc32-int-flt-vmx"; 1365 if (c == (F|V|FX)) return "ppc32-int-flt-vmx-FX"; 1366 if (c == (F|V|GX)) return "ppc32-int-flt-vmx-GX"; 1367 if (c == (F|V|FX|GX)) return "ppc32-int-flt-vmx-FX-GX"; 1368 if (c == (F|V|FX|GX|DFP)) return "ppc32-int-flt-vmx-FX-GX-DFP"; 1369 if (c == (F|V|FX|GX|VX|DFP)) return "ppc32-int-flt-vmx-FX-GX-VX-DFP"; 1370 if (c == (F|V|FX|GX|VX|DFP|ISA2_07)) 1371 return "ppc32-int-flt-vmx-FX-GX-VX-DFP-ISA2_07"; 1372 1373 return NULL; 1374 } 1375 1376 static const HChar* show_hwcaps_ppc64 ( UInt hwcaps ) 1377 { 1378 /* Monotonic with complications. Basically V > baseline(==F), 1379 but once you have F then you can have FX or GX too. */ 1380 const UInt V = VEX_HWCAPS_PPC64_V; 1381 const UInt FX = VEX_HWCAPS_PPC64_FX; 1382 const UInt GX = VEX_HWCAPS_PPC64_GX; 1383 const UInt VX = VEX_HWCAPS_PPC64_VX; 1384 const UInt DFP = VEX_HWCAPS_PPC64_DFP; 1385 const UInt ISA2_07 = VEX_HWCAPS_PPC64_ISA2_07; 1386 UInt c = hwcaps; 1387 if (c == 0) return "ppc64-int-flt"; 1388 if (c == FX) return "ppc64-int-flt-FX"; 1389 if (c == GX) return "ppc64-int-flt-GX"; 1390 if (c == (FX|GX)) return "ppc64-int-flt-FX-GX"; 1391 if (c == V) return "ppc64-int-flt-vmx"; 1392 if (c == (V|FX)) return "ppc64-int-flt-vmx-FX"; 1393 if (c == (V|GX)) return "ppc64-int-flt-vmx-GX"; 1394 if (c == (V|FX|GX)) return "ppc64-int-flt-vmx-FX-GX"; 1395 if (c == (V|FX|GX|DFP)) return "ppc64-int-flt-vmx-FX-GX-DFP"; 1396 if (c == (V|FX|GX|VX|DFP)) return "ppc64-int-flt-vmx-FX-GX-VX-DFP"; 1397 if (c == (V|FX|GX|VX|DFP|ISA2_07)) 1398 return "ppc64-int-flt-vmx-FX-GX-VX-DFP-ISA2_07"; 1399 return NULL; 1400 } 1401 1402 static const HChar* show_hwcaps_arm ( UInt hwcaps ) 1403 { 1404 Bool N = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0); 1405 Bool vfp = ((hwcaps & (VEX_HWCAPS_ARM_VFP | 1406 VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3)) != 0); 1407 switch (VEX_ARM_ARCHLEVEL(hwcaps)) { 1408 case 5: 1409 if (N) 1410 return NULL; 1411 if (vfp) 1412 return "ARMv5-vfp"; 1413 else 1414 return "ARMv5"; 1415 return NULL; 1416 case 6: 1417 if (N) 1418 return NULL; 1419 if (vfp) 1420 return "ARMv6-vfp"; 1421 else 1422 return "ARMv6"; 1423 return NULL; 1424 case 7: 1425 if (vfp) { 1426 if (N) 1427 return "ARMv7-vfp-neon"; 1428 else 1429 return "ARMv7-vfp"; 1430 } else { 1431 if (N) 1432 return "ARMv7-neon"; 1433 else 1434 return "ARMv7"; 1435 } 1436 default: 1437 return NULL; 1438 } 1439 return NULL; 1440 } 1441 1442 static const HChar* show_hwcaps_arm64 ( UInt hwcaps ) 1443 { 1444 /* Since there are no variants, just insist that hwcaps is zero, 1445 and declare it invalid otherwise. */ 1446 if (hwcaps == 0) 1447 return "baseline"; 1448 return NULL; 1449 } 1450 1451 static const HChar* show_hwcaps_s390x ( UInt hwcaps ) 1452 { 1453 static const HChar prefix[] = "s390x"; 1454 static const struct { 1455 UInt hwcaps_bit; 1456 HChar name[6]; 1457 } hwcaps_list[] = { 1458 { VEX_HWCAPS_S390X_LDISP, "ldisp" }, 1459 { VEX_HWCAPS_S390X_EIMM, "eimm" }, 1460 { VEX_HWCAPS_S390X_GIE, "gie" }, 1461 { VEX_HWCAPS_S390X_DFP, "dfp" }, 1462 { VEX_HWCAPS_S390X_FGX, "fgx" }, 1463 { VEX_HWCAPS_S390X_STFLE, "stfle" }, 1464 { VEX_HWCAPS_S390X_ETF2, "etf2" }, 1465 { VEX_HWCAPS_S390X_ETF3, "etf3" }, 1466 { VEX_HWCAPS_S390X_STCKF, "stckf" }, 1467 { VEX_HWCAPS_S390X_FPEXT, "fpext" }, 1468 { VEX_HWCAPS_S390X_LSC, "lsc" }, 1469 { VEX_HWCAPS_S390X_PFPO, "pfpo" }, 1470 }; 1471 #define NUM_HWCAPS (sizeof hwcaps_list / sizeof hwcaps_list[0]) 1472 static HChar buf[sizeof prefix + 1473 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1474 1]; // '\0' 1475 HChar *p; 1476 UInt i; 1477 1478 if (buf[0] != '\0') return buf; /* already constructed */ 1479 1480 hwcaps = VEX_HWCAPS_S390X(hwcaps); 1481 1482 p = buf + vex_sprintf(buf, "%s", prefix); 1483 for (i = 0 ; i < NUM_HWCAPS; ++i) { 1484 if (hwcaps & hwcaps_list[i].hwcaps_bit) 1485 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name); 1486 } 1487 1488 /* If there are no facilities, add "zarch" */ 1489 if (hwcaps == 0) 1490 vex_sprintf(p, "-%s", "zarch"); 1491 1492 return buf; 1493 } 1494 1495 static const HChar* show_hwcaps_mips32 ( UInt hwcaps ) 1496 { 1497 /* MIPS baseline. */ 1498 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_MIPS) { 1499 /* MIPS baseline with dspr2. */ 1500 if (VEX_MIPS_PROC_DSP2(hwcaps)) { 1501 return "MIPS-baseline-dspr2"; 1502 } 1503 /* MIPS baseline with dsp. */ 1504 if (VEX_MIPS_PROC_DSP(hwcaps)) { 1505 return "MIPS-baseline-dsp"; 1506 } 1507 return "MIPS-baseline"; 1508 } 1509 1510 /* Broadcom baseline. */ 1511 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_BROADCOM) { 1512 return "Broadcom-baseline"; 1513 } 1514 1515 /* Netlogic baseline. */ 1516 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_NETLOGIC) { 1517 return "Netlogic-baseline"; 1518 } 1519 1520 /* Cavium baseline. */ 1521 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_CAVIUM) { 1522 return "Cavium-baseline"; 1523 } 1524 1525 return NULL; 1526 } 1527 1528 static const HChar* show_hwcaps_mips64 ( UInt hwcaps ) 1529 { 1530 return "mips64-baseline"; 1531 } 1532 1533 /* ---- */ 1534 static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps ) 1535 { 1536 switch (arch) { 1537 case VexArchX86: return show_hwcaps_x86(hwcaps); 1538 case VexArchAMD64: return show_hwcaps_amd64(hwcaps); 1539 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps); 1540 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps); 1541 case VexArchARM: return show_hwcaps_arm(hwcaps); 1542 case VexArchARM64: return show_hwcaps_arm64(hwcaps); 1543 case VexArchS390X: return show_hwcaps_s390x(hwcaps); 1544 case VexArchMIPS32: return show_hwcaps_mips32(hwcaps); 1545 case VexArchMIPS64: return show_hwcaps_mips64(hwcaps); 1546 default: return NULL; 1547 } 1548 } 1549 1550 static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps ) 1551 { 1552 return show_hwcaps(arch,hwcaps) != NULL; 1553 } 1554 1555 1556 /*---------------------------------------------------------------*/ 1557 /*--- end main_main.c ---*/ 1558 /*---------------------------------------------------------------*/ 1559