2 /*---------------------------------------------------------------*/
3 /*--- begin main_main.c ---*/
4 /*---------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2004-2010 OpenWorks LLP
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.
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.
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
28 The GNU General Public License is contained in the file COPYING.
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.
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"
44 #include "main_globals.h"
45 #include "main_util.h"
46 #include "host_generic_regs.h"
49 #include "host_x86_defs.h"
50 #include "host_amd64_defs.h"
51 #include "host_ppc_defs.h"
52 #include "host_arm_defs.h"
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"
60 #include "host_generic_simd128.h"
63 /* This file contains the top level interface to the library. */
65 /* --------- fwds ... --------- */
67 static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps );
68 static HChar* show_hwcaps ( VexArch arch, UInt hwcaps );
71 /* --------- Initialise the library. --------- */
73 /* Exported to library client. */
75 void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon )
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;
87 /* Exported to library client. */
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 */
97 /* Are we supporting valgrind checking? */
98 Bool valgrind_support,
100 /*READONLY*/VexControl* vcon
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;
108 /* Now it's safe to check parameters for sanity. */
109 vassert(!vex_initdone);
110 vassert(failure_exit);
112 vassert(debuglevel >= 0);
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);
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. */
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));
148 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
149 vassert(sizeof(void*) == sizeof(int*));
150 vassert(sizeof(void*) == sizeof(HWord));
152 vassert(VEX_HOST_WORDSIZE == sizeof(void*));
153 vassert(VEX_HOST_WORDSIZE == sizeof(HWord));
155 /* Really start up .. */
156 vex_debuglevel = debuglevel;
157 vex_valgrind_support = valgrind_support;
160 vexSetAllocMode ( VexAllocModeTEMP );
164 /* --------- Make a translation. --------- */
166 /* Exported to library client. */
168 VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
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*,
185 Int (*emit) ( UChar*, Int, HInstr*, Bool, void* );
186 IRExpr* (*specHelper) ( HChar*, IRExpr**, IRStmt**, Int );
187 Bool (*preciseMemExnsFn) ( Int, Int );
189 DisOneInstrFn disInstrFn;
191 VexGuestLayout* guest_layout;
192 Bool host_is_bigendian = False;
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;
204 available_real_regs = NULL;
205 n_available_real_regs = 0;
217 preciseMemExnsFn = NULL;
219 guest_word_type = Ity_INVALID;
220 host_word_type = Ity_INVALID;
225 vex_traceflags = vta->traceflags;
227 vassert(vex_initdone);
228 vexSetAllocModeTEMP_and_clear();
229 vexAllocSanityCheck();
231 /* First off, check that the guest and host insn sets
234 switch (vta->arch_host) {
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))
246 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
248 directReload = (HInstr*(*)(HInstr*,HReg,Short)) directReload_X86;
249 ppInstr = (void(*)(HInstr*, Bool)) ppX86Instr;
250 ppReg = (void(*)(HReg)) ppHRegX86;
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 */
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))
269 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
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 */
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;
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 */
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;
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 */
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;
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 */
339 vpanic("LibVEX_Translate: unsupported host insn set");
343 switch (vta->arch_guest) {
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);
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);
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);
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);
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);
427 vpanic("LibVEX_Translate: unsupported guest insn set");
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);
438 vexAllocSanityCheck();
440 if (vex_traceflags & VEX_TRACE_FE)
441 vex_printf("\n------------------------"
443 "------------------------\n\n");
445 irsb = bb_to_IR ( vta->guest_extents,
446 vta->callback_opaque,
449 vta->guest_bytes_addr,
453 &vta->archinfo_guest,
457 vta->preamble_function,
461 vexAllocSanityCheck();
464 /* Access failure. */
465 vexSetAllocModeTEMP_and_clear();
467 return VexTransAccessFail;
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 */
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");
482 UChar* p = (UChar*)vta->guest_bytes;
484 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0];
485 vex_printf("GuestBytes %llx %u ", vta->guest_bytes_addr,
487 for (i = 0; i < guest_bytes_read; i++) {
489 vex_printf(" %02x", b );
490 sum = (sum << 1) ^ b;
492 vex_printf(" %08x\n\n", sum);
496 /* Sanity check the initial IR. */
497 sanityCheckIRSB( irsb, "initial IR",
498 False/*can be non-flat*/, guest_word_type );
500 vexAllocSanityCheck();
502 /* Clean it up, hopefully a lot. */
503 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn,
504 vta->guest_bytes_addr,
506 sanityCheckIRSB( irsb, "after initial iropt",
507 True/*must be flat*/, guest_word_type );
509 if (vex_traceflags & VEX_TRACE_OPT1) {
510 vex_printf("\n------------------------"
511 " After pre-instr IR optimisation "
512 "------------------------\n\n");
517 vexAllocSanityCheck();
519 /* Get the thing instrumented. */
520 if (vta->instrument1)
521 irsb = vta->instrument1(vta->callback_opaque,
524 guest_word_type, host_word_type);
525 vexAllocSanityCheck();
527 if (vta->instrument2)
528 irsb = vta->instrument2(vta->callback_opaque,
531 guest_word_type, host_word_type);
533 if (vex_traceflags & VEX_TRACE_INST) {
534 vex_printf("\n------------------------"
535 " After instrumentation "
536 "------------------------\n\n");
541 if (vta->instrument1 || vta->instrument2)
542 sanityCheckIRSB( irsb, "after instrumentation",
543 True/*must be flat*/, guest_word_type );
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 );
554 vexAllocSanityCheck();
556 if (vex_traceflags & VEX_TRACE_OPT2) {
557 vex_printf("\n------------------------"
558 " After post-instr IR optimisation "
559 "------------------------\n\n");
564 /* Turn it into virtual-registerised code. Build trees -- this
565 also throws away any dead bindings. */
566 ado_treebuild_BB( irsb );
568 if (vta->finaltidy) {
569 irsb = vta->finaltidy(irsb);
572 vexAllocSanityCheck();
574 if (vex_traceflags & VEX_TRACE_TREES) {
575 vex_printf("\n------------------------"
576 " After tree-building "
577 "------------------------\n\n");
583 if (0) { *(vta->host_bytes_used) = 0; return VexTransOK; }
586 if (vex_traceflags & VEX_TRACE_VCODE)
587 vex_printf("\n------------------------"
588 " Instruction selection "
589 "------------------------\n");
591 vcode = iselSB ( irsb, vta->arch_host, &vta->archinfo_host,
592 &vta->abiinfo_both );
594 vexAllocSanityCheck();
596 if (vex_traceflags & VEX_TRACE_VCODE)
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);
608 /* Register allocate. */
609 rcode = doRegisterAllocation ( vcode, available_real_regs,
610 n_available_real_regs,
611 isMove, getRegUsage, mapRegs,
612 genSpill, genReload, directReload,
614 ppInstr, ppReg, mode64 );
616 vexAllocSanityCheck();
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);
631 if (0) { *(vta->host_bytes_used) = 0; return VexTransOK; }
635 if (vex_traceflags & VEX_TRACE_ASM) {
636 vex_printf("\n------------------------"
638 "------------------------\n\n");
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);
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]);
653 vex_printf("%x ", (UInt)insn_bytes[k]);
656 if (out_used + j > vta->host_bytes_size) {
657 vexSetAllocModeTEMP_and_clear();
659 return VexTransOutputFull;
661 for (k = 0; k < j; k++) {
662 vta->host_bytes[out_used] = insn_bytes[k];
665 vassert(out_used <= vta->host_bytes_size);
667 *(vta->host_bytes_used) = out_used;
669 vexAllocSanityCheck();
671 vexSetAllocModeTEMP_and_clear();
678 /* --------- Emulation warnings. --------- */
680 HChar* LibVEX_EmWarn_string ( VexEmWarn ew )
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";
692 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
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)";
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";
704 vpanic("LibVEX_EmWarn_string: unknown warning");
708 /* ------------------ Arch/HwCaps stuff. ------------------ */
710 const HChar* LibVEX_ppVexArch ( VexArch 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???";
723 const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
725 HChar* str = show_hwcaps(arch,hwcaps);
726 return str ? str : "INVALID";
730 /* Write default settings info *vai. */
731 void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
734 vai->ppc_cache_line_szB = 0;
735 vai->ppc_dcbz_szB = 0;
736 vai->ppc_dcbzl_szB = 0;
740 /* Write default settings info *vbi. */
741 void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
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;
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. */
758 static HChar* show_hwcaps_x86 ( UInt hwcaps )
760 /* Monotonic, SSE3 > SSE2 > SSE1 > baseline. */
764 case VEX_HWCAPS_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";
782 static HChar* show_hwcaps_amd64 ( UInt hwcaps )
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
791 case VEX_HWCAPS_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";
810 static HChar* show_hwcaps_ppc32 ( UInt hwcaps )
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;
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";
831 static HChar* show_hwcaps_ppc64 ( UInt hwcaps )
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;
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";
850 static HChar* show_hwcaps_arm ( UInt hwcaps )
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)) {
875 return "ARMv7-vfp-neon";
891 static HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
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;
903 static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps )
905 return show_hwcaps(arch,hwcaps) != NULL;
909 /*---------------------------------------------------------------*/
910 /*--- end main_main.c ---*/
911 /*---------------------------------------------------------------*/