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