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