blob: cf9789bdb20eabdf9d61a6a237882e414ec567d9 [file] [log] [blame]
sewardj35421a32004-07-05 13:12:34 +00001
2/*---------------------------------------------------------------*/
sewardj752f9062010-05-03 21:38:49 +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));
sewardj9b769162014-07-24 12:42:03 +0000381 vassert(vta->archinfo_host.endness == VexEndnessBE
382 /* later: || 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));
sewardj9b769162014-07-24 12:42:03 +0000574 vassert(vta->archinfo_guest.endness == VexEndnessBE
575 /* later: || vta->archinfo_guest.endness == VexEndnessBE */);
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;
florian8844a632012-04-13 04:04:06 +00001143 case VexArchS390X:
1144 patchProfInc = patchProfInc_S390; break;
sewardj3dee8492012-04-20 00:13:28 +00001145 case VexArchPPC32:
sewardj9b769162014-07-24 12:42:03 +00001146 return patchProfInc_PPC(endness_host, place_to_patch,
sewardj3dee8492012-04-20 00:13:28 +00001147 location_of_counter, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +00001148 case VexArchPPC64:
sewardj9b769162014-07-24 12:42:03 +00001149 return patchProfInc_PPC(endness_host, place_to_patch,
sewardjf252de52012-04-20 10:42:24 +00001150 location_of_counter, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +00001151 case VexArchMIPS32:
sewardj9b769162014-07-24 12:42:03 +00001152 return patchProfInc_MIPS(endness_host, place_to_patch,
sewardjd0e5fe72012-06-07 08:51:02 +00001153 location_of_counter, False/*!mode64*/);
petarjb92a9542013-02-27 22:57:17 +00001154 case VexArchMIPS64:
sewardj9b769162014-07-24 12:42:03 +00001155 return patchProfInc_MIPS(endness_host, place_to_patch,
petarjb92a9542013-02-27 22:57:17 +00001156 location_of_counter, True/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +00001157 default:
1158 vassert(0);
1159 }
1160 vassert(patchProfInc);
1161 VexInvalRange vir
sewardj9b769162014-07-24 12:42:03 +00001162 = patchProfInc(endness_host, place_to_patch, location_of_counter);
sewardjc6f970f2012-04-02 21:54:49 +00001163 return vir;
1164}
1165
1166
sewardj893aada2004-11-29 19:57:54 +00001167/* --------- Emulation warnings. --------- */
1168
florian1ff47562012-10-21 02:09:51 +00001169const HChar* LibVEX_EmNote_string ( VexEmNote ew )
sewardj893aada2004-11-29 19:57:54 +00001170{
1171 switch (ew) {
florian6ef84be2012-08-26 03:20:07 +00001172 case EmNote_NONE:
sewardj893aada2004-11-29 19:57:54 +00001173 return "none";
1174 case EmWarn_X86_x87exns:
1175 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +00001176 case EmWarn_X86_x87precision:
1177 return "Selection of non-80-bit x87 FP precision";
1178 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +00001179 return "Unmasking SSE FP exceptions";
1180 case EmWarn_X86_fz:
1181 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
1182 case EmWarn_X86_daz:
1183 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +00001184 case EmWarn_X86_acFlag:
1185 return "Setting %eflags.ac (setting noted but ignored)";
sewardj9dd9cf12006-01-20 14:13:55 +00001186 case EmWarn_PPCexns:
1187 return "Unmasking PPC32/64 FP exceptions";
1188 case EmWarn_PPC64_redir_overflow:
1189 return "PPC64 function redirection stack overflow";
1190 case EmWarn_PPC64_redir_underflow:
1191 return "PPC64 function redirection stack underflow";
florian4b8efad2012-09-02 18:07:08 +00001192 case EmWarn_S390X_fpext_rounding:
1193 return "The specified rounding mode cannot be supported. That\n"
1194 " feature requires the floating point extension facility.\n"
1195 " which is not available on this host. Continuing using\n"
1196 " the rounding mode from FPC. Results may differ!";
florianf0fa1be2012-09-18 20:24:38 +00001197 case EmWarn_S390X_invalid_rounding:
1198 return "The specified rounding mode is invalid.\n"
1199 " Continuing using 'round to nearest'. Results may differ!";
floriane75dafa2012-09-01 17:54:09 +00001200 case EmFail_S390X_stfle:
florian4e0083e2012-08-26 03:41:56 +00001201 return "Instruction stfle is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001202 case EmFail_S390X_stckf:
florianc5c669b2012-08-26 14:32:28 +00001203 return "Instruction stckf is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001204 case EmFail_S390X_ecag:
florian8c88cb62012-08-26 18:58:13 +00001205 return "Instruction ecag is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001206 case EmFail_S390X_fpext:
1207 return "Encountered an instruction that requires the floating "
1208 "point extension facility.\n"
1209 " That facility is not available on this host";
florian78d5ef72013-05-11 15:02:58 +00001210 case EmFail_S390X_invalid_PFPO_rounding_mode:
1211 return "The rounding mode specified in GPR 0 for PFPO instruction"
1212 " is invalid";
1213 case EmFail_S390X_invalid_PFPO_function:
1214 return "The function code specified in GPR 0 for PFPO instruction"
1215 " is invalid";
sewardj893aada2004-11-29 19:57:54 +00001216 default:
florian6ef84be2012-08-26 03:20:07 +00001217 vpanic("LibVEX_EmNote_string: unknown warning");
sewardj893aada2004-11-29 19:57:54 +00001218 }
1219}
sewardj35421a32004-07-05 13:12:34 +00001220
sewardj5117ce12006-01-27 21:20:15 +00001221/* ------------------ Arch/HwCaps stuff. ------------------ */
sewardjbef170b2004-12-21 01:23:00 +00001222
1223const HChar* LibVEX_ppVexArch ( VexArch arch )
1224{
1225 switch (arch) {
1226 case VexArch_INVALID: return "INVALID";
1227 case VexArchX86: return "X86";
1228 case VexArchAMD64: return "AMD64";
1229 case VexArchARM: return "ARM";
sewardjbbcf1882014-01-12 12:49:10 +00001230 case VexArchARM64: return "ARM64";
sewardj0ec57c52005-02-01 15:24:10 +00001231 case VexArchPPC32: return "PPC32";
cerionf0de28c2005-12-13 20:21:11 +00001232 case VexArchPPC64: return "PPC64";
sewardj2019a972011-03-07 16:04:07 +00001233 case VexArchS390X: return "S390X";
sewardjd0e5fe72012-06-07 08:51:02 +00001234 case VexArchMIPS32: return "MIPS32";
petarjb92a9542013-02-27 22:57:17 +00001235 case VexArchMIPS64: return "MIPS64";
sewardjbef170b2004-12-21 01:23:00 +00001236 default: return "VexArch???";
1237 }
1238}
1239
sewardj9b769162014-07-24 12:42:03 +00001240const HChar* LibVEX_ppVexEndness ( VexEndness endness )
1241{
1242 switch (endness) {
1243 case VexEndness_INVALID: return "INVALID";
1244 case VexEndnessLE: return "LittleEndian";
1245 case VexEndnessBE: return "BigEndian";
1246 default: return "VexEndness???";
1247 }
1248}
1249
sewardj5117ce12006-01-27 21:20:15 +00001250const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
sewardjbef170b2004-12-21 01:23:00 +00001251{
florian55085f82012-11-21 00:36:55 +00001252 const HChar* str = show_hwcaps(arch,hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001253 return str ? str : "INVALID";
sewardjbef170b2004-12-21 01:23:00 +00001254}
1255
sewardj5117ce12006-01-27 21:20:15 +00001256
sewardj27e1dd62005-06-30 11:49:14 +00001257/* Write default settings info *vai. */
1258void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
1259{
sewardj65902992014-05-03 21:20:56 +00001260 vex_bzero(vai, sizeof(*vai));
sewardj9b769162014-07-24 12:42:03 +00001261 vai->hwcaps = 0;
1262 vai->endness = VexEndness_INVALID;
1263 vai->ppc_icache_line_szB = 0;
1264 vai->ppc_dcbz_szB = 0;
1265 vai->ppc_dcbzl_szB = 0;
sewardj65902992014-05-03 21:20:56 +00001266 vai->arm64_dMinLine_lg2_szB = 0;
1267 vai->arm64_iMinLine_lg2_szB = 0;
florianf192a392012-10-07 19:44:40 +00001268 vai->hwcache_info.num_levels = 0;
1269 vai->hwcache_info.num_caches = 0;
sewardj65902992014-05-03 21:20:56 +00001270 vai->hwcache_info.caches = NULL;
florianf192a392012-10-07 19:44:40 +00001271 vai->hwcache_info.icaches_maintain_coherence = True; // whatever
sewardj27e1dd62005-06-30 11:49:14 +00001272}
1273
sewardjdd40fdf2006-12-24 02:20:24 +00001274/* Write default settings info *vbi. */
1275void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
sewardjaca070a2006-10-17 00:28:22 +00001276{
sewardj65902992014-05-03 21:20:56 +00001277 vex_bzero(vbi, sizeof(*vbi));
sewardjdd40fdf2006-12-24 02:20:24 +00001278 vbi->guest_stack_redzone_size = 0;
sewardj2e28ac42008-12-04 00:05:12 +00001279 vbi->guest_amd64_assume_fs_is_zero = False;
1280 vbi->guest_amd64_assume_gs_is_0x60 = False;
sewardjdd40fdf2006-12-24 02:20:24 +00001281 vbi->guest_ppc_zap_RZ_at_blr = False;
1282 vbi->guest_ppc_zap_RZ_at_bl = NULL;
sewardjdd40fdf2006-12-24 02:20:24 +00001283 vbi->host_ppc_calls_use_fndescrs = False;
sewardjaca070a2006-10-17 00:28:22 +00001284}
1285
sewardj27e1dd62005-06-30 11:49:14 +00001286
sewardj5117ce12006-01-27 21:20:15 +00001287/* Return a string showing the hwcaps in a nice way. The string will
1288 be NULL for invalid combinations of flags, so these functions also
1289 serve as a way to validate hwcaps values. */
1290
florian55085f82012-11-21 00:36:55 +00001291static const HChar* show_hwcaps_x86 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001292{
mjw6c65c122013-08-27 10:19:03 +00001293 /* Monotonic, LZCNT > SSE3 > SSE2 > SSE1 > MMXEXT > baseline. */
sewardj536fbab2010-07-29 15:39:05 +00001294 switch (hwcaps) {
1295 case 0:
1296 return "x86-sse0";
mjw6c65c122013-08-27 10:19:03 +00001297 case VEX_HWCAPS_X86_MMXEXT:
1298 return "x86-mmxext";
1299 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1:
1300 return "x86-mmxext-sse1";
1301 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2:
1302 return "x86-mmxext-sse1-sse2";
1303 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
sewardj536fbab2010-07-29 15:39:05 +00001304 | VEX_HWCAPS_X86_LZCNT:
mjw6c65c122013-08-27 10:19:03 +00001305 return "x86-mmxext-sse1-sse2-lzcnt";
1306 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
sewardj536fbab2010-07-29 15:39:05 +00001307 | VEX_HWCAPS_X86_SSE3:
mjw6c65c122013-08-27 10:19:03 +00001308 return "x86-mmxext-sse1-sse2-sse3";
1309 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
sewardj536fbab2010-07-29 15:39:05 +00001310 | VEX_HWCAPS_X86_SSE3 | VEX_HWCAPS_X86_LZCNT:
mjw6c65c122013-08-27 10:19:03 +00001311 return "x86-mmxext-sse1-sse2-sse3-lzcnt";
sewardj536fbab2010-07-29 15:39:05 +00001312 default:
1313 return NULL;
1314 }
sewardj5117ce12006-01-27 21:20:15 +00001315}
1316
florian55085f82012-11-21 00:36:55 +00001317static const HChar* show_hwcaps_amd64 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001318{
sewardje9d8a262009-07-01 08:06:34 +00001319 /* SSE3 and CX16 are orthogonal and > baseline, although we really
1320 don't expect to come across anything which can do SSE3 but can't
sewardj536fbab2010-07-29 15:39:05 +00001321 do CX16. Still, we can handle that case. LZCNT is similarly
sewardj818c7302013-03-26 13:53:18 +00001322 orthogonal. */
1323
1324 /* Throw out obviously stupid cases: */
sewardj818c7302013-03-26 13:53:18 +00001325 Bool have_sse3 = (hwcaps & VEX_HWCAPS_AMD64_SSE3) != 0;
1326 Bool have_avx = (hwcaps & VEX_HWCAPS_AMD64_AVX) != 0;
sewardjcc3d2192013-03-27 11:37:33 +00001327 Bool have_bmi = (hwcaps & VEX_HWCAPS_AMD64_BMI) != 0;
1328 Bool have_avx2 = (hwcaps & VEX_HWCAPS_AMD64_AVX2) != 0;
1329 /* AVX without SSE3 */
sewardj818c7302013-03-26 13:53:18 +00001330 if (have_avx && !have_sse3)
1331 return NULL;
sewardjcc3d2192013-03-27 11:37:33 +00001332 /* AVX2 or BMI without AVX */
1333 if ((have_avx2 || have_bmi) && !have_avx)
1334 return NULL;
sewardj818c7302013-03-26 13:53:18 +00001335
1336 /* This isn't threadsafe. We might need to fix it at some point. */
1337 static HChar buf[100] = { 0 };
1338 if (buf[0] != 0) return buf; /* already constructed */
1339
1340 vex_bzero(buf, sizeof(buf));
1341
1342 HChar* p = &buf[0];
1343
1344 p = p + vex_sprintf(p, "%s", "amd64");
1345 if (hwcaps == 0) {
1346 /* special-case the baseline case */
1347 p = p + vex_sprintf(p, "%s", "-sse2");
1348 goto out;
sewardj536fbab2010-07-29 15:39:05 +00001349 }
sewardj818c7302013-03-26 13:53:18 +00001350 if (hwcaps & VEX_HWCAPS_AMD64_CX16) {
1351 p = p + vex_sprintf(p, "%s", "-cx16");
1352 }
1353 if (hwcaps & VEX_HWCAPS_AMD64_LZCNT) {
1354 p = p + vex_sprintf(p, "%s", "-lzcnt");
1355 }
1356 if (hwcaps & VEX_HWCAPS_AMD64_RDTSCP) {
1357 p = p + vex_sprintf(p, "%s", "-rdtscp");
1358 }
1359 if (hwcaps & VEX_HWCAPS_AMD64_SSE3) {
1360 p = p + vex_sprintf(p, "%s", "-sse3");
1361 }
1362 if (hwcaps & VEX_HWCAPS_AMD64_AVX) {
1363 p = p + vex_sprintf(p, "%s", "-avx");
1364 }
sewardjcc3d2192013-03-27 11:37:33 +00001365 if (hwcaps & VEX_HWCAPS_AMD64_AVX2) {
1366 p = p + vex_sprintf(p, "%s", "-avx2");
1367 }
1368 if (hwcaps & VEX_HWCAPS_AMD64_BMI) {
1369 p = p + vex_sprintf(p, "%s", "-bmi");
1370 }
sewardj818c7302013-03-26 13:53:18 +00001371
1372 out:
1373 vassert(buf[sizeof(buf)-1] == 0);
1374 return buf;
sewardj5117ce12006-01-27 21:20:15 +00001375}
1376
florian55085f82012-11-21 00:36:55 +00001377static const HChar* show_hwcaps_ppc32 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001378{
1379 /* Monotonic with complications. Basically V > F > baseline,
1380 but once you have F then you can have FX or GX too. */
1381 const UInt F = VEX_HWCAPS_PPC32_F;
1382 const UInt V = VEX_HWCAPS_PPC32_V;
1383 const UInt FX = VEX_HWCAPS_PPC32_FX;
1384 const UInt GX = VEX_HWCAPS_PPC32_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001385 const UInt VX = VEX_HWCAPS_PPC32_VX;
sewardjc66d6fa2012-04-02 21:24:12 +00001386 const UInt DFP = VEX_HWCAPS_PPC32_DFP;
carll0c74bb52013-08-12 18:01:40 +00001387 const UInt ISA2_07 = VEX_HWCAPS_PPC32_ISA2_07;
sewardj5117ce12006-01-27 21:20:15 +00001388 UInt c = hwcaps;
1389 if (c == 0) return "ppc32-int";
1390 if (c == F) return "ppc32-int-flt";
1391 if (c == (F|FX)) return "ppc32-int-flt-FX";
1392 if (c == (F|GX)) return "ppc32-int-flt-GX";
1393 if (c == (F|FX|GX)) return "ppc32-int-flt-FX-GX";
1394 if (c == (F|V)) return "ppc32-int-flt-vmx";
1395 if (c == (F|V|FX)) return "ppc32-int-flt-vmx-FX";
1396 if (c == (F|V|GX)) return "ppc32-int-flt-vmx-GX";
1397 if (c == (F|V|FX|GX)) return "ppc32-int-flt-vmx-FX-GX";
sewardjc66d6fa2012-04-02 21:24:12 +00001398 if (c == (F|V|FX|GX|DFP)) return "ppc32-int-flt-vmx-FX-GX-DFP";
1399 if (c == (F|V|FX|GX|VX|DFP)) return "ppc32-int-flt-vmx-FX-GX-VX-DFP";
carll0c74bb52013-08-12 18:01:40 +00001400 if (c == (F|V|FX|GX|VX|DFP|ISA2_07))
1401 return "ppc32-int-flt-vmx-FX-GX-VX-DFP-ISA2_07";
1402
sewardj5117ce12006-01-27 21:20:15 +00001403 return NULL;
1404}
1405
florian55085f82012-11-21 00:36:55 +00001406static const HChar* show_hwcaps_ppc64 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001407{
1408 /* Monotonic with complications. Basically V > baseline(==F),
1409 but once you have F then you can have FX or GX too. */
sewardj3fd39672006-01-27 22:05:55 +00001410 const UInt V = VEX_HWCAPS_PPC64_V;
1411 const UInt FX = VEX_HWCAPS_PPC64_FX;
1412 const UInt GX = VEX_HWCAPS_PPC64_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001413 const UInt VX = VEX_HWCAPS_PPC64_VX;
sewardjc66d6fa2012-04-02 21:24:12 +00001414 const UInt DFP = VEX_HWCAPS_PPC64_DFP;
carll0c74bb52013-08-12 18:01:40 +00001415 const UInt ISA2_07 = VEX_HWCAPS_PPC64_ISA2_07;
sewardj5117ce12006-01-27 21:20:15 +00001416 UInt c = hwcaps;
1417 if (c == 0) return "ppc64-int-flt";
1418 if (c == FX) return "ppc64-int-flt-FX";
1419 if (c == GX) return "ppc64-int-flt-GX";
1420 if (c == (FX|GX)) return "ppc64-int-flt-FX-GX";
1421 if (c == V) return "ppc64-int-flt-vmx";
1422 if (c == (V|FX)) return "ppc64-int-flt-vmx-FX";
1423 if (c == (V|GX)) return "ppc64-int-flt-vmx-GX";
1424 if (c == (V|FX|GX)) return "ppc64-int-flt-vmx-FX-GX";
sewardjc66d6fa2012-04-02 21:24:12 +00001425 if (c == (V|FX|GX|DFP)) return "ppc64-int-flt-vmx-FX-GX-DFP";
1426 if (c == (V|FX|GX|VX|DFP)) return "ppc64-int-flt-vmx-FX-GX-VX-DFP";
carll0c74bb52013-08-12 18:01:40 +00001427 if (c == (V|FX|GX|VX|DFP|ISA2_07))
1428 return "ppc64-int-flt-vmx-FX-GX-VX-DFP-ISA2_07";
sewardj5117ce12006-01-27 21:20:15 +00001429 return NULL;
1430}
1431
florian55085f82012-11-21 00:36:55 +00001432static const HChar* show_hwcaps_arm ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001433{
sewardjec0d9a02010-08-22 12:54:56 +00001434 Bool N = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0);
1435 Bool vfp = ((hwcaps & (VEX_HWCAPS_ARM_VFP |
1436 VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3)) != 0);
1437 switch (VEX_ARM_ARCHLEVEL(hwcaps)) {
1438 case 5:
1439 if (N)
1440 return NULL;
1441 if (vfp)
1442 return "ARMv5-vfp";
1443 else
1444 return "ARMv5";
1445 return NULL;
1446 case 6:
1447 if (N)
1448 return NULL;
1449 if (vfp)
1450 return "ARMv6-vfp";
1451 else
1452 return "ARMv6";
1453 return NULL;
1454 case 7:
1455 if (vfp) {
1456 if (N)
1457 return "ARMv7-vfp-neon";
1458 else
1459 return "ARMv7-vfp";
1460 } else {
1461 if (N)
1462 return "ARMv7-neon";
1463 else
1464 return "ARMv7";
1465 }
1466 default:
1467 return NULL;
1468 }
sewardj5117ce12006-01-27 21:20:15 +00001469 return NULL;
1470}
1471
sewardjbbcf1882014-01-12 12:49:10 +00001472static const HChar* show_hwcaps_arm64 ( UInt hwcaps )
1473{
1474 /* Since there are no variants, just insist that hwcaps is zero,
1475 and declare it invalid otherwise. */
1476 if (hwcaps == 0)
1477 return "baseline";
1478 return NULL;
1479}
1480
florian55085f82012-11-21 00:36:55 +00001481static const HChar* show_hwcaps_s390x ( UInt hwcaps )
sewardj2019a972011-03-07 16:04:07 +00001482{
sewardjd07b8562011-04-27 11:58:22 +00001483 static const HChar prefix[] = "s390x";
florian9061eb32012-12-09 17:53:45 +00001484 static const struct {
1485 UInt hwcaps_bit;
1486 HChar name[6];
1487 } hwcaps_list[] = {
1488 { VEX_HWCAPS_S390X_LDISP, "ldisp" },
1489 { VEX_HWCAPS_S390X_EIMM, "eimm" },
1490 { VEX_HWCAPS_S390X_GIE, "gie" },
1491 { VEX_HWCAPS_S390X_DFP, "dfp" },
1492 { VEX_HWCAPS_S390X_FGX, "fgx" },
1493 { VEX_HWCAPS_S390X_STFLE, "stfle" },
1494 { VEX_HWCAPS_S390X_ETF2, "etf2" },
1495 { VEX_HWCAPS_S390X_ETF3, "etf3" },
1496 { VEX_HWCAPS_S390X_STCKF, "stckf" },
1497 { VEX_HWCAPS_S390X_FPEXT, "fpext" },
1498 { VEX_HWCAPS_S390X_LSC, "lsc" },
florian78d5ef72013-05-11 15:02:58 +00001499 { VEX_HWCAPS_S390X_PFPO, "pfpo" },
sewardjd07b8562011-04-27 11:58:22 +00001500 };
florian9061eb32012-12-09 17:53:45 +00001501#define NUM_HWCAPS (sizeof hwcaps_list / sizeof hwcaps_list[0])
1502 static HChar buf[sizeof prefix +
1503 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) +
1504 1]; // '\0'
1505 HChar *p;
1506 UInt i;
sewardjd07b8562011-04-27 11:58:22 +00001507
1508 if (buf[0] != '\0') return buf; /* already constructed */
sewardj2019a972011-03-07 16:04:07 +00001509
sewardj652b56a2011-04-13 15:38:17 +00001510 hwcaps = VEX_HWCAPS_S390X(hwcaps);
1511
sewardjd07b8562011-04-27 11:58:22 +00001512 p = buf + vex_sprintf(buf, "%s", prefix);
florian9061eb32012-12-09 17:53:45 +00001513 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1514 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1515 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1516 }
sewardj2019a972011-03-07 16:04:07 +00001517
sewardjd07b8562011-04-27 11:58:22 +00001518 /* If there are no facilities, add "zarch" */
1519 if (hwcaps == 0)
1520 vex_sprintf(p, "-%s", "zarch");
1521
1522 return buf;
sewardj2019a972011-03-07 16:04:07 +00001523}
1524
florian55085f82012-11-21 00:36:55 +00001525static const HChar* show_hwcaps_mips32 ( UInt hwcaps )
sewardjd0e5fe72012-06-07 08:51:02 +00001526{
dejanjc3fee0d2013-07-25 09:08:03 +00001527 /* MIPS baseline. */
petarjbc7d6f42013-09-16 18:11:59 +00001528 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_MIPS) {
dejanjc3fee0d2013-07-25 09:08:03 +00001529 /* MIPS baseline with dspr2. */
petarjbc7d6f42013-09-16 18:11:59 +00001530 if (VEX_MIPS_PROC_DSP2(hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +00001531 return "MIPS-baseline-dspr2";
1532 }
1533 /* MIPS baseline with dsp. */
petarjbc7d6f42013-09-16 18:11:59 +00001534 if (VEX_MIPS_PROC_DSP(hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +00001535 return "MIPS-baseline-dsp";
1536 }
1537 return "MIPS-baseline";
1538 }
1539
1540 /* Broadcom baseline. */
petarjbc7d6f42013-09-16 18:11:59 +00001541 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_BROADCOM) {
dejanjc3fee0d2013-07-25 09:08:03 +00001542 return "Broadcom-baseline";
1543 }
1544
1545 /* Netlogic baseline. */
petarjbc7d6f42013-09-16 18:11:59 +00001546 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_NETLOGIC) {
dejanjc3fee0d2013-07-25 09:08:03 +00001547 return "Netlogic-baseline";
1548 }
1549
petarjbc7d6f42013-09-16 18:11:59 +00001550 /* Cavium baseline. */
1551 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_CAVIUM) {
1552 return "Cavium-baseline";
1553 }
1554
sewardjd0e5fe72012-06-07 08:51:02 +00001555 return NULL;
1556}
1557
petarjb92a9542013-02-27 22:57:17 +00001558static const HChar* show_hwcaps_mips64 ( UInt hwcaps )
1559{
1560 return "mips64-baseline";
1561}
1562
sewardj5117ce12006-01-27 21:20:15 +00001563/* ---- */
florian55085f82012-11-21 00:36:55 +00001564static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001565{
1566 switch (arch) {
sewardjd0e5fe72012-06-07 08:51:02 +00001567 case VexArchX86: return show_hwcaps_x86(hwcaps);
1568 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
1569 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
1570 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
1571 case VexArchARM: return show_hwcaps_arm(hwcaps);
sewardjbbcf1882014-01-12 12:49:10 +00001572 case VexArchARM64: return show_hwcaps_arm64(hwcaps);
sewardjd0e5fe72012-06-07 08:51:02 +00001573 case VexArchS390X: return show_hwcaps_s390x(hwcaps);
1574 case VexArchMIPS32: return show_hwcaps_mips32(hwcaps);
petarjb92a9542013-02-27 22:57:17 +00001575 case VexArchMIPS64: return show_hwcaps_mips64(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001576 default: return NULL;
1577 }
1578}
1579
1580static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps )
1581{
1582 return show_hwcaps(arch,hwcaps) != NULL;
1583}
1584
1585
sewardj35421a32004-07-05 13:12:34 +00001586/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +00001587/*--- end main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +00001588/*---------------------------------------------------------------*/