blob: b007fa1c8f06abc6454c3c98155c04cb7e3a5f2a [file] [log] [blame]
florianf3652c92014-12-10 16:10:24 +00001/* -*- mode: C; c-basic-offset: 3; -*- */
sewardj35421a32004-07-05 13:12:34 +00002
3/*---------------------------------------------------------------*/
carll1f5fe1f2014-08-07 23:25:23 +00004/*--- Begin main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +00005/*---------------------------------------------------------------*/
6
sewardjf8ed9d82004-11-12 17:40:23 +00007/*
sewardj752f9062010-05-03 21:38:49 +00008 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
sewardjf8ed9d82004-11-12 17:40:23 +000010
sewardj89ae8472013-10-18 14:12:58 +000011 Copyright (C) 2004-2013 OpenWorks LLP
sewardj752f9062010-05-03 21:38:49 +000012 info@open-works.net
sewardjf8ed9d82004-11-12 17:40:23 +000013
sewardj752f9062010-05-03 21:38:49 +000014 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.
sewardjf8ed9d82004-11-12 17:40:23 +000018
sewardj752f9062010-05-03 21:38:49 +000019 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
sewardj7bd6ffe2005-08-03 16:07:36 +000027 02110-1301, USA.
28
sewardj752f9062010-05-03 21:38:49 +000029 The GNU General Public License is contained in the file COPYING.
sewardjf8ed9d82004-11-12 17:40:23 +000030
31 Neither the names of the U.S. Department of Energy nor the
32 University of California nor the names of its contributors may be
33 used to endorse or promote products derived from this software
34 without prior written permission.
sewardjf8ed9d82004-11-12 17:40:23 +000035*/
36
sewardj887a11a2004-07-05 17:26:47 +000037#include "libvex.h"
florian33b02432012-08-25 21:48:04 +000038#include "libvex_emnote.h"
sewardj81ec4182004-10-25 23:15:52 +000039#include "libvex_guest_x86.h"
sewardj44d494d2005-01-20 20:26:33 +000040#include "libvex_guest_amd64.h"
sewardj2a9ad022004-11-25 02:46:58 +000041#include "libvex_guest_arm.h"
sewardjbbcf1882014-01-12 12:49:10 +000042#include "libvex_guest_arm64.h"
cerionaabdfbf2005-01-29 12:56:15 +000043#include "libvex_guest_ppc32.h"
cerionf0de28c2005-12-13 20:21:11 +000044#include "libvex_guest_ppc64.h"
sewardj2019a972011-03-07 16:04:07 +000045#include "libvex_guest_s390x.h"
sewardjd0e5fe72012-06-07 08:51:02 +000046#include "libvex_guest_mips32.h"
petarjb92a9542013-02-27 22:57:17 +000047#include "libvex_guest_mips64.h"
sewardjf13a16a2004-07-05 17:10:14 +000048
sewardjcef7d3e2009-07-02 12:21:59 +000049#include "main_globals.h"
50#include "main_util.h"
51#include "host_generic_regs.h"
52#include "ir_opt.h"
sewardj35421a32004-07-05 13:12:34 +000053
sewardjcef7d3e2009-07-02 12:21:59 +000054#include "host_x86_defs.h"
55#include "host_amd64_defs.h"
56#include "host_ppc_defs.h"
sewardj6c299f32009-12-31 18:00:12 +000057#include "host_arm_defs.h"
sewardjbbcf1882014-01-12 12:49:10 +000058#include "host_arm64_defs.h"
sewardj2019a972011-03-07 16:04:07 +000059#include "host_s390_defs.h"
sewardjd0e5fe72012-06-07 08:51:02 +000060#include "host_mips_defs.h"
sewardj2a9ad022004-11-25 02:46:58 +000061
sewardjcef7d3e2009-07-02 12:21:59 +000062#include "guest_generic_bb_to_IR.h"
63#include "guest_x86_defs.h"
64#include "guest_amd64_defs.h"
65#include "guest_arm_defs.h"
sewardjbbcf1882014-01-12 12:49:10 +000066#include "guest_arm64_defs.h"
sewardjcef7d3e2009-07-02 12:21:59 +000067#include "guest_ppc_defs.h"
sewardj2019a972011-03-07 16:04:07 +000068#include "guest_s390_defs.h"
sewardjd0e5fe72012-06-07 08:51:02 +000069#include "guest_mips_defs.h"
sewardj2a9ad022004-11-25 02:46:58 +000070
sewardj69d98e32010-06-18 08:17:41 +000071#include "host_generic_simd128.h"
72
sewardj35421a32004-07-05 13:12:34 +000073
74/* This file contains the top level interface to the library. */
75
sewardj5117ce12006-01-27 21:20:15 +000076/* --------- fwds ... --------- */
77
florianf3652c92014-12-10 16:10:24 +000078static void check_hwcaps ( VexArch arch, UInt hwcaps );
florian55085f82012-11-21 00:36:55 +000079static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps );
sewardj5117ce12006-01-27 21:20:15 +000080
81
sewardj8bde7f12013-04-11 13:57:43 +000082/* --------- helpers --------- */
83
84__attribute__((noinline))
85static UInt udiv32 ( UInt x, UInt y ) { return x/y; }
86__attribute__((noinline))
87static Int sdiv32 ( Int x, Int y ) { return x/y; }
88
89
sewardj35421a32004-07-05 13:12:34 +000090/* --------- Initialise the library. --------- */
91
92/* Exported to library client. */
93
sewardj08613742004-10-25 13:01:45 +000094void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon )
95{
sewardj65902992014-05-03 21:20:56 +000096 vex_bzero(vcon, sizeof(*vcon));
sewardj08613742004-10-25 13:01:45 +000097 vcon->iropt_verbosity = 0;
98 vcon->iropt_level = 2;
philippec8e2f982012-08-01 22:04:13 +000099 vcon->iropt_register_updates = VexRegUpdUnwindregsAtMemAccess;
sewardj08613742004-10-25 13:01:45 +0000100 vcon->iropt_unroll_thresh = 120;
sewardj18b4bb72005-03-29 21:32:41 +0000101 vcon->guest_max_insns = 60;
sewardj08613742004-10-25 13:01:45 +0000102 vcon->guest_chase_thresh = 10;
sewardj984d9b12010-01-15 10:53:21 +0000103 vcon->guest_chase_cond = False;
sewardj08613742004-10-25 13:01:45 +0000104}
105
106
107/* Exported to library client. */
108
sewardj887a11a2004-07-05 17:26:47 +0000109void LibVEX_Init (
sewardj35421a32004-07-05 13:12:34 +0000110 /* failure exit function */
sewardj2b515872004-07-05 20:50:45 +0000111 __attribute__ ((noreturn))
sewardj35421a32004-07-05 13:12:34 +0000112 void (*failure_exit) ( void ),
113 /* logging output function */
sewardjd9763622005-02-07 03:12:19 +0000114 void (*log_bytes) ( HChar*, Int nbytes ),
sewardj35421a32004-07-05 13:12:34 +0000115 /* debug paranoia level */
116 Int debuglevel,
sewardj08613742004-10-25 13:01:45 +0000117 /* Control ... */
florianf72c2c12014-09-05 21:52:29 +0000118 const VexControl* vcon
sewardj35421a32004-07-05 13:12:34 +0000119)
120{
sewardj08613742004-10-25 13:01:45 +0000121 /* First off, do enough minimal setup so that the following
122 assertions can fail in a sane fashion, if need be. */
sewardjea602bc2004-10-14 21:40:12 +0000123 vex_failure_exit = failure_exit;
124 vex_log_bytes = log_bytes;
125
126 /* Now it's safe to check parameters for sanity. */
sewardj35421a32004-07-05 13:12:34 +0000127 vassert(!vex_initdone);
128 vassert(failure_exit);
sewardj35421a32004-07-05 13:12:34 +0000129 vassert(log_bytes);
sewardj35421a32004-07-05 13:12:34 +0000130 vassert(debuglevel >= 0);
sewardj08613742004-10-25 13:01:45 +0000131
132 vassert(vcon->iropt_verbosity >= 0);
133 vassert(vcon->iropt_level >= 0);
134 vassert(vcon->iropt_level <= 2);
135 vassert(vcon->iropt_unroll_thresh >= 0);
136 vassert(vcon->iropt_unroll_thresh <= 400);
137 vassert(vcon->guest_max_insns >= 1);
138 vassert(vcon->guest_max_insns <= 100);
139 vassert(vcon->guest_chase_thresh >= 0);
140 vassert(vcon->guest_chase_thresh < vcon->guest_max_insns);
sewardj984d9b12010-01-15 10:53:21 +0000141 vassert(vcon->guest_chase_cond == True
142 || vcon->guest_chase_cond == False);
sewardj443cd9d2004-07-18 23:06:45 +0000143
sewardjea602bc2004-10-14 21:40:12 +0000144 /* Check that Vex has been built with sizes of basic types as
145 stated in priv/libvex_basictypes.h. Failure of any of these is
146 a serious configuration error and should be corrected
147 immediately. If any of these assertions fail you can fully
148 expect Vex not to work properly, if at all. */
149
150 vassert(1 == sizeof(UChar));
151 vassert(1 == sizeof(Char));
152 vassert(2 == sizeof(UShort));
153 vassert(2 == sizeof(Short));
154 vassert(4 == sizeof(UInt));
155 vassert(4 == sizeof(Int));
156 vassert(8 == sizeof(ULong));
157 vassert(8 == sizeof(Long));
158 vassert(4 == sizeof(Float));
159 vassert(8 == sizeof(Double));
160 vassert(1 == sizeof(Bool));
161 vassert(4 == sizeof(Addr32));
162 vassert(8 == sizeof(Addr64));
sewardjc9a43662004-11-30 18:51:59 +0000163 vassert(16 == sizeof(U128));
sewardj69d98e32010-06-18 08:17:41 +0000164 vassert(16 == sizeof(V128));
sewardjc9069f22012-06-01 16:09:50 +0000165 vassert(32 == sizeof(U256));
sewardjea602bc2004-10-14 21:40:12 +0000166
167 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
168 vassert(sizeof(void*) == sizeof(int*));
169 vassert(sizeof(void*) == sizeof(HWord));
170
sewardj97e87932005-02-07 00:00:50 +0000171 vassert(VEX_HOST_WORDSIZE == sizeof(void*));
172 vassert(VEX_HOST_WORDSIZE == sizeof(HWord));
173
sewardjc6f970f2012-04-02 21:54:49 +0000174 /* These take a lot of space, so make sure we don't have
175 any unnoticed size regressions. */
176 if (VEX_HOST_WORDSIZE == 4) {
florian420bfa92012-06-02 20:29:22 +0000177 vassert(sizeof(IRExpr) == 16);
sewardjc6f970f2012-04-02 21:54:49 +0000178 vassert(sizeof(IRStmt) == 20 /* x86 */
179 || sizeof(IRStmt) == 24 /* arm */);
180 } else {
florian420bfa92012-06-02 20:29:22 +0000181 vassert(sizeof(IRExpr) == 32);
floriand6f38b32012-05-31 15:46:18 +0000182 vassert(sizeof(IRStmt) == 32);
sewardjc6f970f2012-04-02 21:54:49 +0000183 }
184
sewardj8bde7f12013-04-11 13:57:43 +0000185 /* Check that signed integer division on the host rounds towards
186 zero. If not, h_calc_sdiv32_w_arm_semantics() won't work
187 correctly. */
188 /* 100.0 / 7.0 == 14.2857 */
189 vassert(udiv32(100, 7) == 14);
190 vassert(sdiv32(100, 7) == 14);
191 vassert(sdiv32(-100, 7) == -14); /* and not -15 */
192 vassert(sdiv32(100, -7) == -14); /* ditto */
193 vassert(sdiv32(-100, -7) == 14); /* not sure what this proves */
194
sewardjea602bc2004-10-14 21:40:12 +0000195 /* Really start up .. */
sewardj443cd9d2004-07-18 23:06:45 +0000196 vex_debuglevel = debuglevel;
sewardj08613742004-10-25 13:01:45 +0000197 vex_control = *vcon;
sewardj443cd9d2004-07-18 23:06:45 +0000198 vex_initdone = True;
sewardjd887b862005-01-17 18:34:34 +0000199 vexSetAllocMode ( VexAllocModeTEMP );
sewardj35421a32004-07-05 13:12:34 +0000200}
201
202
203/* --------- Make a translation. --------- */
204
205/* Exported to library client. */
206
sewardj17c7f952005-12-15 14:02:34 +0000207VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
sewardj35421a32004-07-05 13:12:34 +0000208{
sewardj81bd5502004-07-21 18:49:27 +0000209 /* This the bundle of functions we need to do the back-end stuff
210 (insn selection, reg-alloc, assembly) whilst being insulated
211 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +0000212 HReg* available_real_regs;
213 Int n_available_real_regs;
floriand8c64e02014-10-08 08:54:44 +0000214 Bool (*isMove) ( const HInstr*, HReg*, HReg* );
215 void (*getRegUsage) ( HRegUsage*, const HInstr*, Bool );
sewardjfb7373a2007-08-25 21:29:03 +0000216 void (*mapRegs) ( HRegRemap*, HInstr*, Bool );
sewardj6c299f32009-12-31 18:00:12 +0000217 void (*genSpill) ( HInstr**, HInstr**, HReg, Int, Bool );
218 void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool );
sewardjfb7373a2007-08-25 21:29:03 +0000219 HInstr* (*directReload) ( HInstr*, HReg, Short );
floriand8c64e02014-10-08 08:54:44 +0000220 void (*ppInstr) ( const HInstr*, Bool );
sewardjfb7373a2007-08-25 21:29:03 +0000221 void (*ppReg) ( HReg );
floriancacba8e2014-12-15 18:58:07 +0000222 HInstrArray* (*iselSB) ( const IRSB*, VexArch, const VexArchInfo*,
floriand8c64e02014-10-08 08:54:44 +0000223 const VexAbiInfo*, Int, Int, Bool, Bool,
224 Addr64 );
sewardjc6f970f2012-04-02 21:54:49 +0000225 Int (*emit) ( /*MB_MOD*/Bool*,
floriand8c64e02014-10-08 08:54:44 +0000226 UChar*, Int, const HInstr*, Bool, VexEndness,
florian8462d112014-09-24 15:18:09 +0000227 const void*, const void*, const void*,
228 const void* );
florian1ff47562012-10-21 02:09:51 +0000229 IRExpr* (*specHelper) ( const HChar*, IRExpr**, IRStmt**, Int );
sewardj8d2291c2004-10-25 14:50:21 +0000230 Bool (*preciseMemExnsFn) ( Int, Int );
sewardjf13a16a2004-07-05 17:10:14 +0000231
sewardj9e6491a2005-07-02 19:24:10 +0000232 DisOneInstrFn disInstrFn;
233
sewardjeeac8412004-11-02 00:26:55 +0000234 VexGuestLayout* guest_layout;
sewardjdd40fdf2006-12-24 02:20:24 +0000235 IRSB* irsb;
sewardjeeac8412004-11-02 00:26:55 +0000236 HInstrArray* vcode;
237 HInstrArray* rcode;
238 Int i, j, k, out_used, guest_sizeB;
sewardj05f5e012014-05-04 10:52:11 +0000239 Int offB_CMSTART, offB_CMLEN, offB_GUEST_IP, szB_GUEST_IP;
sewardjc6f970f2012-04-02 21:54:49 +0000240 Int offB_HOST_EvC_COUNTER, offB_HOST_EvC_FAILADDR;
petarjb92a9542013-02-27 22:57:17 +0000241 UChar insn_bytes[128];
sewardjcf787902004-11-03 09:08:33 +0000242 IRType guest_word_type;
243 IRType host_word_type;
sewardjc6f970f2012-04-02 21:54:49 +0000244 Bool mode64, chainingAllowed;
245 Addr64 max_ga;
sewardjf13a16a2004-07-05 17:10:14 +0000246
sewardj49651f42004-10-28 22:11:04 +0000247 guest_layout = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000248 available_real_regs = NULL;
249 n_available_real_regs = 0;
250 isMove = NULL;
251 getRegUsage = NULL;
252 mapRegs = NULL;
253 genSpill = NULL;
254 genReload = NULL;
sewardjfb7373a2007-08-25 21:29:03 +0000255 directReload = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000256 ppInstr = NULL;
257 ppReg = NULL;
sewardjdd40fdf2006-12-24 02:20:24 +0000258 iselSB = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000259 emit = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000260 specHelper = NULL;
sewardj8d2291c2004-10-25 14:50:21 +0000261 preciseMemExnsFn = NULL;
sewardj9e6491a2005-07-02 19:24:10 +0000262 disInstrFn = NULL;
sewardjcf787902004-11-03 09:08:33 +0000263 guest_word_type = Ity_INVALID;
264 host_word_type = Ity_INVALID;
sewardj05f5e012014-05-04 10:52:11 +0000265 offB_CMSTART = 0;
266 offB_CMLEN = 0;
sewardjc6f970f2012-04-02 21:54:49 +0000267 offB_GUEST_IP = 0;
268 szB_GUEST_IP = 0;
269 offB_HOST_EvC_COUNTER = 0;
270 offB_HOST_EvC_FAILADDR = 0;
cerion92b64362005-12-13 12:02:26 +0000271 mode64 = False;
sewardjc6f970f2012-04-02 21:54:49 +0000272 chainingAllowed = False;
sewardj36ca5132004-07-24 13:12:23 +0000273
sewardj17c7f952005-12-15 14:02:34 +0000274 vex_traceflags = vta->traceflags;
sewardj58800ff2004-07-28 01:51:10 +0000275
sewardj35421a32004-07-05 13:12:34 +0000276 vassert(vex_initdone);
sewardjc6f970f2012-04-02 21:54:49 +0000277 vassert(vta->needs_self_check != NULL);
278 vassert(vta->disp_cp_xassisted != NULL);
279 /* Both the chainers and the indir are either NULL or non-NULL. */
280 if (vta->disp_cp_chain_me_to_slowEP != NULL) {
281 vassert(vta->disp_cp_chain_me_to_fastEP != NULL);
282 vassert(vta->disp_cp_xindir != NULL);
283 chainingAllowed = True;
284 } else {
285 vassert(vta->disp_cp_chain_me_to_fastEP == NULL);
286 vassert(vta->disp_cp_xindir == NULL);
287 }
florian2eeeb9b2011-09-23 18:03:21 +0000288
sewardj2d6b14a2005-11-23 04:25:07 +0000289 vexSetAllocModeTEMP_and_clear();
290 vexAllocSanityCheck();
sewardj2a9ad022004-11-25 02:46:58 +0000291
sewardjf13a16a2004-07-05 17:10:14 +0000292 /* First off, check that the guest and host insn sets
293 are supported. */
sewardj2a9ad022004-11-25 02:46:58 +0000294
sewardj17c7f952005-12-15 14:02:34 +0000295 switch (vta->arch_host) {
sewardj2a9ad022004-11-25 02:46:58 +0000296
sewardjbef170b2004-12-21 01:23:00 +0000297 case VexArchX86:
sewardjfb7373a2007-08-25 21:29:03 +0000298 mode64 = False;
sewardjf13a16a2004-07-05 17:10:14 +0000299 getAllocableRegs_X86 ( &n_available_real_regs,
300 &available_real_regs );
florianb66ad462014-10-07 22:13:47 +0000301 isMove = (__typeof__(isMove)) isMove_X86Instr;
302 getRegUsage = (__typeof__(getRegUsage)) getRegUsage_X86Instr;
303 mapRegs = (__typeof__(mapRegs)) mapRegs_X86Instr;
304 genSpill = (__typeof__(genSpill)) genSpill_X86;
305 genReload = (__typeof__(genReload)) genReload_X86;
306 directReload = (__typeof__(directReload)) directReload_X86;
307 ppInstr = (__typeof__(ppInstr)) ppX86Instr;
308 ppReg = (__typeof__(ppReg)) ppHRegX86;
sewardjfb7373a2007-08-25 21:29:03 +0000309 iselSB = iselSB_X86;
florianb66ad462014-10-07 22:13:47 +0000310 emit = (__typeof__(emit)) emit_X86Instr;
sewardjcf787902004-11-03 09:08:33 +0000311 host_word_type = Ity_I32;
sewardj9b769162014-07-24 12:42:03 +0000312 vassert(vta->archinfo_host.endness == VexEndnessLE);
sewardjf13a16a2004-07-05 17:10:14 +0000313 break;
sewardj2a9ad022004-11-25 02:46:58 +0000314
sewardjc33671d2005-02-01 20:30:00 +0000315 case VexArchAMD64:
cerion92b64362005-12-13 12:02:26 +0000316 mode64 = True;
sewardjc33671d2005-02-01 20:30:00 +0000317 getAllocableRegs_AMD64 ( &n_available_real_regs,
318 &available_real_regs );
florianb66ad462014-10-07 22:13:47 +0000319 isMove = (__typeof__(isMove)) isMove_AMD64Instr;
320 getRegUsage = (__typeof__(getRegUsage)) getRegUsage_AMD64Instr;
321 mapRegs = (__typeof__(mapRegs)) mapRegs_AMD64Instr;
322 genSpill = (__typeof__(genSpill)) genSpill_AMD64;
323 genReload = (__typeof__(genReload)) genReload_AMD64;
324 ppInstr = (__typeof__(ppInstr)) ppAMD64Instr;
325 ppReg = (__typeof__(ppReg)) ppHRegAMD64;
326 iselSB = iselSB_AMD64;
327 emit = (__typeof__(emit)) emit_AMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000328 host_word_type = Ity_I64;
sewardj9b769162014-07-24 12:42:03 +0000329 vassert(vta->archinfo_host.endness == VexEndnessLE);
sewardjc33671d2005-02-01 20:30:00 +0000330 break;
331
cerion487e4c92005-02-04 16:28:19 +0000332 case VexArchPPC32:
cerion92b64362005-12-13 12:02:26 +0000333 mode64 = False;
cerion5b2325f2005-12-23 00:55:09 +0000334 getAllocableRegs_PPC ( &n_available_real_regs,
335 &available_real_regs, mode64 );
florianb66ad462014-10-07 22:13:47 +0000336 isMove = (__typeof__(isMove)) isMove_PPCInstr;
337 getRegUsage = (__typeof__(getRegUsage)) getRegUsage_PPCInstr;
338 mapRegs = (__typeof__(mapRegs)) mapRegs_PPCInstr;
339 genSpill = (__typeof__(genSpill)) genSpill_PPC;
340 genReload = (__typeof__(genReload)) genReload_PPC;
341 ppInstr = (__typeof__(ppInstr)) ppPPCInstr;
342 ppReg = (__typeof__(ppReg)) ppHRegPPC;
343 iselSB = iselSB_PPC;
344 emit = (__typeof__(emit)) emit_PPCInstr;
cerion487e4c92005-02-04 16:28:19 +0000345 host_word_type = Ity_I32;
sewardj9b769162014-07-24 12:42:03 +0000346 vassert(vta->archinfo_host.endness == VexEndnessBE);
cerion487e4c92005-02-04 16:28:19 +0000347 break;
348
cerionf0de28c2005-12-13 20:21:11 +0000349 case VexArchPPC64:
350 mode64 = True;
cerion5b2325f2005-12-23 00:55:09 +0000351 getAllocableRegs_PPC ( &n_available_real_regs,
352 &available_real_regs, mode64 );
florianb66ad462014-10-07 22:13:47 +0000353 isMove = (__typeof__(isMove)) isMove_PPCInstr;
354 getRegUsage = (__typeof__(getRegUsage)) getRegUsage_PPCInstr;
355 mapRegs = (__typeof__(mapRegs)) mapRegs_PPCInstr;
356 genSpill = (__typeof__(genSpill)) genSpill_PPC;
357 genReload = (__typeof__(genReload)) genReload_PPC;
358 ppInstr = (__typeof__(ppInstr)) ppPPCInstr;
359 ppReg = (__typeof__(ppReg)) ppHRegPPC;
360 iselSB = iselSB_PPC;
361 emit = (__typeof__(emit)) emit_PPCInstr;
cerionf0de28c2005-12-13 20:21:11 +0000362 host_word_type = Ity_I64;
carll1f5fe1f2014-08-07 23:25:23 +0000363 vassert(vta->archinfo_host.endness == VexEndnessBE ||
364 vta->archinfo_host.endness == VexEndnessLE );
cerionf0de28c2005-12-13 20:21:11 +0000365 break;
366
sewardj2019a972011-03-07 16:04:07 +0000367 case VexArchS390X:
368 mode64 = True;
florian3eb7bab2014-12-08 12:42:26 +0000369 /* KLUDGE: export hwcaps. */
370 s390_host_hwcaps = vta->archinfo_host.hwcaps;
sewardj2019a972011-03-07 16:04:07 +0000371 getAllocableRegs_S390 ( &n_available_real_regs,
372 &available_real_regs, mode64 );
florianb66ad462014-10-07 22:13:47 +0000373 isMove = (__typeof__(isMove)) isMove_S390Instr;
374 getRegUsage = (__typeof__(getRegUsage)) getRegUsage_S390Instr;
375 mapRegs = (__typeof__(mapRegs)) mapRegs_S390Instr;
376 genSpill = (__typeof__(genSpill)) genSpill_S390;
377 genReload = (__typeof__(genReload)) genReload_S390;
florian017c0d52014-10-07 21:57:05 +0000378 // fixs390: consider implementing directReload_S390
florianb66ad462014-10-07 22:13:47 +0000379 ppInstr = (__typeof__(ppInstr)) ppS390Instr;
380 ppReg = (__typeof__(ppReg)) ppHRegS390;
381 iselSB = iselSB_S390;
382 emit = (__typeof__(emit)) emit_S390Instr;
sewardj2019a972011-03-07 16:04:07 +0000383 host_word_type = Ity_I64;
sewardj9b769162014-07-24 12:42:03 +0000384 vassert(vta->archinfo_host.endness == VexEndnessBE);
sewardj2019a972011-03-07 16:04:07 +0000385 break;
386
sewardj6c299f32009-12-31 18:00:12 +0000387 case VexArchARM:
sewardj2a1ed8e2009-12-31 19:26:03 +0000388 mode64 = False;
sewardj6c299f32009-12-31 18:00:12 +0000389 getAllocableRegs_ARM ( &n_available_real_regs,
390 &available_real_regs );
florianb66ad462014-10-07 22:13:47 +0000391 isMove = (__typeof__(isMove)) isMove_ARMInstr;
392 getRegUsage = (__typeof__(getRegUsage)) getRegUsage_ARMInstr;
393 mapRegs = (__typeof__(mapRegs)) mapRegs_ARMInstr;
394 genSpill = (__typeof__(genSpill)) genSpill_ARM;
395 genReload = (__typeof__(genReload)) genReload_ARM;
396 ppInstr = (__typeof__(ppInstr)) ppARMInstr;
397 ppReg = (__typeof__(ppReg)) ppHRegARM;
398 iselSB = iselSB_ARM;
399 emit = (__typeof__(emit)) emit_ARMInstr;
sewardj6c299f32009-12-31 18:00:12 +0000400 host_word_type = Ity_I32;
sewardj9b769162014-07-24 12:42:03 +0000401 vassert(vta->archinfo_host.endness == VexEndnessLE);
sewardj6c299f32009-12-31 18:00:12 +0000402 break;
403
sewardjbbcf1882014-01-12 12:49:10 +0000404 case VexArchARM64:
405 mode64 = True;
406 getAllocableRegs_ARM64 ( &n_available_real_regs,
407 &available_real_regs );
florianb66ad462014-10-07 22:13:47 +0000408 isMove = (__typeof__(isMove)) isMove_ARM64Instr;
409 getRegUsage = (__typeof__(getRegUsage)) getRegUsage_ARM64Instr;
410 mapRegs = (__typeof__(mapRegs)) mapRegs_ARM64Instr;
411 genSpill = (__typeof__(genSpill)) genSpill_ARM64;
412 genReload = (__typeof__(genReload)) genReload_ARM64;
413 ppInstr = (__typeof__(ppInstr)) ppARM64Instr;
414 ppReg = (__typeof__(ppReg)) ppHRegARM64;
415 iselSB = iselSB_ARM64;
416 emit = (__typeof__(emit)) emit_ARM64Instr;
sewardjbbcf1882014-01-12 12:49:10 +0000417 host_word_type = Ity_I64;
sewardj9b769162014-07-24 12:42:03 +0000418 vassert(vta->archinfo_host.endness == VexEndnessLE);
sewardjbbcf1882014-01-12 12:49:10 +0000419 break;
420
sewardjd0e5fe72012-06-07 08:51:02 +0000421 case VexArchMIPS32:
422 mode64 = False;
423 getAllocableRegs_MIPS ( &n_available_real_regs,
424 &available_real_regs, mode64 );
florianb66ad462014-10-07 22:13:47 +0000425 isMove = (__typeof__(isMove)) isMove_MIPSInstr;
426 getRegUsage = (__typeof__(getRegUsage)) getRegUsage_MIPSInstr;
427 mapRegs = (__typeof__(mapRegs)) mapRegs_MIPSInstr;
428 genSpill = (__typeof__(genSpill)) genSpill_MIPS;
429 genReload = (__typeof__(genReload)) genReload_MIPS;
430 ppInstr = (__typeof__(ppInstr)) ppMIPSInstr;
431 ppReg = (__typeof__(ppReg)) ppHRegMIPS;
432 iselSB = iselSB_MIPS;
433 emit = (__typeof__(emit)) emit_MIPSInstr;
sewardjd0e5fe72012-06-07 08:51:02 +0000434 host_word_type = Ity_I32;
sewardj9b769162014-07-24 12:42:03 +0000435 vassert(vta->archinfo_host.endness == VexEndnessLE
436 || vta->archinfo_host.endness == VexEndnessBE);
sewardjd0e5fe72012-06-07 08:51:02 +0000437 break;
438
petarjb92a9542013-02-27 22:57:17 +0000439 case VexArchMIPS64:
440 mode64 = True;
441 getAllocableRegs_MIPS ( &n_available_real_regs,
442 &available_real_regs, mode64 );
florianb66ad462014-10-07 22:13:47 +0000443 isMove = (__typeof__(isMove)) isMove_MIPSInstr;
444 getRegUsage = (__typeof__(getRegUsage)) getRegUsage_MIPSInstr;
445 mapRegs = (__typeof__(mapRegs)) mapRegs_MIPSInstr;
446 genSpill = (__typeof__(genSpill)) genSpill_MIPS;
447 genReload = (__typeof__(genReload)) genReload_MIPS;
448 ppInstr = (__typeof__(ppInstr)) ppMIPSInstr;
449 ppReg = (__typeof__(ppReg)) ppHRegMIPS;
450 iselSB = iselSB_MIPS;
451 emit = (__typeof__(emit)) emit_MIPSInstr;
petarjb92a9542013-02-27 22:57:17 +0000452 host_word_type = Ity_I64;
sewardj9b769162014-07-24 12:42:03 +0000453 vassert(vta->archinfo_host.endness == VexEndnessLE
454 || vta->archinfo_host.endness == VexEndnessBE);
petarjb92a9542013-02-27 22:57:17 +0000455 break;
456
sewardjf13a16a2004-07-05 17:10:14 +0000457 default:
sewardj6c299f32009-12-31 18:00:12 +0000458 vpanic("LibVEX_Translate: unsupported host insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000459 }
460
florianf3652c92014-12-10 16:10:24 +0000461 // Are the host's hardware capabilities feasible. The function will
462 // not return if hwcaps are infeasible in some sense.
463 check_hwcaps(vta->arch_host, vta->archinfo_host.hwcaps);
sewardj2a9ad022004-11-25 02:46:58 +0000464
sewardj17c7f952005-12-15 14:02:34 +0000465 switch (vta->arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000466
sewardjbef170b2004-12-21 01:23:00 +0000467 case VexArchX86:
sewardjc6f970f2012-04-02 21:54:49 +0000468 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
469 disInstrFn = disInstr_X86;
470 specHelper = guest_x86_spechelper;
471 guest_sizeB = sizeof(VexGuestX86State);
472 guest_word_type = Ity_I32;
473 guest_layout = &x86guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000474 offB_CMSTART = offsetof(VexGuestX86State,guest_CMSTART);
475 offB_CMLEN = offsetof(VexGuestX86State,guest_CMLEN);
sewardjc6f970f2012-04-02 21:54:49 +0000476 offB_GUEST_IP = offsetof(VexGuestX86State,guest_EIP);
477 szB_GUEST_IP = sizeof( ((VexGuestX86State*)0)->guest_EIP );
478 offB_HOST_EvC_COUNTER = offsetof(VexGuestX86State,host_EvC_COUNTER);
479 offB_HOST_EvC_FAILADDR = offsetof(VexGuestX86State,host_EvC_FAILADDR);
sewardj9b769162014-07-24 12:42:03 +0000480 vassert(vta->archinfo_guest.endness == VexEndnessLE);
sewardj6c299f32009-12-31 18:00:12 +0000481 vassert(0 == sizeof(VexGuestX86State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000482 vassert(sizeof( ((VexGuestX86State*)0)->guest_CMSTART) == 4);
483 vassert(sizeof( ((VexGuestX86State*)0)->guest_CMLEN ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000484 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000485 break;
sewardj2a9ad022004-11-25 02:46:58 +0000486
sewardj44d494d2005-01-20 20:26:33 +0000487 case VexArchAMD64:
sewardjc6f970f2012-04-02 21:54:49 +0000488 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
489 disInstrFn = disInstr_AMD64;
490 specHelper = guest_amd64_spechelper;
491 guest_sizeB = sizeof(VexGuestAMD64State);
492 guest_word_type = Ity_I64;
493 guest_layout = &amd64guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000494 offB_CMSTART = offsetof(VexGuestAMD64State,guest_CMSTART);
495 offB_CMLEN = offsetof(VexGuestAMD64State,guest_CMLEN);
sewardjc6f970f2012-04-02 21:54:49 +0000496 offB_GUEST_IP = offsetof(VexGuestAMD64State,guest_RIP);
497 szB_GUEST_IP = sizeof( ((VexGuestAMD64State*)0)->guest_RIP );
498 offB_HOST_EvC_COUNTER = offsetof(VexGuestAMD64State,host_EvC_COUNTER);
499 offB_HOST_EvC_FAILADDR = offsetof(VexGuestAMD64State,host_EvC_FAILADDR);
sewardj9b769162014-07-24 12:42:03 +0000500 vassert(vta->archinfo_guest.endness == VexEndnessLE);
sewardj6c299f32009-12-31 18:00:12 +0000501 vassert(0 == sizeof(VexGuestAMD64State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000502 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_CMSTART ) == 8);
503 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_CMLEN ) == 8);
sewardjce02aa72006-01-12 12:27:58 +0000504 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000505 break;
506
cerionaabdfbf2005-01-29 12:56:15 +0000507 case VexArchPPC32:
sewardj3dee8492012-04-20 00:13:28 +0000508 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
509 disInstrFn = disInstr_PPC;
510 specHelper = guest_ppc32_spechelper;
511 guest_sizeB = sizeof(VexGuestPPC32State);
512 guest_word_type = Ity_I32;
513 guest_layout = &ppc32Guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000514 offB_CMSTART = offsetof(VexGuestPPC32State,guest_CMSTART);
515 offB_CMLEN = offsetof(VexGuestPPC32State,guest_CMLEN);
sewardj3dee8492012-04-20 00:13:28 +0000516 offB_GUEST_IP = offsetof(VexGuestPPC32State,guest_CIA);
517 szB_GUEST_IP = sizeof( ((VexGuestPPC32State*)0)->guest_CIA );
518 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC32State,host_EvC_COUNTER);
519 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC32State,host_EvC_FAILADDR);
sewardj9b769162014-07-24 12:42:03 +0000520 vassert(vta->archinfo_guest.endness == VexEndnessBE);
sewardj6c299f32009-12-31 18:00:12 +0000521 vassert(0 == sizeof(VexGuestPPC32State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000522 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_CMSTART ) == 4);
523 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_CMLEN ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000524 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000525 break;
526
cerionf0de28c2005-12-13 20:21:11 +0000527 case VexArchPPC64:
sewardj9e1cf152012-04-20 02:18:31 +0000528 preciseMemExnsFn = guest_ppc64_state_requires_precise_mem_exns;
529 disInstrFn = disInstr_PPC;
530 specHelper = guest_ppc64_spechelper;
531 guest_sizeB = sizeof(VexGuestPPC64State);
532 guest_word_type = Ity_I64;
533 guest_layout = &ppc64Guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000534 offB_CMSTART = offsetof(VexGuestPPC64State,guest_CMSTART);
535 offB_CMLEN = offsetof(VexGuestPPC64State,guest_CMLEN);
sewardj9e1cf152012-04-20 02:18:31 +0000536 offB_GUEST_IP = offsetof(VexGuestPPC64State,guest_CIA);
537 szB_GUEST_IP = sizeof( ((VexGuestPPC64State*)0)->guest_CIA );
538 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC64State,host_EvC_COUNTER);
539 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC64State,host_EvC_FAILADDR);
carll1f5fe1f2014-08-07 23:25:23 +0000540 vassert(vta->archinfo_guest.endness == VexEndnessBE ||
541 vta->archinfo_guest.endness == VexEndnessLE );
cerionf0de28c2005-12-13 20:21:11 +0000542 vassert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000543 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_CMSTART ) == 8);
544 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_CMLEN ) == 8);
sewardj3fd39672006-01-27 22:05:55 +0000545 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8);
546 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8);
cerionf0de28c2005-12-13 20:21:11 +0000547 break;
548
sewardj2019a972011-03-07 16:04:07 +0000549 case VexArchS390X:
550 preciseMemExnsFn = guest_s390x_state_requires_precise_mem_exns;
551 disInstrFn = disInstr_S390;
552 specHelper = guest_s390x_spechelper;
553 guest_sizeB = sizeof(VexGuestS390XState);
554 guest_word_type = Ity_I64;
555 guest_layout = &s390xGuest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000556 offB_CMSTART = offsetof(VexGuestS390XState,guest_CMSTART);
557 offB_CMLEN = offsetof(VexGuestS390XState,guest_CMLEN);
florian8844a632012-04-13 04:04:06 +0000558 offB_GUEST_IP = offsetof(VexGuestS390XState,guest_IA);
559 szB_GUEST_IP = sizeof( ((VexGuestS390XState*)0)->guest_IA);
560 offB_HOST_EvC_COUNTER = offsetof(VexGuestS390XState,host_EvC_COUNTER);
561 offB_HOST_EvC_FAILADDR = offsetof(VexGuestS390XState,host_EvC_FAILADDR);
sewardj9b769162014-07-24 12:42:03 +0000562 vassert(vta->archinfo_guest.endness == VexEndnessBE);
sewardj2019a972011-03-07 16:04:07 +0000563 vassert(0 == sizeof(VexGuestS390XState) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000564 vassert(sizeof( ((VexGuestS390XState*)0)->guest_CMSTART ) == 8);
565 vassert(sizeof( ((VexGuestS390XState*)0)->guest_CMLEN ) == 8);
sewardj2019a972011-03-07 16:04:07 +0000566 vassert(sizeof( ((VexGuestS390XState*)0)->guest_NRADDR ) == 8);
567 break;
568
sewardj6c299f32009-12-31 18:00:12 +0000569 case VexArchARM:
sewardjc6f970f2012-04-02 21:54:49 +0000570 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
571 disInstrFn = disInstr_ARM;
572 specHelper = guest_arm_spechelper;
573 guest_sizeB = sizeof(VexGuestARMState);
574 guest_word_type = Ity_I32;
575 guest_layout = &armGuest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000576 offB_CMSTART = offsetof(VexGuestARMState,guest_CMSTART);
577 offB_CMLEN = offsetof(VexGuestARMState,guest_CMLEN);
sewardjc6f970f2012-04-02 21:54:49 +0000578 offB_GUEST_IP = offsetof(VexGuestARMState,guest_R15T);
579 szB_GUEST_IP = sizeof( ((VexGuestARMState*)0)->guest_R15T );
580 offB_HOST_EvC_COUNTER = offsetof(VexGuestARMState,host_EvC_COUNTER);
581 offB_HOST_EvC_FAILADDR = offsetof(VexGuestARMState,host_EvC_FAILADDR);
sewardj9b769162014-07-24 12:42:03 +0000582 vassert(vta->archinfo_guest.endness == VexEndnessLE);
sewardj6c299f32009-12-31 18:00:12 +0000583 vassert(0 == sizeof(VexGuestARMState) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000584 vassert(sizeof( ((VexGuestARMState*)0)->guest_CMSTART) == 4);
585 vassert(sizeof( ((VexGuestARMState*)0)->guest_CMLEN ) == 4);
sewardj6c299f32009-12-31 18:00:12 +0000586 vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4);
587 break;
588
sewardjbbcf1882014-01-12 12:49:10 +0000589 case VexArchARM64:
590 preciseMemExnsFn = guest_arm64_state_requires_precise_mem_exns;
591 disInstrFn = disInstr_ARM64;
592 specHelper = guest_arm64_spechelper;
593 guest_sizeB = sizeof(VexGuestARM64State);
594 guest_word_type = Ity_I64;
595 guest_layout = &arm64Guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000596 offB_CMSTART = offsetof(VexGuestARM64State,guest_CMSTART);
597 offB_CMLEN = offsetof(VexGuestARM64State,guest_CMLEN);
sewardjbbcf1882014-01-12 12:49:10 +0000598 offB_GUEST_IP = offsetof(VexGuestARM64State,guest_PC);
599 szB_GUEST_IP = sizeof( ((VexGuestARM64State*)0)->guest_PC );
600 offB_HOST_EvC_COUNTER = offsetof(VexGuestARM64State,host_EvC_COUNTER);
601 offB_HOST_EvC_FAILADDR = offsetof(VexGuestARM64State,host_EvC_FAILADDR);
sewardj9b769162014-07-24 12:42:03 +0000602 vassert(vta->archinfo_guest.endness == VexEndnessLE);
sewardjbbcf1882014-01-12 12:49:10 +0000603 vassert(0 == sizeof(VexGuestARM64State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000604 vassert(sizeof( ((VexGuestARM64State*)0)->guest_CMSTART) == 8);
605 vassert(sizeof( ((VexGuestARM64State*)0)->guest_CMLEN ) == 8);
sewardjbbcf1882014-01-12 12:49:10 +0000606 vassert(sizeof( ((VexGuestARM64State*)0)->guest_NRADDR ) == 8);
607 break;
608
sewardjd0e5fe72012-06-07 08:51:02 +0000609 case VexArchMIPS32:
610 preciseMemExnsFn = guest_mips32_state_requires_precise_mem_exns;
611 disInstrFn = disInstr_MIPS;
612 specHelper = guest_mips32_spechelper;
613 guest_sizeB = sizeof(VexGuestMIPS32State);
614 guest_word_type = Ity_I32;
615 guest_layout = &mips32Guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000616 offB_CMSTART = offsetof(VexGuestMIPS32State,guest_CMSTART);
617 offB_CMLEN = offsetof(VexGuestMIPS32State,guest_CMLEN);
sewardjd0e5fe72012-06-07 08:51:02 +0000618 offB_GUEST_IP = offsetof(VexGuestMIPS32State,guest_PC);
619 szB_GUEST_IP = sizeof( ((VexGuestMIPS32State*)0)->guest_PC );
620 offB_HOST_EvC_COUNTER = offsetof(VexGuestMIPS32State,host_EvC_COUNTER);
621 offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS32State,host_EvC_FAILADDR);
sewardj9b769162014-07-24 12:42:03 +0000622 vassert(vta->archinfo_guest.endness == VexEndnessLE
623 || vta->archinfo_guest.endness == VexEndnessBE);
sewardjd0e5fe72012-06-07 08:51:02 +0000624 vassert(0 == sizeof(VexGuestMIPS32State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000625 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_CMSTART) == 4);
626 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_CMLEN ) == 4);
sewardjd0e5fe72012-06-07 08:51:02 +0000627 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_NRADDR ) == 4);
628 break;
629
petarjb92a9542013-02-27 22:57:17 +0000630 case VexArchMIPS64:
631 preciseMemExnsFn = guest_mips64_state_requires_precise_mem_exns;
632 disInstrFn = disInstr_MIPS;
633 specHelper = guest_mips64_spechelper;
634 guest_sizeB = sizeof(VexGuestMIPS64State);
635 guest_word_type = Ity_I64;
636 guest_layout = &mips64Guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000637 offB_CMSTART = offsetof(VexGuestMIPS64State,guest_CMSTART);
638 offB_CMLEN = offsetof(VexGuestMIPS64State,guest_CMLEN);
petarjb92a9542013-02-27 22:57:17 +0000639 offB_GUEST_IP = offsetof(VexGuestMIPS64State,guest_PC);
640 szB_GUEST_IP = sizeof( ((VexGuestMIPS64State*)0)->guest_PC );
641 offB_HOST_EvC_COUNTER = offsetof(VexGuestMIPS64State,host_EvC_COUNTER);
642 offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS64State,host_EvC_FAILADDR);
sewardj9b769162014-07-24 12:42:03 +0000643 vassert(vta->archinfo_guest.endness == VexEndnessLE
644 || vta->archinfo_guest.endness == VexEndnessBE);
petarjb92a9542013-02-27 22:57:17 +0000645 vassert(0 == sizeof(VexGuestMIPS64State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000646 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_CMSTART) == 8);
647 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_CMLEN ) == 8);
petarjb92a9542013-02-27 22:57:17 +0000648 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_NRADDR ) == 8);
649 break;
650
sewardjf13a16a2004-07-05 17:10:14 +0000651 default:
sewardj887a11a2004-07-05 17:26:47 +0000652 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000653 }
654
florianf3652c92014-12-10 16:10:24 +0000655 // Are the guest's hardware capabilities feasible. The function will
656 // not return if hwcaps are infeasible in some sense.
657 // FIXME: how can we know the guest's hardware capabilities?
658 check_hwcaps(vta->arch_guest, vta->archinfo_guest.hwcaps);
659
sewardjbc161a42011-06-07 21:28:38 +0000660 /* Set up result struct. */
661 VexTranslateResult res;
sewardjfadbbe22012-04-24 11:49:03 +0000662 res.status = VexTransOK;
663 res.n_sc_extents = 0;
664 res.offs_profInc = -1;
665 res.n_guest_instrs = 0;
sewardjbc161a42011-06-07 21:28:38 +0000666
sewardj9df271d2004-12-31 22:37:42 +0000667 /* yet more sanity checks ... */
sewardj17c7f952005-12-15 14:02:34 +0000668 if (vta->arch_guest == vta->arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000669 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000670 we are simulating one flavour of an architecture a different
671 flavour of the same architecture, which is pretty strange. */
sewardj5117ce12006-01-27 21:20:15 +0000672 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps);
sewardj9b769162014-07-24 12:42:03 +0000673 /* ditto */
674 vassert(vta->archinfo_guest.endness == vta->archinfo_host.endness);
sewardj9df271d2004-12-31 22:37:42 +0000675 }
sewardj2a9ad022004-11-25 02:46:58 +0000676
sewardj2d6b14a2005-11-23 04:25:07 +0000677 vexAllocSanityCheck();
678
sewardjf48ac192004-10-29 00:41:29 +0000679 if (vex_traceflags & VEX_TRACE_FE)
680 vex_printf("\n------------------------"
681 " Front end "
682 "------------------------\n\n");
683
sewardjdd40fdf2006-12-24 02:20:24 +0000684 irsb = bb_to_IR ( vta->guest_extents,
sewardjbc161a42011-06-07 21:28:38 +0000685 &res.n_sc_extents,
sewardjfadbbe22012-04-24 11:49:03 +0000686 &res.n_guest_instrs,
sewardjc716aea2006-01-17 01:48:46 +0000687 vta->callback_opaque,
sewardj9e6491a2005-07-02 19:24:10 +0000688 disInstrFn,
sewardj17c7f952005-12-15 14:02:34 +0000689 vta->guest_bytes,
690 vta->guest_bytes_addr,
691 vta->chase_into_ok,
sewardj9b769162014-07-24 12:42:03 +0000692 vta->archinfo_host.endness,
sewardj442e51a2012-12-06 18:08:04 +0000693 vta->sigill_diag,
sewardja5f55da2006-04-30 23:37:32 +0000694 vta->arch_guest,
sewardj17c7f952005-12-15 14:02:34 +0000695 &vta->archinfo_guest,
sewardjdd40fdf2006-12-24 02:20:24 +0000696 &vta->abiinfo_both,
sewardjdb4738a2005-07-07 01:32:16 +0000697 guest_word_type,
sewardjbc161a42011-06-07 21:28:38 +0000698 vta->needs_self_check,
sewardjc716aea2006-01-17 01:48:46 +0000699 vta->preamble_function,
sewardj05f5e012014-05-04 10:52:11 +0000700 offB_CMSTART,
701 offB_CMLEN,
sewardjc6f970f2012-04-02 21:54:49 +0000702 offB_GUEST_IP,
703 szB_GUEST_IP );
sewardjf13a16a2004-07-05 17:10:14 +0000704
sewardj2d6b14a2005-11-23 04:25:07 +0000705 vexAllocSanityCheck();
706
sewardjdd40fdf2006-12-24 02:20:24 +0000707 if (irsb == NULL) {
sewardjf13a16a2004-07-05 17:10:14 +0000708 /* Access failure. */
sewardj2d6b14a2005-11-23 04:25:07 +0000709 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000710 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000711 res.status = VexTransAccessFail; return res;
sewardjf13a16a2004-07-05 17:10:14 +0000712 }
sewardjaa59f942004-10-09 09:34:36 +0000713
sewardj17c7f952005-12-15 14:02:34 +0000714 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3);
715 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr);
716 for (i = 0; i < vta->guest_extents->n_used; i++) {
717 vassert(vta->guest_extents->len[i] < 10000); /* sanity */
sewardj72c72812005-01-19 11:49:45 +0000718 }
719
sewardjaa59f942004-10-09 09:34:36 +0000720 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000721 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj17c7f952005-12-15 14:02:34 +0000722 if (vta->guest_extents->n_used > 1) {
sewardj72c72812005-01-19 11:49:45 +0000723 vex_printf("can't show code due to extents > 1\n");
724 } else {
725 /* HACK */
florian8462d112014-09-24 15:18:09 +0000726 const UChar* p = vta->guest_bytes;
sewardj01f8cce2009-08-31 08:50:02 +0000727 UInt sum = 0;
sewardj17c7f952005-12-15 14:02:34 +0000728 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0];
sewardj01f8cce2009-08-31 08:50:02 +0000729 vex_printf("GuestBytes %llx %u ", vta->guest_bytes_addr,
730 guest_bytes_read );
731 for (i = 0; i < guest_bytes_read; i++) {
732 UInt b = (UInt)p[i];
733 vex_printf(" %02x", b );
734 sum = (sum << 1) ^ b;
735 }
736 vex_printf(" %08x\n\n", sum);
sewardj72c72812005-01-19 11:49:45 +0000737 }
sewardjaa59f942004-10-09 09:34:36 +0000738 }
739
740 /* Sanity check the initial IR. */
sewardjdd40fdf2006-12-24 02:20:24 +0000741 sanityCheckIRSB( irsb, "initial IR",
sewardjb9230752004-12-29 19:25:06 +0000742 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000743
sewardj2d6b14a2005-11-23 04:25:07 +0000744 vexAllocSanityCheck();
745
sewardjedf4d692004-08-17 13:52:58 +0000746 /* Clean it up, hopefully a lot. */
sewardjdd40fdf2006-12-24 02:20:24 +0000747 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn,
sewardjec0d9a02010-08-22 12:54:56 +0000748 vta->guest_bytes_addr,
749 vta->arch_guest );
sewardjdd40fdf2006-12-24 02:20:24 +0000750 sanityCheckIRSB( irsb, "after initial iropt",
sewardjb9230752004-12-29 19:25:06 +0000751 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000752
sewardjf48ac192004-10-29 00:41:29 +0000753 if (vex_traceflags & VEX_TRACE_OPT1) {
754 vex_printf("\n------------------------"
755 " After pre-instr IR optimisation "
756 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000757 ppIRSB ( irsb );
sewardjedf4d692004-08-17 13:52:58 +0000758 vex_printf("\n");
759 }
760
sewardj2d6b14a2005-11-23 04:25:07 +0000761 vexAllocSanityCheck();
762
sewardjf13a16a2004-07-05 17:10:14 +0000763 /* Get the thing instrumented. */
sewardj17c7f952005-12-15 14:02:34 +0000764 if (vta->instrument1)
sewardjdd40fdf2006-12-24 02:20:24 +0000765 irsb = vta->instrument1(vta->callback_opaque,
766 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000767 vta->guest_extents,
florian50481922012-10-07 21:58:07 +0000768 &vta->archinfo_host,
sewardj17c7f952005-12-15 14:02:34 +0000769 guest_word_type, host_word_type);
sewardj2d6b14a2005-11-23 04:25:07 +0000770 vexAllocSanityCheck();
771
sewardj17c7f952005-12-15 14:02:34 +0000772 if (vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000773 irsb = vta->instrument2(vta->callback_opaque,
774 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000775 vta->guest_extents,
florian50481922012-10-07 21:58:07 +0000776 &vta->archinfo_host,
sewardj17c7f952005-12-15 14:02:34 +0000777 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000778
sewardjf48ac192004-10-29 00:41:29 +0000779 if (vex_traceflags & VEX_TRACE_INST) {
780 vex_printf("\n------------------------"
781 " After instrumentation "
782 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000783 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000784 vex_printf("\n");
785 }
786
sewardj17c7f952005-12-15 14:02:34 +0000787 if (vta->instrument1 || vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000788 sanityCheckIRSB( irsb, "after instrumentation",
sewardjb9230752004-12-29 19:25:06 +0000789 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000790
sewardj9578a8b2004-11-04 19:44:48 +0000791 /* Do a post-instrumentation cleanup pass. */
sewardj17c7f952005-12-15 14:02:34 +0000792 if (vta->instrument1 || vta->instrument2) {
sewardjdd40fdf2006-12-24 02:20:24 +0000793 do_deadcode_BB( irsb );
794 irsb = cprop_BB( irsb );
795 do_deadcode_BB( irsb );
796 sanityCheckIRSB( irsb, "after post-instrumentation cleanup",
sewardjb9230752004-12-29 19:25:06 +0000797 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000798 }
799
sewardj2d6b14a2005-11-23 04:25:07 +0000800 vexAllocSanityCheck();
801
sewardj9578a8b2004-11-04 19:44:48 +0000802 if (vex_traceflags & VEX_TRACE_OPT2) {
803 vex_printf("\n------------------------"
804 " After post-instr IR optimisation "
805 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000806 ppIRSB ( irsb );
sewardj9578a8b2004-11-04 19:44:48 +0000807 vex_printf("\n");
808 }
809
sewardjf9517d02005-11-28 13:39:37 +0000810 /* Turn it into virtual-registerised code. Build trees -- this
811 also throws away any dead bindings. */
florian62140c12013-01-20 03:51:04 +0000812 max_ga = ado_treebuild_BB( irsb, preciseMemExnsFn );
sewardjf48ac192004-10-29 00:41:29 +0000813
sewardjbe1b6ff2007-08-28 06:06:27 +0000814 if (vta->finaltidy) {
815 irsb = vta->finaltidy(irsb);
816 }
817
sewardj2d6b14a2005-11-23 04:25:07 +0000818 vexAllocSanityCheck();
819
sewardjf48ac192004-10-29 00:41:29 +0000820 if (vex_traceflags & VEX_TRACE_TREES) {
821 vex_printf("\n------------------------"
822 " After tree-building "
823 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000824 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000825 vex_printf("\n");
826 }
827
sewardje908c422005-02-04 21:18:16 +0000828 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000829 if (0) {
830 *(vta->host_bytes_used) = 0;
831 res.status = VexTransOK; return res;
832 }
sewardje908c422005-02-04 21:18:16 +0000833 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000834
sewardjf48ac192004-10-29 00:41:29 +0000835 if (vex_traceflags & VEX_TRACE_VCODE)
836 vex_printf("\n------------------------"
837 " Instruction selection "
838 "------------------------\n");
839
sewardjc6f970f2012-04-02 21:54:49 +0000840 /* No guest has its IP field at offset zero. If this fails it
841 means some transformation pass somewhere failed to update/copy
842 irsb->offsIP properly. */
843 vassert(irsb->offsIP >= 16);
844
845 vcode = iselSB ( irsb, vta->arch_host,
846 &vta->archinfo_host,
847 &vta->abiinfo_both,
848 offB_HOST_EvC_COUNTER,
849 offB_HOST_EvC_FAILADDR,
850 chainingAllowed,
851 vta->addProfInc,
852 max_ga );
sewardjf13a16a2004-07-05 17:10:14 +0000853
sewardj2d6b14a2005-11-23 04:25:07 +0000854 vexAllocSanityCheck();
855
sewardjf48ac192004-10-29 00:41:29 +0000856 if (vex_traceflags & VEX_TRACE_VCODE)
857 vex_printf("\n");
858
sewardjf48ac192004-10-29 00:41:29 +0000859 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000860 for (i = 0; i < vcode->arr_used; i++) {
861 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000862 ppInstr(vcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000863 vex_printf("\n");
864 }
sewardjfbcaf332004-07-08 01:46:01 +0000865 vex_printf("\n");
866 }
sewardjfbcaf332004-07-08 01:46:01 +0000867
sewardjf13a16a2004-07-05 17:10:14 +0000868 /* Register allocate. */
869 rcode = doRegisterAllocation ( vcode, available_real_regs,
cerionf0de28c2005-12-13 20:21:11 +0000870 n_available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000871 isMove, getRegUsage, mapRegs,
sewardjfb7373a2007-08-25 21:29:03 +0000872 genSpill, genReload, directReload,
873 guest_sizeB,
cerion92b64362005-12-13 12:02:26 +0000874 ppInstr, ppReg, mode64 );
sewardjf13a16a2004-07-05 17:10:14 +0000875
sewardj2d6b14a2005-11-23 04:25:07 +0000876 vexAllocSanityCheck();
877
sewardjf48ac192004-10-29 00:41:29 +0000878 if (vex_traceflags & VEX_TRACE_RCODE) {
879 vex_printf("\n------------------------"
880 " Register-allocated code "
881 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000882 for (i = 0; i < rcode->arr_used; i++) {
883 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000884 ppInstr(rcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000885 vex_printf("\n");
886 }
sewardjfbcaf332004-07-08 01:46:01 +0000887 vex_printf("\n");
888 }
sewardjfbcaf332004-07-08 01:46:01 +0000889
sewardje908c422005-02-04 21:18:16 +0000890 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000891 if (0) {
892 *(vta->host_bytes_used) = 0;
893 res.status = VexTransOK; return res;
894 }
sewardje908c422005-02-04 21:18:16 +0000895 /* end HACK */
896
sewardj81bd5502004-07-21 18:49:27 +0000897 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000898 if (vex_traceflags & VEX_TRACE_ASM) {
899 vex_printf("\n------------------------"
900 " Assembly "
901 "------------------------\n\n");
902 }
903
sewardj81bd5502004-07-21 18:49:27 +0000904 out_used = 0; /* tracks along the host_bytes array */
905 for (i = 0; i < rcode->arr_used; i++) {
sewardjc6f970f2012-04-02 21:54:49 +0000906 HInstr* hi = rcode->arr[i];
907 Bool hi_isProfInc = False;
908 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
909 ppInstr(hi, mode64);
sewardjbad34a92004-07-22 01:14:11 +0000910 vex_printf("\n");
911 }
sewardjc6f970f2012-04-02 21:54:49 +0000912 j = emit( &hi_isProfInc,
sewardj9b769162014-07-24 12:42:03 +0000913 insn_bytes, sizeof insn_bytes, hi,
914 mode64, vta->archinfo_host.endness,
sewardjc6f970f2012-04-02 21:54:49 +0000915 vta->disp_cp_chain_me_to_slowEP,
916 vta->disp_cp_chain_me_to_fastEP,
917 vta->disp_cp_xindir,
918 vta->disp_cp_xassisted );
919 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
sewardjbad34a92004-07-22 01:14:11 +0000920 for (k = 0; k < j; k++)
floriane5540422014-12-15 21:07:37 +0000921 vex_printf("%02x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000922 vex_printf("\n\n");
923 }
sewardjc6f970f2012-04-02 21:54:49 +0000924 if (UNLIKELY(out_used + j > vta->host_bytes_size)) {
sewardj2d6b14a2005-11-23 04:25:07 +0000925 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000926 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000927 res.status = VexTransOutputFull;
928 return res;
sewardj81bd5502004-07-21 18:49:27 +0000929 }
sewardjc6f970f2012-04-02 21:54:49 +0000930 if (UNLIKELY(hi_isProfInc)) {
931 vassert(vta->addProfInc); /* else where did it come from? */
932 vassert(res.offs_profInc == -1); /* there can be only one (tm) */
933 vassert(out_used >= 0);
934 res.offs_profInc = out_used;
935 }
936 { UChar* dst = &vta->host_bytes[out_used];
937 for (k = 0; k < j; k++) {
938 dst[k] = insn_bytes[k];
939 }
940 out_used += j;
sewardj81bd5502004-07-21 18:49:27 +0000941 }
sewardj81bd5502004-07-21 18:49:27 +0000942 }
sewardj17c7f952005-12-15 14:02:34 +0000943 *(vta->host_bytes_used) = out_used;
sewardj81bd5502004-07-21 18:49:27 +0000944
sewardj2d6b14a2005-11-23 04:25:07 +0000945 vexAllocSanityCheck();
946
947 vexSetAllocModeTEMP_and_clear();
sewardjf13a16a2004-07-05 17:10:14 +0000948
sewardj65ea17e2012-12-28 09:01:59 +0000949 if (vex_traceflags) {
950 /* Print the expansion ratio for this SB. */
951 j = 0; /* total guest bytes */
952 for (i = 0; i < vta->guest_extents->n_used; i++) {
953 j += vta->guest_extents->len[i];
954 }
955 if (1) vex_printf("VexExpansionRatio %d %d %d :10\n\n",
956 j, out_used, (10 * out_used) / (j == 0 ? 1 : j));
957 }
958
sewardjf48ac192004-10-29 00:41:29 +0000959 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000960 res.status = VexTransOK;
961 return res;
sewardj35421a32004-07-05 13:12:34 +0000962}
963
964
sewardjc6f970f2012-04-02 21:54:49 +0000965/* --------- Chain/Unchain XDirects. --------- */
966
florian7d6f81d2014-09-22 21:43:37 +0000967VexInvalRange LibVEX_Chain ( VexArch arch_host,
968 VexEndness endness_host,
969 void* place_to_chain,
970 const void* disp_cp_chain_me_EXPECTED,
971 const void* place_to_jump_to )
sewardjc6f970f2012-04-02 21:54:49 +0000972{
sewardjc6f970f2012-04-02 21:54:49 +0000973 switch (arch_host) {
974 case VexArchX86:
florian7d6f81d2014-09-22 21:43:37 +0000975 return chainXDirect_X86(endness_host,
976 place_to_chain,
977 disp_cp_chain_me_EXPECTED,
978 place_to_jump_to);
sewardjc6f970f2012-04-02 21:54:49 +0000979 case VexArchAMD64:
florian7d6f81d2014-09-22 21:43:37 +0000980 return chainXDirect_AMD64(endness_host,
981 place_to_chain,
982 disp_cp_chain_me_EXPECTED,
983 place_to_jump_to);
sewardjc6f970f2012-04-02 21:54:49 +0000984 case VexArchARM:
florian7d6f81d2014-09-22 21:43:37 +0000985 return chainXDirect_ARM(endness_host,
986 place_to_chain,
987 disp_cp_chain_me_EXPECTED,
988 place_to_jump_to);
sewardjbbcf1882014-01-12 12:49:10 +0000989 case VexArchARM64:
florian7d6f81d2014-09-22 21:43:37 +0000990 return chainXDirect_ARM64(endness_host,
991 place_to_chain,
992 disp_cp_chain_me_EXPECTED,
993 place_to_jump_to);
florian8844a632012-04-13 04:04:06 +0000994 case VexArchS390X:
florian7d6f81d2014-09-22 21:43:37 +0000995 return chainXDirect_S390(endness_host,
996 place_to_chain,
997 disp_cp_chain_me_EXPECTED,
998 place_to_jump_to);
sewardj3dee8492012-04-20 00:13:28 +0000999 case VexArchPPC32:
sewardj9b769162014-07-24 12:42:03 +00001000 return chainXDirect_PPC(endness_host,
1001 place_to_chain,
sewardj3dee8492012-04-20 00:13:28 +00001002 disp_cp_chain_me_EXPECTED,
1003 place_to_jump_to, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +00001004 case VexArchPPC64:
sewardj9b769162014-07-24 12:42:03 +00001005 return chainXDirect_PPC(endness_host,
1006 place_to_chain,
sewardjf252de52012-04-20 10:42:24 +00001007 disp_cp_chain_me_EXPECTED,
1008 place_to_jump_to, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +00001009 case VexArchMIPS32:
sewardj9b769162014-07-24 12:42:03 +00001010 return chainXDirect_MIPS(endness_host,
1011 place_to_chain,
sewardjd0e5fe72012-06-07 08:51:02 +00001012 disp_cp_chain_me_EXPECTED,
1013 place_to_jump_to, False/*!mode64*/);
petarjb92a9542013-02-27 22:57:17 +00001014 case VexArchMIPS64:
sewardj9b769162014-07-24 12:42:03 +00001015 return chainXDirect_MIPS(endness_host,
1016 place_to_chain,
petarjb92a9542013-02-27 22:57:17 +00001017 disp_cp_chain_me_EXPECTED,
1018 place_to_jump_to, True/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +00001019 default:
1020 vassert(0);
1021 }
sewardjc6f970f2012-04-02 21:54:49 +00001022}
1023
florian7d6f81d2014-09-22 21:43:37 +00001024VexInvalRange LibVEX_UnChain ( VexArch arch_host,
1025 VexEndness endness_host,
1026 void* place_to_unchain,
1027 const void* place_to_jump_to_EXPECTED,
1028 const void* disp_cp_chain_me )
sewardjc6f970f2012-04-02 21:54:49 +00001029{
sewardjc6f970f2012-04-02 21:54:49 +00001030 switch (arch_host) {
1031 case VexArchX86:
florian7d6f81d2014-09-22 21:43:37 +00001032 return unchainXDirect_X86(endness_host,
1033 place_to_unchain,
1034 place_to_jump_to_EXPECTED,
1035 disp_cp_chain_me);
sewardjc6f970f2012-04-02 21:54:49 +00001036 case VexArchAMD64:
florian7d6f81d2014-09-22 21:43:37 +00001037 return unchainXDirect_AMD64(endness_host,
1038 place_to_unchain,
1039 place_to_jump_to_EXPECTED,
1040 disp_cp_chain_me);
sewardjc6f970f2012-04-02 21:54:49 +00001041 case VexArchARM:
florian7d6f81d2014-09-22 21:43:37 +00001042 return unchainXDirect_ARM(endness_host,
1043 place_to_unchain,
1044 place_to_jump_to_EXPECTED,
1045 disp_cp_chain_me);
sewardjc6acaa42014-02-19 17:42:59 +00001046 case VexArchARM64:
florian7d6f81d2014-09-22 21:43:37 +00001047 return unchainXDirect_ARM64(endness_host,
1048 place_to_unchain,
1049 place_to_jump_to_EXPECTED,
1050 disp_cp_chain_me);
florian8844a632012-04-13 04:04:06 +00001051 case VexArchS390X:
florian7d6f81d2014-09-22 21:43:37 +00001052 return unchainXDirect_S390(endness_host,
1053 place_to_unchain,
1054 place_to_jump_to_EXPECTED,
1055 disp_cp_chain_me);
sewardj3dee8492012-04-20 00:13:28 +00001056 case VexArchPPC32:
sewardj9b769162014-07-24 12:42:03 +00001057 return unchainXDirect_PPC(endness_host,
1058 place_to_unchain,
sewardj3dee8492012-04-20 00:13:28 +00001059 place_to_jump_to_EXPECTED,
1060 disp_cp_chain_me, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +00001061 case VexArchPPC64:
sewardj9b769162014-07-24 12:42:03 +00001062 return unchainXDirect_PPC(endness_host,
1063 place_to_unchain,
sewardjf252de52012-04-20 10:42:24 +00001064 place_to_jump_to_EXPECTED,
1065 disp_cp_chain_me, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +00001066 case VexArchMIPS32:
sewardj9b769162014-07-24 12:42:03 +00001067 return unchainXDirect_MIPS(endness_host,
1068 place_to_unchain,
petarjb92a9542013-02-27 22:57:17 +00001069 place_to_jump_to_EXPECTED,
1070 disp_cp_chain_me, False/*!mode64*/);
1071 case VexArchMIPS64:
sewardj9b769162014-07-24 12:42:03 +00001072 return unchainXDirect_MIPS(endness_host,
1073 place_to_unchain,
petarjb92a9542013-02-27 22:57:17 +00001074 place_to_jump_to_EXPECTED,
1075 disp_cp_chain_me, True/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +00001076 default:
1077 vassert(0);
1078 }
sewardjc6f970f2012-04-02 21:54:49 +00001079}
1080
sewardj9b769162014-07-24 12:42:03 +00001081Int LibVEX_evCheckSzB ( VexArch arch_host,
1082 VexEndness endness_host )
sewardjc6f970f2012-04-02 21:54:49 +00001083{
1084 static Int cached = 0; /* DO NOT MAKE NON-STATIC */
1085 if (UNLIKELY(cached == 0)) {
1086 switch (arch_host) {
1087 case VexArchX86:
sewardj9b769162014-07-24 12:42:03 +00001088 cached = evCheckSzB_X86(endness_host); break;
sewardjc6f970f2012-04-02 21:54:49 +00001089 case VexArchAMD64:
sewardj9b769162014-07-24 12:42:03 +00001090 cached = evCheckSzB_AMD64(endness_host); break;
sewardjc6f970f2012-04-02 21:54:49 +00001091 case VexArchARM:
sewardj9b769162014-07-24 12:42:03 +00001092 cached = evCheckSzB_ARM(endness_host); break;
sewardjbbcf1882014-01-12 12:49:10 +00001093 case VexArchARM64:
sewardj9b769162014-07-24 12:42:03 +00001094 cached = evCheckSzB_ARM64(endness_host); break;
florian8844a632012-04-13 04:04:06 +00001095 case VexArchS390X:
sewardj9b769162014-07-24 12:42:03 +00001096 cached = evCheckSzB_S390(endness_host); break;
sewardj3dee8492012-04-20 00:13:28 +00001097 case VexArchPPC32:
sewardjf252de52012-04-20 10:42:24 +00001098 case VexArchPPC64:
sewardj9b769162014-07-24 12:42:03 +00001099 cached = evCheckSzB_PPC(endness_host); break;
sewardjd0e5fe72012-06-07 08:51:02 +00001100 case VexArchMIPS32:
petarjb92a9542013-02-27 22:57:17 +00001101 case VexArchMIPS64:
sewardj9b769162014-07-24 12:42:03 +00001102 cached = evCheckSzB_MIPS(endness_host); break;
sewardjc6f970f2012-04-02 21:54:49 +00001103 default:
1104 vassert(0);
1105 }
1106 }
1107 return cached;
1108}
1109
sewardj9b769162014-07-24 12:42:03 +00001110VexInvalRange LibVEX_PatchProfInc ( VexArch arch_host,
1111 VexEndness endness_host,
1112 void* place_to_patch,
florian7d6f81d2014-09-22 21:43:37 +00001113 const ULong* location_of_counter )
sewardjc6f970f2012-04-02 21:54:49 +00001114{
sewardjc6f970f2012-04-02 21:54:49 +00001115 switch (arch_host) {
1116 case VexArchX86:
florian7d6f81d2014-09-22 21:43:37 +00001117 return patchProfInc_X86(endness_host, place_to_patch,
1118 location_of_counter);
sewardjc6f970f2012-04-02 21:54:49 +00001119 case VexArchAMD64:
florian7d6f81d2014-09-22 21:43:37 +00001120 return patchProfInc_AMD64(endness_host, place_to_patch,
1121 location_of_counter);
sewardjc6f970f2012-04-02 21:54:49 +00001122 case VexArchARM:
florian7d6f81d2014-09-22 21:43:37 +00001123 return patchProfInc_ARM(endness_host, place_to_patch,
1124 location_of_counter);
sewardj0ad37a92014-08-29 21:58:03 +00001125 case VexArchARM64:
florian7d6f81d2014-09-22 21:43:37 +00001126 return patchProfInc_ARM64(endness_host, place_to_patch,
1127 location_of_counter);
florian8844a632012-04-13 04:04:06 +00001128 case VexArchS390X:
florian7d6f81d2014-09-22 21:43:37 +00001129 return patchProfInc_S390(endness_host, place_to_patch,
1130 location_of_counter);
sewardj3dee8492012-04-20 00:13:28 +00001131 case VexArchPPC32:
sewardj9b769162014-07-24 12:42:03 +00001132 return patchProfInc_PPC(endness_host, place_to_patch,
sewardj3dee8492012-04-20 00:13:28 +00001133 location_of_counter, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +00001134 case VexArchPPC64:
sewardj9b769162014-07-24 12:42:03 +00001135 return patchProfInc_PPC(endness_host, place_to_patch,
sewardjf252de52012-04-20 10:42:24 +00001136 location_of_counter, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +00001137 case VexArchMIPS32:
sewardj9b769162014-07-24 12:42:03 +00001138 return patchProfInc_MIPS(endness_host, place_to_patch,
sewardjd0e5fe72012-06-07 08:51:02 +00001139 location_of_counter, False/*!mode64*/);
petarjb92a9542013-02-27 22:57:17 +00001140 case VexArchMIPS64:
sewardj9b769162014-07-24 12:42:03 +00001141 return patchProfInc_MIPS(endness_host, place_to_patch,
petarjb92a9542013-02-27 22:57:17 +00001142 location_of_counter, True/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +00001143 default:
1144 vassert(0);
1145 }
sewardjc6f970f2012-04-02 21:54:49 +00001146}
1147
1148
sewardj893aada2004-11-29 19:57:54 +00001149/* --------- Emulation warnings. --------- */
1150
florian1ff47562012-10-21 02:09:51 +00001151const HChar* LibVEX_EmNote_string ( VexEmNote ew )
sewardj893aada2004-11-29 19:57:54 +00001152{
1153 switch (ew) {
florian6ef84be2012-08-26 03:20:07 +00001154 case EmNote_NONE:
sewardj893aada2004-11-29 19:57:54 +00001155 return "none";
1156 case EmWarn_X86_x87exns:
1157 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +00001158 case EmWarn_X86_x87precision:
1159 return "Selection of non-80-bit x87 FP precision";
1160 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +00001161 return "Unmasking SSE FP exceptions";
1162 case EmWarn_X86_fz:
1163 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
1164 case EmWarn_X86_daz:
1165 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +00001166 case EmWarn_X86_acFlag:
1167 return "Setting %eflags.ac (setting noted but ignored)";
sewardj9dd9cf12006-01-20 14:13:55 +00001168 case EmWarn_PPCexns:
1169 return "Unmasking PPC32/64 FP exceptions";
1170 case EmWarn_PPC64_redir_overflow:
1171 return "PPC64 function redirection stack overflow";
1172 case EmWarn_PPC64_redir_underflow:
1173 return "PPC64 function redirection stack underflow";
florian4b8efad2012-09-02 18:07:08 +00001174 case EmWarn_S390X_fpext_rounding:
1175 return "The specified rounding mode cannot be supported. That\n"
florian2a4de0b2014-12-05 18:28:29 +00001176 " feature requires the floating point extension facility\n"
florian4b8efad2012-09-02 18:07:08 +00001177 " which is not available on this host. Continuing using\n"
1178 " the rounding mode from FPC. Results may differ!";
florianf0fa1be2012-09-18 20:24:38 +00001179 case EmWarn_S390X_invalid_rounding:
1180 return "The specified rounding mode is invalid.\n"
1181 " Continuing using 'round to nearest'. Results may differ!";
floriane75dafa2012-09-01 17:54:09 +00001182 case EmFail_S390X_stfle:
florian4e0083e2012-08-26 03:41:56 +00001183 return "Instruction stfle is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001184 case EmFail_S390X_stckf:
florianc5c669b2012-08-26 14:32:28 +00001185 return "Instruction stckf is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001186 case EmFail_S390X_ecag:
florian8c88cb62012-08-26 18:58:13 +00001187 return "Instruction ecag is not supported on this host";
florianad00ea92014-12-05 18:55:39 +00001188 case EmFail_S390X_pfpo:
1189 return "Instruction pfpo is not supported on this host";
florianfb596602014-12-06 16:34:48 +00001190 case EmFail_S390X_DFP_insn:
1191 return "DFP instructions are not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001192 case EmFail_S390X_fpext:
1193 return "Encountered an instruction that requires the floating "
1194 "point extension facility.\n"
1195 " That facility is not available on this host";
florian78d5ef72013-05-11 15:02:58 +00001196 case EmFail_S390X_invalid_PFPO_rounding_mode:
florian2a4de0b2014-12-05 18:28:29 +00001197 return "The rounding mode in GPR 0 for the PFPO instruction"
florian78d5ef72013-05-11 15:02:58 +00001198 " is invalid";
1199 case EmFail_S390X_invalid_PFPO_function:
florian2a4de0b2014-12-05 18:28:29 +00001200 return "The function code in GPR 0 for the PFPO instruction"
florian78d5ef72013-05-11 15:02:58 +00001201 " is invalid";
sewardj893aada2004-11-29 19:57:54 +00001202 default:
florian6ef84be2012-08-26 03:20:07 +00001203 vpanic("LibVEX_EmNote_string: unknown warning");
sewardj893aada2004-11-29 19:57:54 +00001204 }
1205}
sewardj35421a32004-07-05 13:12:34 +00001206
sewardj5117ce12006-01-27 21:20:15 +00001207/* ------------------ Arch/HwCaps stuff. ------------------ */
sewardjbef170b2004-12-21 01:23:00 +00001208
1209const HChar* LibVEX_ppVexArch ( VexArch arch )
1210{
1211 switch (arch) {
1212 case VexArch_INVALID: return "INVALID";
1213 case VexArchX86: return "X86";
1214 case VexArchAMD64: return "AMD64";
1215 case VexArchARM: return "ARM";
sewardjbbcf1882014-01-12 12:49:10 +00001216 case VexArchARM64: return "ARM64";
sewardj0ec57c52005-02-01 15:24:10 +00001217 case VexArchPPC32: return "PPC32";
cerionf0de28c2005-12-13 20:21:11 +00001218 case VexArchPPC64: return "PPC64";
sewardj2019a972011-03-07 16:04:07 +00001219 case VexArchS390X: return "S390X";
sewardjd0e5fe72012-06-07 08:51:02 +00001220 case VexArchMIPS32: return "MIPS32";
petarjb92a9542013-02-27 22:57:17 +00001221 case VexArchMIPS64: return "MIPS64";
sewardjbef170b2004-12-21 01:23:00 +00001222 default: return "VexArch???";
1223 }
1224}
1225
sewardj9b769162014-07-24 12:42:03 +00001226const HChar* LibVEX_ppVexEndness ( VexEndness endness )
1227{
1228 switch (endness) {
1229 case VexEndness_INVALID: return "INVALID";
1230 case VexEndnessLE: return "LittleEndian";
1231 case VexEndnessBE: return "BigEndian";
1232 default: return "VexEndness???";
1233 }
1234}
1235
florianf3652c92014-12-10 16:10:24 +00001236/* Return a string with the hardware capabilities to the extent as
1237 they pertain to the translation process. No attempt is made, to
1238 detect *all* capabilities an architecture may have. */
sewardj5117ce12006-01-27 21:20:15 +00001239const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
sewardjbef170b2004-12-21 01:23:00 +00001240{
florianf3652c92014-12-10 16:10:24 +00001241 return show_hwcaps(arch, hwcaps);
sewardjbef170b2004-12-21 01:23:00 +00001242}
1243
sewardj5117ce12006-01-27 21:20:15 +00001244
sewardj27e1dd62005-06-30 11:49:14 +00001245/* Write default settings info *vai. */
1246void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
1247{
sewardj65902992014-05-03 21:20:56 +00001248 vex_bzero(vai, sizeof(*vai));
sewardj9b769162014-07-24 12:42:03 +00001249 vai->hwcaps = 0;
1250 vai->endness = VexEndness_INVALID;
1251 vai->ppc_icache_line_szB = 0;
1252 vai->ppc_dcbz_szB = 0;
1253 vai->ppc_dcbzl_szB = 0;
sewardj65902992014-05-03 21:20:56 +00001254 vai->arm64_dMinLine_lg2_szB = 0;
1255 vai->arm64_iMinLine_lg2_szB = 0;
florianf192a392012-10-07 19:44:40 +00001256 vai->hwcache_info.num_levels = 0;
1257 vai->hwcache_info.num_caches = 0;
sewardj65902992014-05-03 21:20:56 +00001258 vai->hwcache_info.caches = NULL;
florianf192a392012-10-07 19:44:40 +00001259 vai->hwcache_info.icaches_maintain_coherence = True; // whatever
sewardj27e1dd62005-06-30 11:49:14 +00001260}
1261
sewardjdd40fdf2006-12-24 02:20:24 +00001262/* Write default settings info *vbi. */
1263void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
sewardjaca070a2006-10-17 00:28:22 +00001264{
sewardj65902992014-05-03 21:20:56 +00001265 vex_bzero(vbi, sizeof(*vbi));
sewardjdd40fdf2006-12-24 02:20:24 +00001266 vbi->guest_stack_redzone_size = 0;
philippee2cc4de2014-12-16 23:57:51 +00001267 vbi->guest_amd64_assume_fs_is_const = False;
1268 vbi->guest_amd64_assume_gs_is_const = False;
sewardjdd40fdf2006-12-24 02:20:24 +00001269 vbi->guest_ppc_zap_RZ_at_blr = False;
1270 vbi->guest_ppc_zap_RZ_at_bl = NULL;
sewardjdd40fdf2006-12-24 02:20:24 +00001271 vbi->host_ppc_calls_use_fndescrs = False;
sewardjaca070a2006-10-17 00:28:22 +00001272}
1273
sewardj27e1dd62005-06-30 11:49:14 +00001274
florianf3652c92014-12-10 16:10:24 +00001275/* Convenience macro to be used in show_hwcaps_ARCH functions */
1276#define NUM_HWCAPS (sizeof hwcaps_list / sizeof hwcaps_list[0])
1277
sewardj5117ce12006-01-27 21:20:15 +00001278/* Return a string showing the hwcaps in a nice way. The string will
florianf3652c92014-12-10 16:10:24 +00001279 be NULL for unrecognised hardware capabilities. */
sewardj5117ce12006-01-27 21:20:15 +00001280
florian55085f82012-11-21 00:36:55 +00001281static const HChar* show_hwcaps_x86 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001282{
florianf3652c92014-12-10 16:10:24 +00001283 static const HChar prefix[] = "x86";
1284 static const struct {
1285 UInt hwcaps_bit;
1286 HChar name[7];
1287 } hwcaps_list[] = {
1288 { VEX_HWCAPS_X86_MMXEXT, "mmxext" },
1289 { VEX_HWCAPS_X86_SSE1, "sse1" },
1290 { VEX_HWCAPS_X86_SSE2, "sse2" },
1291 { VEX_HWCAPS_X86_SSE3, "sse3" },
1292 { VEX_HWCAPS_X86_LZCNT, "lzcnt" },
1293 };
1294 /* Allocate a large enough buffer */
1295 static HChar buf[sizeof prefix +
1296 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1297 if (buf[0] != '\0') return buf; /* already constructed */
1298
1299 HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1300
1301 if (hwcaps == 0) {
1302 vex_sprintf(p, "-%s", "sse0");
1303 } else {
1304 UInt i;
1305 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1306 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1307 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1308 }
sewardj536fbab2010-07-29 15:39:05 +00001309 }
florianf3652c92014-12-10 16:10:24 +00001310 return buf;
sewardj5117ce12006-01-27 21:20:15 +00001311}
1312
florian55085f82012-11-21 00:36:55 +00001313static const HChar* show_hwcaps_amd64 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001314{
florianf3652c92014-12-10 16:10:24 +00001315 static const HChar prefix[] = "amd64";
1316 static const struct {
1317 UInt hwcaps_bit;
1318 HChar name[7];
1319 } hwcaps_list[] = {
1320 { VEX_HWCAPS_AMD64_CX16, "cx16" },
1321 { VEX_HWCAPS_AMD64_LZCNT, "lzcnt" },
1322 { VEX_HWCAPS_AMD64_RDTSCP, "rdtscp" },
1323 { VEX_HWCAPS_AMD64_SSE3, "sse3" },
1324 { VEX_HWCAPS_AMD64_AVX, "avx" },
1325 { VEX_HWCAPS_AMD64_AVX2, "avx2" },
1326 { VEX_HWCAPS_AMD64_BMI, "bmi" },
1327 };
1328 /* Allocate a large enough buffer */
1329 static HChar buf[sizeof prefix +
1330 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1331 if (buf[0] != '\0') return buf; /* already constructed */
sewardj818c7302013-03-26 13:53:18 +00001332
florianf3652c92014-12-10 16:10:24 +00001333 HChar *p = buf + vex_sprintf(buf, "%s", prefix);
sewardj818c7302013-03-26 13:53:18 +00001334
sewardj818c7302013-03-26 13:53:18 +00001335 if (hwcaps == 0) {
florianf3652c92014-12-10 16:10:24 +00001336 vex_sprintf(p, "-%s", "sse2");
1337 } else {
1338 UInt i;
1339 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1340 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1341 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1342 }
sewardj536fbab2010-07-29 15:39:05 +00001343 }
sewardj818c7302013-03-26 13:53:18 +00001344 return buf;
sewardj5117ce12006-01-27 21:20:15 +00001345}
1346
florian55085f82012-11-21 00:36:55 +00001347static const HChar* show_hwcaps_ppc32 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001348{
florianf3652c92014-12-10 16:10:24 +00001349 static const HChar prefix[] = "ppc32-int";
1350 static const struct {
1351 UInt hwcaps_bit;
1352 HChar name[8];
1353 } hwcaps_list[] = {
1354 { VEX_HWCAPS_PPC32_F, "flt" },
1355 { VEX_HWCAPS_PPC32_V, "vmx" },
1356 { VEX_HWCAPS_PPC32_FX, "FX" },
1357 { VEX_HWCAPS_PPC32_GX, "GX" },
1358 { VEX_HWCAPS_PPC32_VX, "VX" },
1359 { VEX_HWCAPS_PPC32_DFP, "DFP" },
1360 { VEX_HWCAPS_PPC32_ISA2_07, "ISA2_07" },
1361 };
1362 /* Allocate a large enough buffer */
1363 static HChar buf[sizeof prefix +
1364 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1365 if (buf[0] != '\0') return buf; /* already constructed */
carll0c74bb52013-08-12 18:01:40 +00001366
florianf3652c92014-12-10 16:10:24 +00001367 HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1368
1369 if (hwcaps == 0) return buf;
1370
1371 UInt i;
1372 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1373 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1374 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1375 }
1376 return buf;
sewardj5117ce12006-01-27 21:20:15 +00001377}
1378
florian55085f82012-11-21 00:36:55 +00001379static const HChar* show_hwcaps_ppc64 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001380{
florianf3652c92014-12-10 16:10:24 +00001381 static const HChar prefix[] = "ppc64-int-flt";
1382 static const struct {
1383 UInt hwcaps_bit;
1384 HChar name[8];
1385 } hwcaps_list[] = {
1386 { VEX_HWCAPS_PPC64_FX, "FX" },
1387 { VEX_HWCAPS_PPC64_GX, "GX" },
1388 { VEX_HWCAPS_PPC64_V, "vmx" },
1389 { VEX_HWCAPS_PPC64_DFP, "DFP" },
1390 { VEX_HWCAPS_PPC64_ISA2_07, "ISA2_07" },
1391 };
1392 /* Allocate a large enough buffer */
1393 static HChar buf[sizeof prefix +
1394 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1395 if (buf[0] != '\0') return buf; /* already constructed */
1396
1397 HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1398
1399 if (hwcaps == 0) return buf;
1400
1401 UInt i;
1402 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1403 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1404 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1405 }
1406 return buf;
sewardj5117ce12006-01-27 21:20:15 +00001407}
1408
florian55085f82012-11-21 00:36:55 +00001409static const HChar* show_hwcaps_arm ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001410{
florianf3652c92014-12-10 16:10:24 +00001411 static const HChar prefix[] = "ARM";
1412 static const struct {
1413 UInt hwcaps_bit;
1414 HChar name[6];
1415 } hwcaps_list[] = {
1416 { VEX_HWCAPS_ARM_NEON, "neon" },
1417 { VEX_HWCAPS_ARM_VFP | VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3, "vfp" },
1418 };
1419 /* Allocate a large enough buffer */
1420 static HChar buf[sizeof prefix + 12 + // level
1421 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1422 if (buf[0] != '\0') return buf; /* already constructed */
1423
1424 HChar *p;
1425 UInt i, level;
1426
1427 level = VEX_ARM_ARCHLEVEL(hwcaps);
1428
1429 p = buf + vex_sprintf(buf, "%sv%u", prefix, level);
1430 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1431 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1432 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
sewardjec0d9a02010-08-22 12:54:56 +00001433 }
florianf3652c92014-12-10 16:10:24 +00001434 return buf;
sewardj5117ce12006-01-27 21:20:15 +00001435}
1436
sewardjbbcf1882014-01-12 12:49:10 +00001437static const HChar* show_hwcaps_arm64 ( UInt hwcaps )
1438{
1439 /* Since there are no variants, just insist that hwcaps is zero,
1440 and declare it invalid otherwise. */
1441 if (hwcaps == 0)
1442 return "baseline";
florianf3652c92014-12-10 16:10:24 +00001443 return "Unsupported";
sewardjbbcf1882014-01-12 12:49:10 +00001444}
1445
florian55085f82012-11-21 00:36:55 +00001446static const HChar* show_hwcaps_s390x ( UInt hwcaps )
sewardj2019a972011-03-07 16:04:07 +00001447{
sewardjd07b8562011-04-27 11:58:22 +00001448 static const HChar prefix[] = "s390x";
florian9061eb32012-12-09 17:53:45 +00001449 static const struct {
1450 UInt hwcaps_bit;
1451 HChar name[6];
1452 } hwcaps_list[] = {
1453 { VEX_HWCAPS_S390X_LDISP, "ldisp" },
1454 { VEX_HWCAPS_S390X_EIMM, "eimm" },
1455 { VEX_HWCAPS_S390X_GIE, "gie" },
1456 { VEX_HWCAPS_S390X_DFP, "dfp" },
1457 { VEX_HWCAPS_S390X_FGX, "fgx" },
1458 { VEX_HWCAPS_S390X_STFLE, "stfle" },
1459 { VEX_HWCAPS_S390X_ETF2, "etf2" },
1460 { VEX_HWCAPS_S390X_ETF3, "etf3" },
1461 { VEX_HWCAPS_S390X_STCKF, "stckf" },
1462 { VEX_HWCAPS_S390X_FPEXT, "fpext" },
1463 { VEX_HWCAPS_S390X_LSC, "lsc" },
florian78d5ef72013-05-11 15:02:58 +00001464 { VEX_HWCAPS_S390X_PFPO, "pfpo" },
sewardjd07b8562011-04-27 11:58:22 +00001465 };
florianf3652c92014-12-10 16:10:24 +00001466 /* Allocate a large enough buffer */
florian9061eb32012-12-09 17:53:45 +00001467 static HChar buf[sizeof prefix +
florianf3652c92014-12-10 16:10:24 +00001468 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
sewardjd07b8562011-04-27 11:58:22 +00001469
1470 if (buf[0] != '\0') return buf; /* already constructed */
sewardj2019a972011-03-07 16:04:07 +00001471
florianf3652c92014-12-10 16:10:24 +00001472 HChar *p;
1473 UInt i;
1474
sewardj652b56a2011-04-13 15:38:17 +00001475 hwcaps = VEX_HWCAPS_S390X(hwcaps);
1476
sewardjd07b8562011-04-27 11:58:22 +00001477 p = buf + vex_sprintf(buf, "%s", prefix);
florian9061eb32012-12-09 17:53:45 +00001478 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1479 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1480 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1481 }
sewardj2019a972011-03-07 16:04:07 +00001482
sewardjd07b8562011-04-27 11:58:22 +00001483 /* If there are no facilities, add "zarch" */
1484 if (hwcaps == 0)
1485 vex_sprintf(p, "-%s", "zarch");
1486
1487 return buf;
sewardj2019a972011-03-07 16:04:07 +00001488}
1489
florian55085f82012-11-21 00:36:55 +00001490static const HChar* show_hwcaps_mips32 ( UInt hwcaps )
sewardjd0e5fe72012-06-07 08:51:02 +00001491{
dejanjc3fee0d2013-07-25 09:08:03 +00001492 /* MIPS baseline. */
petarjbc7d6f42013-09-16 18:11:59 +00001493 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_MIPS) {
dejanjc3fee0d2013-07-25 09:08:03 +00001494 /* MIPS baseline with dspr2. */
petarjbc7d6f42013-09-16 18:11:59 +00001495 if (VEX_MIPS_PROC_DSP2(hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +00001496 return "MIPS-baseline-dspr2";
1497 }
1498 /* MIPS baseline with dsp. */
petarjbc7d6f42013-09-16 18:11:59 +00001499 if (VEX_MIPS_PROC_DSP(hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +00001500 return "MIPS-baseline-dsp";
1501 }
1502 return "MIPS-baseline";
1503 }
1504
1505 /* Broadcom baseline. */
petarjbc7d6f42013-09-16 18:11:59 +00001506 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_BROADCOM) {
dejanjc3fee0d2013-07-25 09:08:03 +00001507 return "Broadcom-baseline";
1508 }
1509
1510 /* Netlogic baseline. */
petarjbc7d6f42013-09-16 18:11:59 +00001511 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_NETLOGIC) {
dejanjc3fee0d2013-07-25 09:08:03 +00001512 return "Netlogic-baseline";
1513 }
1514
petarjbc7d6f42013-09-16 18:11:59 +00001515 /* Cavium baseline. */
1516 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_CAVIUM) {
1517 return "Cavium-baseline";
1518 }
1519
florianf3652c92014-12-10 16:10:24 +00001520 return "Unsupported baseline";
sewardjd0e5fe72012-06-07 08:51:02 +00001521}
1522
petarjb92a9542013-02-27 22:57:17 +00001523static const HChar* show_hwcaps_mips64 ( UInt hwcaps )
1524{
1525 return "mips64-baseline";
1526}
1527
florianf3652c92014-12-10 16:10:24 +00001528#undef NUM_HWCAPS
1529
1530/* Thie function must not return NULL. */
florian55085f82012-11-21 00:36:55 +00001531static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001532{
1533 switch (arch) {
sewardjd0e5fe72012-06-07 08:51:02 +00001534 case VexArchX86: return show_hwcaps_x86(hwcaps);
1535 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
1536 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
1537 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
1538 case VexArchARM: return show_hwcaps_arm(hwcaps);
sewardjbbcf1882014-01-12 12:49:10 +00001539 case VexArchARM64: return show_hwcaps_arm64(hwcaps);
sewardjd0e5fe72012-06-07 08:51:02 +00001540 case VexArchS390X: return show_hwcaps_s390x(hwcaps);
1541 case VexArchMIPS32: return show_hwcaps_mips32(hwcaps);
petarjb92a9542013-02-27 22:57:17 +00001542 case VexArchMIPS64: return show_hwcaps_mips64(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001543 default: return NULL;
1544 }
1545}
1546
florianf3652c92014-12-10 16:10:24 +00001547/* To be used to complain about hwcaps we cannot handle */
1548__attribute__((noreturn))
1549static void invalid_hwcaps ( VexArch arch, UInt hwcaps, const HChar *message )
sewardj5117ce12006-01-27 21:20:15 +00001550{
florianf3652c92014-12-10 16:10:24 +00001551 vfatal("\nVEX: %s"
1552 " Found: %s\n", message, show_hwcaps(arch, hwcaps));
1553}
1554
1555/* This function will not return iff the hwcaps don't pass the test. */
1556static void check_hwcaps ( VexArch arch, UInt hwcaps )
1557{
1558 switch (arch) {
1559 case VexArchX86: {
1560 if (hwcaps == 0) return; // baseline
1561
1562 /* Monotonic: SSE3 > SSE2 > SSE1 > MMXEXT > baseline. */
1563 static const UInt extras[] = {
1564 VEX_HWCAPS_X86_MMXEXT, VEX_HWCAPS_X86_SSE1, VEX_HWCAPS_X86_SSE2,
1565 VEX_HWCAPS_X86_SSE3
1566 };
1567
1568 UInt i, caps = 0;
1569 for (i = 0; i < sizeof extras / sizeof extras[0]; ++i) {
1570 caps |= extras[i];
1571 if (caps == hwcaps) return;
1572 if ((caps & VEX_HWCAPS_X86_SSE2) != 0) {
1573 if ((caps & VEX_HWCAPS_X86_LZCNT) != 0) return;
1574 }
1575 }
1576 invalid_hwcaps(arch, hwcaps, "Cannot handle capabilities\n");
1577 }
1578
1579 case VexArchAMD64: {
florianf3652c92014-12-10 16:10:24 +00001580 /* SSE3 and CX16 are orthogonal and > baseline, although we really
1581 don't expect to come across anything which can do SSE3 but can't
1582 do CX16. Still, we can handle that case. LZCNT is similarly
1583 orthogonal. */
1584
1585 /* Throw out obviously stupid cases: */
1586 Bool have_sse3 = (hwcaps & VEX_HWCAPS_AMD64_SSE3) != 0;
1587 Bool have_avx = (hwcaps & VEX_HWCAPS_AMD64_AVX) != 0;
1588 Bool have_bmi = (hwcaps & VEX_HWCAPS_AMD64_BMI) != 0;
1589 Bool have_avx2 = (hwcaps & VEX_HWCAPS_AMD64_AVX2) != 0;
1590
1591 /* AVX without SSE3 */
1592 if (have_avx && !have_sse3)
1593 invalid_hwcaps(arch, hwcaps,
1594 "Support for AVX requires SSE3 capabilities\n");
1595 /* AVX2 or BMI without AVX */
1596 if (have_avx2 && !have_avx)
1597 invalid_hwcaps(arch, hwcaps,
1598 "Support for AVX2 requires AVX capabilities\n");
1599 if (have_bmi && !have_avx)
1600 invalid_hwcaps(arch, hwcaps,
1601 "Support for BMI requires AVX capabilities\n");
1602 return;
1603 }
1604
1605 case VexArchPPC32: {
1606 /* Monotonic with complications. Basically V > F > baseline,
1607 but once you have F then you can have FX or GX too. */
1608 if (hwcaps == 0) return; // baseline
1609
1610 if ((hwcaps & VEX_HWCAPS_PPC32_F) == 0)
1611 invalid_hwcaps(arch, hwcaps,
1612 "Missing floating point capability\n");
1613 /* V, FX, and GX can appear in any combination */
1614
1615 /* DFP requires V and FX and GX */
1616 UInt v_fx_gx = VEX_HWCAPS_PPC32_V | VEX_HWCAPS_PPC32_FX |
1617 VEX_HWCAPS_PPC32_GX;
1618 Bool has_v_fx_gx = (hwcaps & v_fx_gx) == v_fx_gx;
1619
1620 if ((hwcaps & VEX_HWCAPS_PPC32_DFP) && ! has_v_fx_gx)
1621 invalid_hwcaps(arch, hwcaps,
1622 "DFP requires VMX and FX and GX capabilities\n");
1623
1624 /* VX requires V and FX and GX */
1625 if ((hwcaps & VEX_HWCAPS_PPC32_VX) && ! has_v_fx_gx)
1626 invalid_hwcaps(arch, hwcaps,
1627 "VX requires VMX and FX and GX capabilities\n");
1628
1629 /* ISA2_07 requires everything else */
1630 if ((hwcaps & VEX_HWCAPS_PPC32_ISA2_07) != 0) {
1631 if (! has_v_fx_gx)
1632 invalid_hwcaps(arch, hwcaps,
1633 "ISA2_07 requires VMX and FX and GX capabilities\n");
1634 if (! (hwcaps & VEX_HWCAPS_PPC32_VX))
1635 invalid_hwcaps(arch, hwcaps,
1636 "ISA2_07 requires VX capabilities\n");
1637 if (! (hwcaps & VEX_HWCAPS_PPC32_DFP))
1638 invalid_hwcaps(arch, hwcaps,
1639 "ISA2_07 requires DFP capabilities\n");
1640 }
1641 return;
1642 }
1643
1644 case VexArchPPC64: {
1645 /* Monotonic with complications. Basically V > baseline(==F),
1646 but once you have F then you can have FX or GX too. */
1647 if (hwcaps == 0) return; // baseline
1648
1649 /* V, FX, and GX can appear in any combination */
1650
1651 /* DFP requires V and FX and GX */
1652 UInt v_fx_gx = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX |
1653 VEX_HWCAPS_PPC64_GX;
1654 Bool has_v_fx_gx = (hwcaps & v_fx_gx) == v_fx_gx;
1655
1656 if ((hwcaps & VEX_HWCAPS_PPC64_DFP) && ! has_v_fx_gx)
1657 invalid_hwcaps(arch, hwcaps,
1658 "DFP requires VMX and FX and GX capabilities\n");
1659
1660 /* VX requires V and FX and GX */
1661 if ((hwcaps & VEX_HWCAPS_PPC32_VX) && ! has_v_fx_gx)
1662 invalid_hwcaps(arch, hwcaps,
1663 "VX requires VMX and FX and GX capabilities\n");
1664
1665 /* ISA2_07 requires everything else */
1666 if ((hwcaps & VEX_HWCAPS_PPC64_ISA2_07) != 0) {
1667 if (! has_v_fx_gx)
1668 invalid_hwcaps(arch, hwcaps,
1669 "ISA2_07 requires VMX and FX and GX capabilities\n");
1670 if (! (hwcaps & VEX_HWCAPS_PPC64_VX))
1671 invalid_hwcaps(arch, hwcaps,
1672 "ISA2_07 requires VX capabilities\n");
1673 if (! (hwcaps & VEX_HWCAPS_PPC64_DFP))
1674 invalid_hwcaps(arch, hwcaps,
1675 "ISA2_07 requires DFP capabilities\n");
1676 }
1677 return;
1678 }
1679
1680 case VexArchARM: {
1681 Bool NEON = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0);
1682 UInt level = VEX_ARM_ARCHLEVEL(hwcaps);
1683
1684 switch (level) {
1685 case 5:
1686 if (NEON)
1687 invalid_hwcaps(arch, hwcaps,
1688 "NEON instructions are not supported for ARMv5.\n");
1689 return;
1690 case 6:
1691 if (NEON)
1692 invalid_hwcaps(arch, hwcaps,
1693 "NEON instructions are not supported for ARMv6.\n");
1694 return;
1695 case 7:
1696 return;
1697 default:
1698 invalid_hwcaps(arch, hwcaps,
1699 "ARM architecture level is not supported.\n");
1700 }
1701 }
1702
1703 case VexArchARM64:
1704 if (hwcaps != 0)
1705 invalid_hwcaps(arch, hwcaps,
1706 "Unsupported hardware capabilities.\n");
1707 return;
1708
1709 case VexArchS390X:
1710 if (! s390_host_has_ldisp)
1711 invalid_hwcaps(arch, hwcaps,
1712 "Host does not have long displacement facility.\n");
1713 return;
1714
1715 case VexArchMIPS32:
1716 switch (VEX_MIPS_COMP_ID(hwcaps)) {
1717 case VEX_PRID_COMP_MIPS:
1718 case VEX_PRID_COMP_BROADCOM:
1719 case VEX_PRID_COMP_NETLOGIC:
1720 return;
1721 default:
1722 invalid_hwcaps(arch, hwcaps, "Unsupported baseline\n");
1723 }
1724
1725 case VexArchMIPS64:
1726 return;
1727
1728 default:
1729 vpanic("unknown architecture");
floriandc6e7472014-12-08 14:01:33 +00001730 }
sewardj5117ce12006-01-27 21:20:15 +00001731}
1732
1733
sewardj35421a32004-07-05 13:12:34 +00001734/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +00001735/*--- end main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +00001736/*---------------------------------------------------------------*/