blob: 21889e3ef489adc7fbf851c424df097d07a10278 [file] [log] [blame]
sewardj35421a32004-07-05 13:12:34 +00001
2/*---------------------------------------------------------------*/
carll1f5fe1f2014-08-07 23:25:23 +00003/*--- Begin main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +00004/*---------------------------------------------------------------*/
5
sewardjf8ed9d82004-11-12 17:40:23 +00006/*
sewardj752f9062010-05-03 21:38:49 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjf8ed9d82004-11-12 17:40:23 +00009
sewardj89ae8472013-10-18 14:12:58 +000010 Copyright (C) 2004-2013 OpenWorks LLP
sewardj752f9062010-05-03 21:38:49 +000011 info@open-works.net
sewardjf8ed9d82004-11-12 17:40:23 +000012
sewardj752f9062010-05-03 21:38:49 +000013 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
sewardjf8ed9d82004-11-12 17:40:23 +000017
sewardj752f9062010-05-03 21:38:49 +000018 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
sewardj7bd6ffe2005-08-03 16:07:36 +000026 02110-1301, USA.
27
sewardj752f9062010-05-03 21:38:49 +000028 The GNU General Public License is contained in the file COPYING.
sewardjf8ed9d82004-11-12 17:40:23 +000029
30 Neither the names of the U.S. Department of Energy nor the
31 University of California nor the names of its contributors may be
32 used to endorse or promote products derived from this software
33 without prior written permission.
sewardjf8ed9d82004-11-12 17:40:23 +000034*/
35
sewardj887a11a2004-07-05 17:26:47 +000036#include "libvex.h"
florian33b02432012-08-25 21:48:04 +000037#include "libvex_emnote.h"
sewardj81ec4182004-10-25 23:15:52 +000038#include "libvex_guest_x86.h"
sewardj44d494d2005-01-20 20:26:33 +000039#include "libvex_guest_amd64.h"
sewardj2a9ad022004-11-25 02:46:58 +000040#include "libvex_guest_arm.h"
sewardjbbcf1882014-01-12 12:49:10 +000041#include "libvex_guest_arm64.h"
cerionaabdfbf2005-01-29 12:56:15 +000042#include "libvex_guest_ppc32.h"
cerionf0de28c2005-12-13 20:21:11 +000043#include "libvex_guest_ppc64.h"
sewardj2019a972011-03-07 16:04:07 +000044#include "libvex_guest_s390x.h"
sewardjd0e5fe72012-06-07 08:51:02 +000045#include "libvex_guest_mips32.h"
petarjb92a9542013-02-27 22:57:17 +000046#include "libvex_guest_mips64.h"
sewardjf13a16a2004-07-05 17:10:14 +000047
sewardjcef7d3e2009-07-02 12:21:59 +000048#include "main_globals.h"
49#include "main_util.h"
50#include "host_generic_regs.h"
51#include "ir_opt.h"
sewardj35421a32004-07-05 13:12:34 +000052
sewardjcef7d3e2009-07-02 12:21:59 +000053#include "host_x86_defs.h"
54#include "host_amd64_defs.h"
55#include "host_ppc_defs.h"
sewardj6c299f32009-12-31 18:00:12 +000056#include "host_arm_defs.h"
sewardjbbcf1882014-01-12 12:49:10 +000057#include "host_arm64_defs.h"
sewardj2019a972011-03-07 16:04:07 +000058#include "host_s390_defs.h"
sewardjd0e5fe72012-06-07 08:51:02 +000059#include "host_mips_defs.h"
sewardj2a9ad022004-11-25 02:46:58 +000060
sewardjcef7d3e2009-07-02 12:21:59 +000061#include "guest_generic_bb_to_IR.h"
62#include "guest_x86_defs.h"
63#include "guest_amd64_defs.h"
64#include "guest_arm_defs.h"
sewardjbbcf1882014-01-12 12:49:10 +000065#include "guest_arm64_defs.h"
sewardjcef7d3e2009-07-02 12:21:59 +000066#include "guest_ppc_defs.h"
sewardj2019a972011-03-07 16:04:07 +000067#include "guest_s390_defs.h"
sewardjd0e5fe72012-06-07 08:51:02 +000068#include "guest_mips_defs.h"
sewardj2a9ad022004-11-25 02:46:58 +000069
sewardj69d98e32010-06-18 08:17:41 +000070#include "host_generic_simd128.h"
71
sewardj35421a32004-07-05 13:12:34 +000072
73/* This file contains the top level interface to the library. */
74
sewardj5117ce12006-01-27 21:20:15 +000075/* --------- fwds ... --------- */
76
77static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps );
florian55085f82012-11-21 00:36:55 +000078static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps );
sewardj5117ce12006-01-27 21:20:15 +000079
80
sewardj8bde7f12013-04-11 13:57:43 +000081/* --------- helpers --------- */
82
83__attribute__((noinline))
84static UInt udiv32 ( UInt x, UInt y ) { return x/y; }
85__attribute__((noinline))
86static Int sdiv32 ( Int x, Int y ) { return x/y; }
87
88
sewardj35421a32004-07-05 13:12:34 +000089/* --------- Initialise the library. --------- */
90
91/* Exported to library client. */
92
sewardj08613742004-10-25 13:01:45 +000093void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon )
94{
sewardj65902992014-05-03 21:20:56 +000095 vex_bzero(vcon, sizeof(*vcon));
sewardj08613742004-10-25 13:01:45 +000096 vcon->iropt_verbosity = 0;
97 vcon->iropt_level = 2;
philippec8e2f982012-08-01 22:04:13 +000098 vcon->iropt_register_updates = VexRegUpdUnwindregsAtMemAccess;
sewardj08613742004-10-25 13:01:45 +000099 vcon->iropt_unroll_thresh = 120;
sewardj18b4bb72005-03-29 21:32:41 +0000100 vcon->guest_max_insns = 60;
sewardj08613742004-10-25 13:01:45 +0000101 vcon->guest_chase_thresh = 10;
sewardj984d9b12010-01-15 10:53:21 +0000102 vcon->guest_chase_cond = False;
sewardj08613742004-10-25 13:01:45 +0000103}
104
105
106/* Exported to library client. */
107
sewardj887a11a2004-07-05 17:26:47 +0000108void LibVEX_Init (
sewardj35421a32004-07-05 13:12:34 +0000109 /* failure exit function */
sewardj2b515872004-07-05 20:50:45 +0000110 __attribute__ ((noreturn))
sewardj35421a32004-07-05 13:12:34 +0000111 void (*failure_exit) ( void ),
112 /* logging output function */
sewardjd9763622005-02-07 03:12:19 +0000113 void (*log_bytes) ( HChar*, Int nbytes ),
sewardj35421a32004-07-05 13:12:34 +0000114 /* debug paranoia level */
115 Int debuglevel,
sewardj35421a32004-07-05 13:12:34 +0000116 /* Are we supporting valgrind checking? */
117 Bool valgrind_support,
sewardj08613742004-10-25 13:01:45 +0000118 /* Control ... */
119 /*READONLY*/VexControl* vcon
sewardj35421a32004-07-05 13:12:34 +0000120)
121{
sewardj08613742004-10-25 13:01:45 +0000122 /* First off, do enough minimal setup so that the following
123 assertions can fail in a sane fashion, if need be. */
sewardjea602bc2004-10-14 21:40:12 +0000124 vex_failure_exit = failure_exit;
125 vex_log_bytes = log_bytes;
126
127 /* Now it's safe to check parameters for sanity. */
sewardj35421a32004-07-05 13:12:34 +0000128 vassert(!vex_initdone);
129 vassert(failure_exit);
sewardj35421a32004-07-05 13:12:34 +0000130 vassert(log_bytes);
sewardj35421a32004-07-05 13:12:34 +0000131 vassert(debuglevel >= 0);
sewardj08613742004-10-25 13:01:45 +0000132
133 vassert(vcon->iropt_verbosity >= 0);
134 vassert(vcon->iropt_level >= 0);
135 vassert(vcon->iropt_level <= 2);
136 vassert(vcon->iropt_unroll_thresh >= 0);
137 vassert(vcon->iropt_unroll_thresh <= 400);
138 vassert(vcon->guest_max_insns >= 1);
139 vassert(vcon->guest_max_insns <= 100);
140 vassert(vcon->guest_chase_thresh >= 0);
141 vassert(vcon->guest_chase_thresh < vcon->guest_max_insns);
sewardj984d9b12010-01-15 10:53:21 +0000142 vassert(vcon->guest_chase_cond == True
143 || vcon->guest_chase_cond == False);
sewardj443cd9d2004-07-18 23:06:45 +0000144
sewardjea602bc2004-10-14 21:40:12 +0000145 /* Check that Vex has been built with sizes of basic types as
146 stated in priv/libvex_basictypes.h. Failure of any of these is
147 a serious configuration error and should be corrected
148 immediately. If any of these assertions fail you can fully
149 expect Vex not to work properly, if at all. */
150
151 vassert(1 == sizeof(UChar));
152 vassert(1 == sizeof(Char));
153 vassert(2 == sizeof(UShort));
154 vassert(2 == sizeof(Short));
155 vassert(4 == sizeof(UInt));
156 vassert(4 == sizeof(Int));
157 vassert(8 == sizeof(ULong));
158 vassert(8 == sizeof(Long));
159 vassert(4 == sizeof(Float));
160 vassert(8 == sizeof(Double));
161 vassert(1 == sizeof(Bool));
162 vassert(4 == sizeof(Addr32));
163 vassert(8 == sizeof(Addr64));
sewardjc9a43662004-11-30 18:51:59 +0000164 vassert(16 == sizeof(U128));
sewardj69d98e32010-06-18 08:17:41 +0000165 vassert(16 == sizeof(V128));
sewardjc9069f22012-06-01 16:09:50 +0000166 vassert(32 == sizeof(U256));
sewardjea602bc2004-10-14 21:40:12 +0000167
168 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
169 vassert(sizeof(void*) == sizeof(int*));
170 vassert(sizeof(void*) == sizeof(HWord));
171
sewardj97e87932005-02-07 00:00:50 +0000172 vassert(VEX_HOST_WORDSIZE == sizeof(void*));
173 vassert(VEX_HOST_WORDSIZE == sizeof(HWord));
174
sewardjc6f970f2012-04-02 21:54:49 +0000175 /* These take a lot of space, so make sure we don't have
176 any unnoticed size regressions. */
177 if (VEX_HOST_WORDSIZE == 4) {
florian420bfa92012-06-02 20:29:22 +0000178 vassert(sizeof(IRExpr) == 16);
sewardjc6f970f2012-04-02 21:54:49 +0000179 vassert(sizeof(IRStmt) == 20 /* x86 */
180 || sizeof(IRStmt) == 24 /* arm */);
181 } else {
florian420bfa92012-06-02 20:29:22 +0000182 vassert(sizeof(IRExpr) == 32);
floriand6f38b32012-05-31 15:46:18 +0000183 vassert(sizeof(IRStmt) == 32);
sewardjc6f970f2012-04-02 21:54:49 +0000184 }
185
sewardj8bde7f12013-04-11 13:57:43 +0000186 /* Check that signed integer division on the host rounds towards
187 zero. If not, h_calc_sdiv32_w_arm_semantics() won't work
188 correctly. */
189 /* 100.0 / 7.0 == 14.2857 */
190 vassert(udiv32(100, 7) == 14);
191 vassert(sdiv32(100, 7) == 14);
192 vassert(sdiv32(-100, 7) == -14); /* and not -15 */
193 vassert(sdiv32(100, -7) == -14); /* ditto */
194 vassert(sdiv32(-100, -7) == 14); /* not sure what this proves */
195
sewardjea602bc2004-10-14 21:40:12 +0000196 /* Really start up .. */
sewardj443cd9d2004-07-18 23:06:45 +0000197 vex_debuglevel = debuglevel;
sewardj443cd9d2004-07-18 23:06:45 +0000198 vex_valgrind_support = valgrind_support;
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;
sewardjfb7373a2007-08-25 21:29:03 +0000216 Bool (*isMove) ( HInstr*, HReg*, HReg* );
217 void (*getRegUsage) ( HRegUsage*, HInstr*, Bool );
218 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 );
222 void (*ppInstr) ( HInstr*, Bool );
223 void (*ppReg) ( HReg );
sewardjc6f970f2012-04-02 21:54:49 +0000224 HInstrArray* (*iselSB) ( IRSB*, VexArch, VexArchInfo*, VexAbiInfo*,
225 Int, Int, Bool, Bool, Addr64 );
226 Int (*emit) ( /*MB_MOD*/Bool*,
sewardj9b769162014-07-24 12:42:03 +0000227 UChar*, Int, HInstr*, Bool, VexEndness,
sewardjc6f970f2012-04-02 21:54:49 +0000228 void*, void*, void*, 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 );
sewardjfb7373a2007-08-25 21:29:03 +0000301 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000302 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
303 getRegUsage_X86Instr;
sewardjfb7373a2007-08-25 21:29:03 +0000304 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000305 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
306 genSpill_X86;
307 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
308 genReload_X86;
sewardjfb7373a2007-08-25 21:29:03 +0000309 directReload = (HInstr*(*)(HInstr*,HReg,Short)) directReload_X86;
310 ppInstr = (void(*)(HInstr*, Bool)) ppX86Instr;
311 ppReg = (void(*)(HReg)) ppHRegX86;
312 iselSB = iselSB_X86;
sewardj9b769162014-07-24 12:42:03 +0000313 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,VexEndness,
sewardjc6f970f2012-04-02 21:54:49 +0000314 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000315 emit_X86Instr;
sewardjcf787902004-11-03 09:08:33 +0000316 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000317 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_host.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000318 vassert(vta->archinfo_host.endness == VexEndnessLE);
sewardjf13a16a2004-07-05 17:10:14 +0000319 break;
sewardj2a9ad022004-11-25 02:46:58 +0000320
sewardjc33671d2005-02-01 20:30:00 +0000321 case VexArchAMD64:
cerion92b64362005-12-13 12:02:26 +0000322 mode64 = True;
sewardjc33671d2005-02-01 20:30:00 +0000323 getAllocableRegs_AMD64 ( &n_available_real_regs,
324 &available_real_regs );
325 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000326 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
327 getRegUsage_AMD64Instr;
cerion92b64362005-12-13 12:02:26 +0000328 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000329 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
330 genSpill_AMD64;
331 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
332 genReload_AMD64;
cerion92b64362005-12-13 12:02:26 +0000333 ppInstr = (void(*)(HInstr*, Bool)) ppAMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000334 ppReg = (void(*)(HReg)) ppHRegAMD64;
sewardjdd40fdf2006-12-24 02:20:24 +0000335 iselSB = iselSB_AMD64;
sewardj9b769162014-07-24 12:42:03 +0000336 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,VexEndness,
sewardjc6f970f2012-04-02 21:54:49 +0000337 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000338 emit_AMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000339 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000340 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_host.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000341 vassert(vta->archinfo_host.endness == VexEndnessLE);
sewardjc33671d2005-02-01 20:30:00 +0000342 break;
343
cerion487e4c92005-02-04 16:28:19 +0000344 case VexArchPPC32:
cerion92b64362005-12-13 12:02:26 +0000345 mode64 = False;
cerion5b2325f2005-12-23 00:55:09 +0000346 getAllocableRegs_PPC ( &n_available_real_regs,
347 &available_real_regs, mode64 );
348 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
349 getRegUsage = (void(*)(HRegUsage*,HInstr*,Bool)) getRegUsage_PPCInstr;
350 mapRegs = (void(*)(HRegRemap*,HInstr*,Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000351 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
352 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000353 ppInstr = (void(*)(HInstr*,Bool)) ppPPCInstr;
354 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000355 iselSB = iselSB_PPC;
sewardj9b769162014-07-24 12:42:03 +0000356 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,VexEndness,
sewardj3dee8492012-04-20 00:13:28 +0000357 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000358 emit_PPCInstr;
cerion487e4c92005-02-04 16:28:19 +0000359 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000360 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_host.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000361 vassert(vta->archinfo_host.endness == VexEndnessBE);
cerion487e4c92005-02-04 16:28:19 +0000362 break;
363
cerionf0de28c2005-12-13 20:21:11 +0000364 case VexArchPPC64:
365 mode64 = True;
cerion5b2325f2005-12-23 00:55:09 +0000366 getAllocableRegs_PPC ( &n_available_real_regs,
367 &available_real_regs, mode64 );
368 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
369 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_PPCInstr;
370 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000371 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
372 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000373 ppInstr = (void(*)(HInstr*, Bool)) ppPPCInstr;
374 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000375 iselSB = iselSB_PPC;
sewardj9b769162014-07-24 12:42:03 +0000376 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,VexEndness,
sewardj9e1cf152012-04-20 02:18:31 +0000377 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000378 emit_PPCInstr;
cerionf0de28c2005-12-13 20:21:11 +0000379 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000380 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_host.hwcaps));
carll1f5fe1f2014-08-07 23:25:23 +0000381 vassert(vta->archinfo_host.endness == VexEndnessBE ||
382 vta->archinfo_host.endness == VexEndnessLE );
cerionf0de28c2005-12-13 20:21:11 +0000383 break;
384
sewardj2019a972011-03-07 16:04:07 +0000385 case VexArchS390X:
386 mode64 = True;
387 getAllocableRegs_S390 ( &n_available_real_regs,
388 &available_real_regs, mode64 );
389 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_S390Instr;
390 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_S390Instr;
391 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_S390Instr;
392 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_S390;
393 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_S390;
394 ppInstr = (void(*)(HInstr*, Bool)) ppS390Instr;
395 ppReg = (void(*)(HReg)) ppHRegS390;
396 iselSB = iselSB_S390;
sewardj9b769162014-07-24 12:42:03 +0000397 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,VexEndness,
florian8844a632012-04-13 04:04:06 +0000398 void*,void*,void*,void*)) emit_S390Instr;
sewardj2019a972011-03-07 16:04:07 +0000399 host_word_type = Ity_I64;
400 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_host.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000401 vassert(vta->archinfo_host.endness == VexEndnessBE);
sewardj2019a972011-03-07 16:04:07 +0000402 break;
403
sewardj6c299f32009-12-31 18:00:12 +0000404 case VexArchARM:
sewardj2a1ed8e2009-12-31 19:26:03 +0000405 mode64 = False;
sewardj6c299f32009-12-31 18:00:12 +0000406 getAllocableRegs_ARM ( &n_available_real_regs,
407 &available_real_regs );
sewardj2a1ed8e2009-12-31 19:26:03 +0000408 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARMInstr;
409 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_ARMInstr;
410 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_ARMInstr;
411 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_ARM;
412 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_ARM;
413 ppInstr = (void(*)(HInstr*, Bool)) ppARMInstr;
414 ppReg = (void(*)(HReg)) ppHRegARM;
415 iselSB = iselSB_ARM;
sewardj9b769162014-07-24 12:42:03 +0000416 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,VexEndness,
sewardjc6f970f2012-04-02 21:54:49 +0000417 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000418 emit_ARMInstr;
sewardj6c299f32009-12-31 18:00:12 +0000419 host_word_type = Ity_I32;
420 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_host.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000421 vassert(vta->archinfo_host.endness == VexEndnessLE);
sewardj6c299f32009-12-31 18:00:12 +0000422 break;
423
sewardjbbcf1882014-01-12 12:49:10 +0000424 case VexArchARM64:
425 mode64 = True;
426 getAllocableRegs_ARM64 ( &n_available_real_regs,
427 &available_real_regs );
428 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARM64Instr;
429 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
430 getRegUsage_ARM64Instr;
431 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool))
432 mapRegs_ARM64Instr;
433 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
434 genSpill_ARM64;
435 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
436 genReload_ARM64;
437 ppInstr = (void(*)(HInstr*, Bool)) ppARM64Instr;
438 ppReg = (void(*)(HReg)) ppHRegARM64;
439 iselSB = iselSB_ARM64;
sewardj9b769162014-07-24 12:42:03 +0000440 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,VexEndness,
sewardjbbcf1882014-01-12 12:49:10 +0000441 void*,void*,void*,void*))
442 emit_ARM64Instr;
sewardjbbcf1882014-01-12 12:49:10 +0000443 host_word_type = Ity_I64;
444 vassert(are_valid_hwcaps(VexArchARM64, vta->archinfo_host.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000445 vassert(vta->archinfo_host.endness == VexEndnessLE);
sewardjbbcf1882014-01-12 12:49:10 +0000446 break;
447
sewardjd0e5fe72012-06-07 08:51:02 +0000448 case VexArchMIPS32:
449 mode64 = False;
450 getAllocableRegs_MIPS ( &n_available_real_regs,
451 &available_real_regs, mode64 );
452 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_MIPSInstr;
453 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_MIPSInstr;
454 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_MIPSInstr;
455 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_MIPS;
456 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_MIPS;
457 ppInstr = (void(*)(HInstr*, Bool)) ppMIPSInstr;
458 ppReg = (void(*)(HReg)) ppHRegMIPS;
459 iselSB = iselSB_MIPS;
sewardj9b769162014-07-24 12:42:03 +0000460 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,VexEndness,
sewardjd0e5fe72012-06-07 08:51:02 +0000461 void*,void*,void*,void*))
462 emit_MIPSInstr;
sewardjd0e5fe72012-06-07 08:51:02 +0000463 host_word_type = Ity_I32;
464 vassert(are_valid_hwcaps(VexArchMIPS32, vta->archinfo_host.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000465 vassert(vta->archinfo_host.endness == VexEndnessLE
466 || vta->archinfo_host.endness == VexEndnessBE);
sewardjd0e5fe72012-06-07 08:51:02 +0000467 break;
468
petarjb92a9542013-02-27 22:57:17 +0000469 case VexArchMIPS64:
470 mode64 = True;
471 getAllocableRegs_MIPS ( &n_available_real_regs,
472 &available_real_regs, mode64 );
473 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_MIPSInstr;
474 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_MIPSInstr;
475 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_MIPSInstr;
476 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_MIPS;
477 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_MIPS;
478 ppInstr = (void(*)(HInstr*, Bool)) ppMIPSInstr;
479 ppReg = (void(*)(HReg)) ppHRegMIPS;
480 iselSB = iselSB_MIPS;
sewardj9b769162014-07-24 12:42:03 +0000481 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,VexEndness,
petarjb92a9542013-02-27 22:57:17 +0000482 void*,void*,void*,void*))
483 emit_MIPSInstr;
petarjb92a9542013-02-27 22:57:17 +0000484 host_word_type = Ity_I64;
485 vassert(are_valid_hwcaps(VexArchMIPS64, vta->archinfo_host.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000486 vassert(vta->archinfo_host.endness == VexEndnessLE
487 || vta->archinfo_host.endness == VexEndnessBE);
petarjb92a9542013-02-27 22:57:17 +0000488 break;
489
sewardjf13a16a2004-07-05 17:10:14 +0000490 default:
sewardj6c299f32009-12-31 18:00:12 +0000491 vpanic("LibVEX_Translate: unsupported host insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000492 }
493
sewardj2a9ad022004-11-25 02:46:58 +0000494
sewardj17c7f952005-12-15 14:02:34 +0000495 switch (vta->arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000496
sewardjbef170b2004-12-21 01:23:00 +0000497 case VexArchX86:
sewardjc6f970f2012-04-02 21:54:49 +0000498 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
499 disInstrFn = disInstr_X86;
500 specHelper = guest_x86_spechelper;
501 guest_sizeB = sizeof(VexGuestX86State);
502 guest_word_type = Ity_I32;
503 guest_layout = &x86guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000504 offB_CMSTART = offsetof(VexGuestX86State,guest_CMSTART);
505 offB_CMLEN = offsetof(VexGuestX86State,guest_CMLEN);
sewardjc6f970f2012-04-02 21:54:49 +0000506 offB_GUEST_IP = offsetof(VexGuestX86State,guest_EIP);
507 szB_GUEST_IP = sizeof( ((VexGuestX86State*)0)->guest_EIP );
508 offB_HOST_EvC_COUNTER = offsetof(VexGuestX86State,host_EvC_COUNTER);
509 offB_HOST_EvC_FAILADDR = offsetof(VexGuestX86State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000510 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_guest.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000511 vassert(vta->archinfo_guest.endness == VexEndnessLE);
sewardj6c299f32009-12-31 18:00:12 +0000512 vassert(0 == sizeof(VexGuestX86State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000513 vassert(sizeof( ((VexGuestX86State*)0)->guest_CMSTART) == 4);
514 vassert(sizeof( ((VexGuestX86State*)0)->guest_CMLEN ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000515 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000516 break;
sewardj2a9ad022004-11-25 02:46:58 +0000517
sewardj44d494d2005-01-20 20:26:33 +0000518 case VexArchAMD64:
sewardjc6f970f2012-04-02 21:54:49 +0000519 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
520 disInstrFn = disInstr_AMD64;
521 specHelper = guest_amd64_spechelper;
522 guest_sizeB = sizeof(VexGuestAMD64State);
523 guest_word_type = Ity_I64;
524 guest_layout = &amd64guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000525 offB_CMSTART = offsetof(VexGuestAMD64State,guest_CMSTART);
526 offB_CMLEN = offsetof(VexGuestAMD64State,guest_CMLEN);
sewardjc6f970f2012-04-02 21:54:49 +0000527 offB_GUEST_IP = offsetof(VexGuestAMD64State,guest_RIP);
528 szB_GUEST_IP = sizeof( ((VexGuestAMD64State*)0)->guest_RIP );
529 offB_HOST_EvC_COUNTER = offsetof(VexGuestAMD64State,host_EvC_COUNTER);
530 offB_HOST_EvC_FAILADDR = offsetof(VexGuestAMD64State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000531 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_guest.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000532 vassert(vta->archinfo_guest.endness == VexEndnessLE);
sewardj6c299f32009-12-31 18:00:12 +0000533 vassert(0 == sizeof(VexGuestAMD64State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000534 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_CMSTART ) == 8);
535 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_CMLEN ) == 8);
sewardjce02aa72006-01-12 12:27:58 +0000536 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000537 break;
538
cerionaabdfbf2005-01-29 12:56:15 +0000539 case VexArchPPC32:
sewardj3dee8492012-04-20 00:13:28 +0000540 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
541 disInstrFn = disInstr_PPC;
542 specHelper = guest_ppc32_spechelper;
543 guest_sizeB = sizeof(VexGuestPPC32State);
544 guest_word_type = Ity_I32;
545 guest_layout = &ppc32Guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000546 offB_CMSTART = offsetof(VexGuestPPC32State,guest_CMSTART);
547 offB_CMLEN = offsetof(VexGuestPPC32State,guest_CMLEN);
sewardj3dee8492012-04-20 00:13:28 +0000548 offB_GUEST_IP = offsetof(VexGuestPPC32State,guest_CIA);
549 szB_GUEST_IP = sizeof( ((VexGuestPPC32State*)0)->guest_CIA );
550 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC32State,host_EvC_COUNTER);
551 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC32State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000552 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_guest.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000553 vassert(vta->archinfo_guest.endness == VexEndnessBE);
sewardj6c299f32009-12-31 18:00:12 +0000554 vassert(0 == sizeof(VexGuestPPC32State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000555 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_CMSTART ) == 4);
556 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_CMLEN ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000557 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000558 break;
559
cerionf0de28c2005-12-13 20:21:11 +0000560 case VexArchPPC64:
sewardj9e1cf152012-04-20 02:18:31 +0000561 preciseMemExnsFn = guest_ppc64_state_requires_precise_mem_exns;
562 disInstrFn = disInstr_PPC;
563 specHelper = guest_ppc64_spechelper;
564 guest_sizeB = sizeof(VexGuestPPC64State);
565 guest_word_type = Ity_I64;
566 guest_layout = &ppc64Guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000567 offB_CMSTART = offsetof(VexGuestPPC64State,guest_CMSTART);
568 offB_CMLEN = offsetof(VexGuestPPC64State,guest_CMLEN);
sewardj9e1cf152012-04-20 02:18:31 +0000569 offB_GUEST_IP = offsetof(VexGuestPPC64State,guest_CIA);
570 szB_GUEST_IP = sizeof( ((VexGuestPPC64State*)0)->guest_CIA );
571 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC64State,host_EvC_COUNTER);
572 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC64State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000573 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_guest.hwcaps));
carll1f5fe1f2014-08-07 23:25:23 +0000574 vassert(vta->archinfo_guest.endness == VexEndnessBE ||
575 vta->archinfo_guest.endness == VexEndnessLE );
cerionf0de28c2005-12-13 20:21:11 +0000576 vassert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000577 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_CMSTART ) == 8);
578 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_CMLEN ) == 8);
sewardj3fd39672006-01-27 22:05:55 +0000579 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8);
580 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8);
cerionf0de28c2005-12-13 20:21:11 +0000581 break;
582
sewardj2019a972011-03-07 16:04:07 +0000583 case VexArchS390X:
584 preciseMemExnsFn = guest_s390x_state_requires_precise_mem_exns;
585 disInstrFn = disInstr_S390;
586 specHelper = guest_s390x_spechelper;
587 guest_sizeB = sizeof(VexGuestS390XState);
588 guest_word_type = Ity_I64;
589 guest_layout = &s390xGuest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000590 offB_CMSTART = offsetof(VexGuestS390XState,guest_CMSTART);
591 offB_CMLEN = offsetof(VexGuestS390XState,guest_CMLEN);
florian8844a632012-04-13 04:04:06 +0000592 offB_GUEST_IP = offsetof(VexGuestS390XState,guest_IA);
593 szB_GUEST_IP = sizeof( ((VexGuestS390XState*)0)->guest_IA);
594 offB_HOST_EvC_COUNTER = offsetof(VexGuestS390XState,host_EvC_COUNTER);
595 offB_HOST_EvC_FAILADDR = offsetof(VexGuestS390XState,host_EvC_FAILADDR);
sewardj2019a972011-03-07 16:04:07 +0000596 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_guest.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000597 vassert(vta->archinfo_guest.endness == VexEndnessBE);
sewardj2019a972011-03-07 16:04:07 +0000598 vassert(0 == sizeof(VexGuestS390XState) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000599 vassert(sizeof( ((VexGuestS390XState*)0)->guest_CMSTART ) == 8);
600 vassert(sizeof( ((VexGuestS390XState*)0)->guest_CMLEN ) == 8);
sewardj2019a972011-03-07 16:04:07 +0000601 vassert(sizeof( ((VexGuestS390XState*)0)->guest_NRADDR ) == 8);
602 break;
603
sewardj6c299f32009-12-31 18:00:12 +0000604 case VexArchARM:
sewardjc6f970f2012-04-02 21:54:49 +0000605 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
606 disInstrFn = disInstr_ARM;
607 specHelper = guest_arm_spechelper;
608 guest_sizeB = sizeof(VexGuestARMState);
609 guest_word_type = Ity_I32;
610 guest_layout = &armGuest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000611 offB_CMSTART = offsetof(VexGuestARMState,guest_CMSTART);
612 offB_CMLEN = offsetof(VexGuestARMState,guest_CMLEN);
sewardjc6f970f2012-04-02 21:54:49 +0000613 offB_GUEST_IP = offsetof(VexGuestARMState,guest_R15T);
614 szB_GUEST_IP = sizeof( ((VexGuestARMState*)0)->guest_R15T );
615 offB_HOST_EvC_COUNTER = offsetof(VexGuestARMState,host_EvC_COUNTER);
616 offB_HOST_EvC_FAILADDR = offsetof(VexGuestARMState,host_EvC_FAILADDR);
sewardj6c299f32009-12-31 18:00:12 +0000617 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_guest.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000618 vassert(vta->archinfo_guest.endness == VexEndnessLE);
sewardj6c299f32009-12-31 18:00:12 +0000619 vassert(0 == sizeof(VexGuestARMState) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000620 vassert(sizeof( ((VexGuestARMState*)0)->guest_CMSTART) == 4);
621 vassert(sizeof( ((VexGuestARMState*)0)->guest_CMLEN ) == 4);
sewardj6c299f32009-12-31 18:00:12 +0000622 vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4);
623 break;
624
sewardjbbcf1882014-01-12 12:49:10 +0000625 case VexArchARM64:
626 preciseMemExnsFn = guest_arm64_state_requires_precise_mem_exns;
627 disInstrFn = disInstr_ARM64;
628 specHelper = guest_arm64_spechelper;
629 guest_sizeB = sizeof(VexGuestARM64State);
630 guest_word_type = Ity_I64;
631 guest_layout = &arm64Guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000632 offB_CMSTART = offsetof(VexGuestARM64State,guest_CMSTART);
633 offB_CMLEN = offsetof(VexGuestARM64State,guest_CMLEN);
sewardjbbcf1882014-01-12 12:49:10 +0000634 offB_GUEST_IP = offsetof(VexGuestARM64State,guest_PC);
635 szB_GUEST_IP = sizeof( ((VexGuestARM64State*)0)->guest_PC );
636 offB_HOST_EvC_COUNTER = offsetof(VexGuestARM64State,host_EvC_COUNTER);
637 offB_HOST_EvC_FAILADDR = offsetof(VexGuestARM64State,host_EvC_FAILADDR);
638 vassert(are_valid_hwcaps(VexArchARM64, vta->archinfo_guest.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000639 vassert(vta->archinfo_guest.endness == VexEndnessLE);
sewardjbbcf1882014-01-12 12:49:10 +0000640 vassert(0 == sizeof(VexGuestARM64State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000641 vassert(sizeof( ((VexGuestARM64State*)0)->guest_CMSTART) == 8);
642 vassert(sizeof( ((VexGuestARM64State*)0)->guest_CMLEN ) == 8);
sewardjbbcf1882014-01-12 12:49:10 +0000643 vassert(sizeof( ((VexGuestARM64State*)0)->guest_NRADDR ) == 8);
644 break;
645
sewardjd0e5fe72012-06-07 08:51:02 +0000646 case VexArchMIPS32:
647 preciseMemExnsFn = guest_mips32_state_requires_precise_mem_exns;
648 disInstrFn = disInstr_MIPS;
649 specHelper = guest_mips32_spechelper;
650 guest_sizeB = sizeof(VexGuestMIPS32State);
651 guest_word_type = Ity_I32;
652 guest_layout = &mips32Guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000653 offB_CMSTART = offsetof(VexGuestMIPS32State,guest_CMSTART);
654 offB_CMLEN = offsetof(VexGuestMIPS32State,guest_CMLEN);
sewardjd0e5fe72012-06-07 08:51:02 +0000655 offB_GUEST_IP = offsetof(VexGuestMIPS32State,guest_PC);
656 szB_GUEST_IP = sizeof( ((VexGuestMIPS32State*)0)->guest_PC );
657 offB_HOST_EvC_COUNTER = offsetof(VexGuestMIPS32State,host_EvC_COUNTER);
658 offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS32State,host_EvC_FAILADDR);
659 vassert(are_valid_hwcaps(VexArchMIPS32, vta->archinfo_guest.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000660 vassert(vta->archinfo_guest.endness == VexEndnessLE
661 || vta->archinfo_guest.endness == VexEndnessBE);
sewardjd0e5fe72012-06-07 08:51:02 +0000662 vassert(0 == sizeof(VexGuestMIPS32State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000663 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_CMSTART) == 4);
664 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_CMLEN ) == 4);
sewardjd0e5fe72012-06-07 08:51:02 +0000665 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_NRADDR ) == 4);
666 break;
667
petarjb92a9542013-02-27 22:57:17 +0000668 case VexArchMIPS64:
669 preciseMemExnsFn = guest_mips64_state_requires_precise_mem_exns;
670 disInstrFn = disInstr_MIPS;
671 specHelper = guest_mips64_spechelper;
672 guest_sizeB = sizeof(VexGuestMIPS64State);
673 guest_word_type = Ity_I64;
674 guest_layout = &mips64Guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000675 offB_CMSTART = offsetof(VexGuestMIPS64State,guest_CMSTART);
676 offB_CMLEN = offsetof(VexGuestMIPS64State,guest_CMLEN);
petarjb92a9542013-02-27 22:57:17 +0000677 offB_GUEST_IP = offsetof(VexGuestMIPS64State,guest_PC);
678 szB_GUEST_IP = sizeof( ((VexGuestMIPS64State*)0)->guest_PC );
679 offB_HOST_EvC_COUNTER = offsetof(VexGuestMIPS64State,host_EvC_COUNTER);
680 offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS64State,host_EvC_FAILADDR);
681 vassert(are_valid_hwcaps(VexArchMIPS64, vta->archinfo_guest.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000682 vassert(vta->archinfo_guest.endness == VexEndnessLE
683 || vta->archinfo_guest.endness == VexEndnessBE);
petarjb92a9542013-02-27 22:57:17 +0000684 vassert(0 == sizeof(VexGuestMIPS64State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000685 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_CMSTART) == 8);
686 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_CMLEN ) == 8);
petarjb92a9542013-02-27 22:57:17 +0000687 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_NRADDR ) == 8);
688 break;
689
sewardjf13a16a2004-07-05 17:10:14 +0000690 default:
sewardj887a11a2004-07-05 17:26:47 +0000691 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000692 }
693
sewardjbc161a42011-06-07 21:28:38 +0000694 /* Set up result struct. */
695 VexTranslateResult res;
sewardjfadbbe22012-04-24 11:49:03 +0000696 res.status = VexTransOK;
697 res.n_sc_extents = 0;
698 res.offs_profInc = -1;
699 res.n_guest_instrs = 0;
sewardjbc161a42011-06-07 21:28:38 +0000700
sewardj9df271d2004-12-31 22:37:42 +0000701 /* yet more sanity checks ... */
sewardj17c7f952005-12-15 14:02:34 +0000702 if (vta->arch_guest == vta->arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000703 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000704 we are simulating one flavour of an architecture a different
705 flavour of the same architecture, which is pretty strange. */
sewardj5117ce12006-01-27 21:20:15 +0000706 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps);
sewardj9b769162014-07-24 12:42:03 +0000707 /* ditto */
708 vassert(vta->archinfo_guest.endness == vta->archinfo_host.endness);
sewardj9df271d2004-12-31 22:37:42 +0000709 }
sewardj2a9ad022004-11-25 02:46:58 +0000710
sewardj2d6b14a2005-11-23 04:25:07 +0000711 vexAllocSanityCheck();
712
sewardjf48ac192004-10-29 00:41:29 +0000713 if (vex_traceflags & VEX_TRACE_FE)
714 vex_printf("\n------------------------"
715 " Front end "
716 "------------------------\n\n");
717
sewardjdd40fdf2006-12-24 02:20:24 +0000718 irsb = bb_to_IR ( vta->guest_extents,
sewardjbc161a42011-06-07 21:28:38 +0000719 &res.n_sc_extents,
sewardjfadbbe22012-04-24 11:49:03 +0000720 &res.n_guest_instrs,
sewardjc716aea2006-01-17 01:48:46 +0000721 vta->callback_opaque,
sewardj9e6491a2005-07-02 19:24:10 +0000722 disInstrFn,
sewardj17c7f952005-12-15 14:02:34 +0000723 vta->guest_bytes,
724 vta->guest_bytes_addr,
725 vta->chase_into_ok,
sewardj9b769162014-07-24 12:42:03 +0000726 vta->archinfo_host.endness,
sewardj442e51a2012-12-06 18:08:04 +0000727 vta->sigill_diag,
sewardja5f55da2006-04-30 23:37:32 +0000728 vta->arch_guest,
sewardj17c7f952005-12-15 14:02:34 +0000729 &vta->archinfo_guest,
sewardjdd40fdf2006-12-24 02:20:24 +0000730 &vta->abiinfo_both,
sewardjdb4738a2005-07-07 01:32:16 +0000731 guest_word_type,
sewardjbc161a42011-06-07 21:28:38 +0000732 vta->needs_self_check,
sewardjc716aea2006-01-17 01:48:46 +0000733 vta->preamble_function,
sewardj05f5e012014-05-04 10:52:11 +0000734 offB_CMSTART,
735 offB_CMLEN,
sewardjc6f970f2012-04-02 21:54:49 +0000736 offB_GUEST_IP,
737 szB_GUEST_IP );
sewardjf13a16a2004-07-05 17:10:14 +0000738
sewardj2d6b14a2005-11-23 04:25:07 +0000739 vexAllocSanityCheck();
740
sewardjdd40fdf2006-12-24 02:20:24 +0000741 if (irsb == NULL) {
sewardjf13a16a2004-07-05 17:10:14 +0000742 /* Access failure. */
sewardj2d6b14a2005-11-23 04:25:07 +0000743 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000744 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000745 res.status = VexTransAccessFail; return res;
sewardjf13a16a2004-07-05 17:10:14 +0000746 }
sewardjaa59f942004-10-09 09:34:36 +0000747
sewardj17c7f952005-12-15 14:02:34 +0000748 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3);
749 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr);
750 for (i = 0; i < vta->guest_extents->n_used; i++) {
751 vassert(vta->guest_extents->len[i] < 10000); /* sanity */
sewardj72c72812005-01-19 11:49:45 +0000752 }
753
sewardjaa59f942004-10-09 09:34:36 +0000754 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000755 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj17c7f952005-12-15 14:02:34 +0000756 if (vta->guest_extents->n_used > 1) {
sewardj72c72812005-01-19 11:49:45 +0000757 vex_printf("can't show code due to extents > 1\n");
758 } else {
759 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000760 UChar* p = (UChar*)vta->guest_bytes;
sewardj01f8cce2009-08-31 08:50:02 +0000761 UInt sum = 0;
sewardj17c7f952005-12-15 14:02:34 +0000762 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0];
sewardj01f8cce2009-08-31 08:50:02 +0000763 vex_printf("GuestBytes %llx %u ", vta->guest_bytes_addr,
764 guest_bytes_read );
765 for (i = 0; i < guest_bytes_read; i++) {
766 UInt b = (UInt)p[i];
767 vex_printf(" %02x", b );
768 sum = (sum << 1) ^ b;
769 }
770 vex_printf(" %08x\n\n", sum);
sewardj72c72812005-01-19 11:49:45 +0000771 }
sewardjaa59f942004-10-09 09:34:36 +0000772 }
773
774 /* Sanity check the initial IR. */
sewardjdd40fdf2006-12-24 02:20:24 +0000775 sanityCheckIRSB( irsb, "initial IR",
sewardjb9230752004-12-29 19:25:06 +0000776 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000777
sewardj2d6b14a2005-11-23 04:25:07 +0000778 vexAllocSanityCheck();
779
sewardjedf4d692004-08-17 13:52:58 +0000780 /* Clean it up, hopefully a lot. */
sewardjdd40fdf2006-12-24 02:20:24 +0000781 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn,
sewardjec0d9a02010-08-22 12:54:56 +0000782 vta->guest_bytes_addr,
783 vta->arch_guest );
sewardjdd40fdf2006-12-24 02:20:24 +0000784 sanityCheckIRSB( irsb, "after initial iropt",
sewardjb9230752004-12-29 19:25:06 +0000785 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000786
sewardjf48ac192004-10-29 00:41:29 +0000787 if (vex_traceflags & VEX_TRACE_OPT1) {
788 vex_printf("\n------------------------"
789 " After pre-instr IR optimisation "
790 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000791 ppIRSB ( irsb );
sewardjedf4d692004-08-17 13:52:58 +0000792 vex_printf("\n");
793 }
794
sewardj2d6b14a2005-11-23 04:25:07 +0000795 vexAllocSanityCheck();
796
sewardjf13a16a2004-07-05 17:10:14 +0000797 /* Get the thing instrumented. */
sewardj17c7f952005-12-15 14:02:34 +0000798 if (vta->instrument1)
sewardjdd40fdf2006-12-24 02:20:24 +0000799 irsb = vta->instrument1(vta->callback_opaque,
800 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000801 vta->guest_extents,
florian50481922012-10-07 21:58:07 +0000802 &vta->archinfo_host,
sewardj17c7f952005-12-15 14:02:34 +0000803 guest_word_type, host_word_type);
sewardj2d6b14a2005-11-23 04:25:07 +0000804 vexAllocSanityCheck();
805
sewardj17c7f952005-12-15 14:02:34 +0000806 if (vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000807 irsb = vta->instrument2(vta->callback_opaque,
808 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000809 vta->guest_extents,
florian50481922012-10-07 21:58:07 +0000810 &vta->archinfo_host,
sewardj17c7f952005-12-15 14:02:34 +0000811 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000812
sewardjf48ac192004-10-29 00:41:29 +0000813 if (vex_traceflags & VEX_TRACE_INST) {
814 vex_printf("\n------------------------"
815 " After instrumentation "
816 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000817 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000818 vex_printf("\n");
819 }
820
sewardj17c7f952005-12-15 14:02:34 +0000821 if (vta->instrument1 || vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000822 sanityCheckIRSB( irsb, "after instrumentation",
sewardjb9230752004-12-29 19:25:06 +0000823 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000824
sewardj9578a8b2004-11-04 19:44:48 +0000825 /* Do a post-instrumentation cleanup pass. */
sewardj17c7f952005-12-15 14:02:34 +0000826 if (vta->instrument1 || vta->instrument2) {
sewardjdd40fdf2006-12-24 02:20:24 +0000827 do_deadcode_BB( irsb );
828 irsb = cprop_BB( irsb );
829 do_deadcode_BB( irsb );
830 sanityCheckIRSB( irsb, "after post-instrumentation cleanup",
sewardjb9230752004-12-29 19:25:06 +0000831 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000832 }
833
sewardj2d6b14a2005-11-23 04:25:07 +0000834 vexAllocSanityCheck();
835
sewardj9578a8b2004-11-04 19:44:48 +0000836 if (vex_traceflags & VEX_TRACE_OPT2) {
837 vex_printf("\n------------------------"
838 " After post-instr IR optimisation "
839 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000840 ppIRSB ( irsb );
sewardj9578a8b2004-11-04 19:44:48 +0000841 vex_printf("\n");
842 }
843
sewardjf9517d02005-11-28 13:39:37 +0000844 /* Turn it into virtual-registerised code. Build trees -- this
845 also throws away any dead bindings. */
florian62140c12013-01-20 03:51:04 +0000846 max_ga = ado_treebuild_BB( irsb, preciseMemExnsFn );
sewardjf48ac192004-10-29 00:41:29 +0000847
sewardjbe1b6ff2007-08-28 06:06:27 +0000848 if (vta->finaltidy) {
849 irsb = vta->finaltidy(irsb);
850 }
851
sewardj2d6b14a2005-11-23 04:25:07 +0000852 vexAllocSanityCheck();
853
sewardjf48ac192004-10-29 00:41:29 +0000854 if (vex_traceflags & VEX_TRACE_TREES) {
855 vex_printf("\n------------------------"
856 " After tree-building "
857 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000858 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000859 vex_printf("\n");
860 }
861
sewardje908c422005-02-04 21:18:16 +0000862 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000863 if (0) {
864 *(vta->host_bytes_used) = 0;
865 res.status = VexTransOK; return res;
866 }
sewardje908c422005-02-04 21:18:16 +0000867 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000868
sewardjf48ac192004-10-29 00:41:29 +0000869 if (vex_traceflags & VEX_TRACE_VCODE)
870 vex_printf("\n------------------------"
871 " Instruction selection "
872 "------------------------\n");
873
sewardjc6f970f2012-04-02 21:54:49 +0000874 /* No guest has its IP field at offset zero. If this fails it
875 means some transformation pass somewhere failed to update/copy
876 irsb->offsIP properly. */
877 vassert(irsb->offsIP >= 16);
878
879 vcode = iselSB ( irsb, vta->arch_host,
880 &vta->archinfo_host,
881 &vta->abiinfo_both,
882 offB_HOST_EvC_COUNTER,
883 offB_HOST_EvC_FAILADDR,
884 chainingAllowed,
885 vta->addProfInc,
886 max_ga );
sewardjf13a16a2004-07-05 17:10:14 +0000887
sewardj2d6b14a2005-11-23 04:25:07 +0000888 vexAllocSanityCheck();
889
sewardjf48ac192004-10-29 00:41:29 +0000890 if (vex_traceflags & VEX_TRACE_VCODE)
891 vex_printf("\n");
892
sewardjf48ac192004-10-29 00:41:29 +0000893 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000894 for (i = 0; i < vcode->arr_used; i++) {
895 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000896 ppInstr(vcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000897 vex_printf("\n");
898 }
sewardjfbcaf332004-07-08 01:46:01 +0000899 vex_printf("\n");
900 }
sewardjfbcaf332004-07-08 01:46:01 +0000901
sewardjf13a16a2004-07-05 17:10:14 +0000902 /* Register allocate. */
903 rcode = doRegisterAllocation ( vcode, available_real_regs,
cerionf0de28c2005-12-13 20:21:11 +0000904 n_available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000905 isMove, getRegUsage, mapRegs,
sewardjfb7373a2007-08-25 21:29:03 +0000906 genSpill, genReload, directReload,
907 guest_sizeB,
cerion92b64362005-12-13 12:02:26 +0000908 ppInstr, ppReg, mode64 );
sewardjf13a16a2004-07-05 17:10:14 +0000909
sewardj2d6b14a2005-11-23 04:25:07 +0000910 vexAllocSanityCheck();
911
sewardjf48ac192004-10-29 00:41:29 +0000912 if (vex_traceflags & VEX_TRACE_RCODE) {
913 vex_printf("\n------------------------"
914 " Register-allocated code "
915 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000916 for (i = 0; i < rcode->arr_used; i++) {
917 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000918 ppInstr(rcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000919 vex_printf("\n");
920 }
sewardjfbcaf332004-07-08 01:46:01 +0000921 vex_printf("\n");
922 }
sewardjfbcaf332004-07-08 01:46:01 +0000923
sewardje908c422005-02-04 21:18:16 +0000924 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000925 if (0) {
926 *(vta->host_bytes_used) = 0;
927 res.status = VexTransOK; return res;
928 }
sewardje908c422005-02-04 21:18:16 +0000929 /* end HACK */
930
sewardj81bd5502004-07-21 18:49:27 +0000931 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000932 if (vex_traceflags & VEX_TRACE_ASM) {
933 vex_printf("\n------------------------"
934 " Assembly "
935 "------------------------\n\n");
936 }
937
sewardj81bd5502004-07-21 18:49:27 +0000938 out_used = 0; /* tracks along the host_bytes array */
939 for (i = 0; i < rcode->arr_used; i++) {
sewardjc6f970f2012-04-02 21:54:49 +0000940 HInstr* hi = rcode->arr[i];
941 Bool hi_isProfInc = False;
942 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
943 ppInstr(hi, mode64);
sewardjbad34a92004-07-22 01:14:11 +0000944 vex_printf("\n");
945 }
sewardjc6f970f2012-04-02 21:54:49 +0000946 j = emit( &hi_isProfInc,
sewardj9b769162014-07-24 12:42:03 +0000947 insn_bytes, sizeof insn_bytes, hi,
948 mode64, vta->archinfo_host.endness,
sewardjc6f970f2012-04-02 21:54:49 +0000949 vta->disp_cp_chain_me_to_slowEP,
950 vta->disp_cp_chain_me_to_fastEP,
951 vta->disp_cp_xindir,
952 vta->disp_cp_xassisted );
953 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
sewardjbad34a92004-07-22 01:14:11 +0000954 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000955 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000956 vex_printf("0%x ", (UInt)insn_bytes[k]);
957 else
958 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000959 vex_printf("\n\n");
960 }
sewardjc6f970f2012-04-02 21:54:49 +0000961 if (UNLIKELY(out_used + j > vta->host_bytes_size)) {
sewardj2d6b14a2005-11-23 04:25:07 +0000962 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000963 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000964 res.status = VexTransOutputFull;
965 return res;
sewardj81bd5502004-07-21 18:49:27 +0000966 }
sewardjc6f970f2012-04-02 21:54:49 +0000967 if (UNLIKELY(hi_isProfInc)) {
968 vassert(vta->addProfInc); /* else where did it come from? */
969 vassert(res.offs_profInc == -1); /* there can be only one (tm) */
970 vassert(out_used >= 0);
971 res.offs_profInc = out_used;
972 }
973 { UChar* dst = &vta->host_bytes[out_used];
974 for (k = 0; k < j; k++) {
975 dst[k] = insn_bytes[k];
976 }
977 out_used += j;
sewardj81bd5502004-07-21 18:49:27 +0000978 }
sewardj17c7f952005-12-15 14:02:34 +0000979 vassert(out_used <= vta->host_bytes_size);
sewardj81bd5502004-07-21 18:49:27 +0000980 }
sewardj17c7f952005-12-15 14:02:34 +0000981 *(vta->host_bytes_used) = out_used;
sewardj81bd5502004-07-21 18:49:27 +0000982
sewardj2d6b14a2005-11-23 04:25:07 +0000983 vexAllocSanityCheck();
984
985 vexSetAllocModeTEMP_and_clear();
sewardjf13a16a2004-07-05 17:10:14 +0000986
sewardj65ea17e2012-12-28 09:01:59 +0000987 if (vex_traceflags) {
988 /* Print the expansion ratio for this SB. */
989 j = 0; /* total guest bytes */
990 for (i = 0; i < vta->guest_extents->n_used; i++) {
991 j += vta->guest_extents->len[i];
992 }
993 if (1) vex_printf("VexExpansionRatio %d %d %d :10\n\n",
994 j, out_used, (10 * out_used) / (j == 0 ? 1 : j));
995 }
996
sewardjf48ac192004-10-29 00:41:29 +0000997 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000998 res.status = VexTransOK;
999 return res;
sewardj35421a32004-07-05 13:12:34 +00001000}
1001
1002
sewardjc6f970f2012-04-02 21:54:49 +00001003/* --------- Chain/Unchain XDirects. --------- */
1004
sewardj9b769162014-07-24 12:42:03 +00001005VexInvalRange LibVEX_Chain ( VexArch arch_host,
1006 VexEndness endness_host,
1007 void* place_to_chain,
1008 void* disp_cp_chain_me_EXPECTED,
1009 void* place_to_jump_to )
sewardjc6f970f2012-04-02 21:54:49 +00001010{
sewardj9b769162014-07-24 12:42:03 +00001011 VexInvalRange (*chainXDirect)(VexEndness, void*, void*, void*) = NULL;
sewardjc6f970f2012-04-02 21:54:49 +00001012 switch (arch_host) {
1013 case VexArchX86:
1014 chainXDirect = chainXDirect_X86; break;
1015 case VexArchAMD64:
1016 chainXDirect = chainXDirect_AMD64; break;
1017 case VexArchARM:
1018 chainXDirect = chainXDirect_ARM; break;
sewardjbbcf1882014-01-12 12:49:10 +00001019 case VexArchARM64:
1020 chainXDirect = chainXDirect_ARM64; break;
florian8844a632012-04-13 04:04:06 +00001021 case VexArchS390X:
1022 chainXDirect = chainXDirect_S390; break;
sewardj3dee8492012-04-20 00:13:28 +00001023 case VexArchPPC32:
sewardj9b769162014-07-24 12:42:03 +00001024 return chainXDirect_PPC(endness_host,
1025 place_to_chain,
sewardj3dee8492012-04-20 00:13:28 +00001026 disp_cp_chain_me_EXPECTED,
1027 place_to_jump_to, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +00001028 case VexArchPPC64:
sewardj9b769162014-07-24 12:42:03 +00001029 return chainXDirect_PPC(endness_host,
1030 place_to_chain,
sewardjf252de52012-04-20 10:42:24 +00001031 disp_cp_chain_me_EXPECTED,
1032 place_to_jump_to, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +00001033 case VexArchMIPS32:
sewardj9b769162014-07-24 12:42:03 +00001034 return chainXDirect_MIPS(endness_host,
1035 place_to_chain,
sewardjd0e5fe72012-06-07 08:51:02 +00001036 disp_cp_chain_me_EXPECTED,
1037 place_to_jump_to, False/*!mode64*/);
petarjb92a9542013-02-27 22:57:17 +00001038 case VexArchMIPS64:
sewardj9b769162014-07-24 12:42:03 +00001039 return chainXDirect_MIPS(endness_host,
1040 place_to_chain,
petarjb92a9542013-02-27 22:57:17 +00001041 disp_cp_chain_me_EXPECTED,
1042 place_to_jump_to, True/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +00001043 default:
1044 vassert(0);
1045 }
1046 vassert(chainXDirect);
1047 VexInvalRange vir
sewardj9b769162014-07-24 12:42:03 +00001048 = chainXDirect(endness_host, place_to_chain,
1049 disp_cp_chain_me_EXPECTED, place_to_jump_to);
sewardjc6f970f2012-04-02 21:54:49 +00001050 return vir;
1051}
1052
sewardj9b769162014-07-24 12:42:03 +00001053VexInvalRange LibVEX_UnChain ( VexArch arch_host,
1054 VexEndness endness_host,
1055 void* place_to_unchain,
1056 void* place_to_jump_to_EXPECTED,
1057 void* disp_cp_chain_me )
sewardjc6f970f2012-04-02 21:54:49 +00001058{
sewardj9b769162014-07-24 12:42:03 +00001059 VexInvalRange (*unchainXDirect)(VexEndness, void*, void*, void*) = NULL;
sewardjc6f970f2012-04-02 21:54:49 +00001060 switch (arch_host) {
1061 case VexArchX86:
1062 unchainXDirect = unchainXDirect_X86; break;
1063 case VexArchAMD64:
1064 unchainXDirect = unchainXDirect_AMD64; break;
1065 case VexArchARM:
1066 unchainXDirect = unchainXDirect_ARM; break;
sewardjc6acaa42014-02-19 17:42:59 +00001067 case VexArchARM64:
1068 unchainXDirect = unchainXDirect_ARM64; break;
florian8844a632012-04-13 04:04:06 +00001069 case VexArchS390X:
1070 unchainXDirect = unchainXDirect_S390; break;
sewardj3dee8492012-04-20 00:13:28 +00001071 case VexArchPPC32:
sewardj9b769162014-07-24 12:42:03 +00001072 return unchainXDirect_PPC(endness_host,
1073 place_to_unchain,
sewardj3dee8492012-04-20 00:13:28 +00001074 place_to_jump_to_EXPECTED,
1075 disp_cp_chain_me, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +00001076 case VexArchPPC64:
sewardj9b769162014-07-24 12:42:03 +00001077 return unchainXDirect_PPC(endness_host,
1078 place_to_unchain,
sewardjf252de52012-04-20 10:42:24 +00001079 place_to_jump_to_EXPECTED,
1080 disp_cp_chain_me, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +00001081 case VexArchMIPS32:
sewardj9b769162014-07-24 12:42:03 +00001082 return unchainXDirect_MIPS(endness_host,
1083 place_to_unchain,
petarjb92a9542013-02-27 22:57:17 +00001084 place_to_jump_to_EXPECTED,
1085 disp_cp_chain_me, False/*!mode64*/);
1086 case VexArchMIPS64:
sewardj9b769162014-07-24 12:42:03 +00001087 return unchainXDirect_MIPS(endness_host,
1088 place_to_unchain,
petarjb92a9542013-02-27 22:57:17 +00001089 place_to_jump_to_EXPECTED,
1090 disp_cp_chain_me, True/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +00001091 default:
1092 vassert(0);
1093 }
1094 vassert(unchainXDirect);
1095 VexInvalRange vir
sewardj9b769162014-07-24 12:42:03 +00001096 = unchainXDirect(endness_host, place_to_unchain,
1097 place_to_jump_to_EXPECTED, disp_cp_chain_me);
sewardjc6f970f2012-04-02 21:54:49 +00001098 return vir;
1099}
1100
sewardj9b769162014-07-24 12:42:03 +00001101Int LibVEX_evCheckSzB ( VexArch arch_host,
1102 VexEndness endness_host )
sewardjc6f970f2012-04-02 21:54:49 +00001103{
1104 static Int cached = 0; /* DO NOT MAKE NON-STATIC */
1105 if (UNLIKELY(cached == 0)) {
1106 switch (arch_host) {
1107 case VexArchX86:
sewardj9b769162014-07-24 12:42:03 +00001108 cached = evCheckSzB_X86(endness_host); break;
sewardjc6f970f2012-04-02 21:54:49 +00001109 case VexArchAMD64:
sewardj9b769162014-07-24 12:42:03 +00001110 cached = evCheckSzB_AMD64(endness_host); break;
sewardjc6f970f2012-04-02 21:54:49 +00001111 case VexArchARM:
sewardj9b769162014-07-24 12:42:03 +00001112 cached = evCheckSzB_ARM(endness_host); break;
sewardjbbcf1882014-01-12 12:49:10 +00001113 case VexArchARM64:
sewardj9b769162014-07-24 12:42:03 +00001114 cached = evCheckSzB_ARM64(endness_host); break;
florian8844a632012-04-13 04:04:06 +00001115 case VexArchS390X:
sewardj9b769162014-07-24 12:42:03 +00001116 cached = evCheckSzB_S390(endness_host); break;
sewardj3dee8492012-04-20 00:13:28 +00001117 case VexArchPPC32:
sewardjf252de52012-04-20 10:42:24 +00001118 case VexArchPPC64:
sewardj9b769162014-07-24 12:42:03 +00001119 cached = evCheckSzB_PPC(endness_host); break;
sewardjd0e5fe72012-06-07 08:51:02 +00001120 case VexArchMIPS32:
petarjb92a9542013-02-27 22:57:17 +00001121 case VexArchMIPS64:
sewardj9b769162014-07-24 12:42:03 +00001122 cached = evCheckSzB_MIPS(endness_host); break;
sewardjc6f970f2012-04-02 21:54:49 +00001123 default:
1124 vassert(0);
1125 }
1126 }
1127 return cached;
1128}
1129
sewardj9b769162014-07-24 12:42:03 +00001130VexInvalRange LibVEX_PatchProfInc ( VexArch arch_host,
1131 VexEndness endness_host,
1132 void* place_to_patch,
1133 ULong* location_of_counter )
sewardjc6f970f2012-04-02 21:54:49 +00001134{
sewardj9b769162014-07-24 12:42:03 +00001135 VexInvalRange (*patchProfInc)(VexEndness,void*,ULong*) = NULL;
sewardjc6f970f2012-04-02 21:54:49 +00001136 switch (arch_host) {
1137 case VexArchX86:
1138 patchProfInc = patchProfInc_X86; break;
1139 case VexArchAMD64:
1140 patchProfInc = patchProfInc_AMD64; break;
1141 case VexArchARM:
1142 patchProfInc = patchProfInc_ARM; break;
sewardj0ad37a92014-08-29 21:58:03 +00001143 case VexArchARM64:
1144 patchProfInc = patchProfInc_ARM64; break;
florian8844a632012-04-13 04:04:06 +00001145 case VexArchS390X:
1146 patchProfInc = patchProfInc_S390; break;
sewardj3dee8492012-04-20 00:13:28 +00001147 case VexArchPPC32:
sewardj9b769162014-07-24 12:42:03 +00001148 return patchProfInc_PPC(endness_host, place_to_patch,
sewardj3dee8492012-04-20 00:13:28 +00001149 location_of_counter, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +00001150 case VexArchPPC64:
sewardj9b769162014-07-24 12:42:03 +00001151 return patchProfInc_PPC(endness_host, place_to_patch,
sewardjf252de52012-04-20 10:42:24 +00001152 location_of_counter, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +00001153 case VexArchMIPS32:
sewardj9b769162014-07-24 12:42:03 +00001154 return patchProfInc_MIPS(endness_host, place_to_patch,
sewardjd0e5fe72012-06-07 08:51:02 +00001155 location_of_counter, False/*!mode64*/);
petarjb92a9542013-02-27 22:57:17 +00001156 case VexArchMIPS64:
sewardj9b769162014-07-24 12:42:03 +00001157 return patchProfInc_MIPS(endness_host, place_to_patch,
petarjb92a9542013-02-27 22:57:17 +00001158 location_of_counter, True/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +00001159 default:
1160 vassert(0);
1161 }
1162 vassert(patchProfInc);
1163 VexInvalRange vir
sewardj9b769162014-07-24 12:42:03 +00001164 = patchProfInc(endness_host, place_to_patch, location_of_counter);
sewardjc6f970f2012-04-02 21:54:49 +00001165 return vir;
1166}
1167
1168
sewardj893aada2004-11-29 19:57:54 +00001169/* --------- Emulation warnings. --------- */
1170
florian1ff47562012-10-21 02:09:51 +00001171const HChar* LibVEX_EmNote_string ( VexEmNote ew )
sewardj893aada2004-11-29 19:57:54 +00001172{
1173 switch (ew) {
florian6ef84be2012-08-26 03:20:07 +00001174 case EmNote_NONE:
sewardj893aada2004-11-29 19:57:54 +00001175 return "none";
1176 case EmWarn_X86_x87exns:
1177 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +00001178 case EmWarn_X86_x87precision:
1179 return "Selection of non-80-bit x87 FP precision";
1180 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +00001181 return "Unmasking SSE FP exceptions";
1182 case EmWarn_X86_fz:
1183 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
1184 case EmWarn_X86_daz:
1185 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +00001186 case EmWarn_X86_acFlag:
1187 return "Setting %eflags.ac (setting noted but ignored)";
sewardj9dd9cf12006-01-20 14:13:55 +00001188 case EmWarn_PPCexns:
1189 return "Unmasking PPC32/64 FP exceptions";
1190 case EmWarn_PPC64_redir_overflow:
1191 return "PPC64 function redirection stack overflow";
1192 case EmWarn_PPC64_redir_underflow:
1193 return "PPC64 function redirection stack underflow";
florian4b8efad2012-09-02 18:07:08 +00001194 case EmWarn_S390X_fpext_rounding:
1195 return "The specified rounding mode cannot be supported. That\n"
1196 " feature requires the floating point extension facility.\n"
1197 " which is not available on this host. Continuing using\n"
1198 " the rounding mode from FPC. Results may differ!";
florianf0fa1be2012-09-18 20:24:38 +00001199 case EmWarn_S390X_invalid_rounding:
1200 return "The specified rounding mode is invalid.\n"
1201 " Continuing using 'round to nearest'. Results may differ!";
floriane75dafa2012-09-01 17:54:09 +00001202 case EmFail_S390X_stfle:
florian4e0083e2012-08-26 03:41:56 +00001203 return "Instruction stfle is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001204 case EmFail_S390X_stckf:
florianc5c669b2012-08-26 14:32:28 +00001205 return "Instruction stckf is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001206 case EmFail_S390X_ecag:
florian8c88cb62012-08-26 18:58:13 +00001207 return "Instruction ecag is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001208 case EmFail_S390X_fpext:
1209 return "Encountered an instruction that requires the floating "
1210 "point extension facility.\n"
1211 " That facility is not available on this host";
florian78d5ef72013-05-11 15:02:58 +00001212 case EmFail_S390X_invalid_PFPO_rounding_mode:
1213 return "The rounding mode specified in GPR 0 for PFPO instruction"
1214 " is invalid";
1215 case EmFail_S390X_invalid_PFPO_function:
1216 return "The function code specified in GPR 0 for PFPO instruction"
1217 " is invalid";
sewardj893aada2004-11-29 19:57:54 +00001218 default:
florian6ef84be2012-08-26 03:20:07 +00001219 vpanic("LibVEX_EmNote_string: unknown warning");
sewardj893aada2004-11-29 19:57:54 +00001220 }
1221}
sewardj35421a32004-07-05 13:12:34 +00001222
sewardj5117ce12006-01-27 21:20:15 +00001223/* ------------------ Arch/HwCaps stuff. ------------------ */
sewardjbef170b2004-12-21 01:23:00 +00001224
1225const HChar* LibVEX_ppVexArch ( VexArch arch )
1226{
1227 switch (arch) {
1228 case VexArch_INVALID: return "INVALID";
1229 case VexArchX86: return "X86";
1230 case VexArchAMD64: return "AMD64";
1231 case VexArchARM: return "ARM";
sewardjbbcf1882014-01-12 12:49:10 +00001232 case VexArchARM64: return "ARM64";
sewardj0ec57c52005-02-01 15:24:10 +00001233 case VexArchPPC32: return "PPC32";
cerionf0de28c2005-12-13 20:21:11 +00001234 case VexArchPPC64: return "PPC64";
sewardj2019a972011-03-07 16:04:07 +00001235 case VexArchS390X: return "S390X";
sewardjd0e5fe72012-06-07 08:51:02 +00001236 case VexArchMIPS32: return "MIPS32";
petarjb92a9542013-02-27 22:57:17 +00001237 case VexArchMIPS64: return "MIPS64";
sewardjbef170b2004-12-21 01:23:00 +00001238 default: return "VexArch???";
1239 }
1240}
1241
sewardj9b769162014-07-24 12:42:03 +00001242const HChar* LibVEX_ppVexEndness ( VexEndness endness )
1243{
1244 switch (endness) {
1245 case VexEndness_INVALID: return "INVALID";
1246 case VexEndnessLE: return "LittleEndian";
1247 case VexEndnessBE: return "BigEndian";
1248 default: return "VexEndness???";
1249 }
1250}
1251
sewardj5117ce12006-01-27 21:20:15 +00001252const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
sewardjbef170b2004-12-21 01:23:00 +00001253{
florian55085f82012-11-21 00:36:55 +00001254 const HChar* str = show_hwcaps(arch,hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001255 return str ? str : "INVALID";
sewardjbef170b2004-12-21 01:23:00 +00001256}
1257
sewardj5117ce12006-01-27 21:20:15 +00001258
sewardj27e1dd62005-06-30 11:49:14 +00001259/* Write default settings info *vai. */
1260void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
1261{
sewardj65902992014-05-03 21:20:56 +00001262 vex_bzero(vai, sizeof(*vai));
sewardj9b769162014-07-24 12:42:03 +00001263 vai->hwcaps = 0;
1264 vai->endness = VexEndness_INVALID;
1265 vai->ppc_icache_line_szB = 0;
1266 vai->ppc_dcbz_szB = 0;
1267 vai->ppc_dcbzl_szB = 0;
sewardj65902992014-05-03 21:20:56 +00001268 vai->arm64_dMinLine_lg2_szB = 0;
1269 vai->arm64_iMinLine_lg2_szB = 0;
florianf192a392012-10-07 19:44:40 +00001270 vai->hwcache_info.num_levels = 0;
1271 vai->hwcache_info.num_caches = 0;
sewardj65902992014-05-03 21:20:56 +00001272 vai->hwcache_info.caches = NULL;
florianf192a392012-10-07 19:44:40 +00001273 vai->hwcache_info.icaches_maintain_coherence = True; // whatever
sewardj27e1dd62005-06-30 11:49:14 +00001274}
1275
sewardjdd40fdf2006-12-24 02:20:24 +00001276/* Write default settings info *vbi. */
1277void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
sewardjaca070a2006-10-17 00:28:22 +00001278{
sewardj65902992014-05-03 21:20:56 +00001279 vex_bzero(vbi, sizeof(*vbi));
sewardjdd40fdf2006-12-24 02:20:24 +00001280 vbi->guest_stack_redzone_size = 0;
sewardj2e28ac42008-12-04 00:05:12 +00001281 vbi->guest_amd64_assume_fs_is_zero = False;
1282 vbi->guest_amd64_assume_gs_is_0x60 = False;
sewardjdd40fdf2006-12-24 02:20:24 +00001283 vbi->guest_ppc_zap_RZ_at_blr = False;
1284 vbi->guest_ppc_zap_RZ_at_bl = NULL;
sewardjdd40fdf2006-12-24 02:20:24 +00001285 vbi->host_ppc_calls_use_fndescrs = False;
sewardjaca070a2006-10-17 00:28:22 +00001286}
1287
sewardj27e1dd62005-06-30 11:49:14 +00001288
sewardj5117ce12006-01-27 21:20:15 +00001289/* Return a string showing the hwcaps in a nice way. The string will
1290 be NULL for invalid combinations of flags, so these functions also
1291 serve as a way to validate hwcaps values. */
1292
florian55085f82012-11-21 00:36:55 +00001293static const HChar* show_hwcaps_x86 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001294{
mjw6c65c122013-08-27 10:19:03 +00001295 /* Monotonic, LZCNT > SSE3 > SSE2 > SSE1 > MMXEXT > baseline. */
sewardj536fbab2010-07-29 15:39:05 +00001296 switch (hwcaps) {
1297 case 0:
1298 return "x86-sse0";
mjw6c65c122013-08-27 10:19:03 +00001299 case VEX_HWCAPS_X86_MMXEXT:
1300 return "x86-mmxext";
1301 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1:
1302 return "x86-mmxext-sse1";
1303 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2:
1304 return "x86-mmxext-sse1-sse2";
1305 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
sewardj536fbab2010-07-29 15:39:05 +00001306 | VEX_HWCAPS_X86_LZCNT:
mjw6c65c122013-08-27 10:19:03 +00001307 return "x86-mmxext-sse1-sse2-lzcnt";
1308 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
sewardj536fbab2010-07-29 15:39:05 +00001309 | VEX_HWCAPS_X86_SSE3:
mjw6c65c122013-08-27 10:19:03 +00001310 return "x86-mmxext-sse1-sse2-sse3";
1311 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
sewardj536fbab2010-07-29 15:39:05 +00001312 | VEX_HWCAPS_X86_SSE3 | VEX_HWCAPS_X86_LZCNT:
mjw6c65c122013-08-27 10:19:03 +00001313 return "x86-mmxext-sse1-sse2-sse3-lzcnt";
sewardj536fbab2010-07-29 15:39:05 +00001314 default:
1315 return NULL;
1316 }
sewardj5117ce12006-01-27 21:20:15 +00001317}
1318
florian55085f82012-11-21 00:36:55 +00001319static const HChar* show_hwcaps_amd64 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001320{
sewardje9d8a262009-07-01 08:06:34 +00001321 /* SSE3 and CX16 are orthogonal and > baseline, although we really
1322 don't expect to come across anything which can do SSE3 but can't
sewardj536fbab2010-07-29 15:39:05 +00001323 do CX16. Still, we can handle that case. LZCNT is similarly
sewardj818c7302013-03-26 13:53:18 +00001324 orthogonal. */
1325
1326 /* Throw out obviously stupid cases: */
sewardj818c7302013-03-26 13:53:18 +00001327 Bool have_sse3 = (hwcaps & VEX_HWCAPS_AMD64_SSE3) != 0;
1328 Bool have_avx = (hwcaps & VEX_HWCAPS_AMD64_AVX) != 0;
sewardjcc3d2192013-03-27 11:37:33 +00001329 Bool have_bmi = (hwcaps & VEX_HWCAPS_AMD64_BMI) != 0;
1330 Bool have_avx2 = (hwcaps & VEX_HWCAPS_AMD64_AVX2) != 0;
1331 /* AVX without SSE3 */
sewardj818c7302013-03-26 13:53:18 +00001332 if (have_avx && !have_sse3)
1333 return NULL;
sewardjcc3d2192013-03-27 11:37:33 +00001334 /* AVX2 or BMI without AVX */
1335 if ((have_avx2 || have_bmi) && !have_avx)
1336 return NULL;
sewardj818c7302013-03-26 13:53:18 +00001337
1338 /* This isn't threadsafe. We might need to fix it at some point. */
1339 static HChar buf[100] = { 0 };
1340 if (buf[0] != 0) return buf; /* already constructed */
1341
1342 vex_bzero(buf, sizeof(buf));
1343
1344 HChar* p = &buf[0];
1345
1346 p = p + vex_sprintf(p, "%s", "amd64");
1347 if (hwcaps == 0) {
1348 /* special-case the baseline case */
1349 p = p + vex_sprintf(p, "%s", "-sse2");
1350 goto out;
sewardj536fbab2010-07-29 15:39:05 +00001351 }
sewardj818c7302013-03-26 13:53:18 +00001352 if (hwcaps & VEX_HWCAPS_AMD64_CX16) {
1353 p = p + vex_sprintf(p, "%s", "-cx16");
1354 }
1355 if (hwcaps & VEX_HWCAPS_AMD64_LZCNT) {
1356 p = p + vex_sprintf(p, "%s", "-lzcnt");
1357 }
1358 if (hwcaps & VEX_HWCAPS_AMD64_RDTSCP) {
1359 p = p + vex_sprintf(p, "%s", "-rdtscp");
1360 }
1361 if (hwcaps & VEX_HWCAPS_AMD64_SSE3) {
1362 p = p + vex_sprintf(p, "%s", "-sse3");
1363 }
1364 if (hwcaps & VEX_HWCAPS_AMD64_AVX) {
1365 p = p + vex_sprintf(p, "%s", "-avx");
1366 }
sewardjcc3d2192013-03-27 11:37:33 +00001367 if (hwcaps & VEX_HWCAPS_AMD64_AVX2) {
1368 p = p + vex_sprintf(p, "%s", "-avx2");
1369 }
1370 if (hwcaps & VEX_HWCAPS_AMD64_BMI) {
1371 p = p + vex_sprintf(p, "%s", "-bmi");
1372 }
sewardj818c7302013-03-26 13:53:18 +00001373
1374 out:
1375 vassert(buf[sizeof(buf)-1] == 0);
1376 return buf;
sewardj5117ce12006-01-27 21:20:15 +00001377}
1378
florian55085f82012-11-21 00:36:55 +00001379static const HChar* show_hwcaps_ppc32 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001380{
1381 /* Monotonic with complications. Basically V > F > baseline,
1382 but once you have F then you can have FX or GX too. */
1383 const UInt F = VEX_HWCAPS_PPC32_F;
1384 const UInt V = VEX_HWCAPS_PPC32_V;
1385 const UInt FX = VEX_HWCAPS_PPC32_FX;
1386 const UInt GX = VEX_HWCAPS_PPC32_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001387 const UInt VX = VEX_HWCAPS_PPC32_VX;
sewardjc66d6fa2012-04-02 21:24:12 +00001388 const UInt DFP = VEX_HWCAPS_PPC32_DFP;
carll0c74bb52013-08-12 18:01:40 +00001389 const UInt ISA2_07 = VEX_HWCAPS_PPC32_ISA2_07;
sewardj5117ce12006-01-27 21:20:15 +00001390 UInt c = hwcaps;
1391 if (c == 0) return "ppc32-int";
1392 if (c == F) return "ppc32-int-flt";
1393 if (c == (F|FX)) return "ppc32-int-flt-FX";
1394 if (c == (F|GX)) return "ppc32-int-flt-GX";
1395 if (c == (F|FX|GX)) return "ppc32-int-flt-FX-GX";
1396 if (c == (F|V)) return "ppc32-int-flt-vmx";
1397 if (c == (F|V|FX)) return "ppc32-int-flt-vmx-FX";
1398 if (c == (F|V|GX)) return "ppc32-int-flt-vmx-GX";
1399 if (c == (F|V|FX|GX)) return "ppc32-int-flt-vmx-FX-GX";
sewardjc66d6fa2012-04-02 21:24:12 +00001400 if (c == (F|V|FX|GX|DFP)) return "ppc32-int-flt-vmx-FX-GX-DFP";
1401 if (c == (F|V|FX|GX|VX|DFP)) return "ppc32-int-flt-vmx-FX-GX-VX-DFP";
carll0c74bb52013-08-12 18:01:40 +00001402 if (c == (F|V|FX|GX|VX|DFP|ISA2_07))
1403 return "ppc32-int-flt-vmx-FX-GX-VX-DFP-ISA2_07";
1404
sewardj5117ce12006-01-27 21:20:15 +00001405 return NULL;
1406}
1407
florian55085f82012-11-21 00:36:55 +00001408static const HChar* show_hwcaps_ppc64 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001409{
1410 /* Monotonic with complications. Basically V > baseline(==F),
1411 but once you have F then you can have FX or GX too. */
sewardj3fd39672006-01-27 22:05:55 +00001412 const UInt V = VEX_HWCAPS_PPC64_V;
1413 const UInt FX = VEX_HWCAPS_PPC64_FX;
1414 const UInt GX = VEX_HWCAPS_PPC64_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001415 const UInt VX = VEX_HWCAPS_PPC64_VX;
sewardjc66d6fa2012-04-02 21:24:12 +00001416 const UInt DFP = VEX_HWCAPS_PPC64_DFP;
carll0c74bb52013-08-12 18:01:40 +00001417 const UInt ISA2_07 = VEX_HWCAPS_PPC64_ISA2_07;
sewardj5117ce12006-01-27 21:20:15 +00001418 UInt c = hwcaps;
1419 if (c == 0) return "ppc64-int-flt";
1420 if (c == FX) return "ppc64-int-flt-FX";
1421 if (c == GX) return "ppc64-int-flt-GX";
1422 if (c == (FX|GX)) return "ppc64-int-flt-FX-GX";
1423 if (c == V) return "ppc64-int-flt-vmx";
1424 if (c == (V|FX)) return "ppc64-int-flt-vmx-FX";
1425 if (c == (V|GX)) return "ppc64-int-flt-vmx-GX";
1426 if (c == (V|FX|GX)) return "ppc64-int-flt-vmx-FX-GX";
sewardjc66d6fa2012-04-02 21:24:12 +00001427 if (c == (V|FX|GX|DFP)) return "ppc64-int-flt-vmx-FX-GX-DFP";
1428 if (c == (V|FX|GX|VX|DFP)) return "ppc64-int-flt-vmx-FX-GX-VX-DFP";
carll0c74bb52013-08-12 18:01:40 +00001429 if (c == (V|FX|GX|VX|DFP|ISA2_07))
1430 return "ppc64-int-flt-vmx-FX-GX-VX-DFP-ISA2_07";
sewardj5117ce12006-01-27 21:20:15 +00001431 return NULL;
1432}
1433
florian55085f82012-11-21 00:36:55 +00001434static const HChar* show_hwcaps_arm ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001435{
sewardjec0d9a02010-08-22 12:54:56 +00001436 Bool N = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0);
1437 Bool vfp = ((hwcaps & (VEX_HWCAPS_ARM_VFP |
1438 VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3)) != 0);
1439 switch (VEX_ARM_ARCHLEVEL(hwcaps)) {
1440 case 5:
1441 if (N)
1442 return NULL;
1443 if (vfp)
1444 return "ARMv5-vfp";
1445 else
1446 return "ARMv5";
1447 return NULL;
1448 case 6:
1449 if (N)
1450 return NULL;
1451 if (vfp)
1452 return "ARMv6-vfp";
1453 else
1454 return "ARMv6";
1455 return NULL;
1456 case 7:
1457 if (vfp) {
1458 if (N)
1459 return "ARMv7-vfp-neon";
1460 else
1461 return "ARMv7-vfp";
1462 } else {
1463 if (N)
1464 return "ARMv7-neon";
1465 else
1466 return "ARMv7";
1467 }
1468 default:
1469 return NULL;
1470 }
sewardj5117ce12006-01-27 21:20:15 +00001471 return NULL;
1472}
1473
sewardjbbcf1882014-01-12 12:49:10 +00001474static const HChar* show_hwcaps_arm64 ( UInt hwcaps )
1475{
1476 /* Since there are no variants, just insist that hwcaps is zero,
1477 and declare it invalid otherwise. */
1478 if (hwcaps == 0)
1479 return "baseline";
1480 return NULL;
1481}
1482
florian55085f82012-11-21 00:36:55 +00001483static const HChar* show_hwcaps_s390x ( UInt hwcaps )
sewardj2019a972011-03-07 16:04:07 +00001484{
sewardjd07b8562011-04-27 11:58:22 +00001485 static const HChar prefix[] = "s390x";
florian9061eb32012-12-09 17:53:45 +00001486 static const struct {
1487 UInt hwcaps_bit;
1488 HChar name[6];
1489 } hwcaps_list[] = {
1490 { VEX_HWCAPS_S390X_LDISP, "ldisp" },
1491 { VEX_HWCAPS_S390X_EIMM, "eimm" },
1492 { VEX_HWCAPS_S390X_GIE, "gie" },
1493 { VEX_HWCAPS_S390X_DFP, "dfp" },
1494 { VEX_HWCAPS_S390X_FGX, "fgx" },
1495 { VEX_HWCAPS_S390X_STFLE, "stfle" },
1496 { VEX_HWCAPS_S390X_ETF2, "etf2" },
1497 { VEX_HWCAPS_S390X_ETF3, "etf3" },
1498 { VEX_HWCAPS_S390X_STCKF, "stckf" },
1499 { VEX_HWCAPS_S390X_FPEXT, "fpext" },
1500 { VEX_HWCAPS_S390X_LSC, "lsc" },
florian78d5ef72013-05-11 15:02:58 +00001501 { VEX_HWCAPS_S390X_PFPO, "pfpo" },
sewardjd07b8562011-04-27 11:58:22 +00001502 };
florian9061eb32012-12-09 17:53:45 +00001503#define NUM_HWCAPS (sizeof hwcaps_list / sizeof hwcaps_list[0])
1504 static HChar buf[sizeof prefix +
1505 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) +
1506 1]; // '\0'
1507 HChar *p;
1508 UInt i;
sewardjd07b8562011-04-27 11:58:22 +00001509
1510 if (buf[0] != '\0') return buf; /* already constructed */
sewardj2019a972011-03-07 16:04:07 +00001511
sewardj652b56a2011-04-13 15:38:17 +00001512 hwcaps = VEX_HWCAPS_S390X(hwcaps);
1513
sewardjd07b8562011-04-27 11:58:22 +00001514 p = buf + vex_sprintf(buf, "%s", prefix);
florian9061eb32012-12-09 17:53:45 +00001515 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1516 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1517 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1518 }
sewardj2019a972011-03-07 16:04:07 +00001519
sewardjd07b8562011-04-27 11:58:22 +00001520 /* If there are no facilities, add "zarch" */
1521 if (hwcaps == 0)
1522 vex_sprintf(p, "-%s", "zarch");
1523
1524 return buf;
sewardj2019a972011-03-07 16:04:07 +00001525}
1526
florian55085f82012-11-21 00:36:55 +00001527static const HChar* show_hwcaps_mips32 ( UInt hwcaps )
sewardjd0e5fe72012-06-07 08:51:02 +00001528{
dejanjc3fee0d2013-07-25 09:08:03 +00001529 /* MIPS baseline. */
petarjbc7d6f42013-09-16 18:11:59 +00001530 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_MIPS) {
dejanjc3fee0d2013-07-25 09:08:03 +00001531 /* MIPS baseline with dspr2. */
petarjbc7d6f42013-09-16 18:11:59 +00001532 if (VEX_MIPS_PROC_DSP2(hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +00001533 return "MIPS-baseline-dspr2";
1534 }
1535 /* MIPS baseline with dsp. */
petarjbc7d6f42013-09-16 18:11:59 +00001536 if (VEX_MIPS_PROC_DSP(hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +00001537 return "MIPS-baseline-dsp";
1538 }
1539 return "MIPS-baseline";
1540 }
1541
1542 /* Broadcom baseline. */
petarjbc7d6f42013-09-16 18:11:59 +00001543 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_BROADCOM) {
dejanjc3fee0d2013-07-25 09:08:03 +00001544 return "Broadcom-baseline";
1545 }
1546
1547 /* Netlogic baseline. */
petarjbc7d6f42013-09-16 18:11:59 +00001548 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_NETLOGIC) {
dejanjc3fee0d2013-07-25 09:08:03 +00001549 return "Netlogic-baseline";
1550 }
1551
petarjbc7d6f42013-09-16 18:11:59 +00001552 /* Cavium baseline. */
1553 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_CAVIUM) {
1554 return "Cavium-baseline";
1555 }
1556
sewardjd0e5fe72012-06-07 08:51:02 +00001557 return NULL;
1558}
1559
petarjb92a9542013-02-27 22:57:17 +00001560static const HChar* show_hwcaps_mips64 ( UInt hwcaps )
1561{
1562 return "mips64-baseline";
1563}
1564
sewardj5117ce12006-01-27 21:20:15 +00001565/* ---- */
florian55085f82012-11-21 00:36:55 +00001566static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001567{
1568 switch (arch) {
sewardjd0e5fe72012-06-07 08:51:02 +00001569 case VexArchX86: return show_hwcaps_x86(hwcaps);
1570 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
1571 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
1572 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
1573 case VexArchARM: return show_hwcaps_arm(hwcaps);
sewardjbbcf1882014-01-12 12:49:10 +00001574 case VexArchARM64: return show_hwcaps_arm64(hwcaps);
sewardjd0e5fe72012-06-07 08:51:02 +00001575 case VexArchS390X: return show_hwcaps_s390x(hwcaps);
1576 case VexArchMIPS32: return show_hwcaps_mips32(hwcaps);
petarjb92a9542013-02-27 22:57:17 +00001577 case VexArchMIPS64: return show_hwcaps_mips64(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001578 default: return NULL;
1579 }
1580}
1581
1582static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps )
1583{
1584 return show_hwcaps(arch,hwcaps) != NULL;
1585}
1586
1587
sewardj35421a32004-07-05 13:12:34 +00001588/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +00001589/*--- end main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +00001590/*---------------------------------------------------------------*/