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