blob: f9adfaa40945a5abd8a1cf603607b08258c5f398 [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 */
florian04fc6b12014-12-29 20:22:26 +0000114 void (*log_bytes) ( const HChar*, SizeT 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));
florianbeac5302014-12-31 12:09:38 +0000170 vassert(sizeof(void*) == sizeof(Addr));
171 vassert(sizeof(unsigned long) == sizeof(SizeT));
sewardjea602bc2004-10-14 21:40:12 +0000172
sewardj97e87932005-02-07 00:00:50 +0000173 vassert(VEX_HOST_WORDSIZE == sizeof(void*));
174 vassert(VEX_HOST_WORDSIZE == sizeof(HWord));
175
sewardjc6f970f2012-04-02 21:54:49 +0000176 /* These take a lot of space, so make sure we don't have
177 any unnoticed size regressions. */
178 if (VEX_HOST_WORDSIZE == 4) {
florian420bfa92012-06-02 20:29:22 +0000179 vassert(sizeof(IRExpr) == 16);
sewardjc6f970f2012-04-02 21:54:49 +0000180 vassert(sizeof(IRStmt) == 20 /* x86 */
181 || sizeof(IRStmt) == 24 /* arm */);
182 } else {
florian420bfa92012-06-02 20:29:22 +0000183 vassert(sizeof(IRExpr) == 32);
floriand6f38b32012-05-31 15:46:18 +0000184 vassert(sizeof(IRStmt) == 32);
sewardjc6f970f2012-04-02 21:54:49 +0000185 }
186
sewardj8bde7f12013-04-11 13:57:43 +0000187 /* Check that signed integer division on the host rounds towards
188 zero. If not, h_calc_sdiv32_w_arm_semantics() won't work
189 correctly. */
190 /* 100.0 / 7.0 == 14.2857 */
191 vassert(udiv32(100, 7) == 14);
192 vassert(sdiv32(100, 7) == 14);
193 vassert(sdiv32(-100, 7) == -14); /* and not -15 */
194 vassert(sdiv32(100, -7) == -14); /* ditto */
195 vassert(sdiv32(-100, -7) == 14); /* not sure what this proves */
196
sewardjea602bc2004-10-14 21:40:12 +0000197 /* Really start up .. */
sewardj443cd9d2004-07-18 23:06:45 +0000198 vex_debuglevel = debuglevel;
sewardj08613742004-10-25 13:01:45 +0000199 vex_control = *vcon;
sewardj443cd9d2004-07-18 23:06:45 +0000200 vex_initdone = True;
sewardjd887b862005-01-17 18:34:34 +0000201 vexSetAllocMode ( VexAllocModeTEMP );
sewardj35421a32004-07-05 13:12:34 +0000202}
203
204
205/* --------- Make a translation. --------- */
206
207/* Exported to library client. */
208
sewardj17c7f952005-12-15 14:02:34 +0000209VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
sewardj35421a32004-07-05 13:12:34 +0000210{
sewardj81bd5502004-07-21 18:49:27 +0000211 /* This the bundle of functions we need to do the back-end stuff
212 (insn selection, reg-alloc, assembly) whilst being insulated
213 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +0000214 HReg* available_real_regs;
215 Int n_available_real_regs;
floriand8c64e02014-10-08 08:54:44 +0000216 Bool (*isMove) ( const HInstr*, HReg*, HReg* );
217 void (*getRegUsage) ( HRegUsage*, const HInstr*, Bool );
sewardjfb7373a2007-08-25 21:29:03 +0000218 void (*mapRegs) ( HRegRemap*, HInstr*, Bool );
sewardj6c299f32009-12-31 18:00:12 +0000219 void (*genSpill) ( HInstr**, HInstr**, HReg, Int, Bool );
220 void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool );
sewardjfb7373a2007-08-25 21:29:03 +0000221 HInstr* (*directReload) ( HInstr*, HReg, Short );
floriand8c64e02014-10-08 08:54:44 +0000222 void (*ppInstr) ( const HInstr*, Bool );
sewardjfb7373a2007-08-25 21:29:03 +0000223 void (*ppReg) ( HReg );
floriancacba8e2014-12-15 18:58:07 +0000224 HInstrArray* (*iselSB) ( const IRSB*, VexArch, const VexArchInfo*,
floriand8c64e02014-10-08 08:54:44 +0000225 const VexAbiInfo*, Int, Int, Bool, Bool,
floriandcd6d232015-01-02 17:32:21 +0000226 Addr );
sewardjc6f970f2012-04-02 21:54:49 +0000227 Int (*emit) ( /*MB_MOD*/Bool*,
floriand8c64e02014-10-08 08:54:44 +0000228 UChar*, Int, const HInstr*, Bool, VexEndness,
florian8462d112014-09-24 15:18:09 +0000229 const void*, const void*, const void*,
230 const void* );
florian1ff47562012-10-21 02:09:51 +0000231 IRExpr* (*specHelper) ( const HChar*, IRExpr**, IRStmt**, Int );
sewardj8d2291c2004-10-25 14:50:21 +0000232 Bool (*preciseMemExnsFn) ( Int, Int );
sewardjf13a16a2004-07-05 17:10:14 +0000233
sewardj9e6491a2005-07-02 19:24:10 +0000234 DisOneInstrFn disInstrFn;
235
sewardjeeac8412004-11-02 00:26:55 +0000236 VexGuestLayout* guest_layout;
sewardjdd40fdf2006-12-24 02:20:24 +0000237 IRSB* irsb;
sewardjeeac8412004-11-02 00:26:55 +0000238 HInstrArray* vcode;
239 HInstrArray* rcode;
240 Int i, j, k, out_used, guest_sizeB;
sewardj05f5e012014-05-04 10:52:11 +0000241 Int offB_CMSTART, offB_CMLEN, offB_GUEST_IP, szB_GUEST_IP;
sewardjc6f970f2012-04-02 21:54:49 +0000242 Int offB_HOST_EvC_COUNTER, offB_HOST_EvC_FAILADDR;
petarjb92a9542013-02-27 22:57:17 +0000243 UChar insn_bytes[128];
sewardjcf787902004-11-03 09:08:33 +0000244 IRType guest_word_type;
245 IRType host_word_type;
sewardjc6f970f2012-04-02 21:54:49 +0000246 Bool mode64, chainingAllowed;
floriandcd6d232015-01-02 17:32:21 +0000247 Addr max_ga;
sewardjf13a16a2004-07-05 17:10:14 +0000248
sewardj49651f42004-10-28 22:11:04 +0000249 guest_layout = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000250 available_real_regs = NULL;
251 n_available_real_regs = 0;
252 isMove = NULL;
253 getRegUsage = NULL;
254 mapRegs = NULL;
255 genSpill = NULL;
256 genReload = NULL;
sewardjfb7373a2007-08-25 21:29:03 +0000257 directReload = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000258 ppInstr = NULL;
259 ppReg = NULL;
sewardjdd40fdf2006-12-24 02:20:24 +0000260 iselSB = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000261 emit = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000262 specHelper = NULL;
sewardj8d2291c2004-10-25 14:50:21 +0000263 preciseMemExnsFn = NULL;
sewardj9e6491a2005-07-02 19:24:10 +0000264 disInstrFn = NULL;
sewardjcf787902004-11-03 09:08:33 +0000265 guest_word_type = Ity_INVALID;
266 host_word_type = Ity_INVALID;
sewardj05f5e012014-05-04 10:52:11 +0000267 offB_CMSTART = 0;
268 offB_CMLEN = 0;
sewardjc6f970f2012-04-02 21:54:49 +0000269 offB_GUEST_IP = 0;
270 szB_GUEST_IP = 0;
271 offB_HOST_EvC_COUNTER = 0;
272 offB_HOST_EvC_FAILADDR = 0;
cerion92b64362005-12-13 12:02:26 +0000273 mode64 = False;
sewardjc6f970f2012-04-02 21:54:49 +0000274 chainingAllowed = False;
sewardj36ca5132004-07-24 13:12:23 +0000275
sewardj17c7f952005-12-15 14:02:34 +0000276 vex_traceflags = vta->traceflags;
sewardj58800ff2004-07-28 01:51:10 +0000277
sewardj35421a32004-07-05 13:12:34 +0000278 vassert(vex_initdone);
sewardjc6f970f2012-04-02 21:54:49 +0000279 vassert(vta->needs_self_check != NULL);
280 vassert(vta->disp_cp_xassisted != NULL);
281 /* Both the chainers and the indir are either NULL or non-NULL. */
282 if (vta->disp_cp_chain_me_to_slowEP != NULL) {
283 vassert(vta->disp_cp_chain_me_to_fastEP != NULL);
284 vassert(vta->disp_cp_xindir != NULL);
285 chainingAllowed = True;
286 } else {
287 vassert(vta->disp_cp_chain_me_to_fastEP == NULL);
288 vassert(vta->disp_cp_xindir == NULL);
289 }
florian2eeeb9b2011-09-23 18:03:21 +0000290
sewardj2d6b14a2005-11-23 04:25:07 +0000291 vexSetAllocModeTEMP_and_clear();
292 vexAllocSanityCheck();
sewardj2a9ad022004-11-25 02:46:58 +0000293
sewardjf13a16a2004-07-05 17:10:14 +0000294 /* First off, check that the guest and host insn sets
295 are supported. */
sewardj2a9ad022004-11-25 02:46:58 +0000296
sewardj17c7f952005-12-15 14:02:34 +0000297 switch (vta->arch_host) {
sewardj2a9ad022004-11-25 02:46:58 +0000298
sewardjbef170b2004-12-21 01:23:00 +0000299 case VexArchX86:
sewardjfb7373a2007-08-25 21:29:03 +0000300 mode64 = False;
sewardjf13a16a2004-07-05 17:10:14 +0000301 getAllocableRegs_X86 ( &n_available_real_regs,
302 &available_real_regs );
florianb66ad462014-10-07 22:13:47 +0000303 isMove = (__typeof__(isMove)) isMove_X86Instr;
304 getRegUsage = (__typeof__(getRegUsage)) getRegUsage_X86Instr;
305 mapRegs = (__typeof__(mapRegs)) mapRegs_X86Instr;
306 genSpill = (__typeof__(genSpill)) genSpill_X86;
307 genReload = (__typeof__(genReload)) genReload_X86;
308 directReload = (__typeof__(directReload)) directReload_X86;
309 ppInstr = (__typeof__(ppInstr)) ppX86Instr;
310 ppReg = (__typeof__(ppReg)) ppHRegX86;
sewardjfb7373a2007-08-25 21:29:03 +0000311 iselSB = iselSB_X86;
florianb66ad462014-10-07 22:13:47 +0000312 emit = (__typeof__(emit)) emit_X86Instr;
sewardjcf787902004-11-03 09:08:33 +0000313 host_word_type = Ity_I32;
sewardj9b769162014-07-24 12:42:03 +0000314 vassert(vta->archinfo_host.endness == VexEndnessLE);
sewardjf13a16a2004-07-05 17:10:14 +0000315 break;
sewardj2a9ad022004-11-25 02:46:58 +0000316
sewardjc33671d2005-02-01 20:30:00 +0000317 case VexArchAMD64:
cerion92b64362005-12-13 12:02:26 +0000318 mode64 = True;
sewardjc33671d2005-02-01 20:30:00 +0000319 getAllocableRegs_AMD64 ( &n_available_real_regs,
320 &available_real_regs );
florianb66ad462014-10-07 22:13:47 +0000321 isMove = (__typeof__(isMove)) isMove_AMD64Instr;
322 getRegUsage = (__typeof__(getRegUsage)) getRegUsage_AMD64Instr;
323 mapRegs = (__typeof__(mapRegs)) mapRegs_AMD64Instr;
324 genSpill = (__typeof__(genSpill)) genSpill_AMD64;
325 genReload = (__typeof__(genReload)) genReload_AMD64;
326 ppInstr = (__typeof__(ppInstr)) ppAMD64Instr;
327 ppReg = (__typeof__(ppReg)) ppHRegAMD64;
328 iselSB = iselSB_AMD64;
329 emit = (__typeof__(emit)) emit_AMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000330 host_word_type = Ity_I64;
sewardj9b769162014-07-24 12:42:03 +0000331 vassert(vta->archinfo_host.endness == VexEndnessLE);
sewardjc33671d2005-02-01 20:30:00 +0000332 break;
333
cerion487e4c92005-02-04 16:28:19 +0000334 case VexArchPPC32:
cerion92b64362005-12-13 12:02:26 +0000335 mode64 = False;
cerion5b2325f2005-12-23 00:55:09 +0000336 getAllocableRegs_PPC ( &n_available_real_regs,
337 &available_real_regs, mode64 );
florianb66ad462014-10-07 22:13:47 +0000338 isMove = (__typeof__(isMove)) isMove_PPCInstr;
339 getRegUsage = (__typeof__(getRegUsage)) getRegUsage_PPCInstr;
340 mapRegs = (__typeof__(mapRegs)) mapRegs_PPCInstr;
341 genSpill = (__typeof__(genSpill)) genSpill_PPC;
342 genReload = (__typeof__(genReload)) genReload_PPC;
343 ppInstr = (__typeof__(ppInstr)) ppPPCInstr;
344 ppReg = (__typeof__(ppReg)) ppHRegPPC;
345 iselSB = iselSB_PPC;
346 emit = (__typeof__(emit)) emit_PPCInstr;
cerion487e4c92005-02-04 16:28:19 +0000347 host_word_type = Ity_I32;
sewardj9b769162014-07-24 12:42:03 +0000348 vassert(vta->archinfo_host.endness == VexEndnessBE);
cerion487e4c92005-02-04 16:28:19 +0000349 break;
350
cerionf0de28c2005-12-13 20:21:11 +0000351 case VexArchPPC64:
352 mode64 = True;
cerion5b2325f2005-12-23 00:55:09 +0000353 getAllocableRegs_PPC ( &n_available_real_regs,
354 &available_real_regs, mode64 );
florianb66ad462014-10-07 22:13:47 +0000355 isMove = (__typeof__(isMove)) isMove_PPCInstr;
356 getRegUsage = (__typeof__(getRegUsage)) getRegUsage_PPCInstr;
357 mapRegs = (__typeof__(mapRegs)) mapRegs_PPCInstr;
358 genSpill = (__typeof__(genSpill)) genSpill_PPC;
359 genReload = (__typeof__(genReload)) genReload_PPC;
360 ppInstr = (__typeof__(ppInstr)) ppPPCInstr;
361 ppReg = (__typeof__(ppReg)) ppHRegPPC;
362 iselSB = iselSB_PPC;
363 emit = (__typeof__(emit)) emit_PPCInstr;
cerionf0de28c2005-12-13 20:21:11 +0000364 host_word_type = Ity_I64;
carll1f5fe1f2014-08-07 23:25:23 +0000365 vassert(vta->archinfo_host.endness == VexEndnessBE ||
366 vta->archinfo_host.endness == VexEndnessLE );
cerionf0de28c2005-12-13 20:21:11 +0000367 break;
368
sewardj2019a972011-03-07 16:04:07 +0000369 case VexArchS390X:
370 mode64 = True;
florian3eb7bab2014-12-08 12:42:26 +0000371 /* KLUDGE: export hwcaps. */
372 s390_host_hwcaps = vta->archinfo_host.hwcaps;
sewardj2019a972011-03-07 16:04:07 +0000373 getAllocableRegs_S390 ( &n_available_real_regs,
374 &available_real_regs, mode64 );
florianb66ad462014-10-07 22:13:47 +0000375 isMove = (__typeof__(isMove)) isMove_S390Instr;
376 getRegUsage = (__typeof__(getRegUsage)) getRegUsage_S390Instr;
377 mapRegs = (__typeof__(mapRegs)) mapRegs_S390Instr;
378 genSpill = (__typeof__(genSpill)) genSpill_S390;
379 genReload = (__typeof__(genReload)) genReload_S390;
florian017c0d52014-10-07 21:57:05 +0000380 // fixs390: consider implementing directReload_S390
florianb66ad462014-10-07 22:13:47 +0000381 ppInstr = (__typeof__(ppInstr)) ppS390Instr;
382 ppReg = (__typeof__(ppReg)) ppHRegS390;
383 iselSB = iselSB_S390;
384 emit = (__typeof__(emit)) emit_S390Instr;
sewardj2019a972011-03-07 16:04:07 +0000385 host_word_type = Ity_I64;
sewardj9b769162014-07-24 12:42:03 +0000386 vassert(vta->archinfo_host.endness == VexEndnessBE);
sewardj2019a972011-03-07 16:04:07 +0000387 break;
388
sewardj6c299f32009-12-31 18:00:12 +0000389 case VexArchARM:
sewardj2a1ed8e2009-12-31 19:26:03 +0000390 mode64 = False;
sewardj6c299f32009-12-31 18:00:12 +0000391 getAllocableRegs_ARM ( &n_available_real_regs,
392 &available_real_regs );
florianb66ad462014-10-07 22:13:47 +0000393 isMove = (__typeof__(isMove)) isMove_ARMInstr;
394 getRegUsage = (__typeof__(getRegUsage)) getRegUsage_ARMInstr;
395 mapRegs = (__typeof__(mapRegs)) mapRegs_ARMInstr;
396 genSpill = (__typeof__(genSpill)) genSpill_ARM;
397 genReload = (__typeof__(genReload)) genReload_ARM;
398 ppInstr = (__typeof__(ppInstr)) ppARMInstr;
399 ppReg = (__typeof__(ppReg)) ppHRegARM;
400 iselSB = iselSB_ARM;
401 emit = (__typeof__(emit)) emit_ARMInstr;
sewardj6c299f32009-12-31 18:00:12 +0000402 host_word_type = Ity_I32;
sewardj9b769162014-07-24 12:42:03 +0000403 vassert(vta->archinfo_host.endness == VexEndnessLE);
sewardj6c299f32009-12-31 18:00:12 +0000404 break;
405
sewardjbbcf1882014-01-12 12:49:10 +0000406 case VexArchARM64:
407 mode64 = True;
408 getAllocableRegs_ARM64 ( &n_available_real_regs,
409 &available_real_regs );
florianb66ad462014-10-07 22:13:47 +0000410 isMove = (__typeof__(isMove)) isMove_ARM64Instr;
411 getRegUsage = (__typeof__(getRegUsage)) getRegUsage_ARM64Instr;
412 mapRegs = (__typeof__(mapRegs)) mapRegs_ARM64Instr;
413 genSpill = (__typeof__(genSpill)) genSpill_ARM64;
414 genReload = (__typeof__(genReload)) genReload_ARM64;
415 ppInstr = (__typeof__(ppInstr)) ppARM64Instr;
416 ppReg = (__typeof__(ppReg)) ppHRegARM64;
417 iselSB = iselSB_ARM64;
418 emit = (__typeof__(emit)) emit_ARM64Instr;
sewardjbbcf1882014-01-12 12:49:10 +0000419 host_word_type = Ity_I64;
sewardj9b769162014-07-24 12:42:03 +0000420 vassert(vta->archinfo_host.endness == VexEndnessLE);
sewardjbbcf1882014-01-12 12:49:10 +0000421 break;
422
sewardjd0e5fe72012-06-07 08:51:02 +0000423 case VexArchMIPS32:
424 mode64 = False;
425 getAllocableRegs_MIPS ( &n_available_real_regs,
426 &available_real_regs, mode64 );
florianb66ad462014-10-07 22:13:47 +0000427 isMove = (__typeof__(isMove)) isMove_MIPSInstr;
428 getRegUsage = (__typeof__(getRegUsage)) getRegUsage_MIPSInstr;
429 mapRegs = (__typeof__(mapRegs)) mapRegs_MIPSInstr;
430 genSpill = (__typeof__(genSpill)) genSpill_MIPS;
431 genReload = (__typeof__(genReload)) genReload_MIPS;
432 ppInstr = (__typeof__(ppInstr)) ppMIPSInstr;
433 ppReg = (__typeof__(ppReg)) ppHRegMIPS;
434 iselSB = iselSB_MIPS;
435 emit = (__typeof__(emit)) emit_MIPSInstr;
sewardjd0e5fe72012-06-07 08:51:02 +0000436 host_word_type = Ity_I32;
sewardj9b769162014-07-24 12:42:03 +0000437 vassert(vta->archinfo_host.endness == VexEndnessLE
438 || vta->archinfo_host.endness == VexEndnessBE);
sewardjd0e5fe72012-06-07 08:51:02 +0000439 break;
440
petarjb92a9542013-02-27 22:57:17 +0000441 case VexArchMIPS64:
442 mode64 = True;
443 getAllocableRegs_MIPS ( &n_available_real_regs,
444 &available_real_regs, mode64 );
florianb66ad462014-10-07 22:13:47 +0000445 isMove = (__typeof__(isMove)) isMove_MIPSInstr;
446 getRegUsage = (__typeof__(getRegUsage)) getRegUsage_MIPSInstr;
447 mapRegs = (__typeof__(mapRegs)) mapRegs_MIPSInstr;
448 genSpill = (__typeof__(genSpill)) genSpill_MIPS;
449 genReload = (__typeof__(genReload)) genReload_MIPS;
450 ppInstr = (__typeof__(ppInstr)) ppMIPSInstr;
451 ppReg = (__typeof__(ppReg)) ppHRegMIPS;
452 iselSB = iselSB_MIPS;
453 emit = (__typeof__(emit)) emit_MIPSInstr;
petarjb92a9542013-02-27 22:57:17 +0000454 host_word_type = Ity_I64;
sewardj9b769162014-07-24 12:42:03 +0000455 vassert(vta->archinfo_host.endness == VexEndnessLE
456 || vta->archinfo_host.endness == VexEndnessBE);
petarjb92a9542013-02-27 22:57:17 +0000457 break;
458
sewardjf13a16a2004-07-05 17:10:14 +0000459 default:
sewardj6c299f32009-12-31 18:00:12 +0000460 vpanic("LibVEX_Translate: unsupported host insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000461 }
462
florianf3652c92014-12-10 16:10:24 +0000463 // Are the host's hardware capabilities feasible. The function will
464 // not return if hwcaps are infeasible in some sense.
465 check_hwcaps(vta->arch_host, vta->archinfo_host.hwcaps);
sewardj2a9ad022004-11-25 02:46:58 +0000466
sewardj17c7f952005-12-15 14:02:34 +0000467 switch (vta->arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000468
sewardjbef170b2004-12-21 01:23:00 +0000469 case VexArchX86:
sewardjc6f970f2012-04-02 21:54:49 +0000470 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
471 disInstrFn = disInstr_X86;
472 specHelper = guest_x86_spechelper;
473 guest_sizeB = sizeof(VexGuestX86State);
474 guest_word_type = Ity_I32;
475 guest_layout = &x86guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000476 offB_CMSTART = offsetof(VexGuestX86State,guest_CMSTART);
477 offB_CMLEN = offsetof(VexGuestX86State,guest_CMLEN);
sewardjc6f970f2012-04-02 21:54:49 +0000478 offB_GUEST_IP = offsetof(VexGuestX86State,guest_EIP);
479 szB_GUEST_IP = sizeof( ((VexGuestX86State*)0)->guest_EIP );
480 offB_HOST_EvC_COUNTER = offsetof(VexGuestX86State,host_EvC_COUNTER);
481 offB_HOST_EvC_FAILADDR = offsetof(VexGuestX86State,host_EvC_FAILADDR);
sewardj9b769162014-07-24 12:42:03 +0000482 vassert(vta->archinfo_guest.endness == VexEndnessLE);
sewardj6c299f32009-12-31 18:00:12 +0000483 vassert(0 == sizeof(VexGuestX86State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000484 vassert(sizeof( ((VexGuestX86State*)0)->guest_CMSTART) == 4);
485 vassert(sizeof( ((VexGuestX86State*)0)->guest_CMLEN ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000486 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000487 break;
sewardj2a9ad022004-11-25 02:46:58 +0000488
sewardj44d494d2005-01-20 20:26:33 +0000489 case VexArchAMD64:
sewardjc6f970f2012-04-02 21:54:49 +0000490 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
491 disInstrFn = disInstr_AMD64;
492 specHelper = guest_amd64_spechelper;
493 guest_sizeB = sizeof(VexGuestAMD64State);
494 guest_word_type = Ity_I64;
495 guest_layout = &amd64guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000496 offB_CMSTART = offsetof(VexGuestAMD64State,guest_CMSTART);
497 offB_CMLEN = offsetof(VexGuestAMD64State,guest_CMLEN);
sewardjc6f970f2012-04-02 21:54:49 +0000498 offB_GUEST_IP = offsetof(VexGuestAMD64State,guest_RIP);
499 szB_GUEST_IP = sizeof( ((VexGuestAMD64State*)0)->guest_RIP );
500 offB_HOST_EvC_COUNTER = offsetof(VexGuestAMD64State,host_EvC_COUNTER);
501 offB_HOST_EvC_FAILADDR = offsetof(VexGuestAMD64State,host_EvC_FAILADDR);
sewardj9b769162014-07-24 12:42:03 +0000502 vassert(vta->archinfo_guest.endness == VexEndnessLE);
sewardj6c299f32009-12-31 18:00:12 +0000503 vassert(0 == sizeof(VexGuestAMD64State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000504 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_CMSTART ) == 8);
505 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_CMLEN ) == 8);
sewardjce02aa72006-01-12 12:27:58 +0000506 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000507 break;
508
cerionaabdfbf2005-01-29 12:56:15 +0000509 case VexArchPPC32:
sewardj3dee8492012-04-20 00:13:28 +0000510 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
511 disInstrFn = disInstr_PPC;
512 specHelper = guest_ppc32_spechelper;
513 guest_sizeB = sizeof(VexGuestPPC32State);
514 guest_word_type = Ity_I32;
515 guest_layout = &ppc32Guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000516 offB_CMSTART = offsetof(VexGuestPPC32State,guest_CMSTART);
517 offB_CMLEN = offsetof(VexGuestPPC32State,guest_CMLEN);
sewardj3dee8492012-04-20 00:13:28 +0000518 offB_GUEST_IP = offsetof(VexGuestPPC32State,guest_CIA);
519 szB_GUEST_IP = sizeof( ((VexGuestPPC32State*)0)->guest_CIA );
520 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC32State,host_EvC_COUNTER);
521 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC32State,host_EvC_FAILADDR);
sewardj9b769162014-07-24 12:42:03 +0000522 vassert(vta->archinfo_guest.endness == VexEndnessBE);
sewardj6c299f32009-12-31 18:00:12 +0000523 vassert(0 == sizeof(VexGuestPPC32State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000524 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_CMSTART ) == 4);
525 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_CMLEN ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000526 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000527 break;
528
cerionf0de28c2005-12-13 20:21:11 +0000529 case VexArchPPC64:
sewardj9e1cf152012-04-20 02:18:31 +0000530 preciseMemExnsFn = guest_ppc64_state_requires_precise_mem_exns;
531 disInstrFn = disInstr_PPC;
532 specHelper = guest_ppc64_spechelper;
533 guest_sizeB = sizeof(VexGuestPPC64State);
534 guest_word_type = Ity_I64;
535 guest_layout = &ppc64Guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000536 offB_CMSTART = offsetof(VexGuestPPC64State,guest_CMSTART);
537 offB_CMLEN = offsetof(VexGuestPPC64State,guest_CMLEN);
sewardj9e1cf152012-04-20 02:18:31 +0000538 offB_GUEST_IP = offsetof(VexGuestPPC64State,guest_CIA);
539 szB_GUEST_IP = sizeof( ((VexGuestPPC64State*)0)->guest_CIA );
540 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC64State,host_EvC_COUNTER);
541 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC64State,host_EvC_FAILADDR);
carll1f5fe1f2014-08-07 23:25:23 +0000542 vassert(vta->archinfo_guest.endness == VexEndnessBE ||
543 vta->archinfo_guest.endness == VexEndnessLE );
cerionf0de28c2005-12-13 20:21:11 +0000544 vassert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000545 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_CMSTART ) == 8);
546 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_CMLEN ) == 8);
sewardj3fd39672006-01-27 22:05:55 +0000547 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8);
548 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8);
cerionf0de28c2005-12-13 20:21:11 +0000549 break;
550
sewardj2019a972011-03-07 16:04:07 +0000551 case VexArchS390X:
552 preciseMemExnsFn = guest_s390x_state_requires_precise_mem_exns;
553 disInstrFn = disInstr_S390;
554 specHelper = guest_s390x_spechelper;
555 guest_sizeB = sizeof(VexGuestS390XState);
556 guest_word_type = Ity_I64;
557 guest_layout = &s390xGuest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000558 offB_CMSTART = offsetof(VexGuestS390XState,guest_CMSTART);
559 offB_CMLEN = offsetof(VexGuestS390XState,guest_CMLEN);
florian8844a632012-04-13 04:04:06 +0000560 offB_GUEST_IP = offsetof(VexGuestS390XState,guest_IA);
561 szB_GUEST_IP = sizeof( ((VexGuestS390XState*)0)->guest_IA);
562 offB_HOST_EvC_COUNTER = offsetof(VexGuestS390XState,host_EvC_COUNTER);
563 offB_HOST_EvC_FAILADDR = offsetof(VexGuestS390XState,host_EvC_FAILADDR);
sewardj9b769162014-07-24 12:42:03 +0000564 vassert(vta->archinfo_guest.endness == VexEndnessBE);
sewardj2019a972011-03-07 16:04:07 +0000565 vassert(0 == sizeof(VexGuestS390XState) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000566 vassert(sizeof( ((VexGuestS390XState*)0)->guest_CMSTART ) == 8);
567 vassert(sizeof( ((VexGuestS390XState*)0)->guest_CMLEN ) == 8);
sewardj2019a972011-03-07 16:04:07 +0000568 vassert(sizeof( ((VexGuestS390XState*)0)->guest_NRADDR ) == 8);
569 break;
570
sewardj6c299f32009-12-31 18:00:12 +0000571 case VexArchARM:
sewardjc6f970f2012-04-02 21:54:49 +0000572 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
573 disInstrFn = disInstr_ARM;
574 specHelper = guest_arm_spechelper;
575 guest_sizeB = sizeof(VexGuestARMState);
576 guest_word_type = Ity_I32;
577 guest_layout = &armGuest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000578 offB_CMSTART = offsetof(VexGuestARMState,guest_CMSTART);
579 offB_CMLEN = offsetof(VexGuestARMState,guest_CMLEN);
sewardjc6f970f2012-04-02 21:54:49 +0000580 offB_GUEST_IP = offsetof(VexGuestARMState,guest_R15T);
581 szB_GUEST_IP = sizeof( ((VexGuestARMState*)0)->guest_R15T );
582 offB_HOST_EvC_COUNTER = offsetof(VexGuestARMState,host_EvC_COUNTER);
583 offB_HOST_EvC_FAILADDR = offsetof(VexGuestARMState,host_EvC_FAILADDR);
sewardj9b769162014-07-24 12:42:03 +0000584 vassert(vta->archinfo_guest.endness == VexEndnessLE);
sewardj6c299f32009-12-31 18:00:12 +0000585 vassert(0 == sizeof(VexGuestARMState) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000586 vassert(sizeof( ((VexGuestARMState*)0)->guest_CMSTART) == 4);
587 vassert(sizeof( ((VexGuestARMState*)0)->guest_CMLEN ) == 4);
sewardj6c299f32009-12-31 18:00:12 +0000588 vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4);
589 break;
590
sewardjbbcf1882014-01-12 12:49:10 +0000591 case VexArchARM64:
592 preciseMemExnsFn = guest_arm64_state_requires_precise_mem_exns;
593 disInstrFn = disInstr_ARM64;
594 specHelper = guest_arm64_spechelper;
595 guest_sizeB = sizeof(VexGuestARM64State);
596 guest_word_type = Ity_I64;
597 guest_layout = &arm64Guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000598 offB_CMSTART = offsetof(VexGuestARM64State,guest_CMSTART);
599 offB_CMLEN = offsetof(VexGuestARM64State,guest_CMLEN);
sewardjbbcf1882014-01-12 12:49:10 +0000600 offB_GUEST_IP = offsetof(VexGuestARM64State,guest_PC);
601 szB_GUEST_IP = sizeof( ((VexGuestARM64State*)0)->guest_PC );
602 offB_HOST_EvC_COUNTER = offsetof(VexGuestARM64State,host_EvC_COUNTER);
603 offB_HOST_EvC_FAILADDR = offsetof(VexGuestARM64State,host_EvC_FAILADDR);
sewardj9b769162014-07-24 12:42:03 +0000604 vassert(vta->archinfo_guest.endness == VexEndnessLE);
sewardjbbcf1882014-01-12 12:49:10 +0000605 vassert(0 == sizeof(VexGuestARM64State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000606 vassert(sizeof( ((VexGuestARM64State*)0)->guest_CMSTART) == 8);
607 vassert(sizeof( ((VexGuestARM64State*)0)->guest_CMLEN ) == 8);
sewardjbbcf1882014-01-12 12:49:10 +0000608 vassert(sizeof( ((VexGuestARM64State*)0)->guest_NRADDR ) == 8);
609 break;
610
sewardjd0e5fe72012-06-07 08:51:02 +0000611 case VexArchMIPS32:
612 preciseMemExnsFn = guest_mips32_state_requires_precise_mem_exns;
613 disInstrFn = disInstr_MIPS;
614 specHelper = guest_mips32_spechelper;
615 guest_sizeB = sizeof(VexGuestMIPS32State);
616 guest_word_type = Ity_I32;
617 guest_layout = &mips32Guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000618 offB_CMSTART = offsetof(VexGuestMIPS32State,guest_CMSTART);
619 offB_CMLEN = offsetof(VexGuestMIPS32State,guest_CMLEN);
sewardjd0e5fe72012-06-07 08:51:02 +0000620 offB_GUEST_IP = offsetof(VexGuestMIPS32State,guest_PC);
621 szB_GUEST_IP = sizeof( ((VexGuestMIPS32State*)0)->guest_PC );
622 offB_HOST_EvC_COUNTER = offsetof(VexGuestMIPS32State,host_EvC_COUNTER);
623 offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS32State,host_EvC_FAILADDR);
sewardj9b769162014-07-24 12:42:03 +0000624 vassert(vta->archinfo_guest.endness == VexEndnessLE
625 || vta->archinfo_guest.endness == VexEndnessBE);
sewardjd0e5fe72012-06-07 08:51:02 +0000626 vassert(0 == sizeof(VexGuestMIPS32State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000627 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_CMSTART) == 4);
628 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_CMLEN ) == 4);
sewardjd0e5fe72012-06-07 08:51:02 +0000629 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_NRADDR ) == 4);
630 break;
631
petarjb92a9542013-02-27 22:57:17 +0000632 case VexArchMIPS64:
633 preciseMemExnsFn = guest_mips64_state_requires_precise_mem_exns;
634 disInstrFn = disInstr_MIPS;
635 specHelper = guest_mips64_spechelper;
636 guest_sizeB = sizeof(VexGuestMIPS64State);
637 guest_word_type = Ity_I64;
638 guest_layout = &mips64Guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000639 offB_CMSTART = offsetof(VexGuestMIPS64State,guest_CMSTART);
640 offB_CMLEN = offsetof(VexGuestMIPS64State,guest_CMLEN);
petarjb92a9542013-02-27 22:57:17 +0000641 offB_GUEST_IP = offsetof(VexGuestMIPS64State,guest_PC);
642 szB_GUEST_IP = sizeof( ((VexGuestMIPS64State*)0)->guest_PC );
643 offB_HOST_EvC_COUNTER = offsetof(VexGuestMIPS64State,host_EvC_COUNTER);
644 offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS64State,host_EvC_FAILADDR);
sewardj9b769162014-07-24 12:42:03 +0000645 vassert(vta->archinfo_guest.endness == VexEndnessLE
646 || vta->archinfo_guest.endness == VexEndnessBE);
petarjb92a9542013-02-27 22:57:17 +0000647 vassert(0 == sizeof(VexGuestMIPS64State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000648 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_CMSTART) == 8);
649 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_CMLEN ) == 8);
petarjb92a9542013-02-27 22:57:17 +0000650 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_NRADDR ) == 8);
651 break;
652
sewardjf13a16a2004-07-05 17:10:14 +0000653 default:
sewardj887a11a2004-07-05 17:26:47 +0000654 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000655 }
656
florianf3652c92014-12-10 16:10:24 +0000657 // Are the guest's hardware capabilities feasible. The function will
658 // not return if hwcaps are infeasible in some sense.
659 // FIXME: how can we know the guest's hardware capabilities?
660 check_hwcaps(vta->arch_guest, vta->archinfo_guest.hwcaps);
661
sewardjbc161a42011-06-07 21:28:38 +0000662 /* Set up result struct. */
663 VexTranslateResult res;
sewardjfadbbe22012-04-24 11:49:03 +0000664 res.status = VexTransOK;
665 res.n_sc_extents = 0;
666 res.offs_profInc = -1;
667 res.n_guest_instrs = 0;
sewardjbc161a42011-06-07 21:28:38 +0000668
sewardj9df271d2004-12-31 22:37:42 +0000669 /* yet more sanity checks ... */
sewardj17c7f952005-12-15 14:02:34 +0000670 if (vta->arch_guest == vta->arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000671 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000672 we are simulating one flavour of an architecture a different
673 flavour of the same architecture, which is pretty strange. */
sewardj5117ce12006-01-27 21:20:15 +0000674 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps);
sewardj9b769162014-07-24 12:42:03 +0000675 /* ditto */
676 vassert(vta->archinfo_guest.endness == vta->archinfo_host.endness);
sewardj9df271d2004-12-31 22:37:42 +0000677 }
sewardj2a9ad022004-11-25 02:46:58 +0000678
sewardj2d6b14a2005-11-23 04:25:07 +0000679 vexAllocSanityCheck();
680
sewardjf48ac192004-10-29 00:41:29 +0000681 if (vex_traceflags & VEX_TRACE_FE)
682 vex_printf("\n------------------------"
683 " Front end "
684 "------------------------\n\n");
685
sewardjdd40fdf2006-12-24 02:20:24 +0000686 irsb = bb_to_IR ( vta->guest_extents,
sewardjbc161a42011-06-07 21:28:38 +0000687 &res.n_sc_extents,
sewardjfadbbe22012-04-24 11:49:03 +0000688 &res.n_guest_instrs,
sewardjc716aea2006-01-17 01:48:46 +0000689 vta->callback_opaque,
sewardj9e6491a2005-07-02 19:24:10 +0000690 disInstrFn,
sewardj17c7f952005-12-15 14:02:34 +0000691 vta->guest_bytes,
692 vta->guest_bytes_addr,
693 vta->chase_into_ok,
sewardj9b769162014-07-24 12:42:03 +0000694 vta->archinfo_host.endness,
sewardj442e51a2012-12-06 18:08:04 +0000695 vta->sigill_diag,
sewardja5f55da2006-04-30 23:37:32 +0000696 vta->arch_guest,
sewardj17c7f952005-12-15 14:02:34 +0000697 &vta->archinfo_guest,
sewardjdd40fdf2006-12-24 02:20:24 +0000698 &vta->abiinfo_both,
sewardjdb4738a2005-07-07 01:32:16 +0000699 guest_word_type,
sewardjbc161a42011-06-07 21:28:38 +0000700 vta->needs_self_check,
sewardjc716aea2006-01-17 01:48:46 +0000701 vta->preamble_function,
sewardj05f5e012014-05-04 10:52:11 +0000702 offB_CMSTART,
703 offB_CMLEN,
sewardjc6f970f2012-04-02 21:54:49 +0000704 offB_GUEST_IP,
705 szB_GUEST_IP );
sewardjf13a16a2004-07-05 17:10:14 +0000706
sewardj2d6b14a2005-11-23 04:25:07 +0000707 vexAllocSanityCheck();
708
sewardjdd40fdf2006-12-24 02:20:24 +0000709 if (irsb == NULL) {
sewardjf13a16a2004-07-05 17:10:14 +0000710 /* Access failure. */
sewardj2d6b14a2005-11-23 04:25:07 +0000711 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000712 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000713 res.status = VexTransAccessFail; return res;
sewardjf13a16a2004-07-05 17:10:14 +0000714 }
sewardjaa59f942004-10-09 09:34:36 +0000715
sewardj17c7f952005-12-15 14:02:34 +0000716 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3);
717 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr);
718 for (i = 0; i < vta->guest_extents->n_used; i++) {
719 vassert(vta->guest_extents->len[i] < 10000); /* sanity */
sewardj72c72812005-01-19 11:49:45 +0000720 }
721
sewardjaa59f942004-10-09 09:34:36 +0000722 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000723 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj17c7f952005-12-15 14:02:34 +0000724 if (vta->guest_extents->n_used > 1) {
sewardj72c72812005-01-19 11:49:45 +0000725 vex_printf("can't show code due to extents > 1\n");
726 } else {
727 /* HACK */
florian8462d112014-09-24 15:18:09 +0000728 const UChar* p = vta->guest_bytes;
sewardj01f8cce2009-08-31 08:50:02 +0000729 UInt sum = 0;
sewardj17c7f952005-12-15 14:02:34 +0000730 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0];
floriand4cc0de2015-01-02 11:44:12 +0000731 vex_printf("GuestBytes %lx %u ", vta->guest_bytes_addr,
732 guest_bytes_read );
sewardj01f8cce2009-08-31 08:50:02 +0000733 for (i = 0; i < guest_bytes_read; i++) {
734 UInt b = (UInt)p[i];
735 vex_printf(" %02x", b );
736 sum = (sum << 1) ^ b;
737 }
738 vex_printf(" %08x\n\n", sum);
sewardj72c72812005-01-19 11:49:45 +0000739 }
sewardjaa59f942004-10-09 09:34:36 +0000740 }
741
742 /* Sanity check the initial IR. */
sewardjdd40fdf2006-12-24 02:20:24 +0000743 sanityCheckIRSB( irsb, "initial IR",
sewardjb9230752004-12-29 19:25:06 +0000744 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000745
sewardj2d6b14a2005-11-23 04:25:07 +0000746 vexAllocSanityCheck();
747
sewardjedf4d692004-08-17 13:52:58 +0000748 /* Clean it up, hopefully a lot. */
sewardjdd40fdf2006-12-24 02:20:24 +0000749 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn,
sewardjec0d9a02010-08-22 12:54:56 +0000750 vta->guest_bytes_addr,
751 vta->arch_guest );
sewardjdd40fdf2006-12-24 02:20:24 +0000752 sanityCheckIRSB( irsb, "after initial iropt",
sewardjb9230752004-12-29 19:25:06 +0000753 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000754
sewardjf48ac192004-10-29 00:41:29 +0000755 if (vex_traceflags & VEX_TRACE_OPT1) {
756 vex_printf("\n------------------------"
757 " After pre-instr IR optimisation "
758 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000759 ppIRSB ( irsb );
sewardjedf4d692004-08-17 13:52:58 +0000760 vex_printf("\n");
761 }
762
sewardj2d6b14a2005-11-23 04:25:07 +0000763 vexAllocSanityCheck();
764
sewardjf13a16a2004-07-05 17:10:14 +0000765 /* Get the thing instrumented. */
sewardj17c7f952005-12-15 14:02:34 +0000766 if (vta->instrument1)
sewardjdd40fdf2006-12-24 02:20:24 +0000767 irsb = vta->instrument1(vta->callback_opaque,
768 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000769 vta->guest_extents,
florian50481922012-10-07 21:58:07 +0000770 &vta->archinfo_host,
sewardj17c7f952005-12-15 14:02:34 +0000771 guest_word_type, host_word_type);
sewardj2d6b14a2005-11-23 04:25:07 +0000772 vexAllocSanityCheck();
773
sewardj17c7f952005-12-15 14:02:34 +0000774 if (vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000775 irsb = vta->instrument2(vta->callback_opaque,
776 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000777 vta->guest_extents,
florian50481922012-10-07 21:58:07 +0000778 &vta->archinfo_host,
sewardj17c7f952005-12-15 14:02:34 +0000779 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000780
sewardjf48ac192004-10-29 00:41:29 +0000781 if (vex_traceflags & VEX_TRACE_INST) {
782 vex_printf("\n------------------------"
783 " After instrumentation "
784 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000785 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000786 vex_printf("\n");
787 }
788
sewardj17c7f952005-12-15 14:02:34 +0000789 if (vta->instrument1 || vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000790 sanityCheckIRSB( irsb, "after instrumentation",
sewardjb9230752004-12-29 19:25:06 +0000791 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000792
sewardj9578a8b2004-11-04 19:44:48 +0000793 /* Do a post-instrumentation cleanup pass. */
sewardj17c7f952005-12-15 14:02:34 +0000794 if (vta->instrument1 || vta->instrument2) {
sewardjdd40fdf2006-12-24 02:20:24 +0000795 do_deadcode_BB( irsb );
796 irsb = cprop_BB( irsb );
797 do_deadcode_BB( irsb );
798 sanityCheckIRSB( irsb, "after post-instrumentation cleanup",
sewardjb9230752004-12-29 19:25:06 +0000799 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000800 }
801
sewardj2d6b14a2005-11-23 04:25:07 +0000802 vexAllocSanityCheck();
803
sewardj9578a8b2004-11-04 19:44:48 +0000804 if (vex_traceflags & VEX_TRACE_OPT2) {
805 vex_printf("\n------------------------"
806 " After post-instr IR optimisation "
807 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000808 ppIRSB ( irsb );
sewardj9578a8b2004-11-04 19:44:48 +0000809 vex_printf("\n");
810 }
811
sewardjf9517d02005-11-28 13:39:37 +0000812 /* Turn it into virtual-registerised code. Build trees -- this
813 also throws away any dead bindings. */
florian62140c12013-01-20 03:51:04 +0000814 max_ga = ado_treebuild_BB( irsb, preciseMemExnsFn );
sewardjf48ac192004-10-29 00:41:29 +0000815
sewardjbe1b6ff2007-08-28 06:06:27 +0000816 if (vta->finaltidy) {
817 irsb = vta->finaltidy(irsb);
818 }
819
sewardj2d6b14a2005-11-23 04:25:07 +0000820 vexAllocSanityCheck();
821
sewardjf48ac192004-10-29 00:41:29 +0000822 if (vex_traceflags & VEX_TRACE_TREES) {
823 vex_printf("\n------------------------"
824 " After tree-building "
825 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000826 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000827 vex_printf("\n");
828 }
829
sewardje908c422005-02-04 21:18:16 +0000830 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000831 if (0) {
832 *(vta->host_bytes_used) = 0;
833 res.status = VexTransOK; return res;
834 }
sewardje908c422005-02-04 21:18:16 +0000835 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000836
sewardjf48ac192004-10-29 00:41:29 +0000837 if (vex_traceflags & VEX_TRACE_VCODE)
838 vex_printf("\n------------------------"
839 " Instruction selection "
840 "------------------------\n");
841
sewardjc6f970f2012-04-02 21:54:49 +0000842 /* No guest has its IP field at offset zero. If this fails it
843 means some transformation pass somewhere failed to update/copy
844 irsb->offsIP properly. */
845 vassert(irsb->offsIP >= 16);
846
847 vcode = iselSB ( irsb, vta->arch_host,
848 &vta->archinfo_host,
849 &vta->abiinfo_both,
850 offB_HOST_EvC_COUNTER,
851 offB_HOST_EvC_FAILADDR,
852 chainingAllowed,
853 vta->addProfInc,
854 max_ga );
sewardjf13a16a2004-07-05 17:10:14 +0000855
sewardj2d6b14a2005-11-23 04:25:07 +0000856 vexAllocSanityCheck();
857
sewardjf48ac192004-10-29 00:41:29 +0000858 if (vex_traceflags & VEX_TRACE_VCODE)
859 vex_printf("\n");
860
sewardjf48ac192004-10-29 00:41:29 +0000861 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000862 for (i = 0; i < vcode->arr_used; i++) {
863 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000864 ppInstr(vcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000865 vex_printf("\n");
866 }
sewardjfbcaf332004-07-08 01:46:01 +0000867 vex_printf("\n");
868 }
sewardjfbcaf332004-07-08 01:46:01 +0000869
sewardjf13a16a2004-07-05 17:10:14 +0000870 /* Register allocate. */
871 rcode = doRegisterAllocation ( vcode, available_real_regs,
cerionf0de28c2005-12-13 20:21:11 +0000872 n_available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000873 isMove, getRegUsage, mapRegs,
sewardjfb7373a2007-08-25 21:29:03 +0000874 genSpill, genReload, directReload,
875 guest_sizeB,
cerion92b64362005-12-13 12:02:26 +0000876 ppInstr, ppReg, mode64 );
sewardjf13a16a2004-07-05 17:10:14 +0000877
sewardj2d6b14a2005-11-23 04:25:07 +0000878 vexAllocSanityCheck();
879
sewardjf48ac192004-10-29 00:41:29 +0000880 if (vex_traceflags & VEX_TRACE_RCODE) {
881 vex_printf("\n------------------------"
882 " Register-allocated code "
883 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000884 for (i = 0; i < rcode->arr_used; i++) {
885 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000886 ppInstr(rcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000887 vex_printf("\n");
888 }
sewardjfbcaf332004-07-08 01:46:01 +0000889 vex_printf("\n");
890 }
sewardjfbcaf332004-07-08 01:46:01 +0000891
sewardje908c422005-02-04 21:18:16 +0000892 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000893 if (0) {
894 *(vta->host_bytes_used) = 0;
895 res.status = VexTransOK; return res;
896 }
sewardje908c422005-02-04 21:18:16 +0000897 /* end HACK */
898
sewardj81bd5502004-07-21 18:49:27 +0000899 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000900 if (vex_traceflags & VEX_TRACE_ASM) {
901 vex_printf("\n------------------------"
902 " Assembly "
903 "------------------------\n\n");
904 }
905
sewardj81bd5502004-07-21 18:49:27 +0000906 out_used = 0; /* tracks along the host_bytes array */
907 for (i = 0; i < rcode->arr_used; i++) {
sewardjc6f970f2012-04-02 21:54:49 +0000908 HInstr* hi = rcode->arr[i];
909 Bool hi_isProfInc = False;
910 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
911 ppInstr(hi, mode64);
sewardjbad34a92004-07-22 01:14:11 +0000912 vex_printf("\n");
913 }
sewardjc6f970f2012-04-02 21:54:49 +0000914 j = emit( &hi_isProfInc,
sewardj9b769162014-07-24 12:42:03 +0000915 insn_bytes, sizeof insn_bytes, hi,
916 mode64, vta->archinfo_host.endness,
sewardjc6f970f2012-04-02 21:54:49 +0000917 vta->disp_cp_chain_me_to_slowEP,
918 vta->disp_cp_chain_me_to_fastEP,
919 vta->disp_cp_xindir,
920 vta->disp_cp_xassisted );
921 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
sewardjbad34a92004-07-22 01:14:11 +0000922 for (k = 0; k < j; k++)
floriane5540422014-12-15 21:07:37 +0000923 vex_printf("%02x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000924 vex_printf("\n\n");
925 }
sewardjc6f970f2012-04-02 21:54:49 +0000926 if (UNLIKELY(out_used + j > vta->host_bytes_size)) {
sewardj2d6b14a2005-11-23 04:25:07 +0000927 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000928 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000929 res.status = VexTransOutputFull;
930 return res;
sewardj81bd5502004-07-21 18:49:27 +0000931 }
sewardjc6f970f2012-04-02 21:54:49 +0000932 if (UNLIKELY(hi_isProfInc)) {
933 vassert(vta->addProfInc); /* else where did it come from? */
934 vassert(res.offs_profInc == -1); /* there can be only one (tm) */
935 vassert(out_used >= 0);
936 res.offs_profInc = out_used;
937 }
938 { UChar* dst = &vta->host_bytes[out_used];
939 for (k = 0; k < j; k++) {
940 dst[k] = insn_bytes[k];
941 }
942 out_used += j;
sewardj81bd5502004-07-21 18:49:27 +0000943 }
sewardj81bd5502004-07-21 18:49:27 +0000944 }
sewardj17c7f952005-12-15 14:02:34 +0000945 *(vta->host_bytes_used) = out_used;
sewardj81bd5502004-07-21 18:49:27 +0000946
sewardj2d6b14a2005-11-23 04:25:07 +0000947 vexAllocSanityCheck();
948
949 vexSetAllocModeTEMP_and_clear();
sewardjf13a16a2004-07-05 17:10:14 +0000950
sewardj65ea17e2012-12-28 09:01:59 +0000951 if (vex_traceflags) {
952 /* Print the expansion ratio for this SB. */
953 j = 0; /* total guest bytes */
954 for (i = 0; i < vta->guest_extents->n_used; i++) {
955 j += vta->guest_extents->len[i];
956 }
957 if (1) vex_printf("VexExpansionRatio %d %d %d :10\n\n",
958 j, out_used, (10 * out_used) / (j == 0 ? 1 : j));
959 }
960
sewardjf48ac192004-10-29 00:41:29 +0000961 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000962 res.status = VexTransOK;
963 return res;
sewardj35421a32004-07-05 13:12:34 +0000964}
965
966
sewardjc6f970f2012-04-02 21:54:49 +0000967/* --------- Chain/Unchain XDirects. --------- */
968
florian7d6f81d2014-09-22 21:43:37 +0000969VexInvalRange LibVEX_Chain ( VexArch arch_host,
970 VexEndness endness_host,
971 void* place_to_chain,
972 const void* disp_cp_chain_me_EXPECTED,
973 const void* place_to_jump_to )
sewardjc6f970f2012-04-02 21:54:49 +0000974{
sewardjc6f970f2012-04-02 21:54:49 +0000975 switch (arch_host) {
976 case VexArchX86:
florian7d6f81d2014-09-22 21:43:37 +0000977 return chainXDirect_X86(endness_host,
978 place_to_chain,
979 disp_cp_chain_me_EXPECTED,
980 place_to_jump_to);
sewardjc6f970f2012-04-02 21:54:49 +0000981 case VexArchAMD64:
florian7d6f81d2014-09-22 21:43:37 +0000982 return chainXDirect_AMD64(endness_host,
983 place_to_chain,
984 disp_cp_chain_me_EXPECTED,
985 place_to_jump_to);
sewardjc6f970f2012-04-02 21:54:49 +0000986 case VexArchARM:
florian7d6f81d2014-09-22 21:43:37 +0000987 return chainXDirect_ARM(endness_host,
988 place_to_chain,
989 disp_cp_chain_me_EXPECTED,
990 place_to_jump_to);
sewardjbbcf1882014-01-12 12:49:10 +0000991 case VexArchARM64:
florian7d6f81d2014-09-22 21:43:37 +0000992 return chainXDirect_ARM64(endness_host,
993 place_to_chain,
994 disp_cp_chain_me_EXPECTED,
995 place_to_jump_to);
florian8844a632012-04-13 04:04:06 +0000996 case VexArchS390X:
florian7d6f81d2014-09-22 21:43:37 +0000997 return chainXDirect_S390(endness_host,
998 place_to_chain,
999 disp_cp_chain_me_EXPECTED,
1000 place_to_jump_to);
sewardj3dee8492012-04-20 00:13:28 +00001001 case VexArchPPC32:
sewardj9b769162014-07-24 12:42:03 +00001002 return chainXDirect_PPC(endness_host,
1003 place_to_chain,
sewardj3dee8492012-04-20 00:13:28 +00001004 disp_cp_chain_me_EXPECTED,
1005 place_to_jump_to, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +00001006 case VexArchPPC64:
sewardj9b769162014-07-24 12:42:03 +00001007 return chainXDirect_PPC(endness_host,
1008 place_to_chain,
sewardjf252de52012-04-20 10:42:24 +00001009 disp_cp_chain_me_EXPECTED,
1010 place_to_jump_to, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +00001011 case VexArchMIPS32:
sewardj9b769162014-07-24 12:42:03 +00001012 return chainXDirect_MIPS(endness_host,
1013 place_to_chain,
sewardjd0e5fe72012-06-07 08:51:02 +00001014 disp_cp_chain_me_EXPECTED,
1015 place_to_jump_to, False/*!mode64*/);
petarjb92a9542013-02-27 22:57:17 +00001016 case VexArchMIPS64:
sewardj9b769162014-07-24 12:42:03 +00001017 return chainXDirect_MIPS(endness_host,
1018 place_to_chain,
petarjb92a9542013-02-27 22:57:17 +00001019 disp_cp_chain_me_EXPECTED,
1020 place_to_jump_to, True/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +00001021 default:
1022 vassert(0);
1023 }
sewardjc6f970f2012-04-02 21:54:49 +00001024}
1025
florian7d6f81d2014-09-22 21:43:37 +00001026VexInvalRange LibVEX_UnChain ( VexArch arch_host,
1027 VexEndness endness_host,
1028 void* place_to_unchain,
1029 const void* place_to_jump_to_EXPECTED,
1030 const void* disp_cp_chain_me )
sewardjc6f970f2012-04-02 21:54:49 +00001031{
sewardjc6f970f2012-04-02 21:54:49 +00001032 switch (arch_host) {
1033 case VexArchX86:
florian7d6f81d2014-09-22 21:43:37 +00001034 return unchainXDirect_X86(endness_host,
1035 place_to_unchain,
1036 place_to_jump_to_EXPECTED,
1037 disp_cp_chain_me);
sewardjc6f970f2012-04-02 21:54:49 +00001038 case VexArchAMD64:
florian7d6f81d2014-09-22 21:43:37 +00001039 return unchainXDirect_AMD64(endness_host,
1040 place_to_unchain,
1041 place_to_jump_to_EXPECTED,
1042 disp_cp_chain_me);
sewardjc6f970f2012-04-02 21:54:49 +00001043 case VexArchARM:
florian7d6f81d2014-09-22 21:43:37 +00001044 return unchainXDirect_ARM(endness_host,
1045 place_to_unchain,
1046 place_to_jump_to_EXPECTED,
1047 disp_cp_chain_me);
sewardjc6acaa42014-02-19 17:42:59 +00001048 case VexArchARM64:
florian7d6f81d2014-09-22 21:43:37 +00001049 return unchainXDirect_ARM64(endness_host,
1050 place_to_unchain,
1051 place_to_jump_to_EXPECTED,
1052 disp_cp_chain_me);
florian8844a632012-04-13 04:04:06 +00001053 case VexArchS390X:
florian7d6f81d2014-09-22 21:43:37 +00001054 return unchainXDirect_S390(endness_host,
1055 place_to_unchain,
1056 place_to_jump_to_EXPECTED,
1057 disp_cp_chain_me);
sewardj3dee8492012-04-20 00:13:28 +00001058 case VexArchPPC32:
sewardj9b769162014-07-24 12:42:03 +00001059 return unchainXDirect_PPC(endness_host,
1060 place_to_unchain,
sewardj3dee8492012-04-20 00:13:28 +00001061 place_to_jump_to_EXPECTED,
1062 disp_cp_chain_me, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +00001063 case VexArchPPC64:
sewardj9b769162014-07-24 12:42:03 +00001064 return unchainXDirect_PPC(endness_host,
1065 place_to_unchain,
sewardjf252de52012-04-20 10:42:24 +00001066 place_to_jump_to_EXPECTED,
1067 disp_cp_chain_me, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +00001068 case VexArchMIPS32:
sewardj9b769162014-07-24 12:42:03 +00001069 return unchainXDirect_MIPS(endness_host,
1070 place_to_unchain,
petarjb92a9542013-02-27 22:57:17 +00001071 place_to_jump_to_EXPECTED,
1072 disp_cp_chain_me, False/*!mode64*/);
1073 case VexArchMIPS64:
sewardj9b769162014-07-24 12:42:03 +00001074 return unchainXDirect_MIPS(endness_host,
1075 place_to_unchain,
petarjb92a9542013-02-27 22:57:17 +00001076 place_to_jump_to_EXPECTED,
1077 disp_cp_chain_me, True/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +00001078 default:
1079 vassert(0);
1080 }
sewardjc6f970f2012-04-02 21:54:49 +00001081}
1082
sewardj9b769162014-07-24 12:42:03 +00001083Int LibVEX_evCheckSzB ( VexArch arch_host,
1084 VexEndness endness_host )
sewardjc6f970f2012-04-02 21:54:49 +00001085{
1086 static Int cached = 0; /* DO NOT MAKE NON-STATIC */
1087 if (UNLIKELY(cached == 0)) {
1088 switch (arch_host) {
1089 case VexArchX86:
sewardj9b769162014-07-24 12:42:03 +00001090 cached = evCheckSzB_X86(endness_host); break;
sewardjc6f970f2012-04-02 21:54:49 +00001091 case VexArchAMD64:
sewardj9b769162014-07-24 12:42:03 +00001092 cached = evCheckSzB_AMD64(endness_host); break;
sewardjc6f970f2012-04-02 21:54:49 +00001093 case VexArchARM:
sewardj9b769162014-07-24 12:42:03 +00001094 cached = evCheckSzB_ARM(endness_host); break;
sewardjbbcf1882014-01-12 12:49:10 +00001095 case VexArchARM64:
sewardj9b769162014-07-24 12:42:03 +00001096 cached = evCheckSzB_ARM64(endness_host); break;
florian8844a632012-04-13 04:04:06 +00001097 case VexArchS390X:
sewardj9b769162014-07-24 12:42:03 +00001098 cached = evCheckSzB_S390(endness_host); break;
sewardj3dee8492012-04-20 00:13:28 +00001099 case VexArchPPC32:
sewardjf252de52012-04-20 10:42:24 +00001100 case VexArchPPC64:
sewardj9b769162014-07-24 12:42:03 +00001101 cached = evCheckSzB_PPC(endness_host); break;
sewardjd0e5fe72012-06-07 08:51:02 +00001102 case VexArchMIPS32:
petarjb92a9542013-02-27 22:57:17 +00001103 case VexArchMIPS64:
sewardj9b769162014-07-24 12:42:03 +00001104 cached = evCheckSzB_MIPS(endness_host); break;
sewardjc6f970f2012-04-02 21:54:49 +00001105 default:
1106 vassert(0);
1107 }
1108 }
1109 return cached;
1110}
1111
sewardj9b769162014-07-24 12:42:03 +00001112VexInvalRange LibVEX_PatchProfInc ( VexArch arch_host,
1113 VexEndness endness_host,
1114 void* place_to_patch,
florian7d6f81d2014-09-22 21:43:37 +00001115 const ULong* location_of_counter )
sewardjc6f970f2012-04-02 21:54:49 +00001116{
sewardjc6f970f2012-04-02 21:54:49 +00001117 switch (arch_host) {
1118 case VexArchX86:
florian7d6f81d2014-09-22 21:43:37 +00001119 return patchProfInc_X86(endness_host, place_to_patch,
1120 location_of_counter);
sewardjc6f970f2012-04-02 21:54:49 +00001121 case VexArchAMD64:
florian7d6f81d2014-09-22 21:43:37 +00001122 return patchProfInc_AMD64(endness_host, place_to_patch,
1123 location_of_counter);
sewardjc6f970f2012-04-02 21:54:49 +00001124 case VexArchARM:
florian7d6f81d2014-09-22 21:43:37 +00001125 return patchProfInc_ARM(endness_host, place_to_patch,
1126 location_of_counter);
sewardj0ad37a92014-08-29 21:58:03 +00001127 case VexArchARM64:
florian7d6f81d2014-09-22 21:43:37 +00001128 return patchProfInc_ARM64(endness_host, place_to_patch,
1129 location_of_counter);
florian8844a632012-04-13 04:04:06 +00001130 case VexArchS390X:
florian7d6f81d2014-09-22 21:43:37 +00001131 return patchProfInc_S390(endness_host, place_to_patch,
1132 location_of_counter);
sewardj3dee8492012-04-20 00:13:28 +00001133 case VexArchPPC32:
sewardj9b769162014-07-24 12:42:03 +00001134 return patchProfInc_PPC(endness_host, place_to_patch,
sewardj3dee8492012-04-20 00:13:28 +00001135 location_of_counter, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +00001136 case VexArchPPC64:
sewardj9b769162014-07-24 12:42:03 +00001137 return patchProfInc_PPC(endness_host, place_to_patch,
sewardjf252de52012-04-20 10:42:24 +00001138 location_of_counter, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +00001139 case VexArchMIPS32:
sewardj9b769162014-07-24 12:42:03 +00001140 return patchProfInc_MIPS(endness_host, place_to_patch,
sewardjd0e5fe72012-06-07 08:51:02 +00001141 location_of_counter, False/*!mode64*/);
petarjb92a9542013-02-27 22:57:17 +00001142 case VexArchMIPS64:
sewardj9b769162014-07-24 12:42:03 +00001143 return patchProfInc_MIPS(endness_host, place_to_patch,
petarjb92a9542013-02-27 22:57:17 +00001144 location_of_counter, True/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +00001145 default:
1146 vassert(0);
1147 }
sewardjc6f970f2012-04-02 21:54:49 +00001148}
1149
1150
sewardj893aada2004-11-29 19:57:54 +00001151/* --------- Emulation warnings. --------- */
1152
florian1ff47562012-10-21 02:09:51 +00001153const HChar* LibVEX_EmNote_string ( VexEmNote ew )
sewardj893aada2004-11-29 19:57:54 +00001154{
1155 switch (ew) {
florian6ef84be2012-08-26 03:20:07 +00001156 case EmNote_NONE:
sewardj893aada2004-11-29 19:57:54 +00001157 return "none";
1158 case EmWarn_X86_x87exns:
1159 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +00001160 case EmWarn_X86_x87precision:
1161 return "Selection of non-80-bit x87 FP precision";
1162 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +00001163 return "Unmasking SSE FP exceptions";
1164 case EmWarn_X86_fz:
1165 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
1166 case EmWarn_X86_daz:
1167 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +00001168 case EmWarn_X86_acFlag:
1169 return "Setting %eflags.ac (setting noted but ignored)";
sewardj9dd9cf12006-01-20 14:13:55 +00001170 case EmWarn_PPCexns:
1171 return "Unmasking PPC32/64 FP exceptions";
1172 case EmWarn_PPC64_redir_overflow:
1173 return "PPC64 function redirection stack overflow";
1174 case EmWarn_PPC64_redir_underflow:
1175 return "PPC64 function redirection stack underflow";
florian4b8efad2012-09-02 18:07:08 +00001176 case EmWarn_S390X_fpext_rounding:
1177 return "The specified rounding mode cannot be supported. That\n"
florian2a4de0b2014-12-05 18:28:29 +00001178 " feature requires the floating point extension facility\n"
florian4b8efad2012-09-02 18:07:08 +00001179 " which is not available on this host. Continuing using\n"
1180 " the rounding mode from FPC. Results may differ!";
florianf0fa1be2012-09-18 20:24:38 +00001181 case EmWarn_S390X_invalid_rounding:
1182 return "The specified rounding mode is invalid.\n"
1183 " Continuing using 'round to nearest'. Results may differ!";
floriane75dafa2012-09-01 17:54:09 +00001184 case EmFail_S390X_stfle:
florian4e0083e2012-08-26 03:41:56 +00001185 return "Instruction stfle is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001186 case EmFail_S390X_stckf:
florianc5c669b2012-08-26 14:32:28 +00001187 return "Instruction stckf is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001188 case EmFail_S390X_ecag:
florian8c88cb62012-08-26 18:58:13 +00001189 return "Instruction ecag is not supported on this host";
florianad00ea92014-12-05 18:55:39 +00001190 case EmFail_S390X_pfpo:
1191 return "Instruction pfpo is not supported on this host";
florianfb596602014-12-06 16:34:48 +00001192 case EmFail_S390X_DFP_insn:
1193 return "DFP instructions are not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001194 case EmFail_S390X_fpext:
1195 return "Encountered an instruction that requires the floating "
1196 "point extension facility.\n"
1197 " That facility is not available on this host";
florian78d5ef72013-05-11 15:02:58 +00001198 case EmFail_S390X_invalid_PFPO_rounding_mode:
florian2a4de0b2014-12-05 18:28:29 +00001199 return "The rounding mode in GPR 0 for the PFPO instruction"
florian78d5ef72013-05-11 15:02:58 +00001200 " is invalid";
1201 case EmFail_S390X_invalid_PFPO_function:
florian2a4de0b2014-12-05 18:28:29 +00001202 return "The function code in GPR 0 for the PFPO instruction"
florian78d5ef72013-05-11 15:02:58 +00001203 " is invalid";
sewardj893aada2004-11-29 19:57:54 +00001204 default:
florian6ef84be2012-08-26 03:20:07 +00001205 vpanic("LibVEX_EmNote_string: unknown warning");
sewardj893aada2004-11-29 19:57:54 +00001206 }
1207}
sewardj35421a32004-07-05 13:12:34 +00001208
sewardj5117ce12006-01-27 21:20:15 +00001209/* ------------------ Arch/HwCaps stuff. ------------------ */
sewardjbef170b2004-12-21 01:23:00 +00001210
1211const HChar* LibVEX_ppVexArch ( VexArch arch )
1212{
1213 switch (arch) {
1214 case VexArch_INVALID: return "INVALID";
1215 case VexArchX86: return "X86";
1216 case VexArchAMD64: return "AMD64";
1217 case VexArchARM: return "ARM";
sewardjbbcf1882014-01-12 12:49:10 +00001218 case VexArchARM64: return "ARM64";
sewardj0ec57c52005-02-01 15:24:10 +00001219 case VexArchPPC32: return "PPC32";
cerionf0de28c2005-12-13 20:21:11 +00001220 case VexArchPPC64: return "PPC64";
sewardj2019a972011-03-07 16:04:07 +00001221 case VexArchS390X: return "S390X";
sewardjd0e5fe72012-06-07 08:51:02 +00001222 case VexArchMIPS32: return "MIPS32";
petarjb92a9542013-02-27 22:57:17 +00001223 case VexArchMIPS64: return "MIPS64";
sewardjbef170b2004-12-21 01:23:00 +00001224 default: return "VexArch???";
1225 }
1226}
1227
sewardj9b769162014-07-24 12:42:03 +00001228const HChar* LibVEX_ppVexEndness ( VexEndness endness )
1229{
1230 switch (endness) {
1231 case VexEndness_INVALID: return "INVALID";
1232 case VexEndnessLE: return "LittleEndian";
1233 case VexEndnessBE: return "BigEndian";
1234 default: return "VexEndness???";
1235 }
1236}
1237
florianf3652c92014-12-10 16:10:24 +00001238/* Return a string with the hardware capabilities to the extent as
1239 they pertain to the translation process. No attempt is made, to
1240 detect *all* capabilities an architecture may have. */
sewardj5117ce12006-01-27 21:20:15 +00001241const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
sewardjbef170b2004-12-21 01:23:00 +00001242{
florianf3652c92014-12-10 16:10:24 +00001243 return show_hwcaps(arch, hwcaps);
sewardjbef170b2004-12-21 01:23:00 +00001244}
1245
sewardj5117ce12006-01-27 21:20:15 +00001246
sewardj27e1dd62005-06-30 11:49:14 +00001247/* Write default settings info *vai. */
1248void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
1249{
sewardj65902992014-05-03 21:20:56 +00001250 vex_bzero(vai, sizeof(*vai));
sewardj9b769162014-07-24 12:42:03 +00001251 vai->hwcaps = 0;
1252 vai->endness = VexEndness_INVALID;
1253 vai->ppc_icache_line_szB = 0;
1254 vai->ppc_dcbz_szB = 0;
1255 vai->ppc_dcbzl_szB = 0;
sewardj65902992014-05-03 21:20:56 +00001256 vai->arm64_dMinLine_lg2_szB = 0;
1257 vai->arm64_iMinLine_lg2_szB = 0;
florianf192a392012-10-07 19:44:40 +00001258 vai->hwcache_info.num_levels = 0;
1259 vai->hwcache_info.num_caches = 0;
sewardj65902992014-05-03 21:20:56 +00001260 vai->hwcache_info.caches = NULL;
florianf192a392012-10-07 19:44:40 +00001261 vai->hwcache_info.icaches_maintain_coherence = True; // whatever
sewardj27e1dd62005-06-30 11:49:14 +00001262}
1263
sewardjdd40fdf2006-12-24 02:20:24 +00001264/* Write default settings info *vbi. */
1265void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
sewardjaca070a2006-10-17 00:28:22 +00001266{
sewardj65902992014-05-03 21:20:56 +00001267 vex_bzero(vbi, sizeof(*vbi));
sewardjdd40fdf2006-12-24 02:20:24 +00001268 vbi->guest_stack_redzone_size = 0;
philippee2cc4de2014-12-16 23:57:51 +00001269 vbi->guest_amd64_assume_fs_is_const = False;
1270 vbi->guest_amd64_assume_gs_is_const = False;
sewardjdd40fdf2006-12-24 02:20:24 +00001271 vbi->guest_ppc_zap_RZ_at_blr = False;
1272 vbi->guest_ppc_zap_RZ_at_bl = NULL;
sewardjdd40fdf2006-12-24 02:20:24 +00001273 vbi->host_ppc_calls_use_fndescrs = False;
sewardjaca070a2006-10-17 00:28:22 +00001274}
1275
sewardj27e1dd62005-06-30 11:49:14 +00001276
florianf3652c92014-12-10 16:10:24 +00001277/* Convenience macro to be used in show_hwcaps_ARCH functions */
1278#define NUM_HWCAPS (sizeof hwcaps_list / sizeof hwcaps_list[0])
1279
sewardj5117ce12006-01-27 21:20:15 +00001280/* Return a string showing the hwcaps in a nice way. The string will
florianf3652c92014-12-10 16:10:24 +00001281 be NULL for unrecognised hardware capabilities. */
sewardj5117ce12006-01-27 21:20:15 +00001282
florian55085f82012-11-21 00:36:55 +00001283static const HChar* show_hwcaps_x86 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001284{
florianf3652c92014-12-10 16:10:24 +00001285 static const HChar prefix[] = "x86";
1286 static const struct {
1287 UInt hwcaps_bit;
1288 HChar name[7];
1289 } hwcaps_list[] = {
1290 { VEX_HWCAPS_X86_MMXEXT, "mmxext" },
1291 { VEX_HWCAPS_X86_SSE1, "sse1" },
1292 { VEX_HWCAPS_X86_SSE2, "sse2" },
1293 { VEX_HWCAPS_X86_SSE3, "sse3" },
1294 { VEX_HWCAPS_X86_LZCNT, "lzcnt" },
1295 };
1296 /* Allocate a large enough buffer */
1297 static HChar buf[sizeof prefix +
1298 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1299 if (buf[0] != '\0') return buf; /* already constructed */
1300
1301 HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1302
1303 if (hwcaps == 0) {
1304 vex_sprintf(p, "-%s", "sse0");
1305 } else {
1306 UInt i;
1307 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1308 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1309 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1310 }
sewardj536fbab2010-07-29 15:39:05 +00001311 }
florianf3652c92014-12-10 16:10:24 +00001312 return buf;
sewardj5117ce12006-01-27 21:20:15 +00001313}
1314
florian55085f82012-11-21 00:36:55 +00001315static const HChar* show_hwcaps_amd64 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001316{
florianf3652c92014-12-10 16:10:24 +00001317 static const HChar prefix[] = "amd64";
1318 static const struct {
1319 UInt hwcaps_bit;
1320 HChar name[7];
1321 } hwcaps_list[] = {
1322 { VEX_HWCAPS_AMD64_CX16, "cx16" },
1323 { VEX_HWCAPS_AMD64_LZCNT, "lzcnt" },
1324 { VEX_HWCAPS_AMD64_RDTSCP, "rdtscp" },
1325 { VEX_HWCAPS_AMD64_SSE3, "sse3" },
1326 { VEX_HWCAPS_AMD64_AVX, "avx" },
1327 { VEX_HWCAPS_AMD64_AVX2, "avx2" },
1328 { VEX_HWCAPS_AMD64_BMI, "bmi" },
1329 };
1330 /* Allocate a large enough buffer */
1331 static HChar buf[sizeof prefix +
1332 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1333 if (buf[0] != '\0') return buf; /* already constructed */
sewardj818c7302013-03-26 13:53:18 +00001334
florianf3652c92014-12-10 16:10:24 +00001335 HChar *p = buf + vex_sprintf(buf, "%s", prefix);
sewardj818c7302013-03-26 13:53:18 +00001336
sewardj818c7302013-03-26 13:53:18 +00001337 if (hwcaps == 0) {
florianf3652c92014-12-10 16:10:24 +00001338 vex_sprintf(p, "-%s", "sse2");
1339 } else {
1340 UInt i;
1341 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1342 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1343 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1344 }
sewardj536fbab2010-07-29 15:39:05 +00001345 }
sewardj818c7302013-03-26 13:53:18 +00001346 return buf;
sewardj5117ce12006-01-27 21:20:15 +00001347}
1348
florian55085f82012-11-21 00:36:55 +00001349static const HChar* show_hwcaps_ppc32 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001350{
florianf3652c92014-12-10 16:10:24 +00001351 static const HChar prefix[] = "ppc32-int";
1352 static const struct {
1353 UInt hwcaps_bit;
1354 HChar name[8];
1355 } hwcaps_list[] = {
1356 { VEX_HWCAPS_PPC32_F, "flt" },
1357 { VEX_HWCAPS_PPC32_V, "vmx" },
1358 { VEX_HWCAPS_PPC32_FX, "FX" },
1359 { VEX_HWCAPS_PPC32_GX, "GX" },
1360 { VEX_HWCAPS_PPC32_VX, "VX" },
1361 { VEX_HWCAPS_PPC32_DFP, "DFP" },
1362 { VEX_HWCAPS_PPC32_ISA2_07, "ISA2_07" },
1363 };
1364 /* Allocate a large enough buffer */
1365 static HChar buf[sizeof prefix +
1366 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1367 if (buf[0] != '\0') return buf; /* already constructed */
carll0c74bb52013-08-12 18:01:40 +00001368
florianf3652c92014-12-10 16:10:24 +00001369 HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1370
1371 if (hwcaps == 0) return buf;
1372
1373 UInt i;
1374 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1375 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1376 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1377 }
1378 return buf;
sewardj5117ce12006-01-27 21:20:15 +00001379}
1380
florian55085f82012-11-21 00:36:55 +00001381static const HChar* show_hwcaps_ppc64 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001382{
florianf3652c92014-12-10 16:10:24 +00001383 static const HChar prefix[] = "ppc64-int-flt";
1384 static const struct {
1385 UInt hwcaps_bit;
1386 HChar name[8];
1387 } hwcaps_list[] = {
1388 { VEX_HWCAPS_PPC64_FX, "FX" },
1389 { VEX_HWCAPS_PPC64_GX, "GX" },
1390 { VEX_HWCAPS_PPC64_V, "vmx" },
1391 { VEX_HWCAPS_PPC64_DFP, "DFP" },
1392 { VEX_HWCAPS_PPC64_ISA2_07, "ISA2_07" },
1393 };
1394 /* Allocate a large enough buffer */
1395 static HChar buf[sizeof prefix +
1396 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1397 if (buf[0] != '\0') return buf; /* already constructed */
1398
1399 HChar *p = buf + vex_sprintf(buf, "%s", prefix);
1400
1401 if (hwcaps == 0) return buf;
1402
1403 UInt i;
1404 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1405 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1406 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1407 }
1408 return buf;
sewardj5117ce12006-01-27 21:20:15 +00001409}
1410
florian55085f82012-11-21 00:36:55 +00001411static const HChar* show_hwcaps_arm ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001412{
florianf3652c92014-12-10 16:10:24 +00001413 static const HChar prefix[] = "ARM";
1414 static const struct {
1415 UInt hwcaps_bit;
1416 HChar name[6];
1417 } hwcaps_list[] = {
1418 { VEX_HWCAPS_ARM_NEON, "neon" },
1419 { VEX_HWCAPS_ARM_VFP | VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3, "vfp" },
1420 };
1421 /* Allocate a large enough buffer */
1422 static HChar buf[sizeof prefix + 12 + // level
1423 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
1424 if (buf[0] != '\0') return buf; /* already constructed */
1425
1426 HChar *p;
1427 UInt i, level;
1428
1429 level = VEX_ARM_ARCHLEVEL(hwcaps);
1430
1431 p = buf + vex_sprintf(buf, "%sv%u", prefix, level);
1432 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1433 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1434 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
sewardjec0d9a02010-08-22 12:54:56 +00001435 }
florianf3652c92014-12-10 16:10:24 +00001436 return buf;
sewardj5117ce12006-01-27 21:20:15 +00001437}
1438
sewardjbbcf1882014-01-12 12:49:10 +00001439static const HChar* show_hwcaps_arm64 ( UInt hwcaps )
1440{
1441 /* Since there are no variants, just insist that hwcaps is zero,
1442 and declare it invalid otherwise. */
1443 if (hwcaps == 0)
1444 return "baseline";
florianf3652c92014-12-10 16:10:24 +00001445 return "Unsupported";
sewardjbbcf1882014-01-12 12:49:10 +00001446}
1447
florian55085f82012-11-21 00:36:55 +00001448static const HChar* show_hwcaps_s390x ( UInt hwcaps )
sewardj2019a972011-03-07 16:04:07 +00001449{
sewardjd07b8562011-04-27 11:58:22 +00001450 static const HChar prefix[] = "s390x";
florian9061eb32012-12-09 17:53:45 +00001451 static const struct {
1452 UInt hwcaps_bit;
1453 HChar name[6];
1454 } hwcaps_list[] = {
1455 { VEX_HWCAPS_S390X_LDISP, "ldisp" },
1456 { VEX_HWCAPS_S390X_EIMM, "eimm" },
1457 { VEX_HWCAPS_S390X_GIE, "gie" },
1458 { VEX_HWCAPS_S390X_DFP, "dfp" },
1459 { VEX_HWCAPS_S390X_FGX, "fgx" },
1460 { VEX_HWCAPS_S390X_STFLE, "stfle" },
1461 { VEX_HWCAPS_S390X_ETF2, "etf2" },
1462 { VEX_HWCAPS_S390X_ETF3, "etf3" },
1463 { VEX_HWCAPS_S390X_STCKF, "stckf" },
1464 { VEX_HWCAPS_S390X_FPEXT, "fpext" },
1465 { VEX_HWCAPS_S390X_LSC, "lsc" },
florian78d5ef72013-05-11 15:02:58 +00001466 { VEX_HWCAPS_S390X_PFPO, "pfpo" },
sewardjd07b8562011-04-27 11:58:22 +00001467 };
florianf3652c92014-12-10 16:10:24 +00001468 /* Allocate a large enough buffer */
florian9061eb32012-12-09 17:53:45 +00001469 static HChar buf[sizeof prefix +
florianf3652c92014-12-10 16:10:24 +00001470 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
sewardjd07b8562011-04-27 11:58:22 +00001471
1472 if (buf[0] != '\0') return buf; /* already constructed */
sewardj2019a972011-03-07 16:04:07 +00001473
florianf3652c92014-12-10 16:10:24 +00001474 HChar *p;
1475 UInt i;
1476
sewardj652b56a2011-04-13 15:38:17 +00001477 hwcaps = VEX_HWCAPS_S390X(hwcaps);
1478
sewardjd07b8562011-04-27 11:58:22 +00001479 p = buf + vex_sprintf(buf, "%s", prefix);
florian9061eb32012-12-09 17:53:45 +00001480 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1481 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1482 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1483 }
sewardj2019a972011-03-07 16:04:07 +00001484
sewardjd07b8562011-04-27 11:58:22 +00001485 /* If there are no facilities, add "zarch" */
1486 if (hwcaps == 0)
1487 vex_sprintf(p, "-%s", "zarch");
1488
1489 return buf;
sewardj2019a972011-03-07 16:04:07 +00001490}
1491
florian55085f82012-11-21 00:36:55 +00001492static const HChar* show_hwcaps_mips32 ( UInt hwcaps )
sewardjd0e5fe72012-06-07 08:51:02 +00001493{
dejanjc3fee0d2013-07-25 09:08:03 +00001494 /* MIPS baseline. */
petarjbc7d6f42013-09-16 18:11:59 +00001495 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_MIPS) {
dejanjc3fee0d2013-07-25 09:08:03 +00001496 /* MIPS baseline with dspr2. */
petarjbc7d6f42013-09-16 18:11:59 +00001497 if (VEX_MIPS_PROC_DSP2(hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +00001498 return "MIPS-baseline-dspr2";
1499 }
1500 /* MIPS baseline with dsp. */
petarjbc7d6f42013-09-16 18:11:59 +00001501 if (VEX_MIPS_PROC_DSP(hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +00001502 return "MIPS-baseline-dsp";
1503 }
1504 return "MIPS-baseline";
1505 }
1506
1507 /* Broadcom baseline. */
petarjbc7d6f42013-09-16 18:11:59 +00001508 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_BROADCOM) {
dejanjc3fee0d2013-07-25 09:08:03 +00001509 return "Broadcom-baseline";
1510 }
1511
1512 /* Netlogic baseline. */
petarjbc7d6f42013-09-16 18:11:59 +00001513 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_NETLOGIC) {
dejanjc3fee0d2013-07-25 09:08:03 +00001514 return "Netlogic-baseline";
1515 }
1516
petarjbc7d6f42013-09-16 18:11:59 +00001517 /* Cavium baseline. */
1518 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_CAVIUM) {
1519 return "Cavium-baseline";
1520 }
1521
florianf3652c92014-12-10 16:10:24 +00001522 return "Unsupported baseline";
sewardjd0e5fe72012-06-07 08:51:02 +00001523}
1524
petarjb92a9542013-02-27 22:57:17 +00001525static const HChar* show_hwcaps_mips64 ( UInt hwcaps )
1526{
1527 return "mips64-baseline";
1528}
1529
florianf3652c92014-12-10 16:10:24 +00001530#undef NUM_HWCAPS
1531
1532/* Thie function must not return NULL. */
florian55085f82012-11-21 00:36:55 +00001533static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001534{
1535 switch (arch) {
sewardjd0e5fe72012-06-07 08:51:02 +00001536 case VexArchX86: return show_hwcaps_x86(hwcaps);
1537 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
1538 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
1539 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
1540 case VexArchARM: return show_hwcaps_arm(hwcaps);
sewardjbbcf1882014-01-12 12:49:10 +00001541 case VexArchARM64: return show_hwcaps_arm64(hwcaps);
sewardjd0e5fe72012-06-07 08:51:02 +00001542 case VexArchS390X: return show_hwcaps_s390x(hwcaps);
1543 case VexArchMIPS32: return show_hwcaps_mips32(hwcaps);
petarjb92a9542013-02-27 22:57:17 +00001544 case VexArchMIPS64: return show_hwcaps_mips64(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001545 default: return NULL;
1546 }
1547}
1548
florianf3652c92014-12-10 16:10:24 +00001549/* To be used to complain about hwcaps we cannot handle */
1550__attribute__((noreturn))
1551static void invalid_hwcaps ( VexArch arch, UInt hwcaps, const HChar *message )
sewardj5117ce12006-01-27 21:20:15 +00001552{
florianf3652c92014-12-10 16:10:24 +00001553 vfatal("\nVEX: %s"
1554 " Found: %s\n", message, show_hwcaps(arch, hwcaps));
1555}
1556
1557/* This function will not return iff the hwcaps don't pass the test. */
1558static void check_hwcaps ( VexArch arch, UInt hwcaps )
1559{
1560 switch (arch) {
1561 case VexArchX86: {
1562 if (hwcaps == 0) return; // baseline
1563
1564 /* Monotonic: SSE3 > SSE2 > SSE1 > MMXEXT > baseline. */
1565 static const UInt extras[] = {
1566 VEX_HWCAPS_X86_MMXEXT, VEX_HWCAPS_X86_SSE1, VEX_HWCAPS_X86_SSE2,
1567 VEX_HWCAPS_X86_SSE3
1568 };
1569
1570 UInt i, caps = 0;
1571 for (i = 0; i < sizeof extras / sizeof extras[0]; ++i) {
1572 caps |= extras[i];
1573 if (caps == hwcaps) return;
1574 if ((caps & VEX_HWCAPS_X86_SSE2) != 0) {
1575 if ((caps & VEX_HWCAPS_X86_LZCNT) != 0) return;
1576 }
1577 }
1578 invalid_hwcaps(arch, hwcaps, "Cannot handle capabilities\n");
1579 }
1580
1581 case VexArchAMD64: {
florianf3652c92014-12-10 16:10:24 +00001582 /* SSE3 and CX16 are orthogonal and > baseline, although we really
1583 don't expect to come across anything which can do SSE3 but can't
1584 do CX16. Still, we can handle that case. LZCNT is similarly
1585 orthogonal. */
1586
1587 /* Throw out obviously stupid cases: */
1588 Bool have_sse3 = (hwcaps & VEX_HWCAPS_AMD64_SSE3) != 0;
1589 Bool have_avx = (hwcaps & VEX_HWCAPS_AMD64_AVX) != 0;
1590 Bool have_bmi = (hwcaps & VEX_HWCAPS_AMD64_BMI) != 0;
1591 Bool have_avx2 = (hwcaps & VEX_HWCAPS_AMD64_AVX2) != 0;
1592
1593 /* AVX without SSE3 */
1594 if (have_avx && !have_sse3)
1595 invalid_hwcaps(arch, hwcaps,
1596 "Support for AVX requires SSE3 capabilities\n");
1597 /* AVX2 or BMI without AVX */
1598 if (have_avx2 && !have_avx)
1599 invalid_hwcaps(arch, hwcaps,
1600 "Support for AVX2 requires AVX capabilities\n");
1601 if (have_bmi && !have_avx)
1602 invalid_hwcaps(arch, hwcaps,
1603 "Support for BMI requires AVX capabilities\n");
1604 return;
1605 }
1606
1607 case VexArchPPC32: {
1608 /* Monotonic with complications. Basically V > F > baseline,
1609 but once you have F then you can have FX or GX too. */
1610 if (hwcaps == 0) return; // baseline
1611
1612 if ((hwcaps & VEX_HWCAPS_PPC32_F) == 0)
1613 invalid_hwcaps(arch, hwcaps,
1614 "Missing floating point capability\n");
1615 /* V, FX, and GX can appear in any combination */
1616
1617 /* DFP requires V and FX and GX */
1618 UInt v_fx_gx = VEX_HWCAPS_PPC32_V | VEX_HWCAPS_PPC32_FX |
1619 VEX_HWCAPS_PPC32_GX;
1620 Bool has_v_fx_gx = (hwcaps & v_fx_gx) == v_fx_gx;
1621
1622 if ((hwcaps & VEX_HWCAPS_PPC32_DFP) && ! has_v_fx_gx)
1623 invalid_hwcaps(arch, hwcaps,
1624 "DFP requires VMX and FX and GX capabilities\n");
1625
1626 /* VX requires V and FX and GX */
1627 if ((hwcaps & VEX_HWCAPS_PPC32_VX) && ! has_v_fx_gx)
1628 invalid_hwcaps(arch, hwcaps,
1629 "VX requires VMX and FX and GX capabilities\n");
1630
1631 /* ISA2_07 requires everything else */
1632 if ((hwcaps & VEX_HWCAPS_PPC32_ISA2_07) != 0) {
1633 if (! has_v_fx_gx)
1634 invalid_hwcaps(arch, hwcaps,
1635 "ISA2_07 requires VMX and FX and GX capabilities\n");
1636 if (! (hwcaps & VEX_HWCAPS_PPC32_VX))
1637 invalid_hwcaps(arch, hwcaps,
1638 "ISA2_07 requires VX capabilities\n");
1639 if (! (hwcaps & VEX_HWCAPS_PPC32_DFP))
1640 invalid_hwcaps(arch, hwcaps,
1641 "ISA2_07 requires DFP capabilities\n");
1642 }
1643 return;
1644 }
1645
1646 case VexArchPPC64: {
1647 /* Monotonic with complications. Basically V > baseline(==F),
1648 but once you have F then you can have FX or GX too. */
1649 if (hwcaps == 0) return; // baseline
1650
1651 /* V, FX, and GX can appear in any combination */
1652
1653 /* DFP requires V and FX and GX */
1654 UInt v_fx_gx = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX |
1655 VEX_HWCAPS_PPC64_GX;
1656 Bool has_v_fx_gx = (hwcaps & v_fx_gx) == v_fx_gx;
1657
1658 if ((hwcaps & VEX_HWCAPS_PPC64_DFP) && ! has_v_fx_gx)
1659 invalid_hwcaps(arch, hwcaps,
1660 "DFP requires VMX and FX and GX capabilities\n");
1661
1662 /* VX requires V and FX and GX */
1663 if ((hwcaps & VEX_HWCAPS_PPC32_VX) && ! has_v_fx_gx)
1664 invalid_hwcaps(arch, hwcaps,
1665 "VX requires VMX and FX and GX capabilities\n");
1666
1667 /* ISA2_07 requires everything else */
1668 if ((hwcaps & VEX_HWCAPS_PPC64_ISA2_07) != 0) {
1669 if (! has_v_fx_gx)
1670 invalid_hwcaps(arch, hwcaps,
1671 "ISA2_07 requires VMX and FX and GX capabilities\n");
1672 if (! (hwcaps & VEX_HWCAPS_PPC64_VX))
1673 invalid_hwcaps(arch, hwcaps,
1674 "ISA2_07 requires VX capabilities\n");
1675 if (! (hwcaps & VEX_HWCAPS_PPC64_DFP))
1676 invalid_hwcaps(arch, hwcaps,
1677 "ISA2_07 requires DFP capabilities\n");
1678 }
1679 return;
1680 }
1681
1682 case VexArchARM: {
1683 Bool NEON = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0);
1684 UInt level = VEX_ARM_ARCHLEVEL(hwcaps);
1685
1686 switch (level) {
1687 case 5:
1688 if (NEON)
1689 invalid_hwcaps(arch, hwcaps,
1690 "NEON instructions are not supported for ARMv5.\n");
1691 return;
1692 case 6:
1693 if (NEON)
1694 invalid_hwcaps(arch, hwcaps,
1695 "NEON instructions are not supported for ARMv6.\n");
1696 return;
1697 case 7:
1698 return;
1699 default:
1700 invalid_hwcaps(arch, hwcaps,
1701 "ARM architecture level is not supported.\n");
1702 }
1703 }
1704
1705 case VexArchARM64:
1706 if (hwcaps != 0)
1707 invalid_hwcaps(arch, hwcaps,
1708 "Unsupported hardware capabilities.\n");
1709 return;
1710
1711 case VexArchS390X:
1712 if (! s390_host_has_ldisp)
1713 invalid_hwcaps(arch, hwcaps,
1714 "Host does not have long displacement facility.\n");
1715 return;
1716
1717 case VexArchMIPS32:
1718 switch (VEX_MIPS_COMP_ID(hwcaps)) {
1719 case VEX_PRID_COMP_MIPS:
1720 case VEX_PRID_COMP_BROADCOM:
1721 case VEX_PRID_COMP_NETLOGIC:
1722 return;
1723 default:
1724 invalid_hwcaps(arch, hwcaps, "Unsupported baseline\n");
1725 }
1726
1727 case VexArchMIPS64:
1728 return;
1729
1730 default:
1731 vpanic("unknown architecture");
floriandc6e7472014-12-08 14:01:33 +00001732 }
sewardj5117ce12006-01-27 21:20:15 +00001733}
1734
1735
sewardj35421a32004-07-05 13:12:34 +00001736/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +00001737/*--- end main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +00001738/*---------------------------------------------------------------*/