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