Bug 497723 - forgot to restore callgrind output cleanup
[valgrind.git] / VEX / priv / main_main.c
blobe6c788d0cb1dcba3b9f7c7453113ef1669181d07
1 /* -*- mode: C; c-basic-offset: 3; -*- */
3 /*---------------------------------------------------------------*/
4 /*--- Begin main_main.c ---*/
5 /*---------------------------------------------------------------*/
7 /*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
11 Copyright (C) 2004-2017 OpenWorks LLP
12 info@open-works.net
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.
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.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, see <http://www.gnu.org/licenses/>.
27 The GNU General Public License is contained in the file COPYING.
29 Neither the names of the U.S. Department of Energy nor the
30 University of California nor the names of its contributors may be
31 used to endorse or promote products derived from this software
32 without prior written permission.
35 #include "libvex.h"
36 #include "libvex_emnote.h"
37 #include "libvex_guest_x86.h"
38 #include "libvex_guest_amd64.h"
39 #include "libvex_guest_arm.h"
40 #include "libvex_guest_arm64.h"
41 #include "libvex_guest_ppc32.h"
42 #include "libvex_guest_ppc64.h"
43 #include "libvex_guest_s390x.h"
44 #include "libvex_guest_mips32.h"
45 #include "libvex_guest_mips64.h"
47 #include "main_globals.h"
48 #include "main_util.h"
49 #include "host_generic_regs.h"
50 #include "ir_opt.h"
52 #include "host_x86_defs.h"
53 #include "host_amd64_defs.h"
54 #include "host_ppc_defs.h"
55 #include "host_arm_defs.h"
56 #include "host_arm64_defs.h"
57 #include "host_s390_defs.h"
58 #include "host_mips_defs.h"
59 #include "host_nanomips_defs.h"
61 #include "guest_generic_bb_to_IR.h"
62 #include "guest_x86_defs.h"
63 #include "guest_amd64_defs.h"
64 #include "guest_arm_defs.h"
65 #include "guest_arm64_defs.h"
66 #include "guest_ppc_defs.h"
67 #include "guest_s390_defs.h"
68 #include "guest_mips_defs.h"
69 #include "guest_nanomips_defs.h"
71 #include "host_generic_simd128.h"
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.
83 To still compile the below for all supported architectures, define
84 VEXMULTIARCH. This is used by the file multiarch_main_main.c */
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
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
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
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
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
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
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
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
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
158 #if defined(VGA_nanomips) || defined(VEXMULTIARCH)
159 #define NANOMIPSFN(f) f
160 #define NANOMIPSST(f) f
161 #else
162 #define NANOMIPSFN(f) NULL
163 #define NANOMIPSST(f) vassert(0)
164 #endif
166 /* This file contains the top level interface to the library. */
168 /* --------- fwds ... --------- */
170 static void check_hwcaps ( VexArch arch, UInt hwcaps );
171 static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps );
172 static IRType arch_word_size ( VexArch arch );
174 /* --------- helpers --------- */
176 __attribute__((noinline))
177 static UInt udiv32 ( UInt x, UInt y ) { return x/y; }
178 __attribute__((noinline))
179 static Int sdiv32 ( Int x, Int y ) { return x/y; }
182 /* --------- Initialise the library. --------- */
184 /* Exported to library client. */
186 void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon )
188 vex_bzero(vcon, sizeof(*vcon));
189 vcon->iropt_verbosity = 0;
190 vcon->iropt_level = 2;
191 vcon->iropt_register_updates_default = VexRegUpdUnwindregsAtMemAccess;
192 vcon->iropt_unroll_thresh = 120;
193 vcon->guest_max_insns = 60;
194 vcon->guest_chase = True;
195 vcon->regalloc_version = 3;
199 /* Exported to library client. */
201 void LibVEX_Init (
202 /* failure exit function */
203 __attribute__ ((noreturn))
204 void (*failure_exit) ( void ),
205 /* logging output function */
206 void (*log_bytes) ( const HChar*, SizeT nbytes ),
207 /* debug paranoia level */
208 Int debuglevel,
209 /* Control ... */
210 const VexControl* vcon
213 /* First off, do enough minimal setup so that the following
214 assertions can fail in a sane fashion, if need be. */
215 vex_failure_exit = failure_exit;
216 vex_log_bytes = log_bytes;
218 /* Now it's safe to check parameters for sanity. */
219 vassert(!vex_initdone);
220 vassert(failure_exit);
221 vassert(log_bytes);
222 vassert(debuglevel >= 0);
224 vassert(vcon->iropt_verbosity >= 0);
225 vassert(vcon->iropt_level >= 0);
226 vassert(vcon->iropt_level <= 2);
227 vassert(vcon->iropt_unroll_thresh >= 0);
228 vassert(vcon->iropt_unroll_thresh <= 400);
229 vassert(vcon->guest_max_insns >= 1);
230 vassert(vcon->guest_max_insns <= 100);
231 vassert(vcon->guest_chase == False || vcon->guest_chase == True);
232 vassert(vcon->regalloc_version == 2 || vcon->regalloc_version == 3);
234 /* Check that Vex has been built with sizes of basic types as
235 stated in priv/libvex_basictypes.h. Failure of any of these is
236 a serious configuration error and should be corrected
237 immediately. If any of these assertions fail you can fully
238 expect Vex not to work properly, if at all. */
240 vassert(1 == sizeof(UChar));
241 vassert(1 == sizeof(Char));
242 vassert(2 == sizeof(UShort));
243 vassert(2 == sizeof(Short));
244 vassert(4 == sizeof(UInt));
245 vassert(4 == sizeof(Int));
246 vassert(8 == sizeof(ULong));
247 vassert(8 == sizeof(Long));
248 vassert(4 == sizeof(Float));
249 vassert(8 == sizeof(Double));
250 vassert(1 == sizeof(Bool));
251 vassert(4 == sizeof(Addr32));
252 vassert(8 == sizeof(Addr64));
253 vassert(16 == sizeof(U128));
254 vassert(16 == sizeof(V128));
255 vassert(32 == sizeof(U256));
257 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
258 vassert(sizeof(void*) == sizeof(int*));
259 vassert(sizeof(void*) == sizeof(HWord));
260 vassert(sizeof(void*) == sizeof(Addr));
261 vassert(sizeof(unsigned long) == sizeof(SizeT));
263 vassert(VEX_HOST_WORDSIZE == sizeof(void*));
264 vassert(VEX_HOST_WORDSIZE == sizeof(HWord));
266 /* These take a lot of space, so make sure we don't have
267 any unnoticed size regressions. */
268 if (VEX_HOST_WORDSIZE == 4) {
269 vassert(sizeof(IRExpr) == 16);
270 vassert(sizeof(IRStmt) == 20 /* x86 */
271 || sizeof(IRStmt) == 24 /* arm */);
272 } else {
273 vassert(sizeof(IRExpr) == 32);
274 vassert(sizeof(IRStmt) == 32);
277 /* Ditto */
278 vassert(sizeof(HReg) == 4);
279 /* If N_RREGUNIVERSE_REGS ever exceeds 64, the bitset fields in
280 RRegSet and HRegUsage will need to be changed to something
281 better than ULong. */
282 vassert(N_RREGUNIVERSE_REGS == 64);
284 /* Check that signed integer division on the host rounds towards
285 zero. If not, h_calc_sdiv32_w_arm_semantics() won't work
286 correctly. */
287 /* 100.0 / 7.0 == 14.2857 */
288 vassert(udiv32(100, 7) == 14);
289 vassert(sdiv32(100, 7) == 14);
290 vassert(sdiv32(-100, 7) == -14); /* and not -15 */
291 vassert(sdiv32(100, -7) == -14); /* ditto */
292 vassert(sdiv32(-100, -7) == 14); /* not sure what this proves */
294 /* Really start up .. */
295 vex_debuglevel = debuglevel;
296 vex_control = *vcon;
297 vex_initdone = True;
298 vexSetAllocMode ( VexAllocModeTEMP );
302 /* --------- Make a translation. --------- */
304 /* KLUDGE: S390 need to know the hwcaps of the host when generating
305 code. But that info is not passed to emit_S390Instr. Only mode64 is
306 being passed. So, ideally, we want this passed as an argument, too.
307 Until then, we use a global variable. This variable is set as a side
308 effect of LibVEX_Translate. The variable is defined here rather than
309 in host_s390_defs.c to avoid having main_main.c dragging S390
310 object files in non VEXMULTIARCH. */
311 UInt s390_host_hwcaps;
314 /* Exported to library client. */
316 IRSB* LibVEX_FrontEnd ( /*MOD*/ VexTranslateArgs* vta,
317 /*OUT*/ VexTranslateResult* res,
318 /*OUT*/ VexRegisterUpdates* pxControl)
320 IRExpr* (*specHelper) ( const HChar*, IRExpr**, IRStmt**, Int );
321 Bool (*preciseMemExnsFn) ( Int, Int, VexRegisterUpdates );
322 DisOneInstrFn disInstrFn;
324 VexGuestLayout* guest_layout;
325 IRSB* irsb;
326 Int i;
327 Int offB_CMSTART, offB_CMLEN, offB_GUEST_IP, szB_GUEST_IP;
328 IRType guest_word_type;
329 IRType host_word_type;
331 guest_layout = NULL;
332 specHelper = NULL;
333 disInstrFn = NULL;
334 preciseMemExnsFn = NULL;
335 guest_word_type = arch_word_size(vta->arch_guest);
336 host_word_type = arch_word_size(vta->arch_host);
337 offB_CMSTART = 0;
338 offB_CMLEN = 0;
339 offB_GUEST_IP = 0;
340 szB_GUEST_IP = 0;
342 vassert(vex_initdone);
343 vassert(vta->needs_self_check != NULL);
344 vassert(vta->disp_cp_xassisted != NULL);
345 /* Both the chainers and the indir are either NULL or non-NULL. */
346 if (vta->disp_cp_chain_me_to_slowEP != NULL) {
347 vassert(vta->disp_cp_chain_me_to_fastEP != NULL);
348 vassert(vta->disp_cp_xindir != NULL);
349 } else {
350 vassert(vta->disp_cp_chain_me_to_fastEP == NULL);
351 vassert(vta->disp_cp_xindir == NULL);
354 vexSetAllocModeTEMP_and_clear();
355 vexAllocSanityCheck();
357 vex_traceflags = vta->traceflags;
359 /* KLUDGE: export hwcaps. */
360 if (vta->arch_host == VexArchS390X) {
361 s390_host_hwcaps = vta->archinfo_host.hwcaps;
364 /* First off, check that the guest and host insn sets
365 are supported. */
367 switch (vta->arch_guest) {
369 case VexArchX86:
370 preciseMemExnsFn
371 = X86FN(guest_x86_state_requires_precise_mem_exns);
372 disInstrFn = X86FN(disInstr_X86);
373 specHelper = X86FN(guest_x86_spechelper);
374 guest_layout = X86FN(&x86guest_layout);
375 offB_CMSTART = offsetof(VexGuestX86State,guest_CMSTART);
376 offB_CMLEN = offsetof(VexGuestX86State,guest_CMLEN);
377 offB_GUEST_IP = offsetof(VexGuestX86State,guest_EIP);
378 szB_GUEST_IP = sizeof( ((VexGuestX86State*)0)->guest_EIP );
379 vassert(vta->archinfo_guest.endness == VexEndnessLE);
380 vassert(0 == sizeof(VexGuestX86State) % LibVEX_GUEST_STATE_ALIGN);
381 vassert(sizeof( ((VexGuestX86State*)0)->guest_CMSTART) == 4);
382 vassert(sizeof( ((VexGuestX86State*)0)->guest_CMLEN ) == 4);
383 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
384 break;
386 case VexArchAMD64:
387 preciseMemExnsFn
388 = AMD64FN(guest_amd64_state_requires_precise_mem_exns);
389 disInstrFn = AMD64FN(disInstr_AMD64);
390 specHelper = AMD64FN(guest_amd64_spechelper);
391 guest_layout = AMD64FN(&amd64guest_layout);
392 offB_CMSTART = offsetof(VexGuestAMD64State,guest_CMSTART);
393 offB_CMLEN = offsetof(VexGuestAMD64State,guest_CMLEN);
394 offB_GUEST_IP = offsetof(VexGuestAMD64State,guest_RIP);
395 szB_GUEST_IP = sizeof( ((VexGuestAMD64State*)0)->guest_RIP );
396 vassert(vta->archinfo_guest.endness == VexEndnessLE);
397 vassert(0 == sizeof(VexGuestAMD64State) % LibVEX_GUEST_STATE_ALIGN);
398 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_CMSTART ) == 8);
399 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_CMLEN ) == 8);
400 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8);
401 break;
403 case VexArchPPC32:
404 preciseMemExnsFn
405 = PPC32FN(guest_ppc32_state_requires_precise_mem_exns);
406 disInstrFn = PPC32FN(disInstr_PPC);
407 specHelper = PPC32FN(guest_ppc32_spechelper);
408 guest_layout = PPC32FN(&ppc32Guest_layout);
409 offB_CMSTART = offsetof(VexGuestPPC32State,guest_CMSTART);
410 offB_CMLEN = offsetof(VexGuestPPC32State,guest_CMLEN);
411 offB_GUEST_IP = offsetof(VexGuestPPC32State,guest_CIA);
412 szB_GUEST_IP = sizeof( ((VexGuestPPC32State*)0)->guest_CIA );
413 vassert(vta->archinfo_guest.endness == VexEndnessBE);
414 vassert(0 == sizeof(VexGuestPPC32State) % LibVEX_GUEST_STATE_ALIGN);
415 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_CMSTART ) == 4);
416 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_CMLEN ) == 4);
417 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4);
418 break;
420 case VexArchPPC64:
421 preciseMemExnsFn
422 = PPC64FN(guest_ppc64_state_requires_precise_mem_exns);
423 disInstrFn = PPC64FN(disInstr_PPC);
424 specHelper = PPC64FN(guest_ppc64_spechelper);
425 guest_layout = PPC64FN(&ppc64Guest_layout);
426 offB_CMSTART = offsetof(VexGuestPPC64State,guest_CMSTART);
427 offB_CMLEN = offsetof(VexGuestPPC64State,guest_CMLEN);
428 offB_GUEST_IP = offsetof(VexGuestPPC64State,guest_CIA);
429 szB_GUEST_IP = sizeof( ((VexGuestPPC64State*)0)->guest_CIA );
430 vassert(vta->archinfo_guest.endness == VexEndnessBE ||
431 vta->archinfo_guest.endness == VexEndnessLE );
432 vassert(0 == sizeof(VexGuestPPC64State) % LibVEX_GUEST_STATE_ALIGN);
433 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_CMSTART ) == 8);
434 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_CMLEN ) == 8);
435 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8);
436 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8);
437 break;
439 case VexArchS390X:
440 preciseMemExnsFn
441 = S390FN(guest_s390x_state_requires_precise_mem_exns);
442 disInstrFn = S390FN(disInstr_S390);
443 specHelper = S390FN(guest_s390x_spechelper);
444 guest_layout = S390FN(&s390xGuest_layout);
445 offB_CMSTART = offsetof(VexGuestS390XState,guest_CMSTART);
446 offB_CMLEN = offsetof(VexGuestS390XState,guest_CMLEN);
447 offB_GUEST_IP = offsetof(VexGuestS390XState,guest_IA);
448 szB_GUEST_IP = sizeof( ((VexGuestS390XState*)0)->guest_IA);
449 vassert(vta->archinfo_guest.endness == VexEndnessBE);
450 vassert(0 == sizeof(VexGuestS390XState) % LibVEX_GUEST_STATE_ALIGN);
451 vassert(sizeof( ((VexGuestS390XState*)0)->guest_CMSTART ) == 8);
452 vassert(sizeof( ((VexGuestS390XState*)0)->guest_CMLEN ) == 8);
453 vassert(sizeof( ((VexGuestS390XState*)0)->guest_NRADDR ) == 8);
454 break;
456 case VexArchARM:
457 preciseMemExnsFn
458 = ARMFN(guest_arm_state_requires_precise_mem_exns);
459 disInstrFn = ARMFN(disInstr_ARM);
460 specHelper = ARMFN(guest_arm_spechelper);
461 guest_layout = ARMFN(&armGuest_layout);
462 offB_CMSTART = offsetof(VexGuestARMState,guest_CMSTART);
463 offB_CMLEN = offsetof(VexGuestARMState,guest_CMLEN);
464 offB_GUEST_IP = offsetof(VexGuestARMState,guest_R15T);
465 szB_GUEST_IP = sizeof( ((VexGuestARMState*)0)->guest_R15T );
466 vassert(vta->archinfo_guest.endness == VexEndnessLE);
467 vassert(0 == sizeof(VexGuestARMState) % LibVEX_GUEST_STATE_ALIGN);
468 vassert(sizeof( ((VexGuestARMState*)0)->guest_CMSTART) == 4);
469 vassert(sizeof( ((VexGuestARMState*)0)->guest_CMLEN ) == 4);
470 vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4);
471 break;
473 case VexArchARM64:
474 preciseMemExnsFn
475 = ARM64FN(guest_arm64_state_requires_precise_mem_exns);
476 disInstrFn = ARM64FN(disInstr_ARM64);
477 specHelper = ARM64FN(guest_arm64_spechelper);
478 guest_layout = ARM64FN(&arm64Guest_layout);
479 offB_CMSTART = offsetof(VexGuestARM64State,guest_CMSTART);
480 offB_CMLEN = offsetof(VexGuestARM64State,guest_CMLEN);
481 offB_GUEST_IP = offsetof(VexGuestARM64State,guest_PC);
482 szB_GUEST_IP = sizeof( ((VexGuestARM64State*)0)->guest_PC );
483 vassert(vta->archinfo_guest.endness == VexEndnessLE);
484 vassert(0 == sizeof(VexGuestARM64State) % LibVEX_GUEST_STATE_ALIGN);
485 vassert(sizeof( ((VexGuestARM64State*)0)->guest_CMSTART) == 8);
486 vassert(sizeof( ((VexGuestARM64State*)0)->guest_CMLEN ) == 8);
487 vassert(sizeof( ((VexGuestARM64State*)0)->guest_NRADDR ) == 8);
488 break;
490 case VexArchMIPS32:
491 preciseMemExnsFn
492 = MIPS32FN(guest_mips32_state_requires_precise_mem_exns);
493 disInstrFn = MIPS32FN(disInstr_MIPS);
494 specHelper = MIPS32FN(guest_mips32_spechelper);
495 guest_layout = MIPS32FN(&mips32Guest_layout);
496 offB_CMSTART = offsetof(VexGuestMIPS32State,guest_CMSTART);
497 offB_CMLEN = offsetof(VexGuestMIPS32State,guest_CMLEN);
498 offB_GUEST_IP = offsetof(VexGuestMIPS32State,guest_PC);
499 szB_GUEST_IP = sizeof( ((VexGuestMIPS32State*)0)->guest_PC );
500 vassert(vta->archinfo_guest.endness == VexEndnessLE
501 || vta->archinfo_guest.endness == VexEndnessBE);
502 vassert(0 == sizeof(VexGuestMIPS32State) % LibVEX_GUEST_STATE_ALIGN);
503 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_CMSTART) == 4);
504 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_CMLEN ) == 4);
505 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_NRADDR ) == 4);
506 break;
508 case VexArchMIPS64:
509 preciseMemExnsFn
510 = MIPS64FN(guest_mips64_state_requires_precise_mem_exns);
511 disInstrFn = MIPS64FN(disInstr_MIPS);
512 specHelper = MIPS64FN(guest_mips64_spechelper);
513 guest_layout = MIPS64FN(&mips64Guest_layout);
514 offB_CMSTART = offsetof(VexGuestMIPS64State,guest_CMSTART);
515 offB_CMLEN = offsetof(VexGuestMIPS64State,guest_CMLEN);
516 offB_GUEST_IP = offsetof(VexGuestMIPS64State,guest_PC);
517 szB_GUEST_IP = sizeof( ((VexGuestMIPS64State*)0)->guest_PC );
518 vassert(vta->archinfo_guest.endness == VexEndnessLE
519 || vta->archinfo_guest.endness == VexEndnessBE);
520 vassert(0 == sizeof(VexGuestMIPS64State) % LibVEX_GUEST_STATE_ALIGN);
521 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_CMSTART) == 8);
522 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_CMLEN ) == 8);
523 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_NRADDR ) == 8);
524 break;
526 case VexArchNANOMIPS:
527 preciseMemExnsFn
528 = NANOMIPSFN(guest_mips32_state_requires_precise_mem_exns);
529 disInstrFn = NANOMIPSFN(disInstr_nanoMIPS);
530 specHelper = NANOMIPSFN(guest_mips32_spechelper);
531 guest_layout = NANOMIPSFN(&mips32Guest_layout);
532 offB_CMSTART = offsetof(VexGuestMIPS32State,guest_CMSTART);
533 offB_CMLEN = offsetof(VexGuestMIPS32State,guest_CMLEN);
534 offB_GUEST_IP = offsetof(VexGuestMIPS32State,guest_PC);
535 szB_GUEST_IP = sizeof( ((VexGuestMIPS32State*)0)->guest_PC );
536 vassert(vta->archinfo_guest.endness == VexEndnessLE
537 || vta->archinfo_guest.endness == VexEndnessBE);
538 vassert(0 == sizeof(VexGuestMIPS32State) % LibVEX_GUEST_STATE_ALIGN);
539 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_CMSTART) == 4);
540 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_CMLEN ) == 4);
541 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_NRADDR ) == 4);
542 break;
544 default:
545 vpanic("LibVEX_Translate: unsupported guest insn set");
548 // Are the guest's hardware capabilities feasible. The function will
549 // not return if hwcaps are infeasible in some sense.
550 // FIXME: how can we know the guest's hardware capabilities?
551 check_hwcaps(vta->arch_guest, vta->archinfo_guest.hwcaps);
553 res->status = VexTransOK;
554 res->n_sc_extents = 0;
555 res->offs_profInc = -1;
556 res->n_guest_instrs = 0;
557 res->n_uncond_in_trace = 0;
558 res->n_cond_in_trace = 0;
560 #ifndef VEXMULTIARCH
561 /* yet more sanity checks ... */
562 if (vta->arch_guest == vta->arch_host) {
563 /* doesn't necessarily have to be true, but if it isn't it means
564 we are simulating one flavour of an architecture a different
565 flavour of the same architecture, which is pretty strange. */
566 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps);
567 /* ditto */
568 vassert(vta->archinfo_guest.endness == vta->archinfo_host.endness);
570 #endif
572 vexAllocSanityCheck();
574 if (vex_traceflags & VEX_TRACE_FE)
575 vex_printf("\n------------------------"
576 " Front end "
577 "------------------------\n\n");
579 *pxControl = vex_control.iropt_register_updates_default;
580 vassert(*pxControl >= VexRegUpdSpAtMemAccess
581 && *pxControl <= VexRegUpdAllregsAtEachInsn);
583 irsb = bb_to_IR ( vta->guest_extents,
584 &res->n_sc_extents,
585 &res->n_guest_instrs,
586 &res->n_uncond_in_trace,
587 &res->n_cond_in_trace,
588 pxControl,
589 vta->callback_opaque,
590 disInstrFn,
591 vta->guest_bytes,
592 vta->guest_bytes_addr,
593 vta->chase_into_ok,
594 vta->archinfo_host.endness,
595 vta->sigill_diag,
596 vta->arch_guest,
597 &vta->archinfo_guest,
598 &vta->abiinfo_both,
599 guest_word_type,
600 vta->needs_self_check,
601 vta->preamble_function,
602 offB_CMSTART,
603 offB_CMLEN,
604 offB_GUEST_IP,
605 szB_GUEST_IP );
607 vexAllocSanityCheck();
609 if (irsb == NULL) {
610 /* Access failure. */
611 vexSetAllocModeTEMP_and_clear();
612 return NULL;
615 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3);
616 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr);
617 for (i = 0; i < vta->guest_extents->n_used; i++) {
618 vassert(vta->guest_extents->len[i] < 10000); /* sanity */
621 /* bb_to_IR() could have caused pxControl to change. */
622 vassert(*pxControl >= VexRegUpdSpAtMemAccess
623 && *pxControl <= VexRegUpdAllregsAtEachInsn);
625 /* If debugging, show the raw guest bytes for this bb. */
626 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
627 if (vta->guest_extents->n_used > 1) {
628 vex_printf("can't show code due to extents > 1\n");
629 } else {
630 /* HACK */
631 const UChar* p = vta->guest_bytes;
632 UInt sum = 0;
633 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0];
634 vex_printf("GuestBytes %lx %u ", vta->guest_bytes_addr,
635 guest_bytes_read );
636 for (i = 0; i < guest_bytes_read; i++) {
637 UInt b = (UInt)p[i];
638 vex_printf(" %02x", b );
639 sum = (sum << 1) ^ b;
641 vex_printf(" %08x\n\n", sum);
645 /* Sanity check the initial IR. */
646 sanityCheckIRSB( irsb, "initial IR",
647 False/*can be non-flat*/, guest_word_type );
649 vexAllocSanityCheck();
651 /* Clean it up, hopefully a lot. */
652 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn, *pxControl,
653 vta->guest_bytes_addr,
654 vta->arch_guest );
656 // JRS 2016 Aug 03: Sanity checking is expensive, we already checked
657 // the output of the front end, and iropt never screws up the IR by
658 // itself, unless it is being hacked on. So remove this post-iropt
659 // check in "production" use.
660 // sanityCheckIRSB( irsb, "after initial iropt",
661 // True/*must be flat*/, guest_word_type );
663 if (vex_traceflags & VEX_TRACE_OPT1) {
664 vex_printf("\n------------------------"
665 " After pre-instr IR optimisation "
666 "------------------------\n\n");
667 ppIRSB ( irsb );
668 vex_printf("\n");
671 vexAllocSanityCheck();
673 /* Get the thing instrumented. */
674 if (vta->instrument1)
675 irsb = vta->instrument1(vta->callback_opaque,
676 irsb, guest_layout,
677 vta->guest_extents,
678 &vta->archinfo_host,
679 guest_word_type, host_word_type);
680 vexAllocSanityCheck();
682 if (vta->instrument2)
683 irsb = vta->instrument2(vta->callback_opaque,
684 irsb, guest_layout,
685 vta->guest_extents,
686 &vta->archinfo_host,
687 guest_word_type, host_word_type);
689 if (vex_traceflags & VEX_TRACE_INST) {
690 vex_printf("\n------------------------"
691 " After instrumentation "
692 "------------------------\n\n");
693 ppIRSB ( irsb );
694 vex_printf("\n");
697 // JRS 2016 Aug 03: as above, this never actually fails in practice.
698 // And we'll sanity check anyway after the post-instrumentation
699 // cleanup pass. So skip this check in "production" use.
700 // if (vta->instrument1 || vta->instrument2)
701 // sanityCheckIRSB( irsb, "after instrumentation",
702 // True/*must be flat*/, guest_word_type );
704 /* Do a post-instrumentation cleanup pass. */
705 if (vta->instrument1 || vta->instrument2) {
706 do_deadcode_BB( irsb );
707 irsb = cprop_BB( irsb );
708 do_deadcode_BB( irsb );
709 sanityCheckIRSB( irsb, "after post-instrumentation cleanup",
710 True/*must be flat*/, guest_word_type );
713 vexAllocSanityCheck();
715 if (vex_traceflags & VEX_TRACE_OPT2) {
716 vex_printf("\n------------------------"
717 " After post-instr IR optimisation "
718 "------------------------\n\n");
719 ppIRSB ( irsb );
720 vex_printf("\n");
723 return irsb;
727 /* Back end of the compilation pipeline. Is not exported. */
729 static void libvex_BackEnd ( const VexTranslateArgs *vta,
730 /*MOD*/ VexTranslateResult* res,
731 /*MOD*/ IRSB* irsb,
732 VexRegisterUpdates pxControl )
734 /* This the bundle of functions we need to do the back-end stuff
735 (insn selection, reg-alloc, assembly) whilst being insulated
736 from the target instruction set. */
737 void (*getRegUsage) ( HRegUsage*, const HInstr*, Bool );
738 void (*mapRegs) ( HRegRemap*, HInstr*, Bool );
739 void (*genSpill) ( HInstr**, HInstr**, HReg, Int, Bool );
740 void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool );
741 HInstr* (*genMove) ( HReg, HReg, Bool );
742 HInstr* (*directReload) ( HInstr*, HReg, Short );
743 void (*ppInstr) ( const HInstr*, Bool );
744 UInt (*ppReg) ( HReg );
745 HInstrArray* (*iselSB) ( const IRSB*, VexArch, const VexArchInfo*,
746 const VexAbiInfo*, Int, Int, Bool, Bool,
747 Addr );
748 Int (*emit) ( /*MB_MOD*/Bool*,
749 UChar*, Int, const HInstr*, Bool, VexEndness,
750 const void*, const void*, const void*,
751 const void* );
752 Bool (*preciseMemExnsFn) ( Int, Int, VexRegisterUpdates );
754 const RRegUniverse* rRegUniv = NULL;
756 Bool mode64, chainingAllowed;
757 Int i, j, k, out_used;
758 Int guest_sizeB;
759 Int offB_HOST_EvC_COUNTER;
760 Int offB_HOST_EvC_FAILADDR;
761 Addr max_ga;
762 UChar insn_bytes[128];
763 HInstrArray* vcode;
764 HInstrArray* rcode;
766 getRegUsage = NULL;
767 mapRegs = NULL;
768 genSpill = NULL;
769 genReload = NULL;
770 genMove = NULL;
771 directReload = NULL;
772 ppInstr = NULL;
773 ppReg = NULL;
774 iselSB = NULL;
775 emit = NULL;
777 mode64 = False;
778 chainingAllowed = False;
779 guest_sizeB = 0;
780 offB_HOST_EvC_COUNTER = 0;
781 offB_HOST_EvC_FAILADDR = 0;
782 preciseMemExnsFn = NULL;
784 vassert(vex_initdone);
785 vassert(vta->disp_cp_xassisted != NULL);
787 vex_traceflags = vta->traceflags;
789 /* Both the chainers and the indir are either NULL or non-NULL. */
790 if (vta->disp_cp_chain_me_to_slowEP != NULL) {
791 vassert(vta->disp_cp_chain_me_to_fastEP != NULL);
792 vassert(vta->disp_cp_xindir != NULL);
793 chainingAllowed = True;
794 } else {
795 vassert(vta->disp_cp_chain_me_to_fastEP == NULL);
796 vassert(vta->disp_cp_xindir == NULL);
799 switch (vta->arch_guest) {
801 case VexArchX86:
802 preciseMemExnsFn
803 = X86FN(guest_x86_state_requires_precise_mem_exns);
804 guest_sizeB = sizeof(VexGuestX86State);
805 offB_HOST_EvC_COUNTER = offsetof(VexGuestX86State,host_EvC_COUNTER);
806 offB_HOST_EvC_FAILADDR = offsetof(VexGuestX86State,host_EvC_FAILADDR);
807 break;
809 case VexArchAMD64:
810 preciseMemExnsFn
811 = AMD64FN(guest_amd64_state_requires_precise_mem_exns);
812 guest_sizeB = sizeof(VexGuestAMD64State);
813 offB_HOST_EvC_COUNTER = offsetof(VexGuestAMD64State,host_EvC_COUNTER);
814 offB_HOST_EvC_FAILADDR = offsetof(VexGuestAMD64State,host_EvC_FAILADDR);
815 break;
817 case VexArchPPC32:
818 preciseMemExnsFn
819 = PPC32FN(guest_ppc32_state_requires_precise_mem_exns);
820 guest_sizeB = sizeof(VexGuestPPC32State);
821 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC32State,host_EvC_COUNTER);
822 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC32State,host_EvC_FAILADDR);
823 break;
825 case VexArchPPC64:
826 preciseMemExnsFn
827 = PPC64FN(guest_ppc64_state_requires_precise_mem_exns);
828 guest_sizeB = sizeof(VexGuestPPC64State);
829 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC64State,host_EvC_COUNTER);
830 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC64State,host_EvC_FAILADDR);
831 break;
833 case VexArchS390X:
834 preciseMemExnsFn
835 = S390FN(guest_s390x_state_requires_precise_mem_exns);
836 guest_sizeB = sizeof(VexGuestS390XState);
837 offB_HOST_EvC_COUNTER = offsetof(VexGuestS390XState,host_EvC_COUNTER);
838 offB_HOST_EvC_FAILADDR = offsetof(VexGuestS390XState,host_EvC_FAILADDR);
839 break;
841 case VexArchARM:
842 preciseMemExnsFn
843 = ARMFN(guest_arm_state_requires_precise_mem_exns);
844 guest_sizeB = sizeof(VexGuestARMState);
845 offB_HOST_EvC_COUNTER = offsetof(VexGuestARMState,host_EvC_COUNTER);
846 offB_HOST_EvC_FAILADDR = offsetof(VexGuestARMState,host_EvC_FAILADDR);
847 break;
849 case VexArchARM64:
850 preciseMemExnsFn
851 = ARM64FN(guest_arm64_state_requires_precise_mem_exns);
852 guest_sizeB = sizeof(VexGuestARM64State);
853 offB_HOST_EvC_COUNTER = offsetof(VexGuestARM64State,host_EvC_COUNTER);
854 offB_HOST_EvC_FAILADDR = offsetof(VexGuestARM64State,host_EvC_FAILADDR);
855 break;
857 case VexArchMIPS32:
858 preciseMemExnsFn
859 = MIPS32FN(guest_mips32_state_requires_precise_mem_exns);
860 guest_sizeB = sizeof(VexGuestMIPS32State);
861 offB_HOST_EvC_COUNTER = offsetof(VexGuestMIPS32State,host_EvC_COUNTER);
862 offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS32State,host_EvC_FAILADDR);
863 break;
865 case VexArchMIPS64:
866 preciseMemExnsFn
867 = MIPS64FN(guest_mips64_state_requires_precise_mem_exns);
868 guest_sizeB = sizeof(VexGuestMIPS64State);
869 offB_HOST_EvC_COUNTER = offsetof(VexGuestMIPS64State,host_EvC_COUNTER);
870 offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS64State,host_EvC_FAILADDR);
871 break;
873 case VexArchNANOMIPS:
874 preciseMemExnsFn
875 = NANOMIPSFN(guest_mips32_state_requires_precise_mem_exns);
876 guest_sizeB = sizeof(VexGuestMIPS32State);
877 offB_HOST_EvC_COUNTER = offsetof(VexGuestMIPS32State,host_EvC_COUNTER);
878 offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS32State,host_EvC_FAILADDR);
879 break;
881 default:
882 vpanic("LibVEX_Codegen: unsupported guest insn set");
886 switch (vta->arch_host) {
888 case VexArchX86:
889 mode64 = False;
890 rRegUniv = X86FN(getRRegUniverse_X86());
891 getRegUsage
892 = CAST_TO_TYPEOF(getRegUsage) X86FN(getRegUsage_X86Instr);
893 mapRegs = CAST_TO_TYPEOF(mapRegs) X86FN(mapRegs_X86Instr);
894 genSpill = CAST_TO_TYPEOF(genSpill) X86FN(genSpill_X86);
895 genReload = CAST_TO_TYPEOF(genReload) X86FN(genReload_X86);
896 genMove = CAST_TO_TYPEOF(genMove) X86FN(genMove_X86);
897 directReload = CAST_TO_TYPEOF(directReload) X86FN(directReload_X86);
898 ppInstr = CAST_TO_TYPEOF(ppInstr) X86FN(ppX86Instr);
899 ppReg = CAST_TO_TYPEOF(ppReg) X86FN(ppHRegX86);
900 iselSB = X86FN(iselSB_X86);
901 emit = CAST_TO_TYPEOF(emit) X86FN(emit_X86Instr);
902 vassert(vta->archinfo_host.endness == VexEndnessLE);
903 break;
905 case VexArchAMD64:
906 mode64 = True;
907 rRegUniv = AMD64FN(getRRegUniverse_AMD64());
908 getRegUsage
909 = CAST_TO_TYPEOF(getRegUsage) AMD64FN(getRegUsage_AMD64Instr);
910 mapRegs = CAST_TO_TYPEOF(mapRegs) AMD64FN(mapRegs_AMD64Instr);
911 genSpill = CAST_TO_TYPEOF(genSpill) AMD64FN(genSpill_AMD64);
912 genReload = CAST_TO_TYPEOF(genReload) AMD64FN(genReload_AMD64);
913 genMove = CAST_TO_TYPEOF(genMove) AMD64FN(genMove_AMD64);
914 directReload = CAST_TO_TYPEOF(directReload) AMD64FN(directReload_AMD64);
915 ppInstr = CAST_TO_TYPEOF(ppInstr) AMD64FN(ppAMD64Instr);
916 ppReg = CAST_TO_TYPEOF(ppReg) AMD64FN(ppHRegAMD64);
917 iselSB = AMD64FN(iselSB_AMD64);
918 emit = CAST_TO_TYPEOF(emit) AMD64FN(emit_AMD64Instr);
919 vassert(vta->archinfo_host.endness == VexEndnessLE);
920 break;
922 case VexArchPPC32:
923 mode64 = False;
924 rRegUniv = PPC32FN(getRRegUniverse_PPC(mode64));
925 getRegUsage
926 = CAST_TO_TYPEOF(getRegUsage) PPC32FN(getRegUsage_PPCInstr);
927 mapRegs = CAST_TO_TYPEOF(mapRegs) PPC32FN(mapRegs_PPCInstr);
928 genSpill = CAST_TO_TYPEOF(genSpill) PPC32FN(genSpill_PPC);
929 genReload = CAST_TO_TYPEOF(genReload) PPC32FN(genReload_PPC);
930 genMove = CAST_TO_TYPEOF(genMove) PPC32FN(genMove_PPC);
931 ppInstr = CAST_TO_TYPEOF(ppInstr) PPC32FN(ppPPCInstr);
932 ppReg = CAST_TO_TYPEOF(ppReg) PPC32FN(ppHRegPPC);
933 iselSB = PPC32FN(iselSB_PPC);
934 emit = CAST_TO_TYPEOF(emit) PPC32FN(emit_PPCInstr);
935 vassert(vta->archinfo_host.endness == VexEndnessBE);
936 break;
938 case VexArchPPC64:
939 mode64 = True;
940 rRegUniv = PPC64FN(getRRegUniverse_PPC(mode64));
941 getRegUsage
942 = CAST_TO_TYPEOF(getRegUsage) PPC64FN(getRegUsage_PPCInstr);
943 mapRegs = CAST_TO_TYPEOF(mapRegs) PPC64FN(mapRegs_PPCInstr);
944 genSpill = CAST_TO_TYPEOF(genSpill) PPC64FN(genSpill_PPC);
945 genReload = CAST_TO_TYPEOF(genReload) PPC64FN(genReload_PPC);
946 genMove = CAST_TO_TYPEOF(genMove) PPC64FN(genMove_PPC);
947 ppInstr = CAST_TO_TYPEOF(ppInstr) PPC64FN(ppPPCInstr);
948 ppReg = CAST_TO_TYPEOF(ppReg) PPC64FN(ppHRegPPC);
949 iselSB = PPC64FN(iselSB_PPC);
950 emit = CAST_TO_TYPEOF(emit) PPC64FN(emit_PPCInstr);
951 vassert(vta->archinfo_host.endness == VexEndnessBE ||
952 vta->archinfo_host.endness == VexEndnessLE );
953 break;
955 case VexArchS390X:
956 mode64 = True;
957 rRegUniv = S390FN(getRRegUniverse_S390());
958 getRegUsage
959 = CAST_TO_TYPEOF(getRegUsage) S390FN(getRegUsage_S390Instr);
960 mapRegs = CAST_TO_TYPEOF(mapRegs) S390FN(mapRegs_S390Instr);
961 genSpill = CAST_TO_TYPEOF(genSpill) S390FN(genSpill_S390);
962 genReload = CAST_TO_TYPEOF(genReload) S390FN(genReload_S390);
963 genMove = CAST_TO_TYPEOF(genMove) S390FN(genMove_S390);
964 directReload = CAST_TO_TYPEOF(directReload) S390FN(directReload_S390);
965 ppInstr = CAST_TO_TYPEOF(ppInstr) S390FN(ppS390Instr);
966 ppReg = CAST_TO_TYPEOF(ppReg) S390FN(ppHRegS390);
967 iselSB = S390FN(iselSB_S390);
968 emit = CAST_TO_TYPEOF(emit) S390FN(emit_S390Instr);
969 vassert(vta->archinfo_host.endness == VexEndnessBE);
970 break;
972 case VexArchARM:
973 mode64 = False;
974 rRegUniv = ARMFN(getRRegUniverse_ARM());
975 getRegUsage
976 = CAST_TO_TYPEOF(getRegUsage) ARMFN(getRegUsage_ARMInstr);
977 mapRegs = CAST_TO_TYPEOF(mapRegs) ARMFN(mapRegs_ARMInstr);
978 genSpill = CAST_TO_TYPEOF(genSpill) ARMFN(genSpill_ARM);
979 genReload = CAST_TO_TYPEOF(genReload) ARMFN(genReload_ARM);
980 genMove = CAST_TO_TYPEOF(genMove) ARMFN(genMove_ARM);
981 ppInstr = CAST_TO_TYPEOF(ppInstr) ARMFN(ppARMInstr);
982 ppReg = CAST_TO_TYPEOF(ppReg) ARMFN(ppHRegARM);
983 iselSB = ARMFN(iselSB_ARM);
984 emit = CAST_TO_TYPEOF(emit) ARMFN(emit_ARMInstr);
985 vassert(vta->archinfo_host.endness == VexEndnessLE);
986 break;
988 case VexArchARM64:
989 mode64 = True;
990 rRegUniv = ARM64FN(getRRegUniverse_ARM64());
991 getRegUsage
992 = CAST_TO_TYPEOF(getRegUsage) ARM64FN(getRegUsage_ARM64Instr);
993 mapRegs = CAST_TO_TYPEOF(mapRegs) ARM64FN(mapRegs_ARM64Instr);
994 genSpill = CAST_TO_TYPEOF(genSpill) ARM64FN(genSpill_ARM64);
995 genReload = CAST_TO_TYPEOF(genReload) ARM64FN(genReload_ARM64);
996 genMove = CAST_TO_TYPEOF(genMove) ARM64FN(genMove_ARM64);
997 ppInstr = CAST_TO_TYPEOF(ppInstr) ARM64FN(ppARM64Instr);
998 ppReg = CAST_TO_TYPEOF(ppReg) ARM64FN(ppHRegARM64);
999 iselSB = ARM64FN(iselSB_ARM64);
1000 emit = CAST_TO_TYPEOF(emit) ARM64FN(emit_ARM64Instr);
1001 vassert(vta->archinfo_host.endness == VexEndnessLE);
1002 break;
1004 case VexArchMIPS32:
1005 mode64 = False;
1006 rRegUniv = MIPS32FN(getRRegUniverse_MIPS(mode64));
1007 getRegUsage
1008 = CAST_TO_TYPEOF(getRegUsage) MIPS32FN(getRegUsage_MIPSInstr);
1009 mapRegs = CAST_TO_TYPEOF(mapRegs) MIPS32FN(mapRegs_MIPSInstr);
1010 genSpill = CAST_TO_TYPEOF(genSpill) MIPS32FN(genSpill_MIPS);
1011 genReload = CAST_TO_TYPEOF(genReload) MIPS32FN(genReload_MIPS);
1012 genMove = CAST_TO_TYPEOF(genMove) MIPS32FN(genMove_MIPS);
1013 ppInstr = CAST_TO_TYPEOF(ppInstr) MIPS32FN(ppMIPSInstr);
1014 ppReg = CAST_TO_TYPEOF(ppReg) MIPS32FN(ppHRegMIPS);
1015 iselSB = MIPS32FN(iselSB_MIPS);
1016 emit = CAST_TO_TYPEOF(emit) MIPS32FN(emit_MIPSInstr);
1017 vassert(vta->archinfo_host.endness == VexEndnessLE
1018 || vta->archinfo_host.endness == VexEndnessBE);
1019 break;
1021 case VexArchMIPS64:
1022 mode64 = True;
1023 rRegUniv = MIPS64FN(getRRegUniverse_MIPS(mode64));
1024 getRegUsage
1025 = CAST_TO_TYPEOF(getRegUsage) MIPS64FN(getRegUsage_MIPSInstr);
1026 mapRegs = CAST_TO_TYPEOF(mapRegs) MIPS64FN(mapRegs_MIPSInstr);
1027 genSpill = CAST_TO_TYPEOF(genSpill) MIPS64FN(genSpill_MIPS);
1028 genReload = CAST_TO_TYPEOF(genReload) MIPS64FN(genReload_MIPS);
1029 genMove = CAST_TO_TYPEOF(genMove) MIPS64FN(genMove_MIPS);
1030 ppInstr = CAST_TO_TYPEOF(ppInstr) MIPS64FN(ppMIPSInstr);
1031 ppReg = CAST_TO_TYPEOF(ppReg) MIPS64FN(ppHRegMIPS);
1032 iselSB = MIPS64FN(iselSB_MIPS);
1033 emit = CAST_TO_TYPEOF(emit) MIPS64FN(emit_MIPSInstr);
1034 vassert(vta->archinfo_host.endness == VexEndnessLE
1035 || vta->archinfo_host.endness == VexEndnessBE);
1036 break;
1038 case VexArchNANOMIPS:
1039 mode64 = False;
1040 rRegUniv = NANOMIPSFN(getRRegUniverse_NANOMIPS(mode64));
1041 getRegUsage
1042 = CAST_TO_TYPEOF(getRegUsage) NANOMIPSFN(getRegUsage_NANOMIPSInstr);
1043 mapRegs = CAST_TO_TYPEOF(mapRegs) NANOMIPSFN(mapRegs_NANOMIPSInstr);
1044 genSpill = CAST_TO_TYPEOF(genSpill) NANOMIPSFN(genSpill_NANOMIPS);
1045 genReload = CAST_TO_TYPEOF(genReload) NANOMIPSFN(genReload_NANOMIPS);
1046 genMove = CAST_TO_TYPEOF(genMove) NANOMIPSFN(genMove_NANOMIPS);
1047 ppInstr = CAST_TO_TYPEOF(ppInstr) NANOMIPSFN(ppNANOMIPSInstr);
1048 ppReg = CAST_TO_TYPEOF(ppReg) NANOMIPSFN(ppHRegNANOMIPS);
1049 iselSB = NANOMIPSFN(iselSB_NANOMIPS);
1050 emit = CAST_TO_TYPEOF(emit) NANOMIPSFN(emit_NANOMIPSInstr);
1051 vassert(vta->archinfo_host.endness == VexEndnessLE
1052 || vta->archinfo_host.endness == VexEndnessBE);
1053 break;
1055 default:
1056 vpanic("LibVEX_Translate: unsupported host insn set");
1059 // Are the host's hardware capabilities feasible. The function will
1060 // not return if hwcaps are infeasible in some sense.
1061 check_hwcaps(vta->arch_host, vta->archinfo_host.hwcaps);
1064 /* Turn it into virtual-registerised code. Build trees -- this
1065 also throws away any dead bindings. */
1066 max_ga = ado_treebuild_BB( irsb, preciseMemExnsFn, pxControl );
1068 if (vta->finaltidy) {
1069 irsb = vta->finaltidy(irsb);
1072 vexAllocSanityCheck();
1074 if (vex_traceflags & VEX_TRACE_TREES) {
1075 vex_printf("\n------------------------"
1076 " After tree-building "
1077 "------------------------\n\n");
1078 ppIRSB ( irsb );
1079 vex_printf("\n");
1082 /* HACK */
1083 if (0) {
1084 *(vta->host_bytes_used) = 0;
1085 res->status = VexTransOK; return;
1087 /* end HACK */
1089 if (vex_traceflags & VEX_TRACE_VCODE)
1090 vex_printf("\n------------------------"
1091 " Instruction selection "
1092 "------------------------\n");
1094 /* No guest has its IP field at offset zero. If this fails it
1095 means some transformation pass somewhere failed to update/copy
1096 irsb->offsIP properly. */
1097 vassert(irsb->offsIP >= 16);
1099 vcode = iselSB ( irsb, vta->arch_host,
1100 &vta->archinfo_host,
1101 &vta->abiinfo_both,
1102 offB_HOST_EvC_COUNTER,
1103 offB_HOST_EvC_FAILADDR,
1104 chainingAllowed,
1105 vta->addProfInc,
1106 max_ga );
1108 vexAllocSanityCheck();
1110 if (vex_traceflags & VEX_TRACE_VCODE)
1111 vex_printf("\n");
1113 if (vex_traceflags & VEX_TRACE_VCODE) {
1114 for (i = 0; i < vcode->arr_used; i++) {
1115 vex_printf("%3d ", i);
1116 ppInstr(vcode->arr[i], mode64);
1117 vex_printf("\n");
1119 vex_printf("\n");
1122 /* Register allocate. */
1123 RegAllocControl con = {
1124 .univ = rRegUniv, .getRegUsage = getRegUsage, .mapRegs = mapRegs,
1125 .genSpill = genSpill, .genReload = genReload, .genMove = genMove,
1126 .directReload = directReload, .guest_sizeB = guest_sizeB,
1127 .ppInstr = ppInstr, .ppReg = ppReg, .mode64 = mode64};
1128 switch (vex_control.regalloc_version) {
1129 case 2:
1130 rcode = doRegisterAllocation_v2(vcode, &con);
1131 break;
1132 case 3:
1133 rcode = doRegisterAllocation_v3(vcode, &con);
1134 break;
1135 default:
1136 vassert(0);
1139 vexAllocSanityCheck();
1141 if (vex_traceflags & VEX_TRACE_RCODE) {
1142 vex_printf("\n------------------------"
1143 " Register-allocated code "
1144 "------------------------\n\n");
1145 for (i = 0; i < rcode->arr_used; i++) {
1146 vex_printf("%3d ", i);
1147 ppInstr(rcode->arr[i], mode64);
1148 vex_printf("\n");
1150 vex_printf("\n");
1153 /* HACK */
1154 if (0) {
1155 *(vta->host_bytes_used) = 0;
1156 res->status = VexTransOK; return;
1158 /* end HACK */
1160 /* Assemble */
1161 if (vex_traceflags & VEX_TRACE_ASM) {
1162 vex_printf("\n------------------------"
1163 " Assembly "
1164 "------------------------\n\n");
1167 out_used = 0; /* tracks along the host_bytes array */
1168 for (i = 0; i < rcode->arr_used; i++) {
1169 HInstr* hi = rcode->arr[i];
1170 Bool hi_isProfInc = False;
1171 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
1172 ppInstr(hi, mode64);
1173 vex_printf("\n");
1175 j = emit( &hi_isProfInc,
1176 insn_bytes, sizeof insn_bytes, hi,
1177 mode64, vta->archinfo_host.endness,
1178 vta->disp_cp_chain_me_to_slowEP,
1179 vta->disp_cp_chain_me_to_fastEP,
1180 vta->disp_cp_xindir,
1181 vta->disp_cp_xassisted );
1182 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
1183 for (k = 0; k < j; k++)
1184 vex_printf("%02x ", (UInt)insn_bytes[k]);
1185 vex_printf("\n\n");
1187 if (UNLIKELY(out_used + j > vta->host_bytes_size)) {
1188 vexSetAllocModeTEMP_and_clear();
1189 vex_traceflags = 0;
1190 res->status = VexTransOutputFull;
1191 return;
1193 if (UNLIKELY(hi_isProfInc)) {
1194 vassert(vta->addProfInc); /* else where did it come from? */
1195 vassert(res->offs_profInc == -1); /* there can be only one (tm) */
1196 vassert(out_used >= 0);
1197 res->offs_profInc = out_used;
1199 { UChar* dst = &vta->host_bytes[out_used];
1200 for (k = 0; k < j; k++) {
1201 dst[k] = insn_bytes[k];
1203 out_used += j;
1206 *(vta->host_bytes_used) = out_used;
1208 vexAllocSanityCheck();
1210 vexSetAllocModeTEMP_and_clear();
1212 if (vex_traceflags) {
1213 /* Print the expansion ratio for this SB. */
1214 j = 0; /* total guest bytes */
1215 for (i = 0; i < vta->guest_extents->n_used; i++) {
1216 j += vta->guest_extents->len[i];
1218 if (1) vex_printf("VexExpansionRatio %d %d %d :10\n\n",
1219 j, out_used, (10 * out_used) / (j == 0 ? 1 : j));
1222 vex_traceflags = 0;
1223 res->status = VexTransOK;
1224 return;
1228 /* Exported to library client. */
1230 VexTranslateResult LibVEX_Translate ( /*MOD*/ VexTranslateArgs* vta )
1232 VexTranslateResult res = { 0 };
1233 VexRegisterUpdates pxControl = VexRegUpd_INVALID;
1235 IRSB* irsb = LibVEX_FrontEnd(vta, &res, &pxControl);
1236 libvex_BackEnd(vta, &res, irsb, pxControl);
1237 return res;
1241 /* --------- Chain/Unchain XDirects. --------- */
1243 VexInvalRange LibVEX_Chain ( VexArch arch_host,
1244 VexEndness endness_host,
1245 void* place_to_chain,
1246 const void* disp_cp_chain_me_EXPECTED,
1247 const void* place_to_jump_to )
1249 switch (arch_host) {
1250 case VexArchX86:
1251 X86ST(return chainXDirect_X86(endness_host,
1252 place_to_chain,
1253 disp_cp_chain_me_EXPECTED,
1254 place_to_jump_to));
1255 case VexArchAMD64:
1256 AMD64ST(return chainXDirect_AMD64(endness_host,
1257 place_to_chain,
1258 disp_cp_chain_me_EXPECTED,
1259 place_to_jump_to));
1260 case VexArchARM:
1261 ARMST(return chainXDirect_ARM(endness_host,
1262 place_to_chain,
1263 disp_cp_chain_me_EXPECTED,
1264 place_to_jump_to));
1265 case VexArchARM64:
1266 ARM64ST(return chainXDirect_ARM64(endness_host,
1267 place_to_chain,
1268 disp_cp_chain_me_EXPECTED,
1269 place_to_jump_to));
1270 case VexArchS390X:
1271 S390ST(return chainXDirect_S390(endness_host,
1272 place_to_chain,
1273 disp_cp_chain_me_EXPECTED,
1274 place_to_jump_to));
1275 case VexArchPPC32:
1276 PPC32ST(return chainXDirect_PPC(endness_host,
1277 place_to_chain,
1278 disp_cp_chain_me_EXPECTED,
1279 place_to_jump_to, False/*!mode64*/));
1280 case VexArchPPC64:
1281 PPC64ST(return chainXDirect_PPC(endness_host,
1282 place_to_chain,
1283 disp_cp_chain_me_EXPECTED,
1284 place_to_jump_to, True/*mode64*/));
1285 case VexArchMIPS32:
1286 MIPS32ST(return chainXDirect_MIPS(endness_host,
1287 place_to_chain,
1288 disp_cp_chain_me_EXPECTED,
1289 place_to_jump_to, False/*!mode64*/));
1290 case VexArchMIPS64:
1291 MIPS64ST(return chainXDirect_MIPS(endness_host,
1292 place_to_chain,
1293 disp_cp_chain_me_EXPECTED,
1294 place_to_jump_to, True/*!mode64*/));
1295 case VexArchNANOMIPS:
1296 NANOMIPSST(return chainXDirect_NANOMIPS(endness_host,
1297 place_to_chain,
1298 disp_cp_chain_me_EXPECTED,
1299 place_to_jump_to));
1300 default:
1301 vassert(0);
1305 VexInvalRange LibVEX_UnChain ( VexArch arch_host,
1306 VexEndness endness_host,
1307 void* place_to_unchain,
1308 const void* place_to_jump_to_EXPECTED,
1309 const void* disp_cp_chain_me )
1311 switch (arch_host) {
1312 case VexArchX86:
1313 X86ST(return unchainXDirect_X86(endness_host,
1314 place_to_unchain,
1315 place_to_jump_to_EXPECTED,
1316 disp_cp_chain_me));
1317 case VexArchAMD64:
1318 AMD64ST(return unchainXDirect_AMD64(endness_host,
1319 place_to_unchain,
1320 place_to_jump_to_EXPECTED,
1321 disp_cp_chain_me));
1322 case VexArchARM:
1323 ARMST(return unchainXDirect_ARM(endness_host,
1324 place_to_unchain,
1325 place_to_jump_to_EXPECTED,
1326 disp_cp_chain_me));
1327 case VexArchARM64:
1328 ARM64ST(return unchainXDirect_ARM64(endness_host,
1329 place_to_unchain,
1330 place_to_jump_to_EXPECTED,
1331 disp_cp_chain_me));
1332 case VexArchS390X:
1333 S390ST(return unchainXDirect_S390(endness_host,
1334 place_to_unchain,
1335 place_to_jump_to_EXPECTED,
1336 disp_cp_chain_me));
1337 case VexArchPPC32:
1338 PPC32ST(return unchainXDirect_PPC(endness_host,
1339 place_to_unchain,
1340 place_to_jump_to_EXPECTED,
1341 disp_cp_chain_me, False/*!mode64*/));
1342 case VexArchPPC64:
1343 PPC64ST(return unchainXDirect_PPC(endness_host,
1344 place_to_unchain,
1345 place_to_jump_to_EXPECTED,
1346 disp_cp_chain_me, True/*mode64*/));
1347 case VexArchMIPS32:
1348 MIPS32ST(return unchainXDirect_MIPS(endness_host,
1349 place_to_unchain,
1350 place_to_jump_to_EXPECTED,
1351 disp_cp_chain_me, False/*!mode64*/));
1352 case VexArchMIPS64:
1353 MIPS64ST(return unchainXDirect_MIPS(endness_host,
1354 place_to_unchain,
1355 place_to_jump_to_EXPECTED,
1356 disp_cp_chain_me, True/*!mode64*/));
1357 case VexArchNANOMIPS:
1358 NANOMIPSST(return unchainXDirect_NANOMIPS(endness_host,
1359 place_to_unchain,
1360 place_to_jump_to_EXPECTED,
1361 disp_cp_chain_me));
1362 default:
1363 vassert(0);
1367 Int LibVEX_evCheckSzB ( VexArch arch_host )
1369 static Int cached = 0; /* DO NOT MAKE NON-STATIC */
1370 if (UNLIKELY(cached == 0)) {
1371 switch (arch_host) {
1372 case VexArchX86:
1373 X86ST(cached = evCheckSzB_X86()); break;
1374 case VexArchAMD64:
1375 AMD64ST(cached = evCheckSzB_AMD64()); break;
1376 case VexArchARM:
1377 ARMST(cached = evCheckSzB_ARM()); break;
1378 case VexArchARM64:
1379 ARM64ST(cached = evCheckSzB_ARM64()); break;
1380 case VexArchS390X:
1381 S390ST(cached = evCheckSzB_S390()); break;
1382 case VexArchPPC32:
1383 PPC32ST(cached = evCheckSzB_PPC()); break;
1384 case VexArchPPC64:
1385 PPC64ST(cached = evCheckSzB_PPC()); break;
1386 case VexArchMIPS32:
1387 MIPS32ST(cached = evCheckSzB_MIPS()); break;
1388 case VexArchMIPS64:
1389 MIPS64ST(cached = evCheckSzB_MIPS()); break;
1390 case VexArchNANOMIPS:
1391 NANOMIPSST(cached = evCheckSzB_NANOMIPS()); break;
1392 default:
1393 vassert(0);
1396 return cached;
1399 VexInvalRange LibVEX_PatchProfInc ( VexArch arch_host,
1400 VexEndness endness_host,
1401 void* place_to_patch,
1402 const ULong* location_of_counter )
1404 switch (arch_host) {
1405 case VexArchX86:
1406 X86ST(return patchProfInc_X86(endness_host, place_to_patch,
1407 location_of_counter));
1408 case VexArchAMD64:
1409 AMD64ST(return patchProfInc_AMD64(endness_host, place_to_patch,
1410 location_of_counter));
1411 case VexArchARM:
1412 ARMST(return patchProfInc_ARM(endness_host, place_to_patch,
1413 location_of_counter));
1414 case VexArchARM64:
1415 ARM64ST(return patchProfInc_ARM64(endness_host, place_to_patch,
1416 location_of_counter));
1417 case VexArchS390X:
1418 S390ST(return patchProfInc_S390(endness_host, place_to_patch,
1419 location_of_counter));
1420 case VexArchPPC32:
1421 PPC32ST(return patchProfInc_PPC(endness_host, place_to_patch,
1422 location_of_counter, False/*!mode64*/));
1423 case VexArchPPC64:
1424 PPC64ST(return patchProfInc_PPC(endness_host, place_to_patch,
1425 location_of_counter, True/*mode64*/));
1426 case VexArchMIPS32:
1427 MIPS32ST(return patchProfInc_MIPS(endness_host, place_to_patch,
1428 location_of_counter, False/*!mode64*/));
1429 case VexArchMIPS64:
1430 MIPS64ST(return patchProfInc_MIPS(endness_host, place_to_patch,
1431 location_of_counter, True/*!mode64*/));
1432 case VexArchNANOMIPS:
1433 NANOMIPSST(return patchProfInc_NANOMIPS(endness_host, place_to_patch,
1434 location_of_counter));
1435 default:
1436 vassert(0);
1441 /* --------- Emulation warnings. --------- */
1443 const HChar* LibVEX_EmNote_string ( VexEmNote ew )
1445 switch (ew) {
1446 case EmNote_NONE:
1447 return "none";
1448 case EmWarn_X86_x87exns:
1449 return "Unmasking x87 FP exceptions";
1450 case EmWarn_X86_x87precision:
1451 return "Selection of non-80-bit x87 FP precision";
1452 case EmWarn_X86_sseExns:
1453 return "Unmasking SSE FP exceptions";
1454 case EmWarn_X86_fz:
1455 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
1456 case EmWarn_X86_daz:
1457 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
1458 case EmWarn_X86_acFlag:
1459 return "Setting %eflags.ac (setting noted but ignored)";
1460 case EmWarn_PPCexns:
1461 return "Unmasking PPC32/64 FP exceptions";
1462 case EmWarn_PPC64_redir_overflow:
1463 return "PPC64 function redirection stack overflow";
1464 case EmWarn_PPC64_redir_underflow:
1465 return "PPC64 function redirection stack underflow";
1466 case EmWarn_S390X_fpext_rounding:
1467 return "The specified rounding mode cannot be supported. That\n"
1468 " feature requires the floating point extension facility\n"
1469 " which is not available on this host. Continuing using\n"
1470 " the rounding mode from FPC. Results may differ!";
1471 case EmWarn_S390X_invalid_rounding:
1472 return "The specified rounding mode is invalid.\n"
1473 " Continuing using 'round to nearest'. Results may differ!";
1474 case EmFail_S390X_stfle:
1475 return "Instruction stfle is not supported on this host";
1476 case EmFail_S390X_stckf:
1477 return "Instruction stckf is not supported on this host";
1478 case EmFail_S390X_ecag:
1479 return "Instruction ecag is not supported on this host";
1480 case EmFail_S390X_pfpo:
1481 return "Instruction pfpo is not supported on this host";
1482 case EmFail_S390X_DFP_insn:
1483 return "DFP instructions are not supported on this host";
1484 case EmFail_S390X_fpext:
1485 return "Encountered an instruction that requires the floating "
1486 "point extension facility.\n"
1487 " That facility is not available on this host";
1488 case EmFail_S390X_invalid_PFPO_rounding_mode:
1489 return "The rounding mode in GPR 0 for the PFPO instruction"
1490 " is invalid";
1491 case EmFail_S390X_invalid_PFPO_function:
1492 return "The function code in GPR 0 for the PFPO instruction"
1493 " is invalid";
1494 case EmFail_S390X_vx:
1495 return "Encountered an instruction that requires the vector facility.\n"
1496 " That facility is not available on this host";
1497 default:
1498 vpanic("LibVEX_EmNote_string: unknown warning");
1502 /* ------------------ Arch/HwCaps stuff. ------------------ */
1504 const HChar* LibVEX_ppVexArch ( VexArch arch )
1506 switch (arch) {
1507 case VexArch_INVALID: return "INVALID";
1508 case VexArchX86: return "X86";
1509 case VexArchAMD64: return "AMD64";
1510 case VexArchARM: return "ARM";
1511 case VexArchARM64: return "ARM64";
1512 case VexArchPPC32: return "PPC32";
1513 case VexArchPPC64: return "PPC64";
1514 case VexArchS390X: return "S390X";
1515 case VexArchMIPS32: return "MIPS32";
1516 case VexArchMIPS64: return "MIPS64";
1517 case VexArchNANOMIPS: return "NANOMIPS";
1518 default: return "VexArch???";
1522 const HChar* LibVEX_ppVexEndness ( VexEndness endness )
1524 switch (endness) {
1525 case VexEndness_INVALID: return "INVALID";
1526 case VexEndnessLE: return "LittleEndian";
1527 case VexEndnessBE: return "BigEndian";
1528 default: return "VexEndness???";
1532 /* Return a string with the hardware capabilities to the extent as
1533 they pertain to the translation process. No attempt is made, to
1534 detect *all* capabilities an architecture may have. */
1535 const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
1537 return show_hwcaps(arch, hwcaps);
1541 /* Write default settings info *vai. */
1542 void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
1544 vex_bzero(vai, sizeof(*vai));
1545 vai->hwcaps = 0;
1546 vai->endness = VexEndness_INVALID;
1547 vai->ppc_icache_line_szB = 0;
1548 vai->ppc_dcbz_szB = 0;
1549 vai->ppc_dcbzl_szB = 0;
1550 vai->arm64_dMinLine_lg2_szB = 0;
1551 vai->arm64_iMinLine_lg2_szB = 0;
1552 vai->arm64_cache_block_size = 0;
1553 vai->arm64_requires_fallback_LLSC = False;
1554 vai->hwcache_info.num_levels = 0;
1555 vai->hwcache_info.num_caches = 0;
1556 vai->hwcache_info.caches = NULL;
1557 vai->hwcache_info.icaches_maintain_coherence = True; // whatever
1560 /* Write default settings info *vbi. */
1561 void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
1563 vex_bzero(vbi, sizeof(*vbi));
1564 vbi->guest_stack_redzone_size = 0;
1565 vbi->guest_amd64_assume_fs_is_const = False;
1566 vbi->guest_amd64_assume_gs_is_const = False;
1567 vbi->guest_amd64_sigbus_on_misalign = False;
1568 vbi->guest_ppc_zap_RZ_at_blr = False;
1569 vbi->guest_ppc_zap_RZ_at_bl = NULL;
1570 vbi->guest__use_fallback_LLSC = False;
1571 vbi->host_ppc_calls_use_fndescrs = False;
1575 static IRType arch_word_size (VexArch arch) {
1576 switch (arch) {
1577 case VexArchX86:
1578 case VexArchARM:
1579 case VexArchMIPS32:
1580 case VexArchNANOMIPS:
1581 case VexArchPPC32:
1582 return Ity_I32;
1584 case VexArchAMD64:
1585 case VexArchARM64:
1586 case VexArchMIPS64:
1587 case VexArchPPC64:
1588 case VexArchS390X:
1589 return Ity_I64;
1591 default:
1592 vex_printf("Fatal: unknown arch in arch_word_size\n");
1593 vassert(0);
1598 /* Convenience macro to be used in show_hwcaps_ARCH functions */
1599 #define NUM_HWCAPS (sizeof hwcaps_list / sizeof hwcaps_list[0])
1601 /* Return a string showing the hwcaps in a nice way. The string will
1602 be NULL for unrecognised hardware capabilities. */
1604 static const HChar* show_hwcaps_x86 ( UInt hwcaps )
1606 static const HChar prefix[] = "x86";
1607 static const struct {
1608 UInt hwcaps_bit;
1609 HChar name[7];
1610 } hwcaps_list[] = {
1611 { VEX_HWCAPS_X86_MMXEXT, "mmxext" },
1612 { VEX_HWCAPS_X86_SSE1, "sse1" },
1613 { VEX_HWCAPS_X86_SSE2, "sse2" },
1614 { VEX_HWCAPS_X86_SSE3, "sse3" },
1615 { VEX_HWCAPS_X86_LZCNT, "lzcnt" },
1617 /* Allocate a large enough buffer */
1618 static HChar buf[sizeof prefix +
1619 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1620 if (buf[0] != '\0') return buf; /* already constructed */
1622 HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1624 if (hwcaps == 0) {
1625 vex_sprintf(p, "-%s", "sse0");
1626 } else {
1627 UInt i;
1628 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1629 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1630 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1633 return buf;
1636 static const HChar* show_hwcaps_amd64 ( UInt hwcaps )
1638 static const HChar prefix[] = "amd64";
1639 static const struct {
1640 UInt hwcaps_bit;
1641 HChar name[7];
1642 } hwcaps_list[] = {
1643 { VEX_HWCAPS_AMD64_CX16, "cx16" },
1644 { VEX_HWCAPS_AMD64_LZCNT, "lzcnt" },
1645 { VEX_HWCAPS_AMD64_RDTSCP, "rdtscp" },
1646 { VEX_HWCAPS_AMD64_SSE3, "sse3" },
1647 { VEX_HWCAPS_AMD64_SSSE3, "ssse3" },
1648 { VEX_HWCAPS_AMD64_AVX, "avx" },
1649 { VEX_HWCAPS_AMD64_AVX2, "avx2" },
1650 { VEX_HWCAPS_AMD64_BMI, "bmi" },
1651 { VEX_HWCAPS_AMD64_F16C, "f16c" },
1652 { VEX_HWCAPS_AMD64_RDRAND, "rdrand" },
1653 { VEX_HWCAPS_AMD64_RDSEED, "rdseed" },
1654 { VEX_HWCAPS_AMD64_FMA3, "fma" }, /*fma to keep the same naming as /proc/cpuinfo*/
1655 { VEX_HWCAPS_AMD64_FMA4, "fma4" },
1657 /* Allocate a large enough buffer */
1658 static HChar buf[sizeof prefix +
1659 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1660 if (buf[0] != '\0') return buf; /* already constructed */
1662 HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1664 if (hwcaps == 0) {
1665 vex_sprintf(p, "-%s", "sse2");
1666 } else {
1667 UInt i;
1668 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1669 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1670 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1673 return buf;
1676 static const HChar* show_hwcaps_ppc32 ( UInt hwcaps )
1678 static const HChar prefix[] = "ppc32-int";
1679 static const struct {
1680 UInt hwcaps_bit;
1681 HChar name[8];
1682 } hwcaps_list[] = {
1683 { VEX_HWCAPS_PPC32_F, "flt" },
1684 { VEX_HWCAPS_PPC32_V, "vmx" },
1685 { VEX_HWCAPS_PPC32_FX, "FX" },
1686 { VEX_HWCAPS_PPC32_GX, "GX" },
1687 { VEX_HWCAPS_PPC32_VX, "VX" },
1688 { VEX_HWCAPS_PPC32_DFP, "DFP" },
1689 { VEX_HWCAPS_PPC32_ISA2_07, "ISA2_07" },
1690 { VEX_HWCAPS_PPC32_ISA3_0, "ISA3_0" },
1691 { VEX_HWCAPS_PPC32_ISA3_1, "ISA3_1" },
1693 /* Allocate a large enough buffer */
1694 static HChar buf[sizeof prefix +
1695 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1696 if (buf[0] != '\0') return buf; /* already constructed */
1698 HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1700 if (hwcaps == 0) return buf;
1702 UInt i;
1703 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1704 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1705 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1707 return buf;
1710 static const HChar* show_hwcaps_ppc64 ( UInt hwcaps )
1712 static const HChar prefix[] = "ppc64-int-flt";
1713 static const struct {
1714 UInt hwcaps_bit;
1715 HChar name[8];
1716 } hwcaps_list[] = {
1717 { VEX_HWCAPS_PPC64_FX, "FX" },
1718 { VEX_HWCAPS_PPC64_GX, "GX" },
1719 { VEX_HWCAPS_PPC64_V, "vmx" },
1720 { VEX_HWCAPS_PPC64_DFP, "DFP" },
1721 { VEX_HWCAPS_PPC64_ISA2_07, "ISA2_07" },
1722 { VEX_HWCAPS_PPC64_ISA3_0, "ISA3_0" },
1723 { VEX_HWCAPS_PPC64_ISA3_1, "ISA3_1" },
1725 /* Allocate a large enough buffer */
1726 static HChar buf[sizeof prefix +
1727 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1728 if (buf[0] != '\0') return buf; /* already constructed */
1730 HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1732 if (hwcaps == 0) return buf;
1734 UInt i;
1735 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1736 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1737 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1739 return buf;
1742 static const HChar* show_hwcaps_arm ( UInt hwcaps )
1744 static const HChar prefix[] = "ARM";
1745 static const struct {
1746 UInt hwcaps_bit;
1747 HChar name[6];
1748 } hwcaps_list[] = {
1749 { VEX_HWCAPS_ARM_NEON, "neon" },
1750 { VEX_HWCAPS_ARM_VFP | VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3, "vfp" },
1752 /* Allocate a large enough buffer */
1753 static HChar buf[sizeof prefix + 12 + // level
1754 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1755 if (buf[0] != '\0') return buf; /* already constructed */
1757 HChar *p;
1758 UInt i, level;
1760 level = VEX_ARM_ARCHLEVEL(hwcaps);
1762 p = buf + vex_sprintf(buf, "%sv%u", prefix, level);
1763 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1764 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1765 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1767 return buf;
1770 static const HChar* show_hwcaps_arm64 ( UInt hwcaps )
1772 static const HChar prefix[] = "v8";
1773 static const struct {
1774 UInt hwcaps_bit;
1775 HChar name[16];
1776 } hwcaps_list[] = {
1777 { VEX_HWCAPS_ARM64_FHM, "fhm" },
1778 { VEX_HWCAPS_ARM64_DPBCVAP, "dpcvap" },
1779 { VEX_HWCAPS_ARM64_DPBCVADP, "dpbcvadp" },
1780 { VEX_HWCAPS_ARM64_SM3, "sm3" },
1781 { VEX_HWCAPS_ARM64_SM4, "sm4" },
1782 { VEX_HWCAPS_ARM64_SHA3, "sha3" },
1783 { VEX_HWCAPS_ARM64_RDM, "rdm" },
1784 { VEX_HWCAPS_ARM64_I8MM, "i8mm" },
1785 { VEX_HWCAPS_ARM64_ATOMICS, "atomics" },
1786 { VEX_HWCAPS_ARM64_BF16, "bf16" },
1787 { VEX_HWCAPS_ARM64_FP16, "fp16" },
1788 { VEX_HWCAPS_ARM64_VFP16, "vfp16" },
1791 static HChar buf[sizeof prefix + // '\0'
1792 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1];
1794 HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1795 UInt i;
1796 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1797 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1798 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1801 return buf;
1804 static const HChar* show_hwcaps_s390x ( UInt hwcaps )
1806 static const HChar prefix[] = "s390x";
1807 static const struct {
1808 UInt hwcaps_bit;
1809 HChar name[6];
1810 } hwcaps_list[] = {
1811 { VEX_HWCAPS_S390X_LDISP, "ldisp" },
1812 { VEX_HWCAPS_S390X_EIMM, "eimm" },
1813 { VEX_HWCAPS_S390X_GIE, "gie" },
1814 { VEX_HWCAPS_S390X_DFP, "dfp" },
1815 { VEX_HWCAPS_S390X_FGX, "fgx" },
1816 { VEX_HWCAPS_S390X_STFLE, "stfle" },
1817 { VEX_HWCAPS_S390X_ETF2, "etf2" },
1818 { VEX_HWCAPS_S390X_ETF3, "etf3" },
1819 { VEX_HWCAPS_S390X_STCKF, "stckf" },
1820 { VEX_HWCAPS_S390X_FPEXT, "fpext" },
1821 { VEX_HWCAPS_S390X_LSC, "lsc" },
1822 { VEX_HWCAPS_S390X_PFPO, "pfpo" },
1823 { VEX_HWCAPS_S390X_VX, "vx" },
1824 { VEX_HWCAPS_S390X_MSA5, "msa5" },
1825 { VEX_HWCAPS_S390X_MI2, "mi2" },
1826 { VEX_HWCAPS_S390X_LSC2, "lsc2" },
1827 { VEX_HWCAPS_S390X_VXE, "vxe" },
1828 { VEX_HWCAPS_S390X_DFLT, "dflt" },
1830 /* Allocate a large enough buffer */
1831 static HChar buf[sizeof prefix +
1832 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1834 if (buf[0] != '\0') return buf; /* already constructed */
1836 HChar *p;
1837 UInt i;
1839 hwcaps = VEX_HWCAPS_S390X(hwcaps);
1841 p = buf + vex_sprintf(buf, "%s", prefix);
1842 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1843 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1844 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1847 /* If there are no facilities, add "zarch" */
1848 if (hwcaps == 0)
1849 vex_sprintf(p, "-%s", "zarch");
1851 return buf;
1854 static const HChar* show_hwcaps_mips32 ( UInt hwcaps )
1856 /* MIPS baseline. */
1857 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_MIPS) {
1858 /* MIPS baseline with msa. */
1859 if (VEX_MIPS_PROC_MSA(hwcaps)) {
1860 return "MIPS-baseline-msa";
1862 /* MIPS baseline with dspr2. */
1863 if (VEX_MIPS_PROC_DSP2(hwcaps)) {
1864 return "MIPS-baseline-dspr2";
1866 /* MIPS baseline with dsp. */
1867 if (VEX_MIPS_PROC_DSP(hwcaps)) {
1868 return "MIPS-baseline-dsp";
1870 return "MIPS-baseline";
1873 /* Broadcom baseline. */
1874 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_BROADCOM) {
1875 return "Broadcom-baseline";
1878 /* Netlogic baseline. */
1879 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_NETLOGIC) {
1880 return "Netlogic-baseline";
1883 /* Cavium baseline. */
1884 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_CAVIUM) {
1885 return "Cavium-baseline";
1888 /* Ingenic baseline. */
1889 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_INGENIC_E1) {
1890 return "Ingenic-baseline";
1893 /* Loongson baseline. */
1894 if ((VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_LEGACY) &&
1895 (VEX_MIPS_PROC_ID(hwcaps) == VEX_PRID_IMP_LOONGSON_64)) {
1896 return "Loongson-baseline";
1899 return "Unsupported baseline";
1902 static const HChar* show_hwcaps_mips64 ( UInt hwcaps )
1904 /* Netlogic baseline. */
1905 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_NETLOGIC) {
1906 return "Netlogic-baseline";
1909 /* Cavium baseline. */
1910 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_CAVIUM) {
1911 return "Cavium-baseline";
1914 /* Loongson baseline. */
1915 if ((VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_LEGACY) &&
1916 (VEX_MIPS_PROC_ID(hwcaps) == VEX_PRID_IMP_LOONGSON_64)) {
1917 return "Loongson-baseline";
1920 /* MIPS64 baseline. */
1921 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_MIPS) {
1922 /* MIPS baseline with msa. */
1923 if (VEX_MIPS_PROC_MSA(hwcaps)) {
1924 return "MIPS64-baseline-msa";
1926 return "MIPS64-baseline";
1929 return "Unsupported baseline";
1932 #undef NUM_HWCAPS
1934 /* Thie function must not return NULL. */
1936 static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
1938 switch (arch) {
1939 case VexArchX86: return show_hwcaps_x86(hwcaps);
1940 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
1941 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
1942 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
1943 case VexArchARM: return show_hwcaps_arm(hwcaps);
1944 case VexArchARM64: return show_hwcaps_arm64(hwcaps);
1945 case VexArchS390X: return show_hwcaps_s390x(hwcaps);
1946 case VexArchMIPS32: return show_hwcaps_mips32(hwcaps);
1947 case VexArchMIPS64: return show_hwcaps_mips64(hwcaps);
1948 default: return NULL;
1952 /* To be used to complain about hwcaps we cannot handle */
1953 __attribute__((noreturn))
1954 static void invalid_hwcaps ( VexArch arch, UInt hwcaps, const HChar *message )
1956 vfatal("\nVEX: %s"
1957 " Found: %s\n", message, show_hwcaps(arch, hwcaps));
1960 /* This function will not return iff the hwcaps don't pass the test. */
1961 static void check_hwcaps ( VexArch arch, UInt hwcaps )
1963 switch (arch) {
1964 case VexArchX86: {
1965 if (hwcaps == 0) return; // baseline
1967 /* Monotonic: SSE3 > SSE2 > SSE1 > MMXEXT > baseline. */
1968 static const UInt extras[] = {
1969 VEX_HWCAPS_X86_MMXEXT, VEX_HWCAPS_X86_SSE1, VEX_HWCAPS_X86_SSE2,
1970 VEX_HWCAPS_X86_SSE3
1973 UInt i, caps = 0;
1974 for (i = 0; i < sizeof extras / sizeof extras[0]; ++i) {
1975 caps |= extras[i];
1976 if (caps == hwcaps) return;
1977 /* For SSE2 or later LZCNT is optional */
1978 if ((caps & VEX_HWCAPS_X86_SSE2) != 0) {
1979 if ((caps | VEX_HWCAPS_X86_LZCNT) == hwcaps) return;
1982 invalid_hwcaps(arch, hwcaps, "Cannot handle capabilities\n");
1985 case VexArchAMD64: {
1986 /* SSE3 and CX16 are orthogonal and > baseline, although we really
1987 don't expect to come across anything which can do SSE3 but can't
1988 do CX16. Still, we can handle that case. LZCNT is similarly
1989 orthogonal. */
1991 /* Throw out obviously stupid cases: */
1992 Bool have_sse3 = (hwcaps & VEX_HWCAPS_AMD64_SSE3) != 0;
1993 Bool have_ssse3 = (hwcaps & VEX_HWCAPS_AMD64_SSSE3) != 0;
1994 Bool have_avx = (hwcaps & VEX_HWCAPS_AMD64_AVX) != 0;
1995 Bool have_bmi = (hwcaps & VEX_HWCAPS_AMD64_BMI) != 0;
1996 Bool have_avx2 = (hwcaps & VEX_HWCAPS_AMD64_AVX2) != 0;
1998 /* SSSE3 without SSE3 */
1999 if (have_ssse3 && !have_sse3)
2000 invalid_hwcaps(arch, hwcaps,
2001 "Support for SSSE3 requires SSE3 capabilities\n");
2002 /* AVX without SSSE3 */
2003 if (have_avx && !have_ssse3)
2004 invalid_hwcaps(arch, hwcaps,
2005 "Support for AVX requires SSSE3 capabilities\n");
2006 /* AVX2 or BMI without AVX */
2007 if (have_avx2 && !have_avx)
2008 invalid_hwcaps(arch, hwcaps,
2009 "Support for AVX2 requires AVX capabilities\n");
2010 if (have_bmi && !have_avx)
2011 invalid_hwcaps(arch, hwcaps,
2012 "Support for BMI requires AVX capabilities\n");
2013 return;
2016 case VexArchPPC32: {
2017 /* Monotonic with complications. Basically V > F > baseline,
2018 but once you have F then you can have FX or GX too. */
2019 if (hwcaps == 0) return; // baseline
2021 if ((hwcaps & VEX_HWCAPS_PPC32_F) == 0)
2022 invalid_hwcaps(arch, hwcaps,
2023 "Missing floating point capability\n");
2024 /* V, FX, and GX can appear in any combination */
2026 /* DFP requires V and FX and GX */
2027 UInt v_fx_gx = VEX_HWCAPS_PPC32_V | VEX_HWCAPS_PPC32_FX |
2028 VEX_HWCAPS_PPC32_GX;
2029 Bool has_v_fx_gx = (hwcaps & v_fx_gx) == v_fx_gx;
2031 if ((hwcaps & VEX_HWCAPS_PPC32_DFP) && ! has_v_fx_gx)
2032 invalid_hwcaps(arch, hwcaps,
2033 "DFP requires VMX and FX and GX capabilities\n");
2035 /* VX requires V and FX and GX */
2036 if ((hwcaps & VEX_HWCAPS_PPC32_VX) && ! has_v_fx_gx)
2037 invalid_hwcaps(arch, hwcaps,
2038 "VX requires VMX and FX and GX capabilities\n");
2040 /* ISA2_07 requires everything else */
2041 if ((hwcaps & VEX_HWCAPS_PPC32_ISA2_07) != 0) {
2042 if (! has_v_fx_gx)
2043 invalid_hwcaps(arch, hwcaps,
2044 "ISA2_07 requires VMX and FX and GX capabilities\n");
2045 if (! (hwcaps & VEX_HWCAPS_PPC32_VX))
2046 invalid_hwcaps(arch, hwcaps,
2047 "ISA2_07 requires VX capabilities\n");
2048 if (! (hwcaps & VEX_HWCAPS_PPC32_DFP))
2049 invalid_hwcaps(arch, hwcaps,
2050 "ISA2_07 requires DFP capabilities\n");
2053 /* ISA 3.0 not supported on 32-bit machines */
2054 if ((hwcaps & VEX_HWCAPS_PPC32_ISA3_0) != 0) {
2055 invalid_hwcaps(arch, hwcaps,
2056 "ISA 3.0 not supported in 32-bit mode \n");
2058 return;
2061 case VexArchPPC64: {
2062 /* Monotonic with complications. Basically V > baseline(==F),
2063 but once you have F then you can have FX or GX too. */
2064 if (hwcaps == 0) return; // baseline
2066 /* V, FX, and GX can appear in any combination */
2068 /* DFP requires V and FX and GX */
2069 UInt v_fx_gx = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX |
2070 VEX_HWCAPS_PPC64_GX;
2071 Bool has_v_fx_gx = (hwcaps & v_fx_gx) == v_fx_gx;
2073 if ((hwcaps & VEX_HWCAPS_PPC64_DFP) && ! has_v_fx_gx)
2074 invalid_hwcaps(arch, hwcaps,
2075 "DFP requires VMX and FX and GX capabilities\n");
2077 /* VX requires V and FX and GX */
2078 if ((hwcaps & VEX_HWCAPS_PPC32_VX) && ! has_v_fx_gx)
2079 invalid_hwcaps(arch, hwcaps,
2080 "VX requires VMX and FX and GX capabilities\n");
2082 /* ISA2_07 requires everything else */
2083 if ((hwcaps & VEX_HWCAPS_PPC64_ISA2_07) != 0) {
2084 if (! has_v_fx_gx)
2085 invalid_hwcaps(arch, hwcaps,
2086 "ISA2_07 requires VMX and FX and GX capabilities\n");
2087 if (! (hwcaps & VEX_HWCAPS_PPC64_VX))
2088 invalid_hwcaps(arch, hwcaps,
2089 "ISA2_07 requires VX capabilities\n");
2090 if (! (hwcaps & VEX_HWCAPS_PPC64_DFP))
2091 invalid_hwcaps(arch, hwcaps,
2092 "ISA2_07 requires DFP capabilities\n");
2095 /* ISA3_0 requires everything else */
2096 if ((hwcaps & VEX_HWCAPS_PPC64_ISA3_0) != 0) {
2097 if ( !((hwcaps
2098 & VEX_HWCAPS_PPC64_ISA2_07) == VEX_HWCAPS_PPC64_ISA2_07))
2099 invalid_hwcaps(arch, hwcaps,
2100 "ISA3_0 requires ISA2_07 capabilities\n");
2101 if ( !has_v_fx_gx)
2102 invalid_hwcaps(arch, hwcaps,
2103 "ISA3_0 requires VMX and FX and GX capabilities\n");
2104 if ( !(hwcaps & VEX_HWCAPS_PPC64_VX))
2105 invalid_hwcaps(arch, hwcaps,
2106 "ISA3_0 requires VX capabilities\n");
2107 if ( !(hwcaps & VEX_HWCAPS_PPC64_DFP))
2108 invalid_hwcaps(arch, hwcaps,
2109 "ISA3_0 requires DFP capabilities\n");
2112 /* ISA3_1 requires everything else */
2113 if ((hwcaps & VEX_HWCAPS_PPC64_ISA3_1) != 0) {
2114 if ( !((hwcaps
2115 & VEX_HWCAPS_PPC64_ISA3_0) == VEX_HWCAPS_PPC64_ISA3_0))
2116 invalid_hwcaps(arch, hwcaps,
2117 "ISA3_1 requires ISA3_0 capabilities\n");
2118 if ( !((hwcaps
2119 & VEX_HWCAPS_PPC64_ISA2_07) == VEX_HWCAPS_PPC64_ISA2_07))
2120 invalid_hwcaps(arch, hwcaps,
2121 "ISA3_1 requires ISA2_07 capabilities\n");
2122 if ( !has_v_fx_gx)
2123 invalid_hwcaps(arch, hwcaps,
2124 "ISA3_1 requires VMX and FX and GX capabilities\n");
2125 if ( !(hwcaps & VEX_HWCAPS_PPC64_VX))
2126 invalid_hwcaps(arch, hwcaps,
2127 "ISA3_1 requires VX capabilities\n");
2128 if ( !(hwcaps & VEX_HWCAPS_PPC64_DFP))
2129 invalid_hwcaps(arch, hwcaps,
2130 "ISA3_1 requires DFP capabilities\n");
2132 return;
2135 case VexArchARM: {
2136 Bool NEON = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0);
2137 Bool VFP3 = ((hwcaps & VEX_HWCAPS_ARM_VFP3) != 0);
2138 UInt level = VEX_ARM_ARCHLEVEL(hwcaps);
2139 switch (level) {
2140 case 5:
2141 if (NEON)
2142 invalid_hwcaps(arch, hwcaps,
2143 "NEON instructions are not supported for ARMv5.\n");
2144 return;
2145 case 6:
2146 if (NEON)
2147 invalid_hwcaps(arch, hwcaps,
2148 "NEON instructions are not supported for ARMv6.\n");
2149 return;
2150 case 7:
2151 return;
2152 case 8:
2153 if (!NEON || !VFP3)
2154 invalid_hwcaps(arch, hwcaps,
2155 "NEON and VFP3 are required for ARMv8.\n");
2156 return;
2157 default:
2158 invalid_hwcaps(arch, hwcaps,
2159 "ARM architecture level is not supported.\n");
2163 case VexArchARM64: {
2164 /* Mandatory dependencies. */
2165 Bool have_fp16 = ((hwcaps & VEX_HWCAPS_ARM64_FP16) != 0);
2166 Bool have_vfp16 = ((hwcaps & VEX_HWCAPS_ARM64_VFP16) != 0);
2167 if (have_fp16 != have_vfp16)
2168 invalid_hwcaps(arch, hwcaps,
2169 "Mismatch detected between scalar and vector FP16 features.\n");
2170 return;
2173 case VexArchS390X:
2174 if (! s390_host_has_ldisp)
2175 invalid_hwcaps(arch, hwcaps,
2176 "Host does not have long displacement facility.\n");
2177 return;
2179 case VexArchMIPS32:
2180 switch (VEX_MIPS_COMP_ID(hwcaps)) {
2181 case VEX_PRID_COMP_MIPS:
2182 case VEX_PRID_COMP_CAVIUM:
2183 case VEX_PRID_COMP_INGENIC_E1:
2184 case VEX_PRID_COMP_BROADCOM:
2185 case VEX_PRID_COMP_NETLOGIC:
2186 return;
2187 default:
2188 invalid_hwcaps(arch, hwcaps, "Unsupported baseline\n");
2191 case VexArchMIPS64:
2192 switch (VEX_MIPS_COMP_ID(hwcaps)) {
2193 case VEX_PRID_COMP_MIPS:
2194 case VEX_PRID_COMP_CAVIUM:
2195 case VEX_PRID_COMP_NETLOGIC:
2196 return;
2197 case VEX_PRID_COMP_LEGACY:
2198 if (VEX_MIPS_PROC_ID(hwcaps) == VEX_PRID_IMP_LOONGSON_64)
2199 return;
2200 /* fallthrough */
2201 default:
2202 invalid_hwcaps(arch, hwcaps, "Unsupported baseline\n");
2205 case VexArchNANOMIPS:
2206 if (hwcaps == 0)
2207 return;
2208 invalid_hwcaps(arch, hwcaps, "Unsupported baseline\n");
2210 default:
2211 vpanic("unknown architecture");
2216 /*---------------------------------------------------------------*/
2217 /*--- end main_main.c ---*/
2218 /*---------------------------------------------------------------*/