-> 3.20.0 final
[valgrind.git] / VEX / priv / main_main.c
blob482047c7aa1a871849880f9939fc8d9511cac9d0
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_requires_fallback_LLSC = False;
1553 vai->hwcache_info.num_levels = 0;
1554 vai->hwcache_info.num_caches = 0;
1555 vai->hwcache_info.caches = NULL;
1556 vai->hwcache_info.icaches_maintain_coherence = True; // whatever
1559 /* Write default settings info *vbi. */
1560 void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
1562 vex_bzero(vbi, sizeof(*vbi));
1563 vbi->guest_stack_redzone_size = 0;
1564 vbi->guest_amd64_assume_fs_is_const = False;
1565 vbi->guest_amd64_assume_gs_is_const = False;
1566 vbi->guest_amd64_sigbus_on_misalign = False;
1567 vbi->guest_ppc_zap_RZ_at_blr = False;
1568 vbi->guest_ppc_zap_RZ_at_bl = NULL;
1569 vbi->guest__use_fallback_LLSC = False;
1570 vbi->host_ppc_calls_use_fndescrs = False;
1574 static IRType arch_word_size (VexArch arch) {
1575 switch (arch) {
1576 case VexArchX86:
1577 case VexArchARM:
1578 case VexArchMIPS32:
1579 case VexArchNANOMIPS:
1580 case VexArchPPC32:
1581 return Ity_I32;
1583 case VexArchAMD64:
1584 case VexArchARM64:
1585 case VexArchMIPS64:
1586 case VexArchPPC64:
1587 case VexArchS390X:
1588 return Ity_I64;
1590 default:
1591 vex_printf("Fatal: unknown arch in arch_word_size\n");
1592 vassert(0);
1597 /* Convenience macro to be used in show_hwcaps_ARCH functions */
1598 #define NUM_HWCAPS (sizeof hwcaps_list / sizeof hwcaps_list[0])
1600 /* Return a string showing the hwcaps in a nice way. The string will
1601 be NULL for unrecognised hardware capabilities. */
1603 static const HChar* show_hwcaps_x86 ( UInt hwcaps )
1605 static const HChar prefix[] = "x86";
1606 static const struct {
1607 UInt hwcaps_bit;
1608 HChar name[7];
1609 } hwcaps_list[] = {
1610 { VEX_HWCAPS_X86_MMXEXT, "mmxext" },
1611 { VEX_HWCAPS_X86_SSE1, "sse1" },
1612 { VEX_HWCAPS_X86_SSE2, "sse2" },
1613 { VEX_HWCAPS_X86_SSE3, "sse3" },
1614 { VEX_HWCAPS_X86_LZCNT, "lzcnt" },
1616 /* Allocate a large enough buffer */
1617 static HChar buf[sizeof prefix +
1618 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1619 if (buf[0] != '\0') return buf; /* already constructed */
1621 HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1623 if (hwcaps == 0) {
1624 vex_sprintf(p, "-%s", "sse0");
1625 } else {
1626 UInt i;
1627 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1628 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1629 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1632 return buf;
1635 static const HChar* show_hwcaps_amd64 ( UInt hwcaps )
1637 static const HChar prefix[] = "amd64";
1638 static const struct {
1639 UInt hwcaps_bit;
1640 HChar name[7];
1641 } hwcaps_list[] = {
1642 { VEX_HWCAPS_AMD64_CX16, "cx16" },
1643 { VEX_HWCAPS_AMD64_LZCNT, "lzcnt" },
1644 { VEX_HWCAPS_AMD64_RDTSCP, "rdtscp" },
1645 { VEX_HWCAPS_AMD64_SSE3, "sse3" },
1646 { VEX_HWCAPS_AMD64_SSSE3, "ssse3" },
1647 { VEX_HWCAPS_AMD64_AVX, "avx" },
1648 { VEX_HWCAPS_AMD64_AVX2, "avx2" },
1649 { VEX_HWCAPS_AMD64_BMI, "bmi" },
1650 { VEX_HWCAPS_AMD64_F16C, "f16c" },
1651 { VEX_HWCAPS_AMD64_RDRAND, "rdrand" },
1652 { VEX_HWCAPS_AMD64_RDSEED, "rdseed" },
1654 /* Allocate a large enough buffer */
1655 static HChar buf[sizeof prefix +
1656 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1657 if (buf[0] != '\0') return buf; /* already constructed */
1659 HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1661 if (hwcaps == 0) {
1662 vex_sprintf(p, "-%s", "sse2");
1663 } else {
1664 UInt i;
1665 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1666 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1667 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1670 return buf;
1673 static const HChar* show_hwcaps_ppc32 ( UInt hwcaps )
1675 static const HChar prefix[] = "ppc32-int";
1676 static const struct {
1677 UInt hwcaps_bit;
1678 HChar name[8];
1679 } hwcaps_list[] = {
1680 { VEX_HWCAPS_PPC32_F, "flt" },
1681 { VEX_HWCAPS_PPC32_V, "vmx" },
1682 { VEX_HWCAPS_PPC32_FX, "FX" },
1683 { VEX_HWCAPS_PPC32_GX, "GX" },
1684 { VEX_HWCAPS_PPC32_VX, "VX" },
1685 { VEX_HWCAPS_PPC32_DFP, "DFP" },
1686 { VEX_HWCAPS_PPC32_ISA2_07, "ISA2_07" },
1687 { VEX_HWCAPS_PPC32_ISA3_0, "ISA3_0" },
1688 { VEX_HWCAPS_PPC32_ISA3_1, "ISA3_1" },
1690 /* Allocate a large enough buffer */
1691 static HChar buf[sizeof prefix +
1692 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1693 if (buf[0] != '\0') return buf; /* already constructed */
1695 HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1697 if (hwcaps == 0) return buf;
1699 UInt i;
1700 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1701 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1702 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1704 return buf;
1707 static const HChar* show_hwcaps_ppc64 ( UInt hwcaps )
1709 static const HChar prefix[] = "ppc64-int-flt";
1710 static const struct {
1711 UInt hwcaps_bit;
1712 HChar name[8];
1713 } hwcaps_list[] = {
1714 { VEX_HWCAPS_PPC64_FX, "FX" },
1715 { VEX_HWCAPS_PPC64_GX, "GX" },
1716 { VEX_HWCAPS_PPC64_V, "vmx" },
1717 { VEX_HWCAPS_PPC64_DFP, "DFP" },
1718 { VEX_HWCAPS_PPC64_ISA2_07, "ISA2_07" },
1719 { VEX_HWCAPS_PPC64_ISA3_0, "ISA3_0" },
1720 { VEX_HWCAPS_PPC64_ISA3_1, "ISA3_1" },
1722 /* Allocate a large enough buffer */
1723 static HChar buf[sizeof prefix +
1724 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1725 if (buf[0] != '\0') return buf; /* already constructed */
1727 HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1729 if (hwcaps == 0) return buf;
1731 UInt i;
1732 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1733 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1734 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1736 return buf;
1739 static const HChar* show_hwcaps_arm ( UInt hwcaps )
1741 static const HChar prefix[] = "ARM";
1742 static const struct {
1743 UInt hwcaps_bit;
1744 HChar name[6];
1745 } hwcaps_list[] = {
1746 { VEX_HWCAPS_ARM_NEON, "neon" },
1747 { VEX_HWCAPS_ARM_VFP | VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3, "vfp" },
1749 /* Allocate a large enough buffer */
1750 static HChar buf[sizeof prefix + 12 + // level
1751 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1752 if (buf[0] != '\0') return buf; /* already constructed */
1754 HChar *p;
1755 UInt i, level;
1757 level = VEX_ARM_ARCHLEVEL(hwcaps);
1759 p = buf + vex_sprintf(buf, "%sv%u", prefix, level);
1760 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1761 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1762 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1764 return buf;
1767 static const HChar* show_hwcaps_arm64 ( UInt hwcaps )
1769 static const HChar prefix[] = "v8";
1770 static const struct {
1771 UInt hwcaps_bit;
1772 HChar name[16];
1773 } hwcaps_list[] = {
1774 { VEX_HWCAPS_ARM64_FHM, "fhm" },
1775 { VEX_HWCAPS_ARM64_DPBCVAP, "dpcvap" },
1776 { VEX_HWCAPS_ARM64_DPBCVADP, "dpbcvadp" },
1777 { VEX_HWCAPS_ARM64_SM3, "sm3" },
1778 { VEX_HWCAPS_ARM64_SM4, "sm4" },
1779 { VEX_HWCAPS_ARM64_SHA3, "sha3" },
1780 { VEX_HWCAPS_ARM64_RDM, "rdm" },
1781 { VEX_HWCAPS_ARM64_I8MM, "i8mm" },
1782 { VEX_HWCAPS_ARM64_ATOMICS, "atomics" },
1783 { VEX_HWCAPS_ARM64_BF16, "bf16" },
1784 { VEX_HWCAPS_ARM64_FP16, "fp16" },
1785 { VEX_HWCAPS_ARM64_VFP16, "vfp16" },
1788 static HChar buf[sizeof prefix + // '\0'
1789 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1];
1791 HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1792 UInt i;
1793 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1794 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1795 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1798 return buf;
1801 static const HChar* show_hwcaps_s390x ( UInt hwcaps )
1803 static const HChar prefix[] = "s390x";
1804 static const struct {
1805 UInt hwcaps_bit;
1806 HChar name[6];
1807 } hwcaps_list[] = {
1808 { VEX_HWCAPS_S390X_LDISP, "ldisp" },
1809 { VEX_HWCAPS_S390X_EIMM, "eimm" },
1810 { VEX_HWCAPS_S390X_GIE, "gie" },
1811 { VEX_HWCAPS_S390X_DFP, "dfp" },
1812 { VEX_HWCAPS_S390X_FGX, "fgx" },
1813 { VEX_HWCAPS_S390X_STFLE, "stfle" },
1814 { VEX_HWCAPS_S390X_ETF2, "etf2" },
1815 { VEX_HWCAPS_S390X_ETF3, "etf3" },
1816 { VEX_HWCAPS_S390X_STCKF, "stckf" },
1817 { VEX_HWCAPS_S390X_FPEXT, "fpext" },
1818 { VEX_HWCAPS_S390X_LSC, "lsc" },
1819 { VEX_HWCAPS_S390X_PFPO, "pfpo" },
1820 { VEX_HWCAPS_S390X_VX, "vx" },
1821 { VEX_HWCAPS_S390X_MSA5, "msa5" },
1822 { VEX_HWCAPS_S390X_MI2, "mi2" },
1823 { VEX_HWCAPS_S390X_LSC2, "lsc2" },
1824 { VEX_HWCAPS_S390X_LSC2, "vxe" },
1826 /* Allocate a large enough buffer */
1827 static HChar buf[sizeof prefix +
1828 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1830 if (buf[0] != '\0') return buf; /* already constructed */
1832 HChar *p;
1833 UInt i;
1835 hwcaps = VEX_HWCAPS_S390X(hwcaps);
1837 p = buf + vex_sprintf(buf, "%s", prefix);
1838 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1839 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1840 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1843 /* If there are no facilities, add "zarch" */
1844 if (hwcaps == 0)
1845 vex_sprintf(p, "-%s", "zarch");
1847 return buf;
1850 static const HChar* show_hwcaps_mips32 ( UInt hwcaps )
1852 /* MIPS baseline. */
1853 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_MIPS) {
1854 /* MIPS baseline with msa. */
1855 if (VEX_MIPS_PROC_MSA(hwcaps)) {
1856 return "MIPS-baseline-msa";
1858 /* MIPS baseline with dspr2. */
1859 if (VEX_MIPS_PROC_DSP2(hwcaps)) {
1860 return "MIPS-baseline-dspr2";
1862 /* MIPS baseline with dsp. */
1863 if (VEX_MIPS_PROC_DSP(hwcaps)) {
1864 return "MIPS-baseline-dsp";
1866 return "MIPS-baseline";
1869 /* Broadcom baseline. */
1870 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_BROADCOM) {
1871 return "Broadcom-baseline";
1874 /* Netlogic baseline. */
1875 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_NETLOGIC) {
1876 return "Netlogic-baseline";
1879 /* Cavium baseline. */
1880 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_CAVIUM) {
1881 return "Cavium-baseline";
1884 /* Ingenic baseline. */
1885 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_INGENIC_E1) {
1886 return "Ingenic-baseline";
1889 /* Loongson baseline. */
1890 if ((VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_LEGACY) &&
1891 (VEX_MIPS_PROC_ID(hwcaps) == VEX_PRID_IMP_LOONGSON_64)) {
1892 return "Loongson-baseline";
1895 return "Unsupported baseline";
1898 static const HChar* show_hwcaps_mips64 ( UInt hwcaps )
1900 /* Netlogic baseline. */
1901 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_NETLOGIC) {
1902 return "Netlogic-baseline";
1905 /* Cavium baseline. */
1906 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_CAVIUM) {
1907 return "Cavium-baseline";
1910 /* Loongson baseline. */
1911 if ((VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_LEGACY) &&
1912 (VEX_MIPS_PROC_ID(hwcaps) == VEX_PRID_IMP_LOONGSON_64)) {
1913 return "Loongson-baseline";
1916 /* MIPS64 baseline. */
1917 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_MIPS) {
1918 /* MIPS baseline with msa. */
1919 if (VEX_MIPS_PROC_MSA(hwcaps)) {
1920 return "MIPS64-baseline-msa";
1922 return "MIPS64-baseline";
1925 return "Unsupported baseline";
1928 #undef NUM_HWCAPS
1930 /* Thie function must not return NULL. */
1932 static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
1934 switch (arch) {
1935 case VexArchX86: return show_hwcaps_x86(hwcaps);
1936 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
1937 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
1938 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
1939 case VexArchARM: return show_hwcaps_arm(hwcaps);
1940 case VexArchARM64: return show_hwcaps_arm64(hwcaps);
1941 case VexArchS390X: return show_hwcaps_s390x(hwcaps);
1942 case VexArchMIPS32: return show_hwcaps_mips32(hwcaps);
1943 case VexArchMIPS64: return show_hwcaps_mips64(hwcaps);
1944 default: return NULL;
1948 /* To be used to complain about hwcaps we cannot handle */
1949 __attribute__((noreturn))
1950 static void invalid_hwcaps ( VexArch arch, UInt hwcaps, const HChar *message )
1952 vfatal("\nVEX: %s"
1953 " Found: %s\n", message, show_hwcaps(arch, hwcaps));
1956 /* This function will not return iff the hwcaps don't pass the test. */
1957 static void check_hwcaps ( VexArch arch, UInt hwcaps )
1959 switch (arch) {
1960 case VexArchX86: {
1961 if (hwcaps == 0) return; // baseline
1963 /* Monotonic: SSE3 > SSE2 > SSE1 > MMXEXT > baseline. */
1964 static const UInt extras[] = {
1965 VEX_HWCAPS_X86_MMXEXT, VEX_HWCAPS_X86_SSE1, VEX_HWCAPS_X86_SSE2,
1966 VEX_HWCAPS_X86_SSE3
1969 UInt i, caps = 0;
1970 for (i = 0; i < sizeof extras / sizeof extras[0]; ++i) {
1971 caps |= extras[i];
1972 if (caps == hwcaps) return;
1973 /* For SSE2 or later LZCNT is optional */
1974 if ((caps & VEX_HWCAPS_X86_SSE2) != 0) {
1975 if ((caps | VEX_HWCAPS_X86_LZCNT) == hwcaps) return;
1978 invalid_hwcaps(arch, hwcaps, "Cannot handle capabilities\n");
1981 case VexArchAMD64: {
1982 /* SSE3 and CX16 are orthogonal and > baseline, although we really
1983 don't expect to come across anything which can do SSE3 but can't
1984 do CX16. Still, we can handle that case. LZCNT is similarly
1985 orthogonal. */
1987 /* Throw out obviously stupid cases: */
1988 Bool have_sse3 = (hwcaps & VEX_HWCAPS_AMD64_SSE3) != 0;
1989 Bool have_ssse3 = (hwcaps & VEX_HWCAPS_AMD64_SSSE3) != 0;
1990 Bool have_avx = (hwcaps & VEX_HWCAPS_AMD64_AVX) != 0;
1991 Bool have_bmi = (hwcaps & VEX_HWCAPS_AMD64_BMI) != 0;
1992 Bool have_avx2 = (hwcaps & VEX_HWCAPS_AMD64_AVX2) != 0;
1994 /* SSSE3 without SSE3 */
1995 if (have_ssse3 && !have_sse3)
1996 invalid_hwcaps(arch, hwcaps,
1997 "Support for SSSE3 requires SSE3 capabilities\n");
1998 /* AVX without SSSE3 */
1999 if (have_avx && !have_ssse3)
2000 invalid_hwcaps(arch, hwcaps,
2001 "Support for AVX requires SSSE3 capabilities\n");
2002 /* AVX2 or BMI without AVX */
2003 if (have_avx2 && !have_avx)
2004 invalid_hwcaps(arch, hwcaps,
2005 "Support for AVX2 requires AVX capabilities\n");
2006 if (have_bmi && !have_avx)
2007 invalid_hwcaps(arch, hwcaps,
2008 "Support for BMI requires AVX capabilities\n");
2009 return;
2012 case VexArchPPC32: {
2013 /* Monotonic with complications. Basically V > F > baseline,
2014 but once you have F then you can have FX or GX too. */
2015 if (hwcaps == 0) return; // baseline
2017 if ((hwcaps & VEX_HWCAPS_PPC32_F) == 0)
2018 invalid_hwcaps(arch, hwcaps,
2019 "Missing floating point capability\n");
2020 /* V, FX, and GX can appear in any combination */
2022 /* DFP requires V and FX and GX */
2023 UInt v_fx_gx = VEX_HWCAPS_PPC32_V | VEX_HWCAPS_PPC32_FX |
2024 VEX_HWCAPS_PPC32_GX;
2025 Bool has_v_fx_gx = (hwcaps & v_fx_gx) == v_fx_gx;
2027 if ((hwcaps & VEX_HWCAPS_PPC32_DFP) && ! has_v_fx_gx)
2028 invalid_hwcaps(arch, hwcaps,
2029 "DFP requires VMX and FX and GX capabilities\n");
2031 /* VX requires V and FX and GX */
2032 if ((hwcaps & VEX_HWCAPS_PPC32_VX) && ! has_v_fx_gx)
2033 invalid_hwcaps(arch, hwcaps,
2034 "VX requires VMX and FX and GX capabilities\n");
2036 /* ISA2_07 requires everything else */
2037 if ((hwcaps & VEX_HWCAPS_PPC32_ISA2_07) != 0) {
2038 if (! has_v_fx_gx)
2039 invalid_hwcaps(arch, hwcaps,
2040 "ISA2_07 requires VMX and FX and GX capabilities\n");
2041 if (! (hwcaps & VEX_HWCAPS_PPC32_VX))
2042 invalid_hwcaps(arch, hwcaps,
2043 "ISA2_07 requires VX capabilities\n");
2044 if (! (hwcaps & VEX_HWCAPS_PPC32_DFP))
2045 invalid_hwcaps(arch, hwcaps,
2046 "ISA2_07 requires DFP capabilities\n");
2049 /* ISA 3.0 not supported on 32-bit machines */
2050 if ((hwcaps & VEX_HWCAPS_PPC32_ISA3_0) != 0) {
2051 invalid_hwcaps(arch, hwcaps,
2052 "ISA 3.0 not supported in 32-bit mode \n");
2054 return;
2057 case VexArchPPC64: {
2058 /* Monotonic with complications. Basically V > baseline(==F),
2059 but once you have F then you can have FX or GX too. */
2060 if (hwcaps == 0) return; // baseline
2062 /* V, FX, and GX can appear in any combination */
2064 /* DFP requires V and FX and GX */
2065 UInt v_fx_gx = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX |
2066 VEX_HWCAPS_PPC64_GX;
2067 Bool has_v_fx_gx = (hwcaps & v_fx_gx) == v_fx_gx;
2069 if ((hwcaps & VEX_HWCAPS_PPC64_DFP) && ! has_v_fx_gx)
2070 invalid_hwcaps(arch, hwcaps,
2071 "DFP requires VMX and FX and GX capabilities\n");
2073 /* VX requires V and FX and GX */
2074 if ((hwcaps & VEX_HWCAPS_PPC32_VX) && ! has_v_fx_gx)
2075 invalid_hwcaps(arch, hwcaps,
2076 "VX requires VMX and FX and GX capabilities\n");
2078 /* ISA2_07 requires everything else */
2079 if ((hwcaps & VEX_HWCAPS_PPC64_ISA2_07) != 0) {
2080 if (! has_v_fx_gx)
2081 invalid_hwcaps(arch, hwcaps,
2082 "ISA2_07 requires VMX and FX and GX capabilities\n");
2083 if (! (hwcaps & VEX_HWCAPS_PPC64_VX))
2084 invalid_hwcaps(arch, hwcaps,
2085 "ISA2_07 requires VX capabilities\n");
2086 if (! (hwcaps & VEX_HWCAPS_PPC64_DFP))
2087 invalid_hwcaps(arch, hwcaps,
2088 "ISA2_07 requires DFP capabilities\n");
2091 /* ISA3_0 requires everything else */
2092 if ((hwcaps & VEX_HWCAPS_PPC64_ISA3_0) != 0) {
2093 if ( !((hwcaps
2094 & VEX_HWCAPS_PPC64_ISA2_07) == VEX_HWCAPS_PPC64_ISA2_07))
2095 invalid_hwcaps(arch, hwcaps,
2096 "ISA3_0 requires ISA2_07 capabilities\n");
2097 if ( !has_v_fx_gx)
2098 invalid_hwcaps(arch, hwcaps,
2099 "ISA3_0 requires VMX and FX and GX capabilities\n");
2100 if ( !(hwcaps & VEX_HWCAPS_PPC64_VX))
2101 invalid_hwcaps(arch, hwcaps,
2102 "ISA3_0 requires VX capabilities\n");
2103 if ( !(hwcaps & VEX_HWCAPS_PPC64_DFP))
2104 invalid_hwcaps(arch, hwcaps,
2105 "ISA3_0 requires DFP capabilities\n");
2108 /* ISA3_1 requires everything else */
2109 if ((hwcaps & VEX_HWCAPS_PPC64_ISA3_1) != 0) {
2110 if ( !((hwcaps
2111 & VEX_HWCAPS_PPC64_ISA3_0) == VEX_HWCAPS_PPC64_ISA3_0))
2112 invalid_hwcaps(arch, hwcaps,
2113 "ISA3_1 requires ISA3_0 capabilities\n");
2114 if ( !((hwcaps
2115 & VEX_HWCAPS_PPC64_ISA2_07) == VEX_HWCAPS_PPC64_ISA2_07))
2116 invalid_hwcaps(arch, hwcaps,
2117 "ISA3_1 requires ISA2_07 capabilities\n");
2118 if ( !has_v_fx_gx)
2119 invalid_hwcaps(arch, hwcaps,
2120 "ISA3_1 requires VMX and FX and GX capabilities\n");
2121 if ( !(hwcaps & VEX_HWCAPS_PPC64_VX))
2122 invalid_hwcaps(arch, hwcaps,
2123 "ISA3_1 requires VX capabilities\n");
2124 if ( !(hwcaps & VEX_HWCAPS_PPC64_DFP))
2125 invalid_hwcaps(arch, hwcaps,
2126 "ISA3_1 requires DFP capabilities\n");
2128 return;
2131 case VexArchARM: {
2132 Bool NEON = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0);
2133 Bool VFP3 = ((hwcaps & VEX_HWCAPS_ARM_VFP3) != 0);
2134 UInt level = VEX_ARM_ARCHLEVEL(hwcaps);
2135 switch (level) {
2136 case 5:
2137 if (NEON)
2138 invalid_hwcaps(arch, hwcaps,
2139 "NEON instructions are not supported for ARMv5.\n");
2140 return;
2141 case 6:
2142 if (NEON)
2143 invalid_hwcaps(arch, hwcaps,
2144 "NEON instructions are not supported for ARMv6.\n");
2145 return;
2146 case 7:
2147 return;
2148 case 8:
2149 if (!NEON || !VFP3)
2150 invalid_hwcaps(arch, hwcaps,
2151 "NEON and VFP3 are required for ARMv8.\n");
2152 return;
2153 default:
2154 invalid_hwcaps(arch, hwcaps,
2155 "ARM architecture level is not supported.\n");
2159 case VexArchARM64: {
2160 /* Mandatory dependencies. */
2161 Bool have_fp16 = ((hwcaps & VEX_HWCAPS_ARM64_FP16) != 0);
2162 Bool have_vfp16 = ((hwcaps & VEX_HWCAPS_ARM64_VFP16) != 0);
2163 if (have_fp16 != have_vfp16)
2164 invalid_hwcaps(arch, hwcaps,
2165 "Mismatch detected between scalar and vector FP16 features.\n");
2166 return;
2169 case VexArchS390X:
2170 if (! s390_host_has_ldisp)
2171 invalid_hwcaps(arch, hwcaps,
2172 "Host does not have long displacement facility.\n");
2173 return;
2175 case VexArchMIPS32:
2176 switch (VEX_MIPS_COMP_ID(hwcaps)) {
2177 case VEX_PRID_COMP_MIPS:
2178 case VEX_PRID_COMP_CAVIUM:
2179 case VEX_PRID_COMP_INGENIC_E1:
2180 case VEX_PRID_COMP_BROADCOM:
2181 case VEX_PRID_COMP_NETLOGIC:
2182 return;
2183 default:
2184 invalid_hwcaps(arch, hwcaps, "Unsupported baseline\n");
2187 case VexArchMIPS64:
2188 switch (VEX_MIPS_COMP_ID(hwcaps)) {
2189 case VEX_PRID_COMP_MIPS:
2190 case VEX_PRID_COMP_CAVIUM:
2191 case VEX_PRID_COMP_NETLOGIC:
2192 return;
2193 case VEX_PRID_COMP_LEGACY:
2194 if (VEX_MIPS_PROC_ID(hwcaps) == VEX_PRID_IMP_LOONGSON_64)
2195 return;
2196 /* fallthrough */
2197 default:
2198 invalid_hwcaps(arch, hwcaps, "Unsupported baseline\n");
2201 case VexArchNANOMIPS:
2202 if (hwcaps == 0)
2203 return;
2204 invalid_hwcaps(arch, hwcaps, "Unsupported baseline\n");
2206 default:
2207 vpanic("unknown architecture");
2212 /*---------------------------------------------------------------*/
2213 /*--- end main_main.c ---*/
2214 /*---------------------------------------------------------------*/