expr_is_guardable, stmt_is_guardable, add_guarded_stmt_to_end_of: handle GetI/PutI...
[valgrind.git] / VEX / priv / main_main.c
blob7a3cb75caf9f44fec61368fe3cfb73a824343007
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_ppc_zap_RZ_at_blr = False;
1567 vbi->guest_ppc_zap_RZ_at_bl = NULL;
1568 vbi->guest__use_fallback_LLSC = False;
1569 vbi->host_ppc_calls_use_fndescrs = False;
1573 static IRType arch_word_size (VexArch arch) {
1574 switch (arch) {
1575 case VexArchX86:
1576 case VexArchARM:
1577 case VexArchMIPS32:
1578 case VexArchNANOMIPS:
1579 case VexArchPPC32:
1580 return Ity_I32;
1582 case VexArchAMD64:
1583 case VexArchARM64:
1584 case VexArchMIPS64:
1585 case VexArchPPC64:
1586 case VexArchS390X:
1587 return Ity_I64;
1589 default:
1590 vex_printf("Fatal: unknown arch in arch_word_size\n");
1591 vassert(0);
1596 /* Convenience macro to be used in show_hwcaps_ARCH functions */
1597 #define NUM_HWCAPS (sizeof hwcaps_list / sizeof hwcaps_list[0])
1599 /* Return a string showing the hwcaps in a nice way. The string will
1600 be NULL for unrecognised hardware capabilities. */
1602 static const HChar* show_hwcaps_x86 ( UInt hwcaps )
1604 static const HChar prefix[] = "x86";
1605 static const struct {
1606 UInt hwcaps_bit;
1607 HChar name[7];
1608 } hwcaps_list[] = {
1609 { VEX_HWCAPS_X86_MMXEXT, "mmxext" },
1610 { VEX_HWCAPS_X86_SSE1, "sse1" },
1611 { VEX_HWCAPS_X86_SSE2, "sse2" },
1612 { VEX_HWCAPS_X86_SSE3, "sse3" },
1613 { VEX_HWCAPS_X86_LZCNT, "lzcnt" },
1615 /* Allocate a large enough buffer */
1616 static HChar buf[sizeof prefix +
1617 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1618 if (buf[0] != '\0') return buf; /* already constructed */
1620 HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1622 if (hwcaps == 0) {
1623 vex_sprintf(p, "-%s", "sse0");
1624 } else {
1625 UInt i;
1626 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1627 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1628 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1631 return buf;
1634 static const HChar* show_hwcaps_amd64 ( UInt hwcaps )
1636 static const HChar prefix[] = "amd64";
1637 static const struct {
1638 UInt hwcaps_bit;
1639 HChar name[7];
1640 } hwcaps_list[] = {
1641 { VEX_HWCAPS_AMD64_CX16, "cx16" },
1642 { VEX_HWCAPS_AMD64_LZCNT, "lzcnt" },
1643 { VEX_HWCAPS_AMD64_RDTSCP, "rdtscp" },
1644 { VEX_HWCAPS_AMD64_SSE3, "sse3" },
1645 { VEX_HWCAPS_AMD64_SSSE3, "ssse3" },
1646 { VEX_HWCAPS_AMD64_AVX, "avx" },
1647 { VEX_HWCAPS_AMD64_AVX2, "avx2" },
1648 { VEX_HWCAPS_AMD64_BMI, "bmi" },
1649 { VEX_HWCAPS_AMD64_F16C, "f16c" },
1650 { VEX_HWCAPS_AMD64_RDRAND, "rdrand" },
1652 /* Allocate a large enough buffer */
1653 static HChar buf[sizeof prefix +
1654 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1655 if (buf[0] != '\0') return buf; /* already constructed */
1657 HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1659 if (hwcaps == 0) {
1660 vex_sprintf(p, "-%s", "sse2");
1661 } else {
1662 UInt i;
1663 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1664 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1665 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1668 return buf;
1671 static const HChar* show_hwcaps_ppc32 ( UInt hwcaps )
1673 static const HChar prefix[] = "ppc32-int";
1674 static const struct {
1675 UInt hwcaps_bit;
1676 HChar name[8];
1677 } hwcaps_list[] = {
1678 { VEX_HWCAPS_PPC32_F, "flt" },
1679 { VEX_HWCAPS_PPC32_V, "vmx" },
1680 { VEX_HWCAPS_PPC32_FX, "FX" },
1681 { VEX_HWCAPS_PPC32_GX, "GX" },
1682 { VEX_HWCAPS_PPC32_VX, "VX" },
1683 { VEX_HWCAPS_PPC32_DFP, "DFP" },
1684 { VEX_HWCAPS_PPC32_ISA2_07, "ISA2_07" },
1685 { VEX_HWCAPS_PPC32_ISA3_0, "ISA3_0" },
1687 /* Allocate a large enough buffer */
1688 static HChar buf[sizeof prefix +
1689 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1690 if (buf[0] != '\0') return buf; /* already constructed */
1692 HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1694 if (hwcaps == 0) return buf;
1696 UInt i;
1697 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1698 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1699 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1701 return buf;
1704 static const HChar* show_hwcaps_ppc64 ( UInt hwcaps )
1706 static const HChar prefix[] = "ppc64-int-flt";
1707 static const struct {
1708 UInt hwcaps_bit;
1709 HChar name[8];
1710 } hwcaps_list[] = {
1711 { VEX_HWCAPS_PPC64_FX, "FX" },
1712 { VEX_HWCAPS_PPC64_GX, "GX" },
1713 { VEX_HWCAPS_PPC64_V, "vmx" },
1714 { VEX_HWCAPS_PPC64_DFP, "DFP" },
1715 { VEX_HWCAPS_PPC64_ISA2_07, "ISA2_07" },
1716 { VEX_HWCAPS_PPC64_ISA3_0, "ISA3_0" },
1718 /* Allocate a large enough buffer */
1719 static HChar buf[sizeof prefix +
1720 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1721 if (buf[0] != '\0') return buf; /* already constructed */
1723 HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1725 if (hwcaps == 0) return buf;
1727 UInt i;
1728 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1729 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1730 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1732 return buf;
1735 static const HChar* show_hwcaps_arm ( UInt hwcaps )
1737 static const HChar prefix[] = "ARM";
1738 static const struct {
1739 UInt hwcaps_bit;
1740 HChar name[6];
1741 } hwcaps_list[] = {
1742 { VEX_HWCAPS_ARM_NEON, "neon" },
1743 { VEX_HWCAPS_ARM_VFP | VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3, "vfp" },
1745 /* Allocate a large enough buffer */
1746 static HChar buf[sizeof prefix + 12 + // level
1747 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1748 if (buf[0] != '\0') return buf; /* already constructed */
1750 HChar *p;
1751 UInt i, level;
1753 level = VEX_ARM_ARCHLEVEL(hwcaps);
1755 p = buf + vex_sprintf(buf, "%sv%u", prefix, level);
1756 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1757 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1758 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1760 return buf;
1763 static const HChar* show_hwcaps_arm64 ( UInt hwcaps )
1765 /* Since there are no variants, just insist that hwcaps is zero,
1766 and declare it invalid otherwise. */
1767 if (hwcaps == 0)
1768 return "baseline";
1769 return "Unsupported";
1772 static const HChar* show_hwcaps_s390x ( UInt hwcaps )
1774 static const HChar prefix[] = "s390x";
1775 static const struct {
1776 UInt hwcaps_bit;
1777 HChar name[6];
1778 } hwcaps_list[] = {
1779 { VEX_HWCAPS_S390X_LDISP, "ldisp" },
1780 { VEX_HWCAPS_S390X_EIMM, "eimm" },
1781 { VEX_HWCAPS_S390X_GIE, "gie" },
1782 { VEX_HWCAPS_S390X_DFP, "dfp" },
1783 { VEX_HWCAPS_S390X_FGX, "fgx" },
1784 { VEX_HWCAPS_S390X_STFLE, "stfle" },
1785 { VEX_HWCAPS_S390X_ETF2, "etf2" },
1786 { VEX_HWCAPS_S390X_ETF3, "etf3" },
1787 { VEX_HWCAPS_S390X_STCKF, "stckf" },
1788 { VEX_HWCAPS_S390X_FPEXT, "fpext" },
1789 { VEX_HWCAPS_S390X_LSC, "lsc" },
1790 { VEX_HWCAPS_S390X_PFPO, "pfpo" },
1791 { VEX_HWCAPS_S390X_VX, "vx" },
1792 { VEX_HWCAPS_S390X_MSA5, "msa5" },
1793 { VEX_HWCAPS_S390X_MI2, "mi2" },
1794 { VEX_HWCAPS_S390X_LSC2, "lsc2" },
1796 /* Allocate a large enough buffer */
1797 static HChar buf[sizeof prefix +
1798 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1800 if (buf[0] != '\0') return buf; /* already constructed */
1802 HChar *p;
1803 UInt i;
1805 hwcaps = VEX_HWCAPS_S390X(hwcaps);
1807 p = buf + vex_sprintf(buf, "%s", prefix);
1808 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1809 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1810 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1813 /* If there are no facilities, add "zarch" */
1814 if (hwcaps == 0)
1815 vex_sprintf(p, "-%s", "zarch");
1817 return buf;
1820 static const HChar* show_hwcaps_mips32 ( UInt hwcaps )
1822 /* MIPS baseline. */
1823 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_MIPS) {
1824 /* MIPS baseline with msa. */
1825 if (VEX_MIPS_PROC_MSA(hwcaps)) {
1826 return "MIPS-baseline-msa";
1828 /* MIPS baseline with dspr2. */
1829 if (VEX_MIPS_PROC_DSP2(hwcaps)) {
1830 return "MIPS-baseline-dspr2";
1832 /* MIPS baseline with dsp. */
1833 if (VEX_MIPS_PROC_DSP(hwcaps)) {
1834 return "MIPS-baseline-dsp";
1836 return "MIPS-baseline";
1839 /* Broadcom baseline. */
1840 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_BROADCOM) {
1841 return "Broadcom-baseline";
1844 /* Netlogic baseline. */
1845 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_NETLOGIC) {
1846 return "Netlogic-baseline";
1849 /* Cavium baseline. */
1850 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_CAVIUM) {
1851 return "Cavium-baseline";
1854 /* Ingenic baseline. */
1855 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_INGENIC_E1) {
1856 return "Ingenic-baseline";
1859 /* Loongson baseline. */
1860 if ((VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_LEGACY) &&
1861 (VEX_MIPS_PROC_ID(hwcaps) == VEX_PRID_IMP_LOONGSON_64)) {
1862 return "Loongson-baseline";
1865 return "Unsupported baseline";
1868 static const HChar* show_hwcaps_mips64 ( UInt hwcaps )
1870 /* Netlogic baseline. */
1871 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_NETLOGIC) {
1872 return "Netlogic-baseline";
1875 /* Cavium baseline. */
1876 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_CAVIUM) {
1877 return "Cavium-baseline";
1880 /* Loongson baseline. */
1881 if ((VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_LEGACY) &&
1882 (VEX_MIPS_PROC_ID(hwcaps) == VEX_PRID_IMP_LOONGSON_64)) {
1883 return "Loongson-baseline";
1886 /* MIPS64 baseline. */
1887 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_MIPS) {
1888 /* MIPS baseline with msa. */
1889 if (VEX_MIPS_PROC_MSA(hwcaps)) {
1890 return "MIPS64-baseline-msa";
1892 return "MIPS64-baseline";
1895 return "Unsupported baseline";
1898 #undef NUM_HWCAPS
1900 /* Thie function must not return NULL. */
1902 static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
1904 switch (arch) {
1905 case VexArchX86: return show_hwcaps_x86(hwcaps);
1906 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
1907 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
1908 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
1909 case VexArchARM: return show_hwcaps_arm(hwcaps);
1910 case VexArchARM64: return show_hwcaps_arm64(hwcaps);
1911 case VexArchS390X: return show_hwcaps_s390x(hwcaps);
1912 case VexArchMIPS32: return show_hwcaps_mips32(hwcaps);
1913 case VexArchMIPS64: return show_hwcaps_mips64(hwcaps);
1914 default: return NULL;
1918 /* To be used to complain about hwcaps we cannot handle */
1919 __attribute__((noreturn))
1920 static void invalid_hwcaps ( VexArch arch, UInt hwcaps, const HChar *message )
1922 vfatal("\nVEX: %s"
1923 " Found: %s\n", message, show_hwcaps(arch, hwcaps));
1926 /* This function will not return iff the hwcaps don't pass the test. */
1927 static void check_hwcaps ( VexArch arch, UInt hwcaps )
1929 switch (arch) {
1930 case VexArchX86: {
1931 if (hwcaps == 0) return; // baseline
1933 /* Monotonic: SSE3 > SSE2 > SSE1 > MMXEXT > baseline. */
1934 static const UInt extras[] = {
1935 VEX_HWCAPS_X86_MMXEXT, VEX_HWCAPS_X86_SSE1, VEX_HWCAPS_X86_SSE2,
1936 VEX_HWCAPS_X86_SSE3
1939 UInt i, caps = 0;
1940 for (i = 0; i < sizeof extras / sizeof extras[0]; ++i) {
1941 caps |= extras[i];
1942 if (caps == hwcaps) return;
1943 /* For SSE2 or later LZCNT is optional */
1944 if ((caps & VEX_HWCAPS_X86_SSE2) != 0) {
1945 if ((caps | VEX_HWCAPS_X86_LZCNT) == hwcaps) return;
1948 invalid_hwcaps(arch, hwcaps, "Cannot handle capabilities\n");
1951 case VexArchAMD64: {
1952 /* SSE3 and CX16 are orthogonal and > baseline, although we really
1953 don't expect to come across anything which can do SSE3 but can't
1954 do CX16. Still, we can handle that case. LZCNT is similarly
1955 orthogonal. */
1957 /* Throw out obviously stupid cases: */
1958 Bool have_sse3 = (hwcaps & VEX_HWCAPS_AMD64_SSE3) != 0;
1959 Bool have_ssse3 = (hwcaps & VEX_HWCAPS_AMD64_SSSE3) != 0;
1960 Bool have_avx = (hwcaps & VEX_HWCAPS_AMD64_AVX) != 0;
1961 Bool have_bmi = (hwcaps & VEX_HWCAPS_AMD64_BMI) != 0;
1962 Bool have_avx2 = (hwcaps & VEX_HWCAPS_AMD64_AVX2) != 0;
1964 /* SSSE3 without SSE3 */
1965 if (have_ssse3 && !have_sse3)
1966 invalid_hwcaps(arch, hwcaps,
1967 "Support for SSSE3 requires SSE3 capabilities\n");
1968 /* AVX without SSSE3 */
1969 if (have_avx && !have_ssse3)
1970 invalid_hwcaps(arch, hwcaps,
1971 "Support for AVX requires SSSE3 capabilities\n");
1972 /* AVX2 or BMI without AVX */
1973 if (have_avx2 && !have_avx)
1974 invalid_hwcaps(arch, hwcaps,
1975 "Support for AVX2 requires AVX capabilities\n");
1976 if (have_bmi && !have_avx)
1977 invalid_hwcaps(arch, hwcaps,
1978 "Support for BMI requires AVX capabilities\n");
1979 return;
1982 case VexArchPPC32: {
1983 /* Monotonic with complications. Basically V > F > baseline,
1984 but once you have F then you can have FX or GX too. */
1985 if (hwcaps == 0) return; // baseline
1987 if ((hwcaps & VEX_HWCAPS_PPC32_F) == 0)
1988 invalid_hwcaps(arch, hwcaps,
1989 "Missing floating point capability\n");
1990 /* V, FX, and GX can appear in any combination */
1992 /* DFP requires V and FX and GX */
1993 UInt v_fx_gx = VEX_HWCAPS_PPC32_V | VEX_HWCAPS_PPC32_FX |
1994 VEX_HWCAPS_PPC32_GX;
1995 Bool has_v_fx_gx = (hwcaps & v_fx_gx) == v_fx_gx;
1997 if ((hwcaps & VEX_HWCAPS_PPC32_DFP) && ! has_v_fx_gx)
1998 invalid_hwcaps(arch, hwcaps,
1999 "DFP requires VMX and FX and GX capabilities\n");
2001 /* VX requires V and FX and GX */
2002 if ((hwcaps & VEX_HWCAPS_PPC32_VX) && ! has_v_fx_gx)
2003 invalid_hwcaps(arch, hwcaps,
2004 "VX requires VMX and FX and GX capabilities\n");
2006 /* ISA2_07 requires everything else */
2007 if ((hwcaps & VEX_HWCAPS_PPC32_ISA2_07) != 0) {
2008 if (! has_v_fx_gx)
2009 invalid_hwcaps(arch, hwcaps,
2010 "ISA2_07 requires VMX and FX and GX capabilities\n");
2011 if (! (hwcaps & VEX_HWCAPS_PPC32_VX))
2012 invalid_hwcaps(arch, hwcaps,
2013 "ISA2_07 requires VX capabilities\n");
2014 if (! (hwcaps & VEX_HWCAPS_PPC32_DFP))
2015 invalid_hwcaps(arch, hwcaps,
2016 "ISA2_07 requires DFP capabilities\n");
2019 /* ISA 3.0 not supported on 32-bit machines */
2020 if ((hwcaps & VEX_HWCAPS_PPC32_ISA3_0) != 0) {
2021 invalid_hwcaps(arch, hwcaps,
2022 "ISA 3.0 not supported in 32-bit mode \n");
2024 return;
2027 case VexArchPPC64: {
2028 /* Monotonic with complications. Basically V > baseline(==F),
2029 but once you have F then you can have FX or GX too. */
2030 if (hwcaps == 0) return; // baseline
2032 /* V, FX, and GX can appear in any combination */
2034 /* DFP requires V and FX and GX */
2035 UInt v_fx_gx = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX |
2036 VEX_HWCAPS_PPC64_GX;
2037 Bool has_v_fx_gx = (hwcaps & v_fx_gx) == v_fx_gx;
2039 if ((hwcaps & VEX_HWCAPS_PPC64_DFP) && ! has_v_fx_gx)
2040 invalid_hwcaps(arch, hwcaps,
2041 "DFP requires VMX and FX and GX capabilities\n");
2043 /* VX requires V and FX and GX */
2044 if ((hwcaps & VEX_HWCAPS_PPC32_VX) && ! has_v_fx_gx)
2045 invalid_hwcaps(arch, hwcaps,
2046 "VX requires VMX and FX and GX capabilities\n");
2048 /* ISA2_07 requires everything else */
2049 if ((hwcaps & VEX_HWCAPS_PPC64_ISA2_07) != 0) {
2050 if (! has_v_fx_gx)
2051 invalid_hwcaps(arch, hwcaps,
2052 "ISA2_07 requires VMX and FX and GX capabilities\n");
2053 if (! (hwcaps & VEX_HWCAPS_PPC64_VX))
2054 invalid_hwcaps(arch, hwcaps,
2055 "ISA2_07 requires VX capabilities\n");
2056 if (! (hwcaps & VEX_HWCAPS_PPC64_DFP))
2057 invalid_hwcaps(arch, hwcaps,
2058 "ISA2_07 requires DFP capabilities\n");
2061 /* ISA3_0 requires everything else */
2062 if ((hwcaps & VEX_HWCAPS_PPC64_ISA3_0) != 0) {
2063 if ( !((hwcaps
2064 & VEX_HWCAPS_PPC64_ISA2_07) == VEX_HWCAPS_PPC64_ISA2_07))
2065 invalid_hwcaps(arch, hwcaps,
2066 "ISA3_0 requires ISA2_07 capabilities\n");
2067 if ( !has_v_fx_gx)
2068 invalid_hwcaps(arch, hwcaps,
2069 "ISA3_0 requires VMX and FX and GX capabilities\n");
2070 if ( !(hwcaps & VEX_HWCAPS_PPC64_VX))
2071 invalid_hwcaps(arch, hwcaps,
2072 "ISA3_0 requires VX capabilities\n");
2073 if ( !(hwcaps & VEX_HWCAPS_PPC64_DFP))
2074 invalid_hwcaps(arch, hwcaps,
2075 "ISA3_0 requires DFP capabilities\n");
2077 return;
2080 case VexArchARM: {
2081 Bool NEON = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0);
2082 Bool VFP3 = ((hwcaps & VEX_HWCAPS_ARM_VFP3) != 0);
2083 UInt level = VEX_ARM_ARCHLEVEL(hwcaps);
2084 switch (level) {
2085 case 5:
2086 if (NEON)
2087 invalid_hwcaps(arch, hwcaps,
2088 "NEON instructions are not supported for ARMv5.\n");
2089 return;
2090 case 6:
2091 if (NEON)
2092 invalid_hwcaps(arch, hwcaps,
2093 "NEON instructions are not supported for ARMv6.\n");
2094 return;
2095 case 7:
2096 return;
2097 case 8:
2098 if (!NEON || !VFP3)
2099 invalid_hwcaps(arch, hwcaps,
2100 "NEON and VFP3 are required for ARMv8.\n");
2101 return;
2102 default:
2103 invalid_hwcaps(arch, hwcaps,
2104 "ARM architecture level is not supported.\n");
2108 case VexArchARM64:
2109 if (hwcaps != 0)
2110 invalid_hwcaps(arch, hwcaps,
2111 "Unsupported hardware capabilities.\n");
2112 return;
2114 case VexArchS390X:
2115 if (! s390_host_has_ldisp)
2116 invalid_hwcaps(arch, hwcaps,
2117 "Host does not have long displacement facility.\n");
2118 return;
2120 case VexArchMIPS32:
2121 switch (VEX_MIPS_COMP_ID(hwcaps)) {
2122 case VEX_PRID_COMP_MIPS:
2123 case VEX_PRID_COMP_CAVIUM:
2124 case VEX_PRID_COMP_INGENIC_E1:
2125 case VEX_PRID_COMP_BROADCOM:
2126 case VEX_PRID_COMP_NETLOGIC:
2127 return;
2128 default:
2129 invalid_hwcaps(arch, hwcaps, "Unsupported baseline\n");
2132 case VexArchMIPS64:
2133 switch (VEX_MIPS_COMP_ID(hwcaps)) {
2134 case VEX_PRID_COMP_MIPS:
2135 case VEX_PRID_COMP_CAVIUM:
2136 case VEX_PRID_COMP_NETLOGIC:
2137 return;
2138 case VEX_PRID_COMP_LEGACY:
2139 if (VEX_MIPS_PROC_ID(hwcaps) == VEX_PRID_IMP_LOONGSON_64)
2140 return;
2141 /* fallthrough */
2142 default:
2143 invalid_hwcaps(arch, hwcaps, "Unsupported baseline\n");
2146 case VexArchNANOMIPS:
2147 if (hwcaps == 0)
2148 return;
2149 invalid_hwcaps(arch, hwcaps, "Unsupported baseline\n");
2151 default:
2152 vpanic("unknown architecture");
2157 /*---------------------------------------------------------------*/
2158 /*--- end main_main.c ---*/
2159 /*---------------------------------------------------------------*/