1/* -*- mode: C; c-basic-offset: 3; -*- */
2
3/*---------------------------------------------------------------*/
4/*--- Begin                                       main_main.c ---*/
5/*---------------------------------------------------------------*/
6
7/*
8   This file is part of Valgrind, a dynamic binary instrumentation
9   framework.
10
11   Copyright (C) 2004-2013 OpenWorks LLP
12      info@open-works.net
13
14   This program is free software; you can redistribute it and/or
15   modify it under the terms of the GNU General Public License as
16   published by the Free Software Foundation; either version 2 of the
17   License, or (at your option) any later version.
18
19   This program is distributed in the hope that it will be useful, but
20   WITHOUT ANY WARRANTY; without even the implied warranty of
21   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22   General Public License for more details.
23
24   You should have received a copy of the GNU General Public License
25   along with this program; if not, write to the Free Software
26   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27   02110-1301, USA.
28
29   The GNU General Public License is contained in the file COPYING.
30
31   Neither the names of the U.S. Department of Energy nor the
32   University of California nor the names of its contributors may be
33   used to endorse or promote products derived from this software
34   without prior written permission.
35*/
36
37#include "libvex.h"
38#include "libvex_emnote.h"
39#include "libvex_guest_x86.h"
40#include "libvex_guest_amd64.h"
41#include "libvex_guest_arm.h"
42#include "libvex_guest_arm64.h"
43#include "libvex_guest_ppc32.h"
44#include "libvex_guest_ppc64.h"
45#include "libvex_guest_s390x.h"
46#include "libvex_guest_mips32.h"
47#include "libvex_guest_mips64.h"
48#include "libvex_guest_tilegx.h"
49
50#include "main_globals.h"
51#include "main_util.h"
52#include "host_generic_regs.h"
53#include "ir_opt.h"
54
55#include "host_x86_defs.h"
56#include "host_amd64_defs.h"
57#include "host_ppc_defs.h"
58#include "host_arm_defs.h"
59#include "host_arm64_defs.h"
60#include "host_s390_defs.h"
61#include "host_mips_defs.h"
62#include "host_tilegx_defs.h"
63
64#include "guest_generic_bb_to_IR.h"
65#include "guest_x86_defs.h"
66#include "guest_amd64_defs.h"
67#include "guest_arm_defs.h"
68#include "guest_arm64_defs.h"
69#include "guest_ppc_defs.h"
70#include "guest_s390_defs.h"
71#include "guest_mips_defs.h"
72#include "guest_tilegx_defs.h"
73
74#include "host_generic_simd128.h"
75
76/* For each architecture <arch>, we define 2 macros:
77   <arch>FN that has as argument a pointer (typically to a function
78            or the return value of a function).
79   <arch>ST that has as argument a statement.
80   If main_main.c is compiled for <arch>, then these macros just expand
81   their arg.
82   Otherwise, the macros expand to respectively NULL and vassert(0).
83   These macros are used to avoid introducing dependencies to object
84   files not needed for the (only) architecture we are compiling for.
85
86   To still compile the below for all supported architectures, define
87   VEXMULTIARCH. This is used by the file multiarch_main_main.c */
88
89#if defined(VGA_x86) || defined(VEXMULTIARCH)
90#define X86FN(f) f
91#define X86ST(f) f
92#else
93#define X86FN(f) NULL
94#define X86ST(f) vassert(0)
95#endif
96
97#if defined(VGA_amd64) || defined(VEXMULTIARCH)
98#define AMD64FN(f) f
99#define AMD64ST(f) f
100#else
101#define AMD64FN(f) NULL
102#define AMD64ST(f) vassert(0)
103#endif
104
105#if defined(VGA_ppc32) || defined(VEXMULTIARCH)
106#define PPC32FN(f) f
107#define PPC32ST(f) f
108#else
109#define PPC32FN(f) NULL
110#define PPC32ST(f) vassert(0)
111#endif
112
113#if defined(VGA_ppc64be) || defined(VGA_ppc64le) || defined(VEXMULTIARCH)
114#define PPC64FN(f) f
115#define PPC64ST(f) f
116#else
117#define PPC64FN(f) NULL
118#define PPC64ST(f) vassert(0)
119#endif
120
121#if defined(VGA_s390x) || defined(VEXMULTIARCH)
122#define S390FN(f) f
123#define S390ST(f) f
124#else
125#define S390FN(f) NULL
126#define S390ST(f) vassert(0)
127#endif
128
129#if defined(VGA_arm) || defined(VEXMULTIARCH)
130#define ARMFN(f) f
131#define ARMST(f) f
132#else
133#define ARMFN(f) NULL
134#define ARMST(f) vassert(0)
135#endif
136
137#if defined(VGA_arm64) || defined(VEXMULTIARCH)
138#define ARM64FN(f) f
139#define ARM64ST(f) f
140#else
141#define ARM64FN(f) NULL
142#define ARM64ST(f) vassert(0)
143#endif
144
145#if defined(VGA_mips32) || defined(VEXMULTIARCH)
146#define MIPS32FN(f) f
147#define MIPS32ST(f) f
148#else
149#define MIPS32FN(f) NULL
150#define MIPS32ST(f) vassert(0)
151#endif
152
153#if defined(VGA_mips64) || defined(VEXMULTIARCH)
154#define MIPS64FN(f) f
155#define MIPS64ST(f) f
156#else
157#define MIPS64FN(f) NULL
158#define MIPS64ST(f) vassert(0)
159#endif
160
161#if defined(VGA_tilegx) || defined(VEXMULTIARCH)
162#define TILEGXFN(f) f
163#define TILEGXST(f) f
164#else
165#define TILEGXFN(f) NULL
166#define TILEGXST(f) vassert(0)
167#endif
168
169
170/* This file contains the top level interface to the library. */
171
172/* --------- fwds ... --------- */
173
174static void  check_hwcaps ( VexArch arch, UInt hwcaps );
175static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps );
176
177
178/* --------- helpers --------- */
179
180__attribute__((noinline))
181static UInt udiv32 ( UInt x, UInt y ) { return x/y; }
182__attribute__((noinline))
183static  Int sdiv32 (  Int x,  Int y ) { return x/y; }
184
185
186/* --------- Initialise the library. --------- */
187
188/* Exported to library client. */
189
190void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon )
191{
192   vex_bzero(vcon, sizeof(*vcon));
193   vcon->iropt_verbosity                = 0;
194   vcon->iropt_level                    = 2;
195   vcon->iropt_register_updates_default = VexRegUpdUnwindregsAtMemAccess;
196   vcon->iropt_unroll_thresh            = 120;
197   vcon->guest_max_insns                = 60;
198   vcon->guest_chase_thresh             = 10;
199   vcon->guest_chase_cond               = False;
200}
201
202
203/* Exported to library client. */
204
205void LibVEX_Init (
206   /* failure exit function */
207   __attribute__ ((noreturn))
208   void (*failure_exit) ( void ),
209   /* logging output function */
210   void (*log_bytes) ( const HChar*, SizeT nbytes ),
211   /* debug paranoia level */
212   Int debuglevel,
213   /* Control ... */
214   const VexControl* vcon
215)
216{
217   /* First off, do enough minimal setup so that the following
218      assertions can fail in a sane fashion, if need be. */
219   vex_failure_exit = failure_exit;
220   vex_log_bytes    = log_bytes;
221
222   /* Now it's safe to check parameters for sanity. */
223   vassert(!vex_initdone);
224   vassert(failure_exit);
225   vassert(log_bytes);
226   vassert(debuglevel >= 0);
227
228   vassert(vcon->iropt_verbosity >= 0);
229   vassert(vcon->iropt_level >= 0);
230   vassert(vcon->iropt_level <= 2);
231   vassert(vcon->iropt_unroll_thresh >= 0);
232   vassert(vcon->iropt_unroll_thresh <= 400);
233   vassert(vcon->guest_max_insns >= 1);
234   vassert(vcon->guest_max_insns <= 100);
235   vassert(vcon->guest_chase_thresh >= 0);
236   vassert(vcon->guest_chase_thresh < vcon->guest_max_insns);
237   vassert(vcon->guest_chase_cond == True
238           || vcon->guest_chase_cond == False);
239
240   /* Check that Vex has been built with sizes of basic types as
241      stated in priv/libvex_basictypes.h.  Failure of any of these is
242      a serious configuration error and should be corrected
243      immediately.  If any of these assertions fail you can fully
244      expect Vex not to work properly, if at all. */
245
246   vassert(1 == sizeof(UChar));
247   vassert(1 == sizeof(Char));
248   vassert(2 == sizeof(UShort));
249   vassert(2 == sizeof(Short));
250   vassert(4 == sizeof(UInt));
251   vassert(4 == sizeof(Int));
252   vassert(8 == sizeof(ULong));
253   vassert(8 == sizeof(Long));
254   vassert(4 == sizeof(Float));
255   vassert(8 == sizeof(Double));
256   vassert(1 == sizeof(Bool));
257   vassert(4 == sizeof(Addr32));
258   vassert(8 == sizeof(Addr64));
259   vassert(16 == sizeof(U128));
260   vassert(16 == sizeof(V128));
261   vassert(32 == sizeof(U256));
262
263   vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
264   vassert(sizeof(void*) == sizeof(int*));
265   vassert(sizeof(void*) == sizeof(HWord));
266   vassert(sizeof(void*) == sizeof(Addr));
267   vassert(sizeof(unsigned long) == sizeof(SizeT));
268
269   vassert(VEX_HOST_WORDSIZE == sizeof(void*));
270   vassert(VEX_HOST_WORDSIZE == sizeof(HWord));
271
272   /* These take a lot of space, so make sure we don't have
273      any unnoticed size regressions. */
274   if (VEX_HOST_WORDSIZE == 4) {
275      vassert(sizeof(IRExpr) == 16);
276      vassert(sizeof(IRStmt) == 20 /* x86 */
277              || sizeof(IRStmt) == 24 /* arm */);
278   } else {
279      vassert(sizeof(IRExpr) == 32);
280      vassert(sizeof(IRStmt) == 32);
281   }
282
283   /* Ditto */
284   vassert(sizeof(HReg) == 4);
285   /* If N_RREGUNIVERSE_REGS ever exceeds 64, the bitset fields in
286      RRegSet and HRegUsage will need to be changed to something
287      better than ULong. */
288   vassert(N_RREGUNIVERSE_REGS == 64);
289
290   /* Check that signed integer division on the host rounds towards
291      zero.  If not, h_calc_sdiv32_w_arm_semantics() won't work
292      correctly. */
293   /* 100.0 / 7.0 == 14.2857 */
294   vassert(udiv32(100, 7) == 14);
295   vassert(sdiv32(100, 7) == 14);
296   vassert(sdiv32(-100, 7) == -14); /* and not -15 */
297   vassert(sdiv32(100, -7) == -14); /* ditto */
298   vassert(sdiv32(-100, -7) == 14); /* not sure what this proves */
299
300   /* Really start up .. */
301   vex_debuglevel         = debuglevel;
302   vex_control            = *vcon;
303   vex_initdone           = True;
304   vexSetAllocMode ( VexAllocModeTEMP );
305}
306
307
308/* --------- Make a translation. --------- */
309/* KLUDGE: S390 need to know the hwcaps of the host when generating
310   code. But that info is not passed to emit_S390Instr. Only mode64 is
311   being passed. So, ideally, we want this passed as an argument, too.
312   Until then, we use a global variable. This variable is set as a side
313   effect of LibVEX_Translate. The variable is defined here rather than
314   in host_s390_defs.c to avoid having main_main.c dragging S390
315   object files in non VEXMULTIARCH. */
316UInt s390_host_hwcaps;
317
318
319/* Exported to library client. */
320
321VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
322{
323   /* This the bundle of functions we need to do the back-end stuff
324      (insn selection, reg-alloc, assembly) whilst being insulated
325      from the target instruction set. */
326   Bool         (*isMove)       ( const HInstr*, HReg*, HReg* );
327   void         (*getRegUsage)  ( HRegUsage*, const HInstr*, Bool );
328   void         (*mapRegs)      ( HRegRemap*, HInstr*, Bool );
329   void         (*genSpill)     ( HInstr**, HInstr**, HReg, Int, Bool );
330   void         (*genReload)    ( HInstr**, HInstr**, HReg, Int, Bool );
331   HInstr*      (*directReload) ( HInstr*, HReg, Short );
332   void         (*ppInstr)      ( const HInstr*, Bool );
333   void         (*ppReg)        ( HReg );
334   HInstrArray* (*iselSB)       ( const IRSB*, VexArch, const VexArchInfo*,
335                                  const VexAbiInfo*, Int, Int, Bool, Bool,
336                                  Addr );
337   Int          (*emit)         ( /*MB_MOD*/Bool*,
338                                  UChar*, Int, const HInstr*, Bool, VexEndness,
339                                  const void*, const void*, const void*,
340                                  const void* );
341   IRExpr*      (*specHelper)   ( const HChar*, IRExpr**, IRStmt**, Int );
342   Bool         (*preciseMemExnsFn) ( Int, Int, VexRegisterUpdates );
343
344   const RRegUniverse* rRegUniv = NULL;
345
346   DisOneInstrFn disInstrFn;
347
348   VexGuestLayout* guest_layout;
349   IRSB*           irsb;
350   HInstrArray*    vcode;
351   HInstrArray*    rcode;
352   Int             i, j, k, out_used, guest_sizeB;
353   Int             offB_CMSTART, offB_CMLEN, offB_GUEST_IP, szB_GUEST_IP;
354   Int             offB_HOST_EvC_COUNTER, offB_HOST_EvC_FAILADDR;
355   UChar           insn_bytes[128];
356   IRType          guest_word_type;
357   IRType          host_word_type;
358   Bool            mode64, chainingAllowed;
359   Addr            max_ga;
360
361   guest_layout           = NULL;
362   isMove                 = NULL;
363   getRegUsage            = NULL;
364   mapRegs                = NULL;
365   genSpill               = NULL;
366   genReload              = NULL;
367   directReload           = NULL;
368   ppInstr                = NULL;
369   ppReg                  = NULL;
370   iselSB                 = NULL;
371   emit                   = NULL;
372   specHelper             = NULL;
373   preciseMemExnsFn       = NULL;
374   disInstrFn             = NULL;
375   guest_word_type        = Ity_INVALID;
376   host_word_type         = Ity_INVALID;
377   offB_CMSTART           = 0;
378   offB_CMLEN             = 0;
379   offB_GUEST_IP          = 0;
380   szB_GUEST_IP           = 0;
381   offB_HOST_EvC_COUNTER  = 0;
382   offB_HOST_EvC_FAILADDR = 0;
383   mode64                 = False;
384   chainingAllowed        = False;
385
386   vex_traceflags = vta->traceflags;
387
388   vassert(vex_initdone);
389   vassert(vta->needs_self_check  != NULL);
390   vassert(vta->disp_cp_xassisted != NULL);
391   /* Both the chainers and the indir are either NULL or non-NULL. */
392   if (vta->disp_cp_chain_me_to_slowEP        != NULL) {
393      vassert(vta->disp_cp_chain_me_to_fastEP != NULL);
394      vassert(vta->disp_cp_xindir             != NULL);
395      chainingAllowed = True;
396   } else {
397      vassert(vta->disp_cp_chain_me_to_fastEP == NULL);
398      vassert(vta->disp_cp_xindir             == NULL);
399   }
400
401   vexSetAllocModeTEMP_and_clear();
402   vexAllocSanityCheck();
403
404   /* First off, check that the guest and host insn sets
405      are supported. */
406
407   switch (vta->arch_host) {
408
409      case VexArchX86:
410         mode64       = False;
411         rRegUniv     = X86FN(getRRegUniverse_X86());
412         isMove       = (__typeof__(isMove)) X86FN(isMove_X86Instr);
413         getRegUsage
414            = (__typeof__(getRegUsage)) X86FN(getRegUsage_X86Instr);
415         mapRegs      = (__typeof__(mapRegs)) X86FN(mapRegs_X86Instr);
416         genSpill     = (__typeof__(genSpill)) X86FN(genSpill_X86);
417         genReload    = (__typeof__(genReload)) X86FN(genReload_X86);
418         directReload = (__typeof__(directReload)) X86FN(directReload_X86);
419         ppInstr      = (__typeof__(ppInstr)) X86FN(ppX86Instr);
420         ppReg        = (__typeof__(ppReg)) X86FN(ppHRegX86);
421         iselSB       = X86FN(iselSB_X86);
422         emit         = (__typeof__(emit)) X86FN(emit_X86Instr);
423         host_word_type = Ity_I32;
424         vassert(vta->archinfo_host.endness == VexEndnessLE);
425         break;
426
427      case VexArchAMD64:
428         mode64       = True;
429         rRegUniv     = AMD64FN(getRRegUniverse_AMD64());
430         isMove       = (__typeof__(isMove)) AMD64FN(isMove_AMD64Instr);
431         getRegUsage
432            = (__typeof__(getRegUsage)) AMD64FN(getRegUsage_AMD64Instr);
433         mapRegs      = (__typeof__(mapRegs)) AMD64FN(mapRegs_AMD64Instr);
434         genSpill     = (__typeof__(genSpill)) AMD64FN(genSpill_AMD64);
435         genReload    = (__typeof__(genReload)) AMD64FN(genReload_AMD64);
436         ppInstr      = (__typeof__(ppInstr)) AMD64FN(ppAMD64Instr);
437         ppReg        = (__typeof__(ppReg)) AMD64FN(ppHRegAMD64);
438         iselSB       = AMD64FN(iselSB_AMD64);
439         emit         = (__typeof__(emit)) AMD64FN(emit_AMD64Instr);
440         host_word_type = Ity_I64;
441         vassert(vta->archinfo_host.endness == VexEndnessLE);
442         break;
443
444      case VexArchPPC32:
445         mode64       = False;
446         rRegUniv     = PPC32FN(getRRegUniverse_PPC(mode64));
447         isMove       = (__typeof__(isMove)) PPC32FN(isMove_PPCInstr);
448         getRegUsage
449            = (__typeof__(getRegUsage)) PPC32FN(getRegUsage_PPCInstr);
450         mapRegs      = (__typeof__(mapRegs)) PPC32FN(mapRegs_PPCInstr);
451         genSpill     = (__typeof__(genSpill)) PPC32FN(genSpill_PPC);
452         genReload    = (__typeof__(genReload)) PPC32FN(genReload_PPC);
453         ppInstr      = (__typeof__(ppInstr)) PPC32FN(ppPPCInstr);
454         ppReg        = (__typeof__(ppReg)) PPC32FN(ppHRegPPC);
455         iselSB       = PPC32FN(iselSB_PPC);
456         emit         = (__typeof__(emit)) PPC32FN(emit_PPCInstr);
457         host_word_type = Ity_I32;
458         vassert(vta->archinfo_host.endness == VexEndnessBE);
459         break;
460
461      case VexArchPPC64:
462         mode64       = True;
463         rRegUniv     = PPC64FN(getRRegUniverse_PPC(mode64));
464         isMove       = (__typeof__(isMove)) PPC64FN(isMove_PPCInstr);
465         getRegUsage
466            = (__typeof__(getRegUsage)) PPC64FN(getRegUsage_PPCInstr);
467         mapRegs      = (__typeof__(mapRegs)) PPC64FN(mapRegs_PPCInstr);
468         genSpill     = (__typeof__(genSpill)) PPC64FN(genSpill_PPC);
469         genReload    = (__typeof__(genReload)) PPC64FN(genReload_PPC);
470         ppInstr      = (__typeof__(ppInstr)) PPC64FN(ppPPCInstr);
471         ppReg        = (__typeof__(ppReg)) PPC64FN(ppHRegPPC);
472         iselSB       = PPC64FN(iselSB_PPC);
473         emit         = (__typeof__(emit)) PPC64FN(emit_PPCInstr);
474         host_word_type = Ity_I64;
475         vassert(vta->archinfo_host.endness == VexEndnessBE ||
476                 vta->archinfo_host.endness == VexEndnessLE );
477         break;
478
479      case VexArchS390X:
480         mode64       = True;
481         /* KLUDGE: export hwcaps. */
482         s390_host_hwcaps = vta->archinfo_host.hwcaps;
483         rRegUniv     = S390FN(getRRegUniverse_S390());
484         isMove       = (__typeof__(isMove)) S390FN(isMove_S390Instr);
485         getRegUsage
486            = (__typeof__(getRegUsage)) S390FN(getRegUsage_S390Instr);
487         mapRegs      = (__typeof__(mapRegs)) S390FN(mapRegs_S390Instr);
488         genSpill     = (__typeof__(genSpill)) S390FN(genSpill_S390);
489         genReload    = (__typeof__(genReload)) S390FN(genReload_S390);
490         // fixs390: consider implementing directReload_S390
491         ppInstr      = (__typeof__(ppInstr)) S390FN(ppS390Instr);
492         ppReg        = (__typeof__(ppReg)) S390FN(ppHRegS390);
493         iselSB       = S390FN(iselSB_S390);
494         emit         = (__typeof__(emit)) S390FN(emit_S390Instr);
495         host_word_type = Ity_I64;
496         vassert(vta->archinfo_host.endness == VexEndnessBE);
497         break;
498
499      case VexArchARM:
500         mode64       = False;
501         rRegUniv     = ARMFN(getRRegUniverse_ARM());
502         isMove       = (__typeof__(isMove)) ARMFN(isMove_ARMInstr);
503         getRegUsage
504            = (__typeof__(getRegUsage)) ARMFN(getRegUsage_ARMInstr);
505         mapRegs      = (__typeof__(mapRegs)) ARMFN(mapRegs_ARMInstr);
506         genSpill     = (__typeof__(genSpill)) ARMFN(genSpill_ARM);
507         genReload    = (__typeof__(genReload)) ARMFN(genReload_ARM);
508         ppInstr      = (__typeof__(ppInstr)) ARMFN(ppARMInstr);
509         ppReg        = (__typeof__(ppReg)) ARMFN(ppHRegARM);
510         iselSB       = ARMFN(iselSB_ARM);
511         emit         = (__typeof__(emit)) ARMFN(emit_ARMInstr);
512         host_word_type = Ity_I32;
513         vassert(vta->archinfo_host.endness == VexEndnessLE);
514         break;
515
516      case VexArchARM64:
517         mode64       = True;
518         rRegUniv     = ARM64FN(getRRegUniverse_ARM64());
519         isMove       = (__typeof__(isMove)) ARM64FN(isMove_ARM64Instr);
520         getRegUsage
521            = (__typeof__(getRegUsage)) ARM64FN(getRegUsage_ARM64Instr);
522         mapRegs      = (__typeof__(mapRegs)) ARM64FN(mapRegs_ARM64Instr);
523         genSpill     = (__typeof__(genSpill)) ARM64FN(genSpill_ARM64);
524         genReload    = (__typeof__(genReload)) ARM64FN(genReload_ARM64);
525         ppInstr      = (__typeof__(ppInstr)) ARM64FN(ppARM64Instr);
526         ppReg        = (__typeof__(ppReg)) ARM64FN(ppHRegARM64);
527         iselSB       = ARM64FN(iselSB_ARM64);
528         emit         = (__typeof__(emit)) ARM64FN(emit_ARM64Instr);
529         host_word_type = Ity_I64;
530         vassert(vta->archinfo_host.endness == VexEndnessLE);
531         break;
532
533      case VexArchMIPS32:
534         mode64       = False;
535         rRegUniv     = MIPS32FN(getRRegUniverse_MIPS(mode64));
536         isMove       = (__typeof__(isMove)) MIPS32FN(isMove_MIPSInstr);
537         getRegUsage
538            = (__typeof__(getRegUsage)) MIPS32FN(getRegUsage_MIPSInstr);
539         mapRegs      = (__typeof__(mapRegs)) MIPS32FN(mapRegs_MIPSInstr);
540         genSpill     = (__typeof__(genSpill)) MIPS32FN(genSpill_MIPS);
541         genReload    = (__typeof__(genReload)) MIPS32FN(genReload_MIPS);
542         ppInstr      = (__typeof__(ppInstr)) MIPS32FN(ppMIPSInstr);
543         ppReg        = (__typeof__(ppReg)) MIPS32FN(ppHRegMIPS);
544         iselSB       = MIPS32FN(iselSB_MIPS);
545         emit         = (__typeof__(emit)) MIPS32FN(emit_MIPSInstr);
546         host_word_type = Ity_I32;
547         vassert(vta->archinfo_host.endness == VexEndnessLE
548                 || vta->archinfo_host.endness == VexEndnessBE);
549         break;
550
551      case VexArchMIPS64:
552         mode64       = True;
553         rRegUniv     = MIPS64FN(getRRegUniverse_MIPS(mode64));
554         isMove       = (__typeof__(isMove)) MIPS64FN(isMove_MIPSInstr);
555         getRegUsage
556            = (__typeof__(getRegUsage)) MIPS64FN(getRegUsage_MIPSInstr);
557         mapRegs      = (__typeof__(mapRegs)) MIPS64FN(mapRegs_MIPSInstr);
558         genSpill     = (__typeof__(genSpill)) MIPS64FN(genSpill_MIPS);
559         genReload    = (__typeof__(genReload)) MIPS64FN(genReload_MIPS);
560         ppInstr      = (__typeof__(ppInstr)) MIPS64FN(ppMIPSInstr);
561         ppReg        = (__typeof__(ppReg)) MIPS64FN(ppHRegMIPS);
562         iselSB       = MIPS64FN(iselSB_MIPS);
563         emit         = (__typeof__(emit)) MIPS64FN(emit_MIPSInstr);
564         host_word_type = Ity_I64;
565         vassert(vta->archinfo_host.endness == VexEndnessLE
566                 || vta->archinfo_host.endness == VexEndnessBE);
567         break;
568
569      case VexArchTILEGX:
570         mode64      = True;
571         rRegUniv    = TILEGXFN(getRRegUniverse_TILEGX());
572         isMove      = (__typeof__(isMove)) TILEGXFN(isMove_TILEGXInstr);
573         getRegUsage =
574            (__typeof__(getRegUsage)) TILEGXFN(getRegUsage_TILEGXInstr);
575         mapRegs     = (__typeof__(mapRegs)) TILEGXFN(mapRegs_TILEGXInstr);
576         genSpill    = (__typeof__(genSpill)) TILEGXFN(genSpill_TILEGX);
577         genReload   = (__typeof__(genReload)) TILEGXFN(genReload_TILEGX);
578         ppInstr     = (__typeof__(ppInstr)) TILEGXFN(ppTILEGXInstr);
579         ppReg       = (__typeof__(ppReg)) TILEGXFN(ppHRegTILEGX);
580         iselSB      = TILEGXFN(iselSB_TILEGX);
581         emit        = (__typeof__(emit)) TILEGXFN(emit_TILEGXInstr);
582         host_word_type    = Ity_I64;
583         vassert(vta->archinfo_host.endness == VexEndnessLE);
584         break;
585
586      default:
587         vpanic("LibVEX_Translate: unsupported host insn set");
588   }
589
590   // Are the host's hardware capabilities feasible. The function will
591   // not return if hwcaps are infeasible in some sense.
592   check_hwcaps(vta->arch_host, vta->archinfo_host.hwcaps);
593
594   switch (vta->arch_guest) {
595
596      case VexArchX86:
597         preciseMemExnsFn
598            = X86FN(guest_x86_state_requires_precise_mem_exns);
599         disInstrFn             = X86FN(disInstr_X86);
600         specHelper             = X86FN(guest_x86_spechelper);
601         guest_sizeB            = sizeof(VexGuestX86State);
602         guest_word_type        = Ity_I32;
603         guest_layout           = X86FN(&x86guest_layout);
604         offB_CMSTART           = offsetof(VexGuestX86State,guest_CMSTART);
605         offB_CMLEN             = offsetof(VexGuestX86State,guest_CMLEN);
606         offB_GUEST_IP          = offsetof(VexGuestX86State,guest_EIP);
607         szB_GUEST_IP           = sizeof( ((VexGuestX86State*)0)->guest_EIP );
608         offB_HOST_EvC_COUNTER  = offsetof(VexGuestX86State,host_EvC_COUNTER);
609         offB_HOST_EvC_FAILADDR = offsetof(VexGuestX86State,host_EvC_FAILADDR);
610         vassert(vta->archinfo_guest.endness == VexEndnessLE);
611         vassert(0 == sizeof(VexGuestX86State) % LibVEX_GUEST_STATE_ALIGN);
612         vassert(sizeof( ((VexGuestX86State*)0)->guest_CMSTART) == 4);
613         vassert(sizeof( ((VexGuestX86State*)0)->guest_CMLEN  ) == 4);
614         vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
615         break;
616
617      case VexArchAMD64:
618         preciseMemExnsFn
619            = AMD64FN(guest_amd64_state_requires_precise_mem_exns);
620         disInstrFn             = AMD64FN(disInstr_AMD64);
621         specHelper             = AMD64FN(guest_amd64_spechelper);
622         guest_sizeB            = sizeof(VexGuestAMD64State);
623         guest_word_type        = Ity_I64;
624         guest_layout           = AMD64FN(&amd64guest_layout);
625         offB_CMSTART           = offsetof(VexGuestAMD64State,guest_CMSTART);
626         offB_CMLEN             = offsetof(VexGuestAMD64State,guest_CMLEN);
627         offB_GUEST_IP          = offsetof(VexGuestAMD64State,guest_RIP);
628         szB_GUEST_IP           = sizeof( ((VexGuestAMD64State*)0)->guest_RIP );
629         offB_HOST_EvC_COUNTER  = offsetof(VexGuestAMD64State,host_EvC_COUNTER);
630         offB_HOST_EvC_FAILADDR = offsetof(VexGuestAMD64State,host_EvC_FAILADDR);
631         vassert(vta->archinfo_guest.endness == VexEndnessLE);
632         vassert(0 == sizeof(VexGuestAMD64State) % LibVEX_GUEST_STATE_ALIGN);
633         vassert(sizeof( ((VexGuestAMD64State*)0)->guest_CMSTART ) == 8);
634         vassert(sizeof( ((VexGuestAMD64State*)0)->guest_CMLEN   ) == 8);
635         vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR  ) == 8);
636         break;
637
638      case VexArchPPC32:
639         preciseMemExnsFn
640            = PPC32FN(guest_ppc32_state_requires_precise_mem_exns);
641         disInstrFn             = PPC32FN(disInstr_PPC);
642         specHelper             = PPC32FN(guest_ppc32_spechelper);
643         guest_sizeB            = sizeof(VexGuestPPC32State);
644         guest_word_type        = Ity_I32;
645         guest_layout           = PPC32FN(&ppc32Guest_layout);
646         offB_CMSTART           = offsetof(VexGuestPPC32State,guest_CMSTART);
647         offB_CMLEN             = offsetof(VexGuestPPC32State,guest_CMLEN);
648         offB_GUEST_IP          = offsetof(VexGuestPPC32State,guest_CIA);
649         szB_GUEST_IP           = sizeof( ((VexGuestPPC32State*)0)->guest_CIA );
650         offB_HOST_EvC_COUNTER  = offsetof(VexGuestPPC32State,host_EvC_COUNTER);
651         offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC32State,host_EvC_FAILADDR);
652         vassert(vta->archinfo_guest.endness == VexEndnessBE);
653         vassert(0 == sizeof(VexGuestPPC32State) % LibVEX_GUEST_STATE_ALIGN);
654         vassert(sizeof( ((VexGuestPPC32State*)0)->guest_CMSTART ) == 4);
655         vassert(sizeof( ((VexGuestPPC32State*)0)->guest_CMLEN   ) == 4);
656         vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR  ) == 4);
657         break;
658
659      case VexArchPPC64:
660         preciseMemExnsFn
661            = PPC64FN(guest_ppc64_state_requires_precise_mem_exns);
662         disInstrFn             = PPC64FN(disInstr_PPC);
663         specHelper             = PPC64FN(guest_ppc64_spechelper);
664         guest_sizeB            = sizeof(VexGuestPPC64State);
665         guest_word_type        = Ity_I64;
666         guest_layout           = PPC64FN(&ppc64Guest_layout);
667         offB_CMSTART           = offsetof(VexGuestPPC64State,guest_CMSTART);
668         offB_CMLEN             = offsetof(VexGuestPPC64State,guest_CMLEN);
669         offB_GUEST_IP          = offsetof(VexGuestPPC64State,guest_CIA);
670         szB_GUEST_IP           = sizeof( ((VexGuestPPC64State*)0)->guest_CIA );
671         offB_HOST_EvC_COUNTER  = offsetof(VexGuestPPC64State,host_EvC_COUNTER);
672         offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC64State,host_EvC_FAILADDR);
673         vassert(vta->archinfo_guest.endness == VexEndnessBE ||
674                 vta->archinfo_guest.endness == VexEndnessLE );
675         vassert(0 == sizeof(VexGuestPPC64State) % LibVEX_GUEST_STATE_ALIGN);
676         vassert(sizeof( ((VexGuestPPC64State*)0)->guest_CMSTART    ) == 8);
677         vassert(sizeof( ((VexGuestPPC64State*)0)->guest_CMLEN      ) == 8);
678         vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR     ) == 8);
679         vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8);
680         break;
681
682      case VexArchS390X:
683         preciseMemExnsFn
684            = S390FN(guest_s390x_state_requires_precise_mem_exns);
685         disInstrFn       = S390FN(disInstr_S390);
686         specHelper       = S390FN(guest_s390x_spechelper);
687         guest_sizeB      = sizeof(VexGuestS390XState);
688         guest_word_type  = Ity_I64;
689         guest_layout     = S390FN(&s390xGuest_layout);
690         offB_CMSTART     = offsetof(VexGuestS390XState,guest_CMSTART);
691         offB_CMLEN       = offsetof(VexGuestS390XState,guest_CMLEN);
692         offB_GUEST_IP          = offsetof(VexGuestS390XState,guest_IA);
693         szB_GUEST_IP           = sizeof( ((VexGuestS390XState*)0)->guest_IA);
694         offB_HOST_EvC_COUNTER  = offsetof(VexGuestS390XState,host_EvC_COUNTER);
695         offB_HOST_EvC_FAILADDR = offsetof(VexGuestS390XState,host_EvC_FAILADDR);
696         vassert(vta->archinfo_guest.endness == VexEndnessBE);
697         vassert(0 == sizeof(VexGuestS390XState) % LibVEX_GUEST_STATE_ALIGN);
698         vassert(sizeof( ((VexGuestS390XState*)0)->guest_CMSTART    ) == 8);
699         vassert(sizeof( ((VexGuestS390XState*)0)->guest_CMLEN      ) == 8);
700         vassert(sizeof( ((VexGuestS390XState*)0)->guest_NRADDR     ) == 8);
701         break;
702
703      case VexArchARM:
704         preciseMemExnsFn
705            = ARMFN(guest_arm_state_requires_precise_mem_exns);
706         disInstrFn             = ARMFN(disInstr_ARM);
707         specHelper             = ARMFN(guest_arm_spechelper);
708         guest_sizeB            = sizeof(VexGuestARMState);
709         guest_word_type        = Ity_I32;
710         guest_layout           = ARMFN(&armGuest_layout);
711         offB_CMSTART           = offsetof(VexGuestARMState,guest_CMSTART);
712         offB_CMLEN             = offsetof(VexGuestARMState,guest_CMLEN);
713         offB_GUEST_IP          = offsetof(VexGuestARMState,guest_R15T);
714         szB_GUEST_IP           = sizeof( ((VexGuestARMState*)0)->guest_R15T );
715         offB_HOST_EvC_COUNTER  = offsetof(VexGuestARMState,host_EvC_COUNTER);
716         offB_HOST_EvC_FAILADDR = offsetof(VexGuestARMState,host_EvC_FAILADDR);
717         vassert(vta->archinfo_guest.endness == VexEndnessLE);
718         vassert(0 == sizeof(VexGuestARMState) % LibVEX_GUEST_STATE_ALIGN);
719         vassert(sizeof( ((VexGuestARMState*)0)->guest_CMSTART) == 4);
720         vassert(sizeof( ((VexGuestARMState*)0)->guest_CMLEN  ) == 4);
721         vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4);
722         break;
723
724      case VexArchARM64:
725         preciseMemExnsFn
726            = ARM64FN(guest_arm64_state_requires_precise_mem_exns);
727         disInstrFn           = ARM64FN(disInstr_ARM64);
728         specHelper           = ARM64FN(guest_arm64_spechelper);
729         guest_sizeB          = sizeof(VexGuestARM64State);
730         guest_word_type      = Ity_I64;
731         guest_layout         = ARM64FN(&arm64Guest_layout);
732         offB_CMSTART         = offsetof(VexGuestARM64State,guest_CMSTART);
733         offB_CMLEN           = offsetof(VexGuestARM64State,guest_CMLEN);
734         offB_GUEST_IP        = offsetof(VexGuestARM64State,guest_PC);
735         szB_GUEST_IP         = sizeof( ((VexGuestARM64State*)0)->guest_PC );
736         offB_HOST_EvC_COUNTER  = offsetof(VexGuestARM64State,host_EvC_COUNTER);
737         offB_HOST_EvC_FAILADDR = offsetof(VexGuestARM64State,host_EvC_FAILADDR);
738         vassert(vta->archinfo_guest.endness == VexEndnessLE);
739         vassert(0 == sizeof(VexGuestARM64State) % LibVEX_GUEST_STATE_ALIGN);
740         vassert(sizeof( ((VexGuestARM64State*)0)->guest_CMSTART) == 8);
741         vassert(sizeof( ((VexGuestARM64State*)0)->guest_CMLEN  ) == 8);
742         vassert(sizeof( ((VexGuestARM64State*)0)->guest_NRADDR ) == 8);
743         break;
744
745      case VexArchMIPS32:
746         preciseMemExnsFn
747            = MIPS32FN(guest_mips32_state_requires_precise_mem_exns);
748         disInstrFn             = MIPS32FN(disInstr_MIPS);
749         specHelper             = MIPS32FN(guest_mips32_spechelper);
750         guest_sizeB            = sizeof(VexGuestMIPS32State);
751         guest_word_type        = Ity_I32;
752         guest_layout           = MIPS32FN(&mips32Guest_layout);
753         offB_CMSTART           = offsetof(VexGuestMIPS32State,guest_CMSTART);
754         offB_CMLEN             = offsetof(VexGuestMIPS32State,guest_CMLEN);
755         offB_GUEST_IP          = offsetof(VexGuestMIPS32State,guest_PC);
756         szB_GUEST_IP           = sizeof( ((VexGuestMIPS32State*)0)->guest_PC );
757         offB_HOST_EvC_COUNTER  = offsetof(VexGuestMIPS32State,host_EvC_COUNTER);
758         offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS32State,host_EvC_FAILADDR);
759         vassert(vta->archinfo_guest.endness == VexEndnessLE
760                 || vta->archinfo_guest.endness == VexEndnessBE);
761         vassert(0 == sizeof(VexGuestMIPS32State) % LibVEX_GUEST_STATE_ALIGN);
762         vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_CMSTART) == 4);
763         vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_CMLEN  ) == 4);
764         vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_NRADDR ) == 4);
765         break;
766
767      case VexArchMIPS64:
768         preciseMemExnsFn
769            = MIPS64FN(guest_mips64_state_requires_precise_mem_exns);
770         disInstrFn             = MIPS64FN(disInstr_MIPS);
771         specHelper             = MIPS64FN(guest_mips64_spechelper);
772         guest_sizeB            = sizeof(VexGuestMIPS64State);
773         guest_word_type        = Ity_I64;
774         guest_layout           = MIPS64FN(&mips64Guest_layout);
775         offB_CMSTART           = offsetof(VexGuestMIPS64State,guest_CMSTART);
776         offB_CMLEN             = offsetof(VexGuestMIPS64State,guest_CMLEN);
777         offB_GUEST_IP          = offsetof(VexGuestMIPS64State,guest_PC);
778         szB_GUEST_IP           = sizeof( ((VexGuestMIPS64State*)0)->guest_PC );
779         offB_HOST_EvC_COUNTER  = offsetof(VexGuestMIPS64State,host_EvC_COUNTER);
780         offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS64State,host_EvC_FAILADDR);
781         vassert(vta->archinfo_guest.endness == VexEndnessLE
782                 || vta->archinfo_guest.endness == VexEndnessBE);
783         vassert(0 == sizeof(VexGuestMIPS64State) % LibVEX_GUEST_STATE_ALIGN);
784         vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_CMSTART) == 8);
785         vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_CMLEN  ) == 8);
786         vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_NRADDR ) == 8);
787         break;
788
789      case VexArchTILEGX:
790         preciseMemExnsFn =
791            TILEGXFN(guest_tilegx_state_requires_precise_mem_exns);
792         disInstrFn       = TILEGXFN(disInstr_TILEGX);
793         specHelper       = TILEGXFN(guest_tilegx_spechelper);
794         guest_sizeB      = sizeof(VexGuestTILEGXState);
795         guest_word_type  = Ity_I64;
796         guest_layout     = TILEGXFN(&tilegxGuest_layout);
797         offB_CMSTART     = offsetof(VexGuestTILEGXState,guest_CMSTART);
798         offB_CMLEN       = offsetof(VexGuestTILEGXState,guest_CMLEN);
799         offB_GUEST_IP          = offsetof(VexGuestTILEGXState,guest_pc);
800         szB_GUEST_IP           = sizeof( ((VexGuestTILEGXState*)0)->guest_pc );
801         offB_HOST_EvC_COUNTER  = offsetof(VexGuestTILEGXState,host_EvC_COUNTER);
802         offB_HOST_EvC_FAILADDR = offsetof(VexGuestTILEGXState,host_EvC_FAILADDR);
803         vassert(vta->archinfo_guest.endness == VexEndnessLE);
804         vassert(0 ==
805                 sizeof(VexGuestTILEGXState) % LibVEX_GUEST_STATE_ALIGN);
806         vassert(sizeof( ((VexGuestTILEGXState*)0)->guest_CMSTART    ) == 8);
807         vassert(sizeof( ((VexGuestTILEGXState*)0)->guest_CMLEN      ) == 8);
808         vassert(sizeof( ((VexGuestTILEGXState*)0)->guest_NRADDR     ) == 8);
809         break;
810
811      default:
812         vpanic("LibVEX_Translate: unsupported guest insn set");
813   }
814
815   // Are the guest's hardware capabilities feasible. The function will
816   // not return if hwcaps are infeasible in some sense.
817   // FIXME: how can we know the guest's hardware capabilities?
818   check_hwcaps(vta->arch_guest, vta->archinfo_guest.hwcaps);
819
820   /* Set up result struct. */
821   VexTranslateResult res;
822   res.status         = VexTransOK;
823   res.n_sc_extents   = 0;
824   res.offs_profInc   = -1;
825   res.n_guest_instrs = 0;
826
827   /* yet more sanity checks ... */
828   if (vta->arch_guest == vta->arch_host) {
829      /* doesn't necessarily have to be true, but if it isn't it means
830         we are simulating one flavour of an architecture a different
831         flavour of the same architecture, which is pretty strange. */
832      vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps);
833      /* ditto */
834      vassert(vta->archinfo_guest.endness == vta->archinfo_host.endness);
835   }
836
837   vexAllocSanityCheck();
838
839   if (vex_traceflags & VEX_TRACE_FE)
840      vex_printf("\n------------------------"
841                   " Front end "
842                   "------------------------\n\n");
843
844   VexRegisterUpdates pxControl = vex_control.iropt_register_updates_default;
845   vassert(pxControl >= VexRegUpdSpAtMemAccess
846           && pxControl <= VexRegUpdAllregsAtEachInsn);
847
848   irsb = bb_to_IR ( vta->guest_extents,
849                     &res.n_sc_extents,
850                     &res.n_guest_instrs,
851                     &pxControl,
852                     vta->callback_opaque,
853                     disInstrFn,
854                     vta->guest_bytes,
855                     vta->guest_bytes_addr,
856                     vta->chase_into_ok,
857                     vta->archinfo_host.endness,
858                     vta->sigill_diag,
859                     vta->arch_guest,
860                     &vta->archinfo_guest,
861                     &vta->abiinfo_both,
862                     guest_word_type,
863                     vta->needs_self_check,
864                     vta->preamble_function,
865                     offB_CMSTART,
866                     offB_CMLEN,
867                     offB_GUEST_IP,
868                     szB_GUEST_IP );
869
870   vexAllocSanityCheck();
871
872   if (irsb == NULL) {
873      /* Access failure. */
874      vexSetAllocModeTEMP_and_clear();
875      vex_traceflags = 0;
876      res.status = VexTransAccessFail; return res;
877   }
878
879   vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3);
880   vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr);
881   for (i = 0; i < vta->guest_extents->n_used; i++) {
882      vassert(vta->guest_extents->len[i] < 10000); /* sanity */
883   }
884
885   /* bb_to_IR() could have caused pxControl to change. */
886   vassert(pxControl >= VexRegUpdSpAtMemAccess
887           && pxControl <= VexRegUpdAllregsAtEachInsn);
888
889   /* If debugging, show the raw guest bytes for this bb. */
890   if (0 || (vex_traceflags & VEX_TRACE_FE)) {
891      if (vta->guest_extents->n_used > 1) {
892         vex_printf("can't show code due to extents > 1\n");
893      } else {
894         /* HACK */
895         const UChar* p = vta->guest_bytes;
896         UInt   sum = 0;
897         UInt   guest_bytes_read = (UInt)vta->guest_extents->len[0];
898         vex_printf("GuestBytes %lx %u ", vta->guest_bytes_addr,
899                                          guest_bytes_read );
900         for (i = 0; i < guest_bytes_read; i++) {
901            UInt b = (UInt)p[i];
902            vex_printf(" %02x", b );
903            sum = (sum << 1) ^ b;
904         }
905         vex_printf("  %08x\n\n", sum);
906      }
907   }
908
909   /* Sanity check the initial IR. */
910   sanityCheckIRSB( irsb, "initial IR",
911                    False/*can be non-flat*/, guest_word_type );
912
913   vexAllocSanityCheck();
914
915   /* Clean it up, hopefully a lot. */
916   irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn, pxControl,
917                              vta->guest_bytes_addr,
918                              vta->arch_guest );
919   sanityCheckIRSB( irsb, "after initial iropt",
920                    True/*must be flat*/, guest_word_type );
921
922   if (vex_traceflags & VEX_TRACE_OPT1) {
923      vex_printf("\n------------------------"
924                   " After pre-instr IR optimisation "
925                   "------------------------\n\n");
926      ppIRSB ( irsb );
927      vex_printf("\n");
928   }
929
930   vexAllocSanityCheck();
931
932   /* Get the thing instrumented. */
933   if (vta->instrument1)
934      irsb = vta->instrument1(vta->callback_opaque,
935                              irsb, guest_layout,
936                              vta->guest_extents,
937                              &vta->archinfo_host,
938                              guest_word_type, host_word_type);
939   vexAllocSanityCheck();
940
941   if (vta->instrument2)
942      irsb = vta->instrument2(vta->callback_opaque,
943                              irsb, guest_layout,
944                              vta->guest_extents,
945                              &vta->archinfo_host,
946                              guest_word_type, host_word_type);
947
948   if (vex_traceflags & VEX_TRACE_INST) {
949      vex_printf("\n------------------------"
950                   " After instrumentation "
951                   "------------------------\n\n");
952      ppIRSB ( irsb );
953      vex_printf("\n");
954   }
955
956   if (vta->instrument1 || vta->instrument2)
957      sanityCheckIRSB( irsb, "after instrumentation",
958                       True/*must be flat*/, guest_word_type );
959
960   /* Do a post-instrumentation cleanup pass. */
961   if (vta->instrument1 || vta->instrument2) {
962      do_deadcode_BB( irsb );
963      irsb = cprop_BB( irsb );
964      do_deadcode_BB( irsb );
965      sanityCheckIRSB( irsb, "after post-instrumentation cleanup",
966                       True/*must be flat*/, guest_word_type );
967   }
968
969   vexAllocSanityCheck();
970
971   if (vex_traceflags & VEX_TRACE_OPT2) {
972      vex_printf("\n------------------------"
973                   " After post-instr IR optimisation "
974                   "------------------------\n\n");
975      ppIRSB ( irsb );
976      vex_printf("\n");
977   }
978
979   /* Turn it into virtual-registerised code.  Build trees -- this
980      also throws away any dead bindings. */
981   max_ga = ado_treebuild_BB( irsb, preciseMemExnsFn, pxControl );
982
983   if (vta->finaltidy) {
984      irsb = vta->finaltidy(irsb);
985   }
986
987   vexAllocSanityCheck();
988
989   if (vex_traceflags & VEX_TRACE_TREES) {
990      vex_printf("\n------------------------"
991                   "  After tree-building "
992                   "------------------------\n\n");
993      ppIRSB ( irsb );
994      vex_printf("\n");
995   }
996
997   /* HACK */
998   if (0) {
999      *(vta->host_bytes_used) = 0;
1000      res.status = VexTransOK; return res;
1001   }
1002   /* end HACK */
1003
1004   if (vex_traceflags & VEX_TRACE_VCODE)
1005      vex_printf("\n------------------------"
1006                   " Instruction selection "
1007                   "------------------------\n");
1008
1009   /* No guest has its IP field at offset zero.  If this fails it
1010      means some transformation pass somewhere failed to update/copy
1011      irsb->offsIP properly. */
1012   vassert(irsb->offsIP >= 16);
1013
1014   vcode = iselSB ( irsb, vta->arch_host,
1015                    &vta->archinfo_host,
1016                    &vta->abiinfo_both,
1017                    offB_HOST_EvC_COUNTER,
1018                    offB_HOST_EvC_FAILADDR,
1019                    chainingAllowed,
1020                    vta->addProfInc,
1021                    max_ga );
1022
1023   vexAllocSanityCheck();
1024
1025   if (vex_traceflags & VEX_TRACE_VCODE)
1026      vex_printf("\n");
1027
1028   if (vex_traceflags & VEX_TRACE_VCODE) {
1029      for (i = 0; i < vcode->arr_used; i++) {
1030         vex_printf("%3d   ", i);
1031         ppInstr(vcode->arr[i], mode64);
1032         vex_printf("\n");
1033      }
1034      vex_printf("\n");
1035   }
1036
1037   /* Register allocate. */
1038   rcode = doRegisterAllocation ( vcode, rRegUniv,
1039                                  isMove, getRegUsage, mapRegs,
1040                                  genSpill, genReload, directReload,
1041                                  guest_sizeB,
1042                                  ppInstr, ppReg, mode64 );
1043
1044   vexAllocSanityCheck();
1045
1046   if (vex_traceflags & VEX_TRACE_RCODE) {
1047      vex_printf("\n------------------------"
1048                   " Register-allocated code "
1049                   "------------------------\n\n");
1050      for (i = 0; i < rcode->arr_used; i++) {
1051         vex_printf("%3d   ", i);
1052         ppInstr(rcode->arr[i], mode64);
1053         vex_printf("\n");
1054      }
1055      vex_printf("\n");
1056   }
1057
1058   /* HACK */
1059   if (0) {
1060      *(vta->host_bytes_used) = 0;
1061      res.status = VexTransOK; return res;
1062   }
1063   /* end HACK */
1064
1065   /* Assemble */
1066   if (vex_traceflags & VEX_TRACE_ASM) {
1067      vex_printf("\n------------------------"
1068                   " Assembly "
1069                   "------------------------\n\n");
1070   }
1071
1072   out_used = 0; /* tracks along the host_bytes array */
1073   for (i = 0; i < rcode->arr_used; i++) {
1074      HInstr* hi           = rcode->arr[i];
1075      Bool    hi_isProfInc = False;
1076      if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
1077         ppInstr(hi, mode64);
1078         vex_printf("\n");
1079      }
1080      j = emit( &hi_isProfInc,
1081                insn_bytes, sizeof insn_bytes, hi,
1082                mode64, vta->archinfo_host.endness,
1083                vta->disp_cp_chain_me_to_slowEP,
1084                vta->disp_cp_chain_me_to_fastEP,
1085                vta->disp_cp_xindir,
1086                vta->disp_cp_xassisted );
1087      if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
1088         for (k = 0; k < j; k++)
1089            vex_printf("%02x ", (UInt)insn_bytes[k]);
1090         vex_printf("\n\n");
1091      }
1092      if (UNLIKELY(out_used + j > vta->host_bytes_size)) {
1093         vexSetAllocModeTEMP_and_clear();
1094         vex_traceflags = 0;
1095         res.status = VexTransOutputFull;
1096         return res;
1097      }
1098      if (UNLIKELY(hi_isProfInc)) {
1099         vassert(vta->addProfInc); /* else where did it come from? */
1100         vassert(res.offs_profInc == -1); /* there can be only one (tm) */
1101         vassert(out_used >= 0);
1102         res.offs_profInc = out_used;
1103      }
1104      { UChar* dst = &vta->host_bytes[out_used];
1105        for (k = 0; k < j; k++) {
1106           dst[k] = insn_bytes[k];
1107        }
1108        out_used += j;
1109      }
1110   }
1111   *(vta->host_bytes_used) = out_used;
1112
1113   vexAllocSanityCheck();
1114
1115   vexSetAllocModeTEMP_and_clear();
1116
1117   if (vex_traceflags) {
1118      /* Print the expansion ratio for this SB. */
1119      j = 0; /* total guest bytes */
1120      for (i = 0; i < vta->guest_extents->n_used; i++) {
1121         j += vta->guest_extents->len[i];
1122      }
1123      if (1) vex_printf("VexExpansionRatio %d %d   %d :10\n\n",
1124                        j, out_used, (10 * out_used) / (j == 0 ? 1 : j));
1125   }
1126
1127   vex_traceflags = 0;
1128   res.status = VexTransOK;
1129   return res;
1130}
1131
1132
1133/* --------- Chain/Unchain XDirects. --------- */
1134
1135VexInvalRange LibVEX_Chain ( VexArch     arch_host,
1136                             VexEndness  endness_host,
1137                             void*       place_to_chain,
1138                             const void* disp_cp_chain_me_EXPECTED,
1139                             const void* place_to_jump_to )
1140{
1141   switch (arch_host) {
1142      case VexArchX86:
1143         X86ST(return chainXDirect_X86(endness_host,
1144                                       place_to_chain,
1145                                       disp_cp_chain_me_EXPECTED,
1146                                       place_to_jump_to));
1147      case VexArchAMD64:
1148         AMD64ST(return chainXDirect_AMD64(endness_host,
1149                                           place_to_chain,
1150                                           disp_cp_chain_me_EXPECTED,
1151                                           place_to_jump_to));
1152      case VexArchARM:
1153         ARMST(return chainXDirect_ARM(endness_host,
1154                                       place_to_chain,
1155                                       disp_cp_chain_me_EXPECTED,
1156                                       place_to_jump_to));
1157      case VexArchARM64:
1158         ARM64ST(return chainXDirect_ARM64(endness_host,
1159                                           place_to_chain,
1160                                           disp_cp_chain_me_EXPECTED,
1161                                           place_to_jump_to));
1162      case VexArchS390X:
1163         S390ST(return chainXDirect_S390(endness_host,
1164                                         place_to_chain,
1165                                         disp_cp_chain_me_EXPECTED,
1166                                         place_to_jump_to));
1167      case VexArchPPC32:
1168         PPC32ST(return chainXDirect_PPC(endness_host,
1169                                         place_to_chain,
1170                                         disp_cp_chain_me_EXPECTED,
1171                                         place_to_jump_to, False/*!mode64*/));
1172      case VexArchPPC64:
1173         PPC64ST(return chainXDirect_PPC(endness_host,
1174                                         place_to_chain,
1175                                         disp_cp_chain_me_EXPECTED,
1176                                         place_to_jump_to, True/*mode64*/));
1177      case VexArchMIPS32:
1178         MIPS32ST(return chainXDirect_MIPS(endness_host,
1179                                           place_to_chain,
1180                                           disp_cp_chain_me_EXPECTED,
1181                                           place_to_jump_to, False/*!mode64*/));
1182      case VexArchMIPS64:
1183         MIPS64ST(return chainXDirect_MIPS(endness_host,
1184                                           place_to_chain,
1185                                           disp_cp_chain_me_EXPECTED,
1186                                           place_to_jump_to, True/*!mode64*/));
1187
1188      case VexArchTILEGX:
1189         TILEGXST(return chainXDirect_TILEGX(endness_host,
1190                                             place_to_chain,
1191                                             disp_cp_chain_me_EXPECTED,
1192                                             place_to_jump_to, True/*!mode64*/));
1193      default:
1194         vassert(0);
1195   }
1196}
1197
1198VexInvalRange LibVEX_UnChain ( VexArch     arch_host,
1199                               VexEndness  endness_host,
1200                               void*       place_to_unchain,
1201                               const void* place_to_jump_to_EXPECTED,
1202                               const void* disp_cp_chain_me )
1203{
1204   switch (arch_host) {
1205      case VexArchX86:
1206         X86ST(return unchainXDirect_X86(endness_host,
1207                                         place_to_unchain,
1208                                         place_to_jump_to_EXPECTED,
1209                                         disp_cp_chain_me));
1210      case VexArchAMD64:
1211         AMD64ST(return unchainXDirect_AMD64(endness_host,
1212                                             place_to_unchain,
1213                                             place_to_jump_to_EXPECTED,
1214                                             disp_cp_chain_me));
1215      case VexArchARM:
1216         ARMST(return unchainXDirect_ARM(endness_host,
1217                                         place_to_unchain,
1218                                         place_to_jump_to_EXPECTED,
1219                                         disp_cp_chain_me));
1220      case VexArchARM64:
1221         ARM64ST(return unchainXDirect_ARM64(endness_host,
1222                                             place_to_unchain,
1223                                             place_to_jump_to_EXPECTED,
1224                                             disp_cp_chain_me));
1225      case VexArchS390X:
1226         S390ST(return unchainXDirect_S390(endness_host,
1227                                           place_to_unchain,
1228                                           place_to_jump_to_EXPECTED,
1229                                           disp_cp_chain_me));
1230      case VexArchPPC32:
1231         PPC32ST(return unchainXDirect_PPC(endness_host,
1232                                           place_to_unchain,
1233                                           place_to_jump_to_EXPECTED,
1234                                           disp_cp_chain_me, False/*!mode64*/));
1235      case VexArchPPC64:
1236         PPC64ST(return unchainXDirect_PPC(endness_host,
1237                                           place_to_unchain,
1238                                           place_to_jump_to_EXPECTED,
1239                                           disp_cp_chain_me, True/*mode64*/));
1240      case VexArchMIPS32:
1241         MIPS32ST(return unchainXDirect_MIPS(endness_host,
1242                                             place_to_unchain,
1243                                             place_to_jump_to_EXPECTED,
1244                                             disp_cp_chain_me, False/*!mode64*/));
1245      case VexArchMIPS64:
1246         MIPS64ST(return unchainXDirect_MIPS(endness_host,
1247                                             place_to_unchain,
1248                                             place_to_jump_to_EXPECTED,
1249                                             disp_cp_chain_me, True/*!mode64*/));
1250
1251      case VexArchTILEGX:
1252         TILEGXST(return unchainXDirect_TILEGX(endness_host,
1253                                      place_to_unchain,
1254                                      place_to_jump_to_EXPECTED,
1255                                               disp_cp_chain_me, True/*!mode64*/));
1256
1257      default:
1258         vassert(0);
1259   }
1260}
1261
1262Int LibVEX_evCheckSzB ( VexArch    arch_host )
1263{
1264   static Int cached = 0; /* DO NOT MAKE NON-STATIC */
1265   if (UNLIKELY(cached == 0)) {
1266      switch (arch_host) {
1267         case VexArchX86:
1268            X86ST(cached = evCheckSzB_X86()); break;
1269         case VexArchAMD64:
1270            AMD64ST(cached = evCheckSzB_AMD64()); break;
1271         case VexArchARM:
1272            ARMST(cached = evCheckSzB_ARM()); break;
1273         case VexArchARM64:
1274            ARM64ST(cached = evCheckSzB_ARM64()); break;
1275         case VexArchS390X:
1276            S390ST(cached = evCheckSzB_S390()); break;
1277         case VexArchPPC32:
1278            PPC32ST(cached = evCheckSzB_PPC()); break;
1279         case VexArchPPC64:
1280            PPC64ST(cached = evCheckSzB_PPC()); break;
1281         case VexArchMIPS32:
1282            MIPS32ST(cached = evCheckSzB_MIPS()); break;
1283         case VexArchMIPS64:
1284            MIPS64ST(cached = evCheckSzB_MIPS()); break;
1285         case VexArchTILEGX:
1286            TILEGXST(cached = evCheckSzB_TILEGX()); break;
1287         default:
1288            vassert(0);
1289      }
1290   }
1291   return cached;
1292}
1293
1294VexInvalRange LibVEX_PatchProfInc ( VexArch    arch_host,
1295                                    VexEndness endness_host,
1296                                    void*      place_to_patch,
1297                                    const ULong* location_of_counter )
1298{
1299   switch (arch_host) {
1300      case VexArchX86:
1301         X86ST(return patchProfInc_X86(endness_host, place_to_patch,
1302                                       location_of_counter));
1303      case VexArchAMD64:
1304         AMD64ST(return patchProfInc_AMD64(endness_host, place_to_patch,
1305                                           location_of_counter));
1306      case VexArchARM:
1307         ARMST(return patchProfInc_ARM(endness_host, place_to_patch,
1308                                       location_of_counter));
1309      case VexArchARM64:
1310         ARM64ST(return patchProfInc_ARM64(endness_host, place_to_patch,
1311                                           location_of_counter));
1312      case VexArchS390X:
1313         S390ST(return patchProfInc_S390(endness_host, place_to_patch,
1314                                         location_of_counter));
1315      case VexArchPPC32:
1316         PPC32ST(return patchProfInc_PPC(endness_host, place_to_patch,
1317                                         location_of_counter, False/*!mode64*/));
1318      case VexArchPPC64:
1319         PPC64ST(return patchProfInc_PPC(endness_host, place_to_patch,
1320                                         location_of_counter, True/*mode64*/));
1321      case VexArchMIPS32:
1322         MIPS32ST(return patchProfInc_MIPS(endness_host, place_to_patch,
1323                                           location_of_counter, False/*!mode64*/));
1324      case VexArchMIPS64:
1325         MIPS64ST(return patchProfInc_MIPS(endness_host, place_to_patch,
1326                                           location_of_counter, True/*!mode64*/));
1327      case VexArchTILEGX:
1328         TILEGXST(return patchProfInc_TILEGX(endness_host, place_to_patch,
1329                                             location_of_counter,
1330                                             True/*!mode64*/));
1331      default:
1332         vassert(0);
1333   }
1334}
1335
1336
1337/* --------- Emulation warnings. --------- */
1338
1339const HChar* LibVEX_EmNote_string ( VexEmNote ew )
1340{
1341   switch (ew) {
1342     case EmNote_NONE:
1343        return "none";
1344     case EmWarn_X86_x87exns:
1345        return "Unmasking x87 FP exceptions";
1346     case EmWarn_X86_x87precision:
1347        return "Selection of non-80-bit x87 FP precision";
1348     case EmWarn_X86_sseExns:
1349        return "Unmasking SSE FP exceptions";
1350     case EmWarn_X86_fz:
1351        return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
1352     case EmWarn_X86_daz:
1353        return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
1354     case EmWarn_X86_acFlag:
1355        return "Setting %eflags.ac (setting noted but ignored)";
1356     case EmWarn_PPCexns:
1357        return "Unmasking PPC32/64 FP exceptions";
1358     case EmWarn_PPC64_redir_overflow:
1359        return "PPC64 function redirection stack overflow";
1360     case EmWarn_PPC64_redir_underflow:
1361        return "PPC64 function redirection stack underflow";
1362     case EmWarn_S390X_fpext_rounding:
1363        return "The specified rounding mode cannot be supported. That\n"
1364               "  feature requires the floating point extension facility\n"
1365               "  which is not available on this host. Continuing using\n"
1366               "  the rounding mode from FPC. Results may differ!";
1367     case EmWarn_S390X_invalid_rounding:
1368        return "The specified rounding mode is invalid.\n"
1369               "  Continuing using 'round to nearest'. Results may differ!";
1370     case EmFail_S390X_stfle:
1371        return "Instruction stfle is not supported on this host";
1372     case EmFail_S390X_stckf:
1373        return "Instruction stckf is not supported on this host";
1374     case EmFail_S390X_ecag:
1375        return "Instruction ecag is not supported on this host";
1376     case EmFail_S390X_pfpo:
1377        return "Instruction pfpo is not supported on this host";
1378     case EmFail_S390X_DFP_insn:
1379        return "DFP instructions are not supported on this host";
1380     case EmFail_S390X_fpext:
1381        return "Encountered an instruction that requires the floating "
1382               "point extension facility.\n"
1383               "  That facility is not available on this host";
1384     case EmFail_S390X_invalid_PFPO_rounding_mode:
1385        return "The rounding mode in GPR 0 for the PFPO instruction"
1386               " is invalid";
1387     case EmFail_S390X_invalid_PFPO_function:
1388        return "The function code in GPR 0 for the PFPO instruction"
1389               " is invalid";
1390     default:
1391        vpanic("LibVEX_EmNote_string: unknown warning");
1392   }
1393}
1394
1395/* ------------------ Arch/HwCaps stuff. ------------------ */
1396
1397const HChar* LibVEX_ppVexArch ( VexArch arch )
1398{
1399   switch (arch) {
1400      case VexArch_INVALID: return "INVALID";
1401      case VexArchX86:      return "X86";
1402      case VexArchAMD64:    return "AMD64";
1403      case VexArchARM:      return "ARM";
1404      case VexArchARM64:    return "ARM64";
1405      case VexArchPPC32:    return "PPC32";
1406      case VexArchPPC64:    return "PPC64";
1407      case VexArchS390X:    return "S390X";
1408      case VexArchMIPS32:   return "MIPS32";
1409      case VexArchMIPS64:   return "MIPS64";
1410      case VexArchTILEGX:   return "TILEGX";
1411      default:              return "VexArch???";
1412   }
1413}
1414
1415const HChar* LibVEX_ppVexEndness ( VexEndness endness )
1416{
1417   switch (endness) {
1418      case VexEndness_INVALID: return "INVALID";
1419      case VexEndnessLE:       return "LittleEndian";
1420      case VexEndnessBE:       return "BigEndian";
1421      default:                 return "VexEndness???";
1422   }
1423}
1424
1425/* Return a string with the hardware capabilities to the extent as
1426   they pertain to the translation process. No attempt is made, to
1427   detect *all* capabilities an architecture may have. */
1428const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
1429{
1430   return show_hwcaps(arch, hwcaps);
1431}
1432
1433
1434/* Write default settings info *vai. */
1435void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
1436{
1437   vex_bzero(vai, sizeof(*vai));
1438   vai->hwcaps                  = 0;
1439   vai->endness                 = VexEndness_INVALID;
1440   vai->ppc_icache_line_szB     = 0;
1441   vai->ppc_dcbz_szB            = 0;
1442   vai->ppc_dcbzl_szB           = 0;
1443   vai->arm64_dMinLine_lg2_szB  = 0;
1444   vai->arm64_iMinLine_lg2_szB  = 0;
1445   vai->hwcache_info.num_levels = 0;
1446   vai->hwcache_info.num_caches = 0;
1447   vai->hwcache_info.caches     = NULL;
1448   vai->hwcache_info.icaches_maintain_coherence = True;  // whatever
1449}
1450
1451/* Write default settings info *vbi. */
1452void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
1453{
1454   vex_bzero(vbi, sizeof(*vbi));
1455   vbi->guest_stack_redzone_size       = 0;
1456   vbi->guest_amd64_assume_fs_is_const = False;
1457   vbi->guest_amd64_assume_gs_is_const = False;
1458   vbi->guest_ppc_zap_RZ_at_blr        = False;
1459   vbi->guest_ppc_zap_RZ_at_bl         = NULL;
1460   vbi->host_ppc_calls_use_fndescrs    = False;
1461}
1462
1463
1464/* Convenience macro to be used in show_hwcaps_ARCH functions */
1465#define NUM_HWCAPS (sizeof hwcaps_list / sizeof hwcaps_list[0])
1466
1467/* Return a string showing the hwcaps in a nice way.  The string will
1468   be NULL for unrecognised hardware capabilities. */
1469
1470static const HChar* show_hwcaps_x86 ( UInt hwcaps )
1471{
1472   static const HChar prefix[] = "x86";
1473   static const struct {
1474      UInt  hwcaps_bit;
1475      HChar name[7];
1476   } hwcaps_list[] = {
1477      { VEX_HWCAPS_X86_MMXEXT, "mmxext" },
1478      { VEX_HWCAPS_X86_SSE1,   "sse1"   },
1479      { VEX_HWCAPS_X86_SSE2,   "sse2"   },
1480      { VEX_HWCAPS_X86_SSE3,   "sse3"   },
1481      { VEX_HWCAPS_X86_LZCNT,  "lzcnt"  },
1482   };
1483   /* Allocate a large enough buffer */
1484   static HChar buf[sizeof prefix +
1485                    NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1486   if (buf[0] != '\0') return buf;  /* already constructed */
1487
1488   HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1489
1490   if (hwcaps == 0) {
1491      vex_sprintf(p, "-%s", "sse0");
1492   } else {
1493      UInt i;
1494      for (i = 0 ; i < NUM_HWCAPS; ++i) {
1495         if (hwcaps & hwcaps_list[i].hwcaps_bit)
1496            p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1497      }
1498   }
1499   return buf;
1500}
1501
1502static const HChar* show_hwcaps_amd64 ( UInt hwcaps )
1503{
1504   static const HChar prefix[] = "amd64";
1505   static const struct {
1506      UInt  hwcaps_bit;
1507      HChar name[7];
1508   } hwcaps_list[] = {
1509      { VEX_HWCAPS_AMD64_CX16,   "cx16"   },
1510      { VEX_HWCAPS_AMD64_LZCNT,  "lzcnt"  },
1511      { VEX_HWCAPS_AMD64_RDTSCP, "rdtscp" },
1512      { VEX_HWCAPS_AMD64_SSE3,   "sse3"   },
1513      { VEX_HWCAPS_AMD64_AVX,    "avx"    },
1514      { VEX_HWCAPS_AMD64_AVX2,   "avx2"   },
1515      { VEX_HWCAPS_AMD64_BMI,    "bmi"    },
1516   };
1517   /* Allocate a large enough buffer */
1518   static HChar buf[sizeof prefix +
1519                    NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1520   if (buf[0] != '\0') return buf;  /* already constructed */
1521
1522   HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1523
1524   if (hwcaps == 0) {
1525      vex_sprintf(p, "-%s", "sse2");
1526   } else {
1527      UInt i;
1528      for (i = 0 ; i < NUM_HWCAPS; ++i) {
1529         if (hwcaps & hwcaps_list[i].hwcaps_bit)
1530            p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1531      }
1532   }
1533   return buf;
1534}
1535
1536static const HChar* show_hwcaps_ppc32 ( UInt hwcaps )
1537{
1538   static const HChar prefix[] = "ppc32-int";
1539   static const struct {
1540      UInt  hwcaps_bit;
1541      HChar name[8];
1542   } hwcaps_list[] = {
1543      { VEX_HWCAPS_PPC32_F,       "flt"     },
1544      { VEX_HWCAPS_PPC32_V,       "vmx"     },
1545      { VEX_HWCAPS_PPC32_FX,      "FX"      },
1546      { VEX_HWCAPS_PPC32_GX,      "GX"      },
1547      { VEX_HWCAPS_PPC32_VX,      "VX"      },
1548      { VEX_HWCAPS_PPC32_DFP,     "DFP"     },
1549      { VEX_HWCAPS_PPC32_ISA2_07, "ISA2_07" },
1550   };
1551   /* Allocate a large enough buffer */
1552   static HChar buf[sizeof prefix +
1553                    NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1554   if (buf[0] != '\0') return buf;  /* already constructed */
1555
1556   HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1557
1558   if (hwcaps == 0) return buf;
1559
1560   UInt i;
1561   for (i = 0 ; i < NUM_HWCAPS; ++i) {
1562      if (hwcaps & hwcaps_list[i].hwcaps_bit)
1563         p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1564   }
1565   return buf;
1566}
1567
1568static const HChar* show_hwcaps_ppc64 ( UInt hwcaps )
1569{
1570   static const HChar prefix[] = "ppc64-int-flt";
1571   static const struct {
1572      UInt  hwcaps_bit;
1573      HChar name[8];
1574   } hwcaps_list[] = {
1575      { VEX_HWCAPS_PPC64_FX,      "FX"      },
1576      { VEX_HWCAPS_PPC64_GX,      "GX"      },
1577      { VEX_HWCAPS_PPC64_V,       "vmx"     },
1578      { VEX_HWCAPS_PPC64_DFP,     "DFP"     },
1579      { VEX_HWCAPS_PPC64_ISA2_07, "ISA2_07" },
1580   };
1581   /* Allocate a large enough buffer */
1582   static HChar buf[sizeof prefix +
1583                    NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1584   if (buf[0] != '\0') return buf;  /* already constructed */
1585
1586   HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1587
1588   if (hwcaps == 0) return buf;
1589
1590   UInt i;
1591   for (i = 0 ; i < NUM_HWCAPS; ++i) {
1592      if (hwcaps & hwcaps_list[i].hwcaps_bit)
1593         p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1594   }
1595   return buf;
1596}
1597
1598static const HChar* show_hwcaps_arm ( UInt hwcaps )
1599{
1600   static const HChar prefix[] = "ARM";
1601   static const struct {
1602      UInt  hwcaps_bit;
1603      HChar name[6];
1604   } hwcaps_list[] = {
1605      { VEX_HWCAPS_ARM_NEON, "neon" },
1606      { VEX_HWCAPS_ARM_VFP | VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3, "vfp" },
1607   };
1608   /* Allocate a large enough buffer */
1609   static HChar buf[sizeof prefix + 12 +    // level
1610                    NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1611   if (buf[0] != '\0') return buf;  /* already constructed */
1612
1613   HChar *p;
1614   UInt i, level;
1615
1616   level = VEX_ARM_ARCHLEVEL(hwcaps);
1617
1618   p = buf + vex_sprintf(buf, "%sv%u", prefix, level);
1619   for (i = 0 ; i < NUM_HWCAPS; ++i) {
1620      if (hwcaps & hwcaps_list[i].hwcaps_bit)
1621         p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1622   }
1623   return buf;
1624}
1625
1626static const HChar* show_hwcaps_arm64 ( UInt hwcaps )
1627{
1628   /* Since there are no variants, just insist that hwcaps is zero,
1629      and declare it invalid otherwise. */
1630  if (hwcaps == 0)
1631     return "baseline";
1632  return "Unsupported";
1633}
1634
1635static const HChar* show_hwcaps_s390x ( UInt hwcaps )
1636{
1637   static const HChar prefix[] = "s390x";
1638   static const struct {
1639      UInt  hwcaps_bit;
1640      HChar name[6];
1641   } hwcaps_list[] = {
1642      { VEX_HWCAPS_S390X_LDISP, "ldisp" },
1643      { VEX_HWCAPS_S390X_EIMM,  "eimm" },
1644      { VEX_HWCAPS_S390X_GIE,   "gie" },
1645      { VEX_HWCAPS_S390X_DFP,   "dfp" },
1646      { VEX_HWCAPS_S390X_FGX,   "fgx" },
1647      { VEX_HWCAPS_S390X_STFLE, "stfle" },
1648      { VEX_HWCAPS_S390X_ETF2,  "etf2" },
1649      { VEX_HWCAPS_S390X_ETF3,  "etf3" },
1650      { VEX_HWCAPS_S390X_STCKF, "stckf" },
1651      { VEX_HWCAPS_S390X_FPEXT, "fpext" },
1652      { VEX_HWCAPS_S390X_LSC,   "lsc" },
1653      { VEX_HWCAPS_S390X_PFPO,  "pfpo" },
1654   };
1655   /* Allocate a large enough buffer */
1656   static HChar buf[sizeof prefix +
1657                    NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1658
1659   if (buf[0] != '\0') return buf;  /* already constructed */
1660
1661   HChar *p;
1662   UInt i;
1663
1664   hwcaps = VEX_HWCAPS_S390X(hwcaps);
1665
1666   p = buf + vex_sprintf(buf, "%s", prefix);
1667   for (i = 0 ; i < NUM_HWCAPS; ++i) {
1668      if (hwcaps & hwcaps_list[i].hwcaps_bit)
1669         p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1670   }
1671
1672   /* If there are no facilities, add "zarch" */
1673   if (hwcaps == 0)
1674     vex_sprintf(p, "-%s", "zarch");
1675
1676   return buf;
1677}
1678
1679static const HChar* show_hwcaps_mips32 ( UInt hwcaps )
1680{
1681   /* MIPS baseline. */
1682   if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_MIPS) {
1683      /* MIPS baseline with dspr2. */
1684      if (VEX_MIPS_PROC_DSP2(hwcaps)) {
1685         return "MIPS-baseline-dspr2";
1686      }
1687      /* MIPS baseline with dsp. */
1688      if (VEX_MIPS_PROC_DSP(hwcaps)) {
1689         return "MIPS-baseline-dsp";
1690      }
1691      return "MIPS-baseline";
1692   }
1693
1694   /* Broadcom baseline. */
1695   if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_BROADCOM) {
1696      return "Broadcom-baseline";
1697   }
1698
1699   /* Netlogic baseline. */
1700   if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_NETLOGIC) {
1701      return "Netlogic-baseline";
1702   }
1703
1704   /* Cavium baseline. */
1705   if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_CAVIUM) {
1706      return "Cavium-baseline";
1707   }
1708
1709   return "Unsupported baseline";
1710}
1711
1712static const HChar* show_hwcaps_mips64 ( UInt hwcaps )
1713{
1714   return "mips64-baseline";
1715}
1716
1717static const HChar* show_hwcaps_tilegx ( UInt hwcaps )
1718{
1719   return "tilegx-baseline";
1720}
1721
1722#undef NUM_HWCAPS
1723
1724/* Thie function must not return NULL. */
1725
1726static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
1727{
1728   switch (arch) {
1729      case VexArchX86:    return show_hwcaps_x86(hwcaps);
1730      case VexArchAMD64:  return show_hwcaps_amd64(hwcaps);
1731      case VexArchPPC32:  return show_hwcaps_ppc32(hwcaps);
1732      case VexArchPPC64:  return show_hwcaps_ppc64(hwcaps);
1733      case VexArchARM:    return show_hwcaps_arm(hwcaps);
1734      case VexArchARM64:  return show_hwcaps_arm64(hwcaps);
1735      case VexArchS390X:  return show_hwcaps_s390x(hwcaps);
1736      case VexArchMIPS32: return show_hwcaps_mips32(hwcaps);
1737      case VexArchMIPS64: return show_hwcaps_mips64(hwcaps);
1738      case VexArchTILEGX: return show_hwcaps_tilegx(hwcaps);
1739      default: return NULL;
1740   }
1741}
1742
1743/* To be used to complain about hwcaps we cannot handle */
1744__attribute__((noreturn))
1745static void invalid_hwcaps ( VexArch arch, UInt hwcaps, const HChar *message )
1746{
1747   vfatal("\nVEX: %s"
1748          "     Found: %s\n", message, show_hwcaps(arch, hwcaps));
1749}
1750
1751/* This function will not return iff the hwcaps don't pass the test. */
1752static void check_hwcaps ( VexArch arch, UInt hwcaps )
1753{
1754   switch (arch) {
1755      case VexArchX86: {
1756         if (hwcaps == 0) return;    // baseline
1757
1758         /* Monotonic: SSE3 > SSE2 > SSE1 > MMXEXT > baseline. */
1759         static const UInt extras[] = {
1760            VEX_HWCAPS_X86_MMXEXT, VEX_HWCAPS_X86_SSE1, VEX_HWCAPS_X86_SSE2,
1761            VEX_HWCAPS_X86_SSE3
1762         };
1763
1764         UInt i, caps = 0;
1765         for (i = 0; i < sizeof extras / sizeof extras[0]; ++i) {
1766            caps |= extras[i];
1767            if (caps == hwcaps) return;
1768            /* For SSE2 or later LZCNT is optional */
1769            if ((caps & VEX_HWCAPS_X86_SSE2) != 0) {
1770               if ((caps | VEX_HWCAPS_X86_LZCNT) == hwcaps) return;
1771            }
1772         }
1773         invalid_hwcaps(arch, hwcaps, "Cannot handle capabilities\n");
1774      }
1775
1776      case VexArchAMD64: {
1777         /* SSE3 and CX16 are orthogonal and > baseline, although we really
1778            don't expect to come across anything which can do SSE3 but can't
1779            do CX16.  Still, we can handle that case.  LZCNT is similarly
1780            orthogonal. */
1781
1782         /* Throw out obviously stupid cases: */
1783         Bool have_sse3 = (hwcaps & VEX_HWCAPS_AMD64_SSE3) != 0;
1784         Bool have_avx  = (hwcaps & VEX_HWCAPS_AMD64_AVX)  != 0;
1785         Bool have_bmi  = (hwcaps & VEX_HWCAPS_AMD64_BMI)  != 0;
1786         Bool have_avx2 = (hwcaps & VEX_HWCAPS_AMD64_AVX2) != 0;
1787
1788         /* AVX without SSE3 */
1789         if (have_avx && !have_sse3)
1790            invalid_hwcaps(arch, hwcaps,
1791                           "Support for AVX requires SSE3 capabilities\n");
1792         /* AVX2 or BMI without AVX */
1793         if (have_avx2 && !have_avx)
1794            invalid_hwcaps(arch, hwcaps,
1795                           "Support for AVX2 requires AVX capabilities\n");
1796         if (have_bmi && !have_avx)
1797            invalid_hwcaps(arch, hwcaps,
1798                           "Support for BMI requires AVX capabilities\n");
1799         return;
1800      }
1801
1802      case VexArchPPC32: {
1803         /* Monotonic with complications.  Basically V > F > baseline,
1804            but once you have F then you can have FX or GX too. */
1805         if (hwcaps == 0) return;   // baseline
1806
1807         if ((hwcaps & VEX_HWCAPS_PPC32_F) == 0)
1808            invalid_hwcaps(arch, hwcaps,
1809                           "Missing floating point capability\n");
1810         /* V, FX, and GX can appear in any combination */
1811
1812         /* DFP requires V and FX and GX */
1813         UInt v_fx_gx = VEX_HWCAPS_PPC32_V | VEX_HWCAPS_PPC32_FX |
1814                        VEX_HWCAPS_PPC32_GX;
1815         Bool has_v_fx_gx = (hwcaps & v_fx_gx) == v_fx_gx;
1816
1817         if ((hwcaps & VEX_HWCAPS_PPC32_DFP) && ! has_v_fx_gx)
1818            invalid_hwcaps(arch, hwcaps,
1819                           "DFP requires VMX and FX and GX capabilities\n");
1820
1821         /* VX requires V and FX and GX */
1822         if ((hwcaps & VEX_HWCAPS_PPC32_VX) && ! has_v_fx_gx)
1823            invalid_hwcaps(arch, hwcaps,
1824                           "VX requires VMX and FX and GX capabilities\n");
1825
1826         /* ISA2_07 requires everything else */
1827         if ((hwcaps & VEX_HWCAPS_PPC32_ISA2_07) != 0) {
1828            if (! has_v_fx_gx)
1829               invalid_hwcaps(arch, hwcaps,
1830                          "ISA2_07 requires VMX and FX and GX capabilities\n");
1831            if (! (hwcaps & VEX_HWCAPS_PPC32_VX))
1832               invalid_hwcaps(arch, hwcaps,
1833                              "ISA2_07 requires VX capabilities\n");
1834            if (! (hwcaps & VEX_HWCAPS_PPC32_DFP))
1835               invalid_hwcaps(arch, hwcaps,
1836                              "ISA2_07 requires DFP capabilities\n");
1837         }
1838         return;
1839      }
1840
1841      case VexArchPPC64: {
1842         /* Monotonic with complications.  Basically V > baseline(==F),
1843            but once you have F then you can have FX or GX too. */
1844         if (hwcaps == 0) return;   // baseline
1845
1846         /* V, FX, and GX can appear in any combination */
1847
1848         /* DFP requires V and FX and GX */
1849         UInt v_fx_gx = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX |
1850                        VEX_HWCAPS_PPC64_GX;
1851         Bool has_v_fx_gx = (hwcaps & v_fx_gx) == v_fx_gx;
1852
1853         if ((hwcaps & VEX_HWCAPS_PPC64_DFP) && ! has_v_fx_gx)
1854            invalid_hwcaps(arch, hwcaps,
1855                           "DFP requires VMX and FX and GX capabilities\n");
1856
1857         /* VX requires V and FX and GX */
1858         if ((hwcaps & VEX_HWCAPS_PPC32_VX) && ! has_v_fx_gx)
1859            invalid_hwcaps(arch, hwcaps,
1860                           "VX requires VMX and FX and GX capabilities\n");
1861
1862         /* ISA2_07 requires everything else */
1863         if ((hwcaps & VEX_HWCAPS_PPC64_ISA2_07) != 0) {
1864            if (! has_v_fx_gx)
1865               invalid_hwcaps(arch, hwcaps,
1866                        "ISA2_07 requires VMX and FX and GX capabilities\n");
1867            if (! (hwcaps & VEX_HWCAPS_PPC64_VX))
1868               invalid_hwcaps(arch, hwcaps,
1869                              "ISA2_07 requires VX capabilities\n");
1870            if (! (hwcaps & VEX_HWCAPS_PPC64_DFP))
1871               invalid_hwcaps(arch, hwcaps,
1872                              "ISA2_07 requires DFP capabilities\n");
1873         }
1874         return;
1875      }
1876
1877      case VexArchARM: {
1878         Bool NEON  = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0);
1879         UInt level = VEX_ARM_ARCHLEVEL(hwcaps);
1880
1881         switch (level) {
1882            case 5:
1883               if (NEON)
1884                  invalid_hwcaps(arch, hwcaps,
1885                          "NEON instructions are not supported for ARMv5.\n");
1886               return;
1887            case 6:
1888               if (NEON)
1889                  invalid_hwcaps(arch, hwcaps,
1890                          "NEON instructions are not supported for ARMv6.\n");
1891               return;
1892            case 7:
1893               return;
1894            default:
1895               invalid_hwcaps(arch, hwcaps,
1896                              "ARM architecture level is not supported.\n");
1897         }
1898      }
1899
1900      case VexArchARM64:
1901         if (hwcaps != 0)
1902            invalid_hwcaps(arch, hwcaps,
1903                           "Unsupported hardware capabilities.\n");
1904         return;
1905
1906      case VexArchS390X:
1907         if (! s390_host_has_ldisp)
1908            invalid_hwcaps(arch, hwcaps,
1909                           "Host does not have long displacement facility.\n");
1910         return;
1911
1912      case VexArchMIPS32:
1913         switch (VEX_MIPS_COMP_ID(hwcaps)) {
1914            case VEX_PRID_COMP_MIPS:
1915            case VEX_PRID_COMP_BROADCOM:
1916            case VEX_PRID_COMP_NETLOGIC:
1917               return;
1918            default:
1919               invalid_hwcaps(arch, hwcaps, "Unsupported baseline\n");
1920         }
1921
1922      case VexArchMIPS64:
1923         return;
1924
1925      case VexArchTILEGX:
1926         return;
1927
1928      default:
1929         vpanic("unknown architecture");
1930   }
1931}
1932
1933
1934/*---------------------------------------------------------------*/
1935/*--- end                                         main_main.c ---*/
1936/*---------------------------------------------------------------*/
1937