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"
43 #include "libvex_guest_s390x.h"
45 #include "main_globals.h"
46 #include "main_util.h"
47 #include "host_generic_regs.h"
50 #include "host_x86_defs.h"
51 #include "host_amd64_defs.h"
52 #include "host_ppc_defs.h"
53 #include "host_arm_defs.h"
54 #include "host_s390_defs.h"
56 #include "guest_generic_bb_to_IR.h"
57 #include "guest_x86_defs.h"
58 #include "guest_amd64_defs.h"
59 #include "guest_arm_defs.h"
60 #include "guest_ppc_defs.h"
61 #include "guest_s390_defs.h"
63 #include "host_generic_simd128.h"
66 /* This file contains the top level interface to the library. */
68 /* --------- fwds ... --------- */
70 static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps );
71 static HChar* show_hwcaps ( VexArch arch, UInt hwcaps );
74 /* --------- Initialise the library. --------- */
76 /* Exported to library client. */
78 void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon )
80 vcon->iropt_verbosity = 0;
81 vcon->iropt_level = 2;
82 vcon->iropt_precise_memory_exns = False;
83 vcon->iropt_unroll_thresh = 120;
84 vcon->guest_max_insns = 60;
85 vcon->guest_chase_thresh = 10;
86 vcon->guest_chase_cond = False;
90 /* Exported to library client. */
93 /* failure exit function */
94 __attribute__ ((noreturn))
95 void (*failure_exit) ( void ),
96 /* logging output function */
97 void (*log_bytes) ( HChar*, Int nbytes ),
98 /* debug paranoia level */
100 /* Are we supporting valgrind checking? */
101 Bool valgrind_support,
103 /*READONLY*/VexControl* vcon
106 /* First off, do enough minimal setup so that the following
107 assertions can fail in a sane fashion, if need be. */
108 vex_failure_exit = failure_exit;
109 vex_log_bytes = log_bytes;
111 /* Now it's safe to check parameters for sanity. */
112 vassert(!vex_initdone);
113 vassert(failure_exit);
115 vassert(debuglevel >= 0);
117 vassert(vcon->iropt_verbosity >= 0);
118 vassert(vcon->iropt_level >= 0);
119 vassert(vcon->iropt_level <= 2);
120 vassert(vcon->iropt_unroll_thresh >= 0);
121 vassert(vcon->iropt_unroll_thresh <= 400);
122 vassert(vcon->guest_max_insns >= 1);
123 vassert(vcon->guest_max_insns <= 100);
124 vassert(vcon->guest_chase_thresh >= 0);
125 vassert(vcon->guest_chase_thresh < vcon->guest_max_insns);
126 vassert(vcon->guest_chase_cond == True
127 || vcon->guest_chase_cond == False);
129 /* Check that Vex has been built with sizes of basic types as
130 stated in priv/libvex_basictypes.h. Failure of any of these is
131 a serious configuration error and should be corrected
132 immediately. If any of these assertions fail you can fully
133 expect Vex not to work properly, if at all. */
135 vassert(1 == sizeof(UChar));
136 vassert(1 == sizeof(Char));
137 vassert(2 == sizeof(UShort));
138 vassert(2 == sizeof(Short));
139 vassert(4 == sizeof(UInt));
140 vassert(4 == sizeof(Int));
141 vassert(8 == sizeof(ULong));
142 vassert(8 == sizeof(Long));
143 vassert(4 == sizeof(Float));
144 vassert(8 == sizeof(Double));
145 vassert(1 == sizeof(Bool));
146 vassert(4 == sizeof(Addr32));
147 vassert(8 == sizeof(Addr64));
148 vassert(16 == sizeof(U128));
149 vassert(16 == sizeof(V128));
151 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
152 vassert(sizeof(void*) == sizeof(int*));
153 vassert(sizeof(void*) == sizeof(HWord));
155 vassert(VEX_HOST_WORDSIZE == sizeof(void*));
156 vassert(VEX_HOST_WORDSIZE == sizeof(HWord));
158 /* Really start up .. */
159 vex_debuglevel = debuglevel;
160 vex_valgrind_support = valgrind_support;
163 vexSetAllocMode ( VexAllocModeTEMP );
167 /* --------- Make a translation. --------- */
169 /* Exported to library client. */
171 VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
173 /* This the bundle of functions we need to do the back-end stuff
174 (insn selection, reg-alloc, assembly) whilst being insulated
175 from the target instruction set. */
176 HReg* available_real_regs;
177 Int n_available_real_regs;
178 Bool (*isMove) ( HInstr*, HReg*, HReg* );
179 void (*getRegUsage) ( HRegUsage*, HInstr*, Bool );
180 void (*mapRegs) ( HRegRemap*, HInstr*, Bool );
181 void (*genSpill) ( HInstr**, HInstr**, HReg, Int, Bool );
182 void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool );
183 HInstr* (*directReload) ( HInstr*, HReg, Short );
184 void (*ppInstr) ( HInstr*, Bool );
185 void (*ppReg) ( HReg );
186 HInstrArray* (*iselSB) ( IRSB*, VexArch, VexArchInfo*,
188 Int (*emit) ( UChar*, Int, HInstr*, Bool, void* );
189 IRExpr* (*specHelper) ( HChar*, IRExpr**, IRStmt**, Int );
190 Bool (*preciseMemExnsFn) ( Int, Int );
192 DisOneInstrFn disInstrFn;
194 VexGuestLayout* guest_layout;
195 Bool host_is_bigendian = False;
199 Int i, j, k, out_used, guest_sizeB;
200 Int offB_TISTART, offB_TILEN;
201 UChar insn_bytes[48];
202 IRType guest_word_type;
203 IRType host_word_type;
207 available_real_regs = NULL;
208 n_available_real_regs = 0;
220 preciseMemExnsFn = NULL;
222 guest_word_type = Ity_INVALID;
223 host_word_type = Ity_INVALID;
228 vex_traceflags = vta->traceflags;
230 vassert(vex_initdone);
231 vexSetAllocModeTEMP_and_clear();
232 vexAllocSanityCheck();
234 /* First off, check that the guest and host insn sets
237 switch (vta->arch_host) {
241 getAllocableRegs_X86 ( &n_available_real_regs,
242 &available_real_regs );
243 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
244 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
245 getRegUsage_X86Instr;
246 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_X86Instr;
247 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
249 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
251 directReload = (HInstr*(*)(HInstr*,HReg,Short)) directReload_X86;
252 ppInstr = (void(*)(HInstr*, Bool)) ppX86Instr;
253 ppReg = (void(*)(HReg)) ppHRegX86;
255 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_X86Instr;
256 host_is_bigendian = False;
257 host_word_type = Ity_I32;
258 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_host.hwcaps));
259 vassert(vta->dispatch != NULL); /* jump-to-dispatcher scheme */
264 getAllocableRegs_AMD64 ( &n_available_real_regs,
265 &available_real_regs );
266 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr;
267 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
268 getRegUsage_AMD64Instr;
269 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_AMD64Instr;
270 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
272 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
274 ppInstr = (void(*)(HInstr*, Bool)) ppAMD64Instr;
275 ppReg = (void(*)(HReg)) ppHRegAMD64;
276 iselSB = iselSB_AMD64;
277 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_AMD64Instr;
278 host_is_bigendian = False;
279 host_word_type = Ity_I64;
280 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_host.hwcaps));
281 vassert(vta->dispatch != NULL); /* jump-to-dispatcher scheme */
286 getAllocableRegs_PPC ( &n_available_real_regs,
287 &available_real_regs, mode64 );
288 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
289 getRegUsage = (void(*)(HRegUsage*,HInstr*,Bool)) getRegUsage_PPCInstr;
290 mapRegs = (void(*)(HRegRemap*,HInstr*,Bool)) mapRegs_PPCInstr;
291 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
292 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
293 ppInstr = (void(*)(HInstr*,Bool)) ppPPCInstr;
294 ppReg = (void(*)(HReg)) ppHRegPPC;
296 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_PPCInstr;
297 host_is_bigendian = True;
298 host_word_type = Ity_I32;
299 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_host.hwcaps));
300 vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
305 getAllocableRegs_PPC ( &n_available_real_regs,
306 &available_real_regs, mode64 );
307 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
308 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_PPCInstr;
309 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_PPCInstr;
310 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
311 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
312 ppInstr = (void(*)(HInstr*, Bool)) ppPPCInstr;
313 ppReg = (void(*)(HReg)) ppHRegPPC;
315 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_PPCInstr;
316 host_is_bigendian = True;
317 host_word_type = Ity_I64;
318 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_host.hwcaps));
319 vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
324 getAllocableRegs_S390 ( &n_available_real_regs,
325 &available_real_regs, mode64 );
326 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_S390Instr;
327 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_S390Instr;
328 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_S390Instr;
329 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_S390;
330 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_S390;
331 ppInstr = (void(*)(HInstr*, Bool)) ppS390Instr;
332 ppReg = (void(*)(HReg)) ppHRegS390;
333 iselSB = iselSB_S390;
334 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_S390Instr;
335 host_is_bigendian = True;
336 host_word_type = Ity_I64;
337 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_host.hwcaps));
338 vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
343 getAllocableRegs_ARM ( &n_available_real_regs,
344 &available_real_regs );
345 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARMInstr;
346 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_ARMInstr;
347 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_ARMInstr;
348 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_ARM;
349 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_ARM;
350 ppInstr = (void(*)(HInstr*, Bool)) ppARMInstr;
351 ppReg = (void(*)(HReg)) ppHRegARM;
353 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_ARMInstr;
354 host_is_bigendian = False;
355 host_word_type = Ity_I32;
356 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_host.hwcaps));
357 vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
361 vpanic("LibVEX_Translate: unsupported host insn set");
365 switch (vta->arch_guest) {
368 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
369 disInstrFn = disInstr_X86;
370 specHelper = guest_x86_spechelper;
371 guest_sizeB = sizeof(VexGuestX86State);
372 guest_word_type = Ity_I32;
373 guest_layout = &x86guest_layout;
374 offB_TISTART = offsetof(VexGuestX86State,guest_TISTART);
375 offB_TILEN = offsetof(VexGuestX86State,guest_TILEN);
376 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_guest.hwcaps));
377 vassert(0 == sizeof(VexGuestX86State) % 16);
378 vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART) == 4);
379 vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
380 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
384 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
385 disInstrFn = disInstr_AMD64;
386 specHelper = guest_amd64_spechelper;
387 guest_sizeB = sizeof(VexGuestAMD64State);
388 guest_word_type = Ity_I64;
389 guest_layout = &amd64guest_layout;
390 offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART);
391 offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN);
392 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_guest.hwcaps));
393 vassert(0 == sizeof(VexGuestAMD64State) % 16);
394 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8);
395 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
396 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8);
400 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
401 disInstrFn = disInstr_PPC;
402 specHelper = guest_ppc32_spechelper;
403 guest_sizeB = sizeof(VexGuestPPC32State);
404 guest_word_type = Ity_I32;
405 guest_layout = &ppc32Guest_layout;
406 offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART);
407 offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN);
408 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_guest.hwcaps));
409 vassert(0 == sizeof(VexGuestPPC32State) % 16);
410 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4);
411 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
412 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4);
416 preciseMemExnsFn = guest_ppc64_state_requires_precise_mem_exns;
417 disInstrFn = disInstr_PPC;
418 specHelper = guest_ppc64_spechelper;
419 guest_sizeB = sizeof(VexGuestPPC64State);
420 guest_word_type = Ity_I64;
421 guest_layout = &ppc64Guest_layout;
422 offB_TISTART = offsetof(VexGuestPPC64State,guest_TISTART);
423 offB_TILEN = offsetof(VexGuestPPC64State,guest_TILEN);
424 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_guest.hwcaps));
425 vassert(0 == sizeof(VexGuestPPC64State) % 16);
426 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TISTART ) == 8);
427 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TILEN ) == 8);
428 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8);
429 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8);
433 preciseMemExnsFn = guest_s390x_state_requires_precise_mem_exns;
434 disInstrFn = disInstr_S390;
435 specHelper = guest_s390x_spechelper;
436 guest_sizeB = sizeof(VexGuestS390XState);
437 guest_word_type = Ity_I64;
438 guest_layout = &s390xGuest_layout;
439 offB_TISTART = offsetof(VexGuestS390XState,guest_TISTART);
440 offB_TILEN = offsetof(VexGuestS390XState,guest_TILEN);
441 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_guest.hwcaps));
442 vassert(0 == sizeof(VexGuestS390XState) % 16);
443 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TISTART ) == 8);
444 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TILEN ) == 8);
445 vassert(sizeof( ((VexGuestS390XState*)0)->guest_NRADDR ) == 8);
449 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
450 disInstrFn = disInstr_ARM;
451 specHelper = guest_arm_spechelper;
452 guest_sizeB = sizeof(VexGuestARMState);
453 guest_word_type = Ity_I32;
454 guest_layout = &armGuest_layout;
455 offB_TISTART = offsetof(VexGuestARMState,guest_TISTART);
456 offB_TILEN = offsetof(VexGuestARMState,guest_TILEN);
457 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_guest.hwcaps));
458 vassert(0 == sizeof(VexGuestARMState) % 16);
459 vassert(sizeof( ((VexGuestARMState*)0)->guest_TISTART) == 4);
460 vassert(sizeof( ((VexGuestARMState*)0)->guest_TILEN ) == 4);
461 vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4);
465 vpanic("LibVEX_Translate: unsupported guest insn set");
468 /* yet more sanity checks ... */
469 if (vta->arch_guest == vta->arch_host) {
470 /* doesn't necessarily have to be true, but if it isn't it means
471 we are simulating one flavour of an architecture a different
472 flavour of the same architecture, which is pretty strange. */
473 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps);
476 vexAllocSanityCheck();
478 if (vex_traceflags & VEX_TRACE_FE)
479 vex_printf("\n------------------------"
481 "------------------------\n\n");
483 irsb = bb_to_IR ( vta->guest_extents,
484 vta->callback_opaque,
487 vta->guest_bytes_addr,
491 &vta->archinfo_guest,
495 vta->preamble_function,
499 vexAllocSanityCheck();
502 /* Access failure. */
503 vexSetAllocModeTEMP_and_clear();
505 return VexTransAccessFail;
508 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3);
509 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr);
510 for (i = 0; i < vta->guest_extents->n_used; i++) {
511 vassert(vta->guest_extents->len[i] < 10000); /* sanity */
514 /* If debugging, show the raw guest bytes for this bb. */
515 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
516 if (vta->guest_extents->n_used > 1) {
517 vex_printf("can't show code due to extents > 1\n");
520 UChar* p = (UChar*)vta->guest_bytes;
522 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0];
523 vex_printf("GuestBytes %llx %u ", vta->guest_bytes_addr,
525 for (i = 0; i < guest_bytes_read; i++) {
527 vex_printf(" %02x", b );
528 sum = (sum << 1) ^ b;
530 vex_printf(" %08x\n\n", sum);
534 /* Sanity check the initial IR. */
535 sanityCheckIRSB( irsb, "initial IR",
536 False/*can be non-flat*/, guest_word_type );
538 vexAllocSanityCheck();
540 /* Clean it up, hopefully a lot. */
541 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn,
542 vta->guest_bytes_addr,
544 sanityCheckIRSB( irsb, "after initial iropt",
545 True/*must be flat*/, guest_word_type );
547 if (vex_traceflags & VEX_TRACE_OPT1) {
548 vex_printf("\n------------------------"
549 " After pre-instr IR optimisation "
550 "------------------------\n\n");
555 vexAllocSanityCheck();
557 /* Get the thing instrumented. */
558 if (vta->instrument1)
559 irsb = vta->instrument1(vta->callback_opaque,
562 guest_word_type, host_word_type);
563 vexAllocSanityCheck();
565 if (vta->instrument2)
566 irsb = vta->instrument2(vta->callback_opaque,
569 guest_word_type, host_word_type);
571 if (vex_traceflags & VEX_TRACE_INST) {
572 vex_printf("\n------------------------"
573 " After instrumentation "
574 "------------------------\n\n");
579 if (vta->instrument1 || vta->instrument2)
580 sanityCheckIRSB( irsb, "after instrumentation",
581 True/*must be flat*/, guest_word_type );
583 /* Do a post-instrumentation cleanup pass. */
584 if (vta->instrument1 || vta->instrument2) {
585 do_deadcode_BB( irsb );
586 irsb = cprop_BB( irsb );
587 do_deadcode_BB( irsb );
588 sanityCheckIRSB( irsb, "after post-instrumentation cleanup",
589 True/*must be flat*/, guest_word_type );
592 vexAllocSanityCheck();
594 if (vex_traceflags & VEX_TRACE_OPT2) {
595 vex_printf("\n------------------------"
596 " After post-instr IR optimisation "
597 "------------------------\n\n");
602 /* Turn it into virtual-registerised code. Build trees -- this
603 also throws away any dead bindings. */
604 ado_treebuild_BB( irsb );
606 if (vta->finaltidy) {
607 irsb = vta->finaltidy(irsb);
610 vexAllocSanityCheck();
612 if (vex_traceflags & VEX_TRACE_TREES) {
613 vex_printf("\n------------------------"
614 " After tree-building "
615 "------------------------\n\n");
621 if (0) { *(vta->host_bytes_used) = 0; return VexTransOK; }
624 if (vex_traceflags & VEX_TRACE_VCODE)
625 vex_printf("\n------------------------"
626 " Instruction selection "
627 "------------------------\n");
629 vcode = iselSB ( irsb, vta->arch_host, &vta->archinfo_host,
630 &vta->abiinfo_both );
632 vexAllocSanityCheck();
634 if (vex_traceflags & VEX_TRACE_VCODE)
637 if (vex_traceflags & VEX_TRACE_VCODE) {
638 for (i = 0; i < vcode->arr_used; i++) {
639 vex_printf("%3d ", i);
640 ppInstr(vcode->arr[i], mode64);
646 /* Register allocate. */
647 rcode = doRegisterAllocation ( vcode, available_real_regs,
648 n_available_real_regs,
649 isMove, getRegUsage, mapRegs,
650 genSpill, genReload, directReload,
652 ppInstr, ppReg, mode64 );
654 vexAllocSanityCheck();
656 if (vex_traceflags & VEX_TRACE_RCODE) {
657 vex_printf("\n------------------------"
658 " Register-allocated code "
659 "------------------------\n\n");
660 for (i = 0; i < rcode->arr_used; i++) {
661 vex_printf("%3d ", i);
662 ppInstr(rcode->arr[i], mode64);
669 if (0) { *(vta->host_bytes_used) = 0; return VexTransOK; }
673 if (vex_traceflags & VEX_TRACE_ASM) {
674 vex_printf("\n------------------------"
676 "------------------------\n\n");
679 out_used = 0; /* tracks along the host_bytes array */
680 for (i = 0; i < rcode->arr_used; i++) {
681 if (vex_traceflags & VEX_TRACE_ASM) {
682 ppInstr(rcode->arr[i], mode64);
685 j = (*emit)( insn_bytes, sizeof insn_bytes, rcode->arr[i], mode64,
687 if (vex_traceflags & VEX_TRACE_ASM) {
688 for (k = 0; k < j; k++)
689 if (insn_bytes[k] < 16)
690 vex_printf("0%x ", (UInt)insn_bytes[k]);
692 vex_printf("%x ", (UInt)insn_bytes[k]);
695 if (out_used + j > vta->host_bytes_size) {
696 vexSetAllocModeTEMP_and_clear();
698 return VexTransOutputFull;
700 for (k = 0; k < j; k++) {
701 vta->host_bytes[out_used] = insn_bytes[k];
704 vassert(out_used <= vta->host_bytes_size);
706 *(vta->host_bytes_used) = out_used;
708 vexAllocSanityCheck();
710 vexSetAllocModeTEMP_and_clear();
717 /* --------- Emulation warnings. --------- */
719 HChar* LibVEX_EmWarn_string ( VexEmWarn ew )
724 case EmWarn_X86_x87exns:
725 return "Unmasking x87 FP exceptions";
726 case EmWarn_X86_x87precision:
727 return "Selection of non-80-bit x87 FP precision";
728 case EmWarn_X86_sseExns:
729 return "Unmasking SSE FP exceptions";
731 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
733 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
734 case EmWarn_X86_acFlag:
735 return "Setting %eflags.ac (setting noted but ignored)";
737 return "Unmasking PPC32/64 FP exceptions";
738 case EmWarn_PPC64_redir_overflow:
739 return "PPC64 function redirection stack overflow";
740 case EmWarn_PPC64_redir_underflow:
741 return "PPC64 function redirection stack underflow";
743 vpanic("LibVEX_EmWarn_string: unknown warning");
747 /* ------------------ Arch/HwCaps stuff. ------------------ */
749 const HChar* LibVEX_ppVexArch ( VexArch arch )
752 case VexArch_INVALID: return "INVALID";
753 case VexArchX86: return "X86";
754 case VexArchAMD64: return "AMD64";
755 case VexArchARM: return "ARM";
756 case VexArchPPC32: return "PPC32";
757 case VexArchPPC64: return "PPC64";
758 case VexArchS390X: return "S390X";
759 default: return "VexArch???";
763 const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
765 HChar* str = show_hwcaps(arch,hwcaps);
766 return str ? str : "INVALID";
770 /* Write default settings info *vai. */
771 void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
774 vai->ppc_cache_line_szB = 0;
775 vai->ppc_dcbz_szB = 0;
776 vai->ppc_dcbzl_szB = 0;
780 /* Write default settings info *vbi. */
781 void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
783 vbi->guest_stack_redzone_size = 0;
784 vbi->guest_amd64_assume_fs_is_zero = False;
785 vbi->guest_amd64_assume_gs_is_0x60 = False;
786 vbi->guest_ppc_zap_RZ_at_blr = False;
787 vbi->guest_ppc_zap_RZ_at_bl = NULL;
788 vbi->guest_ppc_sc_continues_at_LR = False;
789 vbi->host_ppc_calls_use_fndescrs = False;
790 vbi->host_ppc32_regalign_int64_args = False;
794 /* Return a string showing the hwcaps in a nice way. The string will
795 be NULL for invalid combinations of flags, so these functions also
796 serve as a way to validate hwcaps values. */
798 static HChar* show_hwcaps_x86 ( UInt hwcaps )
800 /* Monotonic, SSE3 > SSE2 > SSE1 > baseline. */
804 case VEX_HWCAPS_X86_SSE1:
806 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2:
807 return "x86-sse1-sse2";
808 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
809 | VEX_HWCAPS_X86_LZCNT:
810 return "x86-sse1-sse2-lzcnt";
811 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
812 | VEX_HWCAPS_X86_SSE3:
813 return "x86-sse1-sse2-sse3";
814 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
815 | VEX_HWCAPS_X86_SSE3 | VEX_HWCAPS_X86_LZCNT:
816 return "x86-sse1-sse2-sse3-lzcnt";
822 static HChar* show_hwcaps_amd64 ( UInt hwcaps )
824 /* SSE3 and CX16 are orthogonal and > baseline, although we really
825 don't expect to come across anything which can do SSE3 but can't
826 do CX16. Still, we can handle that case. LZCNT is similarly
831 case VEX_HWCAPS_AMD64_SSE3:
833 case VEX_HWCAPS_AMD64_CX16:
834 return "amd64-sse2-cx16";
835 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16:
836 return "amd64-sse3-cx16";
837 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_LZCNT:
838 return "amd64-sse3-lzcnt";
839 case VEX_HWCAPS_AMD64_CX16 | VEX_HWCAPS_AMD64_LZCNT:
840 return "amd64-sse2-cx16-lzcnt";
841 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16
842 | VEX_HWCAPS_AMD64_LZCNT:
843 return "amd64-sse3-cx16-lzcnt";
850 static HChar* show_hwcaps_ppc32 ( UInt hwcaps )
852 /* Monotonic with complications. Basically V > F > baseline,
853 but once you have F then you can have FX or GX too. */
854 const UInt F = VEX_HWCAPS_PPC32_F;
855 const UInt V = VEX_HWCAPS_PPC32_V;
856 const UInt FX = VEX_HWCAPS_PPC32_FX;
857 const UInt GX = VEX_HWCAPS_PPC32_GX;
858 const UInt VX = VEX_HWCAPS_PPC32_VX;
860 if (c == 0) return "ppc32-int";
861 if (c == F) return "ppc32-int-flt";
862 if (c == (F|FX)) return "ppc32-int-flt-FX";
863 if (c == (F|GX)) return "ppc32-int-flt-GX";
864 if (c == (F|FX|GX)) return "ppc32-int-flt-FX-GX";
865 if (c == (F|V)) return "ppc32-int-flt-vmx";
866 if (c == (F|V|FX)) return "ppc32-int-flt-vmx-FX";
867 if (c == (F|V|GX)) return "ppc32-int-flt-vmx-GX";
868 if (c == (F|V|FX|GX)) return "ppc32-int-flt-vmx-FX-GX";
869 if (c == (F|V|FX|GX|VX)) return "ppc32-int-flt-vmx-FX-GX-VX";
873 static HChar* show_hwcaps_ppc64 ( UInt hwcaps )
875 /* Monotonic with complications. Basically V > baseline(==F),
876 but once you have F then you can have FX or GX too. */
877 const UInt V = VEX_HWCAPS_PPC64_V;
878 const UInt FX = VEX_HWCAPS_PPC64_FX;
879 const UInt GX = VEX_HWCAPS_PPC64_GX;
880 const UInt VX = VEX_HWCAPS_PPC64_VX;
882 if (c == 0) return "ppc64-int-flt";
883 if (c == FX) return "ppc64-int-flt-FX";
884 if (c == GX) return "ppc64-int-flt-GX";
885 if (c == (FX|GX)) return "ppc64-int-flt-FX-GX";
886 if (c == V) return "ppc64-int-flt-vmx";
887 if (c == (V|FX)) return "ppc64-int-flt-vmx-FX";
888 if (c == (V|GX)) return "ppc64-int-flt-vmx-GX";
889 if (c == (V|FX|GX)) return "ppc64-int-flt-vmx-FX-GX";
890 if (c == (V|FX|GX|VX)) return "ppc64-int-flt-vmx-FX-GX-VX";
894 static HChar* show_hwcaps_arm ( UInt hwcaps )
896 Bool N = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0);
897 Bool vfp = ((hwcaps & (VEX_HWCAPS_ARM_VFP |
898 VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3)) != 0);
899 switch (VEX_ARM_ARCHLEVEL(hwcaps)) {
919 return "ARMv7-vfp-neon";
934 static HChar* show_hwcaps_s390x ( UInt hwcaps )
936 static const HChar prefix[] = "s390x";
937 static const HChar facilities[][6] = {
944 static HChar buf[sizeof facilities + sizeof prefix + 1];
947 if (buf[0] != '\0') return buf; /* already constructed */
949 hwcaps = VEX_HWCAPS_S390X(hwcaps);
951 p = buf + vex_sprintf(buf, "%s", prefix);
952 if (hwcaps & VEX_HWCAPS_S390X_LDISP)
953 p = p + vex_sprintf(p, "-%s", facilities[0]);
954 if (hwcaps & VEX_HWCAPS_S390X_EIMM)
955 p = p + vex_sprintf(p, "-%s", facilities[1]);
956 if (hwcaps & VEX_HWCAPS_S390X_GIE)
957 p = p + vex_sprintf(p, "-%s", facilities[2]);
958 if (hwcaps & VEX_HWCAPS_S390X_DFP)
959 p = p + vex_sprintf(p, "-%s", facilities[3]);
960 if (hwcaps & VEX_HWCAPS_S390X_FGX)
961 p = p + vex_sprintf(p, "-%s", facilities[4]);
963 /* If there are no facilities, add "zarch" */
965 vex_sprintf(p, "-%s", "zarch");
971 static HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
974 case VexArchX86: return show_hwcaps_x86(hwcaps);
975 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
976 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
977 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
978 case VexArchARM: return show_hwcaps_arm(hwcaps);
979 case VexArchS390X: return show_hwcaps_s390x(hwcaps);
980 default: return NULL;
984 static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps )
986 return show_hwcaps(arch,hwcaps) != NULL;
990 /*---------------------------------------------------------------*/
991 /*--- end main_main.c ---*/
992 /*---------------------------------------------------------------*/