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