blob: 98ab2d213d5c8783619cd771e99a67112c79969f [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,
sewardj08613742004-10-25 13:01:45 +0000116 /* Control ... */
florianf72c2c12014-09-05 21:52:29 +0000117 const VexControl* vcon
sewardj35421a32004-07-05 13:12:34 +0000118)
119{
sewardj08613742004-10-25 13:01:45 +0000120 /* First off, do enough minimal setup so that the following
121 assertions can fail in a sane fashion, if need be. */
sewardjea602bc2004-10-14 21:40:12 +0000122 vex_failure_exit = failure_exit;
123 vex_log_bytes = log_bytes;
124
125 /* Now it's safe to check parameters for sanity. */
sewardj35421a32004-07-05 13:12:34 +0000126 vassert(!vex_initdone);
127 vassert(failure_exit);
sewardj35421a32004-07-05 13:12:34 +0000128 vassert(log_bytes);
sewardj35421a32004-07-05 13:12:34 +0000129 vassert(debuglevel >= 0);
sewardj08613742004-10-25 13:01:45 +0000130
131 vassert(vcon->iropt_verbosity >= 0);
132 vassert(vcon->iropt_level >= 0);
133 vassert(vcon->iropt_level <= 2);
134 vassert(vcon->iropt_unroll_thresh >= 0);
135 vassert(vcon->iropt_unroll_thresh <= 400);
136 vassert(vcon->guest_max_insns >= 1);
137 vassert(vcon->guest_max_insns <= 100);
138 vassert(vcon->guest_chase_thresh >= 0);
139 vassert(vcon->guest_chase_thresh < vcon->guest_max_insns);
sewardj984d9b12010-01-15 10:53:21 +0000140 vassert(vcon->guest_chase_cond == True
141 || vcon->guest_chase_cond == False);
sewardj443cd9d2004-07-18 23:06:45 +0000142
sewardjea602bc2004-10-14 21:40:12 +0000143 /* Check that Vex has been built with sizes of basic types as
144 stated in priv/libvex_basictypes.h. Failure of any of these is
145 a serious configuration error and should be corrected
146 immediately. If any of these assertions fail you can fully
147 expect Vex not to work properly, if at all. */
148
149 vassert(1 == sizeof(UChar));
150 vassert(1 == sizeof(Char));
151 vassert(2 == sizeof(UShort));
152 vassert(2 == sizeof(Short));
153 vassert(4 == sizeof(UInt));
154 vassert(4 == sizeof(Int));
155 vassert(8 == sizeof(ULong));
156 vassert(8 == sizeof(Long));
157 vassert(4 == sizeof(Float));
158 vassert(8 == sizeof(Double));
159 vassert(1 == sizeof(Bool));
160 vassert(4 == sizeof(Addr32));
161 vassert(8 == sizeof(Addr64));
sewardjc9a43662004-11-30 18:51:59 +0000162 vassert(16 == sizeof(U128));
sewardj69d98e32010-06-18 08:17:41 +0000163 vassert(16 == sizeof(V128));
sewardjc9069f22012-06-01 16:09:50 +0000164 vassert(32 == sizeof(U256));
sewardjea602bc2004-10-14 21:40:12 +0000165
166 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
167 vassert(sizeof(void*) == sizeof(int*));
168 vassert(sizeof(void*) == sizeof(HWord));
169
sewardj97e87932005-02-07 00:00:50 +0000170 vassert(VEX_HOST_WORDSIZE == sizeof(void*));
171 vassert(VEX_HOST_WORDSIZE == sizeof(HWord));
172
sewardjc6f970f2012-04-02 21:54:49 +0000173 /* These take a lot of space, so make sure we don't have
174 any unnoticed size regressions. */
175 if (VEX_HOST_WORDSIZE == 4) {
florian420bfa92012-06-02 20:29:22 +0000176 vassert(sizeof(IRExpr) == 16);
sewardjc6f970f2012-04-02 21:54:49 +0000177 vassert(sizeof(IRStmt) == 20 /* x86 */
178 || sizeof(IRStmt) == 24 /* arm */);
179 } else {
florian420bfa92012-06-02 20:29:22 +0000180 vassert(sizeof(IRExpr) == 32);
floriand6f38b32012-05-31 15:46:18 +0000181 vassert(sizeof(IRStmt) == 32);
sewardjc6f970f2012-04-02 21:54:49 +0000182 }
183
sewardj8bde7f12013-04-11 13:57:43 +0000184 /* Check that signed integer division on the host rounds towards
185 zero. If not, h_calc_sdiv32_w_arm_semantics() won't work
186 correctly. */
187 /* 100.0 / 7.0 == 14.2857 */
188 vassert(udiv32(100, 7) == 14);
189 vassert(sdiv32(100, 7) == 14);
190 vassert(sdiv32(-100, 7) == -14); /* and not -15 */
191 vassert(sdiv32(100, -7) == -14); /* ditto */
192 vassert(sdiv32(-100, -7) == 14); /* not sure what this proves */
193
sewardjea602bc2004-10-14 21:40:12 +0000194 /* Really start up .. */
sewardj443cd9d2004-07-18 23:06:45 +0000195 vex_debuglevel = debuglevel;
sewardj08613742004-10-25 13:01:45 +0000196 vex_control = *vcon;
sewardj443cd9d2004-07-18 23:06:45 +0000197 vex_initdone = True;
sewardjd887b862005-01-17 18:34:34 +0000198 vexSetAllocMode ( VexAllocModeTEMP );
sewardj35421a32004-07-05 13:12:34 +0000199}
200
201
202/* --------- Make a translation. --------- */
203
204/* Exported to library client. */
205
sewardj17c7f952005-12-15 14:02:34 +0000206VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
sewardj35421a32004-07-05 13:12:34 +0000207{
sewardj81bd5502004-07-21 18:49:27 +0000208 /* This the bundle of functions we need to do the back-end stuff
209 (insn selection, reg-alloc, assembly) whilst being insulated
210 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +0000211 HReg* available_real_regs;
212 Int n_available_real_regs;
sewardjfb7373a2007-08-25 21:29:03 +0000213 Bool (*isMove) ( HInstr*, HReg*, HReg* );
214 void (*getRegUsage) ( HRegUsage*, HInstr*, Bool );
215 void (*mapRegs) ( HRegRemap*, HInstr*, Bool );
sewardj6c299f32009-12-31 18:00:12 +0000216 void (*genSpill) ( HInstr**, HInstr**, HReg, Int, Bool );
217 void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool );
sewardjfb7373a2007-08-25 21:29:03 +0000218 HInstr* (*directReload) ( HInstr*, HReg, Short );
219 void (*ppInstr) ( HInstr*, Bool );
220 void (*ppReg) ( HReg );
sewardjc6f970f2012-04-02 21:54:49 +0000221 HInstrArray* (*iselSB) ( IRSB*, VexArch, VexArchInfo*, VexAbiInfo*,
222 Int, Int, Bool, Bool, Addr64 );
223 Int (*emit) ( /*MB_MOD*/Bool*,
sewardj9b769162014-07-24 12:42:03 +0000224 UChar*, Int, HInstr*, Bool, VexEndness,
florian8462d112014-09-24 15:18:09 +0000225 const void*, const void*, const void*,
226 const void* );
florian1ff47562012-10-21 02:09:51 +0000227 IRExpr* (*specHelper) ( const HChar*, IRExpr**, IRStmt**, Int );
sewardj8d2291c2004-10-25 14:50:21 +0000228 Bool (*preciseMemExnsFn) ( Int, Int );
sewardjf13a16a2004-07-05 17:10:14 +0000229
sewardj9e6491a2005-07-02 19:24:10 +0000230 DisOneInstrFn disInstrFn;
231
sewardjeeac8412004-11-02 00:26:55 +0000232 VexGuestLayout* guest_layout;
sewardjdd40fdf2006-12-24 02:20:24 +0000233 IRSB* irsb;
sewardjeeac8412004-11-02 00:26:55 +0000234 HInstrArray* vcode;
235 HInstrArray* rcode;
236 Int i, j, k, out_used, guest_sizeB;
sewardj05f5e012014-05-04 10:52:11 +0000237 Int offB_CMSTART, offB_CMLEN, offB_GUEST_IP, szB_GUEST_IP;
sewardjc6f970f2012-04-02 21:54:49 +0000238 Int offB_HOST_EvC_COUNTER, offB_HOST_EvC_FAILADDR;
petarjb92a9542013-02-27 22:57:17 +0000239 UChar insn_bytes[128];
sewardjcf787902004-11-03 09:08:33 +0000240 IRType guest_word_type;
241 IRType host_word_type;
sewardjc6f970f2012-04-02 21:54:49 +0000242 Bool mode64, chainingAllowed;
243 Addr64 max_ga;
sewardjf13a16a2004-07-05 17:10:14 +0000244
sewardj49651f42004-10-28 22:11:04 +0000245 guest_layout = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000246 available_real_regs = NULL;
247 n_available_real_regs = 0;
248 isMove = NULL;
249 getRegUsage = NULL;
250 mapRegs = NULL;
251 genSpill = NULL;
252 genReload = NULL;
sewardjfb7373a2007-08-25 21:29:03 +0000253 directReload = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000254 ppInstr = NULL;
255 ppReg = NULL;
sewardjdd40fdf2006-12-24 02:20:24 +0000256 iselSB = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000257 emit = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000258 specHelper = NULL;
sewardj8d2291c2004-10-25 14:50:21 +0000259 preciseMemExnsFn = NULL;
sewardj9e6491a2005-07-02 19:24:10 +0000260 disInstrFn = NULL;
sewardjcf787902004-11-03 09:08:33 +0000261 guest_word_type = Ity_INVALID;
262 host_word_type = Ity_INVALID;
sewardj05f5e012014-05-04 10:52:11 +0000263 offB_CMSTART = 0;
264 offB_CMLEN = 0;
sewardjc6f970f2012-04-02 21:54:49 +0000265 offB_GUEST_IP = 0;
266 szB_GUEST_IP = 0;
267 offB_HOST_EvC_COUNTER = 0;
268 offB_HOST_EvC_FAILADDR = 0;
cerion92b64362005-12-13 12:02:26 +0000269 mode64 = False;
sewardjc6f970f2012-04-02 21:54:49 +0000270 chainingAllowed = False;
sewardj36ca5132004-07-24 13:12:23 +0000271
sewardj17c7f952005-12-15 14:02:34 +0000272 vex_traceflags = vta->traceflags;
sewardj58800ff2004-07-28 01:51:10 +0000273
sewardj35421a32004-07-05 13:12:34 +0000274 vassert(vex_initdone);
sewardjc6f970f2012-04-02 21:54:49 +0000275 vassert(vta->needs_self_check != NULL);
276 vassert(vta->disp_cp_xassisted != NULL);
277 /* Both the chainers and the indir are either NULL or non-NULL. */
278 if (vta->disp_cp_chain_me_to_slowEP != NULL) {
279 vassert(vta->disp_cp_chain_me_to_fastEP != NULL);
280 vassert(vta->disp_cp_xindir != NULL);
281 chainingAllowed = True;
282 } else {
283 vassert(vta->disp_cp_chain_me_to_fastEP == NULL);
284 vassert(vta->disp_cp_xindir == NULL);
285 }
florian2eeeb9b2011-09-23 18:03:21 +0000286
sewardj2d6b14a2005-11-23 04:25:07 +0000287 vexSetAllocModeTEMP_and_clear();
288 vexAllocSanityCheck();
sewardj2a9ad022004-11-25 02:46:58 +0000289
sewardjf13a16a2004-07-05 17:10:14 +0000290 /* First off, check that the guest and host insn sets
291 are supported. */
sewardj2a9ad022004-11-25 02:46:58 +0000292
sewardj17c7f952005-12-15 14:02:34 +0000293 switch (vta->arch_host) {
sewardj2a9ad022004-11-25 02:46:58 +0000294
sewardjbef170b2004-12-21 01:23:00 +0000295 case VexArchX86:
sewardjfb7373a2007-08-25 21:29:03 +0000296 mode64 = False;
sewardjf13a16a2004-07-05 17:10:14 +0000297 getAllocableRegs_X86 ( &n_available_real_regs,
298 &available_real_regs );
sewardjfb7373a2007-08-25 21:29:03 +0000299 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000300 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
301 getRegUsage_X86Instr;
sewardjfb7373a2007-08-25 21:29:03 +0000302 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000303 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
304 genSpill_X86;
305 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
306 genReload_X86;
sewardjfb7373a2007-08-25 21:29:03 +0000307 directReload = (HInstr*(*)(HInstr*,HReg,Short)) directReload_X86;
308 ppInstr = (void(*)(HInstr*, Bool)) ppX86Instr;
309 ppReg = (void(*)(HReg)) ppHRegX86;
310 iselSB = iselSB_X86;
sewardj9b769162014-07-24 12:42:03 +0000311 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,VexEndness,
florian8462d112014-09-24 15:18:09 +0000312 const void*,const void*,const void*,
313 const void*))
sewardj010ac542011-05-29 09:29:18 +0000314 emit_X86Instr;
sewardjcf787902004-11-03 09:08:33 +0000315 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000316 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_host.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000317 vassert(vta->archinfo_host.endness == VexEndnessLE);
sewardjf13a16a2004-07-05 17:10:14 +0000318 break;
sewardj2a9ad022004-11-25 02:46:58 +0000319
sewardjc33671d2005-02-01 20:30:00 +0000320 case VexArchAMD64:
cerion92b64362005-12-13 12:02:26 +0000321 mode64 = True;
sewardjc33671d2005-02-01 20:30:00 +0000322 getAllocableRegs_AMD64 ( &n_available_real_regs,
323 &available_real_regs );
324 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000325 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
326 getRegUsage_AMD64Instr;
cerion92b64362005-12-13 12:02:26 +0000327 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000328 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
329 genSpill_AMD64;
330 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
331 genReload_AMD64;
cerion92b64362005-12-13 12:02:26 +0000332 ppInstr = (void(*)(HInstr*, Bool)) ppAMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000333 ppReg = (void(*)(HReg)) ppHRegAMD64;
sewardjdd40fdf2006-12-24 02:20:24 +0000334 iselSB = iselSB_AMD64;
sewardj9b769162014-07-24 12:42:03 +0000335 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,VexEndness,
florian8462d112014-09-24 15:18:09 +0000336 const void*,const void*,const void*,
337 const 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,
florian8462d112014-09-24 15:18:09 +0000357 const void*,const void*,const void*,
358 const void*))
sewardj010ac542011-05-29 09:29:18 +0000359 emit_PPCInstr;
cerion487e4c92005-02-04 16:28:19 +0000360 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000361 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_host.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000362 vassert(vta->archinfo_host.endness == VexEndnessBE);
cerion487e4c92005-02-04 16:28:19 +0000363 break;
364
cerionf0de28c2005-12-13 20:21:11 +0000365 case VexArchPPC64:
366 mode64 = True;
cerion5b2325f2005-12-23 00:55:09 +0000367 getAllocableRegs_PPC ( &n_available_real_regs,
368 &available_real_regs, mode64 );
369 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
370 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_PPCInstr;
371 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000372 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
373 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000374 ppInstr = (void(*)(HInstr*, Bool)) ppPPCInstr;
375 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000376 iselSB = iselSB_PPC;
sewardj9b769162014-07-24 12:42:03 +0000377 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,VexEndness,
florian8462d112014-09-24 15:18:09 +0000378 const void*,const void*,const void*,
379 const void*))
sewardj010ac542011-05-29 09:29:18 +0000380 emit_PPCInstr;
cerionf0de28c2005-12-13 20:21:11 +0000381 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000382 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_host.hwcaps));
carll1f5fe1f2014-08-07 23:25:23 +0000383 vassert(vta->archinfo_host.endness == VexEndnessBE ||
384 vta->archinfo_host.endness == VexEndnessLE );
cerionf0de28c2005-12-13 20:21:11 +0000385 break;
386
sewardj2019a972011-03-07 16:04:07 +0000387 case VexArchS390X:
388 mode64 = True;
389 getAllocableRegs_S390 ( &n_available_real_regs,
390 &available_real_regs, mode64 );
391 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_S390Instr;
392 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_S390Instr;
393 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_S390Instr;
394 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_S390;
395 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_S390;
396 ppInstr = (void(*)(HInstr*, Bool)) ppS390Instr;
397 ppReg = (void(*)(HReg)) ppHRegS390;
398 iselSB = iselSB_S390;
sewardj9b769162014-07-24 12:42:03 +0000399 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,VexEndness,
florian8462d112014-09-24 15:18:09 +0000400 const void*,const void*,const void*,
401 const void*))
402 emit_S390Instr;
sewardj2019a972011-03-07 16:04:07 +0000403 host_word_type = Ity_I64;
404 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_host.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000405 vassert(vta->archinfo_host.endness == VexEndnessBE);
sewardj2019a972011-03-07 16:04:07 +0000406 break;
407
sewardj6c299f32009-12-31 18:00:12 +0000408 case VexArchARM:
sewardj2a1ed8e2009-12-31 19:26:03 +0000409 mode64 = False;
sewardj6c299f32009-12-31 18:00:12 +0000410 getAllocableRegs_ARM ( &n_available_real_regs,
411 &available_real_regs );
sewardj2a1ed8e2009-12-31 19:26:03 +0000412 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARMInstr;
413 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_ARMInstr;
414 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_ARMInstr;
415 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_ARM;
416 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_ARM;
417 ppInstr = (void(*)(HInstr*, Bool)) ppARMInstr;
418 ppReg = (void(*)(HReg)) ppHRegARM;
419 iselSB = iselSB_ARM;
sewardj9b769162014-07-24 12:42:03 +0000420 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,VexEndness,
florian8462d112014-09-24 15:18:09 +0000421 const void*,const void*,const void*,
422 const void*))
sewardj010ac542011-05-29 09:29:18 +0000423 emit_ARMInstr;
sewardj6c299f32009-12-31 18:00:12 +0000424 host_word_type = Ity_I32;
425 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_host.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000426 vassert(vta->archinfo_host.endness == VexEndnessLE);
sewardj6c299f32009-12-31 18:00:12 +0000427 break;
428
sewardjbbcf1882014-01-12 12:49:10 +0000429 case VexArchARM64:
430 mode64 = True;
431 getAllocableRegs_ARM64 ( &n_available_real_regs,
432 &available_real_regs );
433 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARM64Instr;
434 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
435 getRegUsage_ARM64Instr;
436 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool))
437 mapRegs_ARM64Instr;
438 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
439 genSpill_ARM64;
440 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
441 genReload_ARM64;
442 ppInstr = (void(*)(HInstr*, Bool)) ppARM64Instr;
443 ppReg = (void(*)(HReg)) ppHRegARM64;
444 iselSB = iselSB_ARM64;
sewardj9b769162014-07-24 12:42:03 +0000445 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,VexEndness,
florian8462d112014-09-24 15:18:09 +0000446 const void*,const void*,const void*,
447 const void*))
sewardjbbcf1882014-01-12 12:49:10 +0000448 emit_ARM64Instr;
sewardjbbcf1882014-01-12 12:49:10 +0000449 host_word_type = Ity_I64;
450 vassert(are_valid_hwcaps(VexArchARM64, vta->archinfo_host.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000451 vassert(vta->archinfo_host.endness == VexEndnessLE);
sewardjbbcf1882014-01-12 12:49:10 +0000452 break;
453
sewardjd0e5fe72012-06-07 08:51:02 +0000454 case VexArchMIPS32:
455 mode64 = False;
456 getAllocableRegs_MIPS ( &n_available_real_regs,
457 &available_real_regs, mode64 );
458 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_MIPSInstr;
459 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_MIPSInstr;
460 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_MIPSInstr;
461 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_MIPS;
462 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_MIPS;
463 ppInstr = (void(*)(HInstr*, Bool)) ppMIPSInstr;
464 ppReg = (void(*)(HReg)) ppHRegMIPS;
465 iselSB = iselSB_MIPS;
sewardj9b769162014-07-24 12:42:03 +0000466 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,VexEndness,
florian8462d112014-09-24 15:18:09 +0000467 const void*,const void*,const void*,
468 const void*))
sewardjd0e5fe72012-06-07 08:51:02 +0000469 emit_MIPSInstr;
sewardjd0e5fe72012-06-07 08:51:02 +0000470 host_word_type = Ity_I32;
471 vassert(are_valid_hwcaps(VexArchMIPS32, vta->archinfo_host.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000472 vassert(vta->archinfo_host.endness == VexEndnessLE
473 || vta->archinfo_host.endness == VexEndnessBE);
sewardjd0e5fe72012-06-07 08:51:02 +0000474 break;
475
petarjb92a9542013-02-27 22:57:17 +0000476 case VexArchMIPS64:
477 mode64 = True;
478 getAllocableRegs_MIPS ( &n_available_real_regs,
479 &available_real_regs, mode64 );
480 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_MIPSInstr;
481 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_MIPSInstr;
482 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_MIPSInstr;
483 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_MIPS;
484 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_MIPS;
485 ppInstr = (void(*)(HInstr*, Bool)) ppMIPSInstr;
486 ppReg = (void(*)(HReg)) ppHRegMIPS;
487 iselSB = iselSB_MIPS;
sewardj9b769162014-07-24 12:42:03 +0000488 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,VexEndness,
florian8462d112014-09-24 15:18:09 +0000489 const void*,const void*,const void*,
490 const void*))
petarjb92a9542013-02-27 22:57:17 +0000491 emit_MIPSInstr;
petarjb92a9542013-02-27 22:57:17 +0000492 host_word_type = Ity_I64;
493 vassert(are_valid_hwcaps(VexArchMIPS64, vta->archinfo_host.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000494 vassert(vta->archinfo_host.endness == VexEndnessLE
495 || vta->archinfo_host.endness == VexEndnessBE);
petarjb92a9542013-02-27 22:57:17 +0000496 break;
497
sewardjf13a16a2004-07-05 17:10:14 +0000498 default:
sewardj6c299f32009-12-31 18:00:12 +0000499 vpanic("LibVEX_Translate: unsupported host insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000500 }
501
sewardj2a9ad022004-11-25 02:46:58 +0000502
sewardj17c7f952005-12-15 14:02:34 +0000503 switch (vta->arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000504
sewardjbef170b2004-12-21 01:23:00 +0000505 case VexArchX86:
sewardjc6f970f2012-04-02 21:54:49 +0000506 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
507 disInstrFn = disInstr_X86;
508 specHelper = guest_x86_spechelper;
509 guest_sizeB = sizeof(VexGuestX86State);
510 guest_word_type = Ity_I32;
511 guest_layout = &x86guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000512 offB_CMSTART = offsetof(VexGuestX86State,guest_CMSTART);
513 offB_CMLEN = offsetof(VexGuestX86State,guest_CMLEN);
sewardjc6f970f2012-04-02 21:54:49 +0000514 offB_GUEST_IP = offsetof(VexGuestX86State,guest_EIP);
515 szB_GUEST_IP = sizeof( ((VexGuestX86State*)0)->guest_EIP );
516 offB_HOST_EvC_COUNTER = offsetof(VexGuestX86State,host_EvC_COUNTER);
517 offB_HOST_EvC_FAILADDR = offsetof(VexGuestX86State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000518 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_guest.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000519 vassert(vta->archinfo_guest.endness == VexEndnessLE);
sewardj6c299f32009-12-31 18:00:12 +0000520 vassert(0 == sizeof(VexGuestX86State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000521 vassert(sizeof( ((VexGuestX86State*)0)->guest_CMSTART) == 4);
522 vassert(sizeof( ((VexGuestX86State*)0)->guest_CMLEN ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000523 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000524 break;
sewardj2a9ad022004-11-25 02:46:58 +0000525
sewardj44d494d2005-01-20 20:26:33 +0000526 case VexArchAMD64:
sewardjc6f970f2012-04-02 21:54:49 +0000527 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
528 disInstrFn = disInstr_AMD64;
529 specHelper = guest_amd64_spechelper;
530 guest_sizeB = sizeof(VexGuestAMD64State);
531 guest_word_type = Ity_I64;
532 guest_layout = &amd64guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000533 offB_CMSTART = offsetof(VexGuestAMD64State,guest_CMSTART);
534 offB_CMLEN = offsetof(VexGuestAMD64State,guest_CMLEN);
sewardjc6f970f2012-04-02 21:54:49 +0000535 offB_GUEST_IP = offsetof(VexGuestAMD64State,guest_RIP);
536 szB_GUEST_IP = sizeof( ((VexGuestAMD64State*)0)->guest_RIP );
537 offB_HOST_EvC_COUNTER = offsetof(VexGuestAMD64State,host_EvC_COUNTER);
538 offB_HOST_EvC_FAILADDR = offsetof(VexGuestAMD64State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000539 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_guest.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000540 vassert(vta->archinfo_guest.endness == VexEndnessLE);
sewardj6c299f32009-12-31 18:00:12 +0000541 vassert(0 == sizeof(VexGuestAMD64State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000542 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_CMSTART ) == 8);
543 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_CMLEN ) == 8);
sewardjce02aa72006-01-12 12:27:58 +0000544 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000545 break;
546
cerionaabdfbf2005-01-29 12:56:15 +0000547 case VexArchPPC32:
sewardj3dee8492012-04-20 00:13:28 +0000548 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
549 disInstrFn = disInstr_PPC;
550 specHelper = guest_ppc32_spechelper;
551 guest_sizeB = sizeof(VexGuestPPC32State);
552 guest_word_type = Ity_I32;
553 guest_layout = &ppc32Guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000554 offB_CMSTART = offsetof(VexGuestPPC32State,guest_CMSTART);
555 offB_CMLEN = offsetof(VexGuestPPC32State,guest_CMLEN);
sewardj3dee8492012-04-20 00:13:28 +0000556 offB_GUEST_IP = offsetof(VexGuestPPC32State,guest_CIA);
557 szB_GUEST_IP = sizeof( ((VexGuestPPC32State*)0)->guest_CIA );
558 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC32State,host_EvC_COUNTER);
559 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC32State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000560 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_guest.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000561 vassert(vta->archinfo_guest.endness == VexEndnessBE);
sewardj6c299f32009-12-31 18:00:12 +0000562 vassert(0 == sizeof(VexGuestPPC32State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000563 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_CMSTART ) == 4);
564 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_CMLEN ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000565 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000566 break;
567
cerionf0de28c2005-12-13 20:21:11 +0000568 case VexArchPPC64:
sewardj9e1cf152012-04-20 02:18:31 +0000569 preciseMemExnsFn = guest_ppc64_state_requires_precise_mem_exns;
570 disInstrFn = disInstr_PPC;
571 specHelper = guest_ppc64_spechelper;
572 guest_sizeB = sizeof(VexGuestPPC64State);
573 guest_word_type = Ity_I64;
574 guest_layout = &ppc64Guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000575 offB_CMSTART = offsetof(VexGuestPPC64State,guest_CMSTART);
576 offB_CMLEN = offsetof(VexGuestPPC64State,guest_CMLEN);
sewardj9e1cf152012-04-20 02:18:31 +0000577 offB_GUEST_IP = offsetof(VexGuestPPC64State,guest_CIA);
578 szB_GUEST_IP = sizeof( ((VexGuestPPC64State*)0)->guest_CIA );
579 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC64State,host_EvC_COUNTER);
580 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC64State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000581 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_guest.hwcaps));
carll1f5fe1f2014-08-07 23:25:23 +0000582 vassert(vta->archinfo_guest.endness == VexEndnessBE ||
583 vta->archinfo_guest.endness == VexEndnessLE );
cerionf0de28c2005-12-13 20:21:11 +0000584 vassert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000585 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_CMSTART ) == 8);
586 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_CMLEN ) == 8);
sewardj3fd39672006-01-27 22:05:55 +0000587 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8);
588 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8);
cerionf0de28c2005-12-13 20:21:11 +0000589 break;
590
sewardj2019a972011-03-07 16:04:07 +0000591 case VexArchS390X:
592 preciseMemExnsFn = guest_s390x_state_requires_precise_mem_exns;
593 disInstrFn = disInstr_S390;
594 specHelper = guest_s390x_spechelper;
595 guest_sizeB = sizeof(VexGuestS390XState);
596 guest_word_type = Ity_I64;
597 guest_layout = &s390xGuest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000598 offB_CMSTART = offsetof(VexGuestS390XState,guest_CMSTART);
599 offB_CMLEN = offsetof(VexGuestS390XState,guest_CMLEN);
florian8844a632012-04-13 04:04:06 +0000600 offB_GUEST_IP = offsetof(VexGuestS390XState,guest_IA);
601 szB_GUEST_IP = sizeof( ((VexGuestS390XState*)0)->guest_IA);
602 offB_HOST_EvC_COUNTER = offsetof(VexGuestS390XState,host_EvC_COUNTER);
603 offB_HOST_EvC_FAILADDR = offsetof(VexGuestS390XState,host_EvC_FAILADDR);
sewardj2019a972011-03-07 16:04:07 +0000604 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_guest.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000605 vassert(vta->archinfo_guest.endness == VexEndnessBE);
sewardj2019a972011-03-07 16:04:07 +0000606 vassert(0 == sizeof(VexGuestS390XState) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000607 vassert(sizeof( ((VexGuestS390XState*)0)->guest_CMSTART ) == 8);
608 vassert(sizeof( ((VexGuestS390XState*)0)->guest_CMLEN ) == 8);
sewardj2019a972011-03-07 16:04:07 +0000609 vassert(sizeof( ((VexGuestS390XState*)0)->guest_NRADDR ) == 8);
610 break;
611
sewardj6c299f32009-12-31 18:00:12 +0000612 case VexArchARM:
sewardjc6f970f2012-04-02 21:54:49 +0000613 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
614 disInstrFn = disInstr_ARM;
615 specHelper = guest_arm_spechelper;
616 guest_sizeB = sizeof(VexGuestARMState);
617 guest_word_type = Ity_I32;
618 guest_layout = &armGuest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000619 offB_CMSTART = offsetof(VexGuestARMState,guest_CMSTART);
620 offB_CMLEN = offsetof(VexGuestARMState,guest_CMLEN);
sewardjc6f970f2012-04-02 21:54:49 +0000621 offB_GUEST_IP = offsetof(VexGuestARMState,guest_R15T);
622 szB_GUEST_IP = sizeof( ((VexGuestARMState*)0)->guest_R15T );
623 offB_HOST_EvC_COUNTER = offsetof(VexGuestARMState,host_EvC_COUNTER);
624 offB_HOST_EvC_FAILADDR = offsetof(VexGuestARMState,host_EvC_FAILADDR);
sewardj6c299f32009-12-31 18:00:12 +0000625 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_guest.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000626 vassert(vta->archinfo_guest.endness == VexEndnessLE);
sewardj6c299f32009-12-31 18:00:12 +0000627 vassert(0 == sizeof(VexGuestARMState) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000628 vassert(sizeof( ((VexGuestARMState*)0)->guest_CMSTART) == 4);
629 vassert(sizeof( ((VexGuestARMState*)0)->guest_CMLEN ) == 4);
sewardj6c299f32009-12-31 18:00:12 +0000630 vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4);
631 break;
632
sewardjbbcf1882014-01-12 12:49:10 +0000633 case VexArchARM64:
634 preciseMemExnsFn = guest_arm64_state_requires_precise_mem_exns;
635 disInstrFn = disInstr_ARM64;
636 specHelper = guest_arm64_spechelper;
637 guest_sizeB = sizeof(VexGuestARM64State);
638 guest_word_type = Ity_I64;
639 guest_layout = &arm64Guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000640 offB_CMSTART = offsetof(VexGuestARM64State,guest_CMSTART);
641 offB_CMLEN = offsetof(VexGuestARM64State,guest_CMLEN);
sewardjbbcf1882014-01-12 12:49:10 +0000642 offB_GUEST_IP = offsetof(VexGuestARM64State,guest_PC);
643 szB_GUEST_IP = sizeof( ((VexGuestARM64State*)0)->guest_PC );
644 offB_HOST_EvC_COUNTER = offsetof(VexGuestARM64State,host_EvC_COUNTER);
645 offB_HOST_EvC_FAILADDR = offsetof(VexGuestARM64State,host_EvC_FAILADDR);
646 vassert(are_valid_hwcaps(VexArchARM64, vta->archinfo_guest.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000647 vassert(vta->archinfo_guest.endness == VexEndnessLE);
sewardjbbcf1882014-01-12 12:49:10 +0000648 vassert(0 == sizeof(VexGuestARM64State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000649 vassert(sizeof( ((VexGuestARM64State*)0)->guest_CMSTART) == 8);
650 vassert(sizeof( ((VexGuestARM64State*)0)->guest_CMLEN ) == 8);
sewardjbbcf1882014-01-12 12:49:10 +0000651 vassert(sizeof( ((VexGuestARM64State*)0)->guest_NRADDR ) == 8);
652 break;
653
sewardjd0e5fe72012-06-07 08:51:02 +0000654 case VexArchMIPS32:
655 preciseMemExnsFn = guest_mips32_state_requires_precise_mem_exns;
656 disInstrFn = disInstr_MIPS;
657 specHelper = guest_mips32_spechelper;
658 guest_sizeB = sizeof(VexGuestMIPS32State);
659 guest_word_type = Ity_I32;
660 guest_layout = &mips32Guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000661 offB_CMSTART = offsetof(VexGuestMIPS32State,guest_CMSTART);
662 offB_CMLEN = offsetof(VexGuestMIPS32State,guest_CMLEN);
sewardjd0e5fe72012-06-07 08:51:02 +0000663 offB_GUEST_IP = offsetof(VexGuestMIPS32State,guest_PC);
664 szB_GUEST_IP = sizeof( ((VexGuestMIPS32State*)0)->guest_PC );
665 offB_HOST_EvC_COUNTER = offsetof(VexGuestMIPS32State,host_EvC_COUNTER);
666 offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS32State,host_EvC_FAILADDR);
667 vassert(are_valid_hwcaps(VexArchMIPS32, vta->archinfo_guest.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000668 vassert(vta->archinfo_guest.endness == VexEndnessLE
669 || vta->archinfo_guest.endness == VexEndnessBE);
sewardjd0e5fe72012-06-07 08:51:02 +0000670 vassert(0 == sizeof(VexGuestMIPS32State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000671 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_CMSTART) == 4);
672 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_CMLEN ) == 4);
sewardjd0e5fe72012-06-07 08:51:02 +0000673 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_NRADDR ) == 4);
674 break;
675
petarjb92a9542013-02-27 22:57:17 +0000676 case VexArchMIPS64:
677 preciseMemExnsFn = guest_mips64_state_requires_precise_mem_exns;
678 disInstrFn = disInstr_MIPS;
679 specHelper = guest_mips64_spechelper;
680 guest_sizeB = sizeof(VexGuestMIPS64State);
681 guest_word_type = Ity_I64;
682 guest_layout = &mips64Guest_layout;
sewardj05f5e012014-05-04 10:52:11 +0000683 offB_CMSTART = offsetof(VexGuestMIPS64State,guest_CMSTART);
684 offB_CMLEN = offsetof(VexGuestMIPS64State,guest_CMLEN);
petarjb92a9542013-02-27 22:57:17 +0000685 offB_GUEST_IP = offsetof(VexGuestMIPS64State,guest_PC);
686 szB_GUEST_IP = sizeof( ((VexGuestMIPS64State*)0)->guest_PC );
687 offB_HOST_EvC_COUNTER = offsetof(VexGuestMIPS64State,host_EvC_COUNTER);
688 offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS64State,host_EvC_FAILADDR);
689 vassert(are_valid_hwcaps(VexArchMIPS64, vta->archinfo_guest.hwcaps));
sewardj9b769162014-07-24 12:42:03 +0000690 vassert(vta->archinfo_guest.endness == VexEndnessLE
691 || vta->archinfo_guest.endness == VexEndnessBE);
petarjb92a9542013-02-27 22:57:17 +0000692 vassert(0 == sizeof(VexGuestMIPS64State) % 16);
sewardj05f5e012014-05-04 10:52:11 +0000693 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_CMSTART) == 8);
694 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_CMLEN ) == 8);
petarjb92a9542013-02-27 22:57:17 +0000695 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_NRADDR ) == 8);
696 break;
697
sewardjf13a16a2004-07-05 17:10:14 +0000698 default:
sewardj887a11a2004-07-05 17:26:47 +0000699 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000700 }
701
sewardjbc161a42011-06-07 21:28:38 +0000702 /* Set up result struct. */
703 VexTranslateResult res;
sewardjfadbbe22012-04-24 11:49:03 +0000704 res.status = VexTransOK;
705 res.n_sc_extents = 0;
706 res.offs_profInc = -1;
707 res.n_guest_instrs = 0;
sewardjbc161a42011-06-07 21:28:38 +0000708
sewardj9df271d2004-12-31 22:37:42 +0000709 /* yet more sanity checks ... */
sewardj17c7f952005-12-15 14:02:34 +0000710 if (vta->arch_guest == vta->arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000711 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000712 we are simulating one flavour of an architecture a different
713 flavour of the same architecture, which is pretty strange. */
sewardj5117ce12006-01-27 21:20:15 +0000714 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps);
sewardj9b769162014-07-24 12:42:03 +0000715 /* ditto */
716 vassert(vta->archinfo_guest.endness == vta->archinfo_host.endness);
sewardj9df271d2004-12-31 22:37:42 +0000717 }
sewardj2a9ad022004-11-25 02:46:58 +0000718
sewardj2d6b14a2005-11-23 04:25:07 +0000719 vexAllocSanityCheck();
720
sewardjf48ac192004-10-29 00:41:29 +0000721 if (vex_traceflags & VEX_TRACE_FE)
722 vex_printf("\n------------------------"
723 " Front end "
724 "------------------------\n\n");
725
sewardjdd40fdf2006-12-24 02:20:24 +0000726 irsb = bb_to_IR ( vta->guest_extents,
sewardjbc161a42011-06-07 21:28:38 +0000727 &res.n_sc_extents,
sewardjfadbbe22012-04-24 11:49:03 +0000728 &res.n_guest_instrs,
sewardjc716aea2006-01-17 01:48:46 +0000729 vta->callback_opaque,
sewardj9e6491a2005-07-02 19:24:10 +0000730 disInstrFn,
sewardj17c7f952005-12-15 14:02:34 +0000731 vta->guest_bytes,
732 vta->guest_bytes_addr,
733 vta->chase_into_ok,
sewardj9b769162014-07-24 12:42:03 +0000734 vta->archinfo_host.endness,
sewardj442e51a2012-12-06 18:08:04 +0000735 vta->sigill_diag,
sewardja5f55da2006-04-30 23:37:32 +0000736 vta->arch_guest,
sewardj17c7f952005-12-15 14:02:34 +0000737 &vta->archinfo_guest,
sewardjdd40fdf2006-12-24 02:20:24 +0000738 &vta->abiinfo_both,
sewardjdb4738a2005-07-07 01:32:16 +0000739 guest_word_type,
sewardjbc161a42011-06-07 21:28:38 +0000740 vta->needs_self_check,
sewardjc716aea2006-01-17 01:48:46 +0000741 vta->preamble_function,
sewardj05f5e012014-05-04 10:52:11 +0000742 offB_CMSTART,
743 offB_CMLEN,
sewardjc6f970f2012-04-02 21:54:49 +0000744 offB_GUEST_IP,
745 szB_GUEST_IP );
sewardjf13a16a2004-07-05 17:10:14 +0000746
sewardj2d6b14a2005-11-23 04:25:07 +0000747 vexAllocSanityCheck();
748
sewardjdd40fdf2006-12-24 02:20:24 +0000749 if (irsb == NULL) {
sewardjf13a16a2004-07-05 17:10:14 +0000750 /* Access failure. */
sewardj2d6b14a2005-11-23 04:25:07 +0000751 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000752 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000753 res.status = VexTransAccessFail; return res;
sewardjf13a16a2004-07-05 17:10:14 +0000754 }
sewardjaa59f942004-10-09 09:34:36 +0000755
sewardj17c7f952005-12-15 14:02:34 +0000756 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3);
757 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr);
758 for (i = 0; i < vta->guest_extents->n_used; i++) {
759 vassert(vta->guest_extents->len[i] < 10000); /* sanity */
sewardj72c72812005-01-19 11:49:45 +0000760 }
761
sewardjaa59f942004-10-09 09:34:36 +0000762 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000763 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj17c7f952005-12-15 14:02:34 +0000764 if (vta->guest_extents->n_used > 1) {
sewardj72c72812005-01-19 11:49:45 +0000765 vex_printf("can't show code due to extents > 1\n");
766 } else {
767 /* HACK */
florian8462d112014-09-24 15:18:09 +0000768 const UChar* p = vta->guest_bytes;
sewardj01f8cce2009-08-31 08:50:02 +0000769 UInt sum = 0;
sewardj17c7f952005-12-15 14:02:34 +0000770 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0];
sewardj01f8cce2009-08-31 08:50:02 +0000771 vex_printf("GuestBytes %llx %u ", vta->guest_bytes_addr,
772 guest_bytes_read );
773 for (i = 0; i < guest_bytes_read; i++) {
774 UInt b = (UInt)p[i];
775 vex_printf(" %02x", b );
776 sum = (sum << 1) ^ b;
777 }
778 vex_printf(" %08x\n\n", sum);
sewardj72c72812005-01-19 11:49:45 +0000779 }
sewardjaa59f942004-10-09 09:34:36 +0000780 }
781
782 /* Sanity check the initial IR. */
sewardjdd40fdf2006-12-24 02:20:24 +0000783 sanityCheckIRSB( irsb, "initial IR",
sewardjb9230752004-12-29 19:25:06 +0000784 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000785
sewardj2d6b14a2005-11-23 04:25:07 +0000786 vexAllocSanityCheck();
787
sewardjedf4d692004-08-17 13:52:58 +0000788 /* Clean it up, hopefully a lot. */
sewardjdd40fdf2006-12-24 02:20:24 +0000789 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn,
sewardjec0d9a02010-08-22 12:54:56 +0000790 vta->guest_bytes_addr,
791 vta->arch_guest );
sewardjdd40fdf2006-12-24 02:20:24 +0000792 sanityCheckIRSB( irsb, "after initial iropt",
sewardjb9230752004-12-29 19:25:06 +0000793 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000794
sewardjf48ac192004-10-29 00:41:29 +0000795 if (vex_traceflags & VEX_TRACE_OPT1) {
796 vex_printf("\n------------------------"
797 " After pre-instr IR optimisation "
798 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000799 ppIRSB ( irsb );
sewardjedf4d692004-08-17 13:52:58 +0000800 vex_printf("\n");
801 }
802
sewardj2d6b14a2005-11-23 04:25:07 +0000803 vexAllocSanityCheck();
804
sewardjf13a16a2004-07-05 17:10:14 +0000805 /* Get the thing instrumented. */
sewardj17c7f952005-12-15 14:02:34 +0000806 if (vta->instrument1)
sewardjdd40fdf2006-12-24 02:20:24 +0000807 irsb = vta->instrument1(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);
sewardj2d6b14a2005-11-23 04:25:07 +0000812 vexAllocSanityCheck();
813
sewardj17c7f952005-12-15 14:02:34 +0000814 if (vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000815 irsb = vta->instrument2(vta->callback_opaque,
816 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000817 vta->guest_extents,
florian50481922012-10-07 21:58:07 +0000818 &vta->archinfo_host,
sewardj17c7f952005-12-15 14:02:34 +0000819 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000820
sewardjf48ac192004-10-29 00:41:29 +0000821 if (vex_traceflags & VEX_TRACE_INST) {
822 vex_printf("\n------------------------"
823 " After instrumentation "
824 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000825 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000826 vex_printf("\n");
827 }
828
sewardj17c7f952005-12-15 14:02:34 +0000829 if (vta->instrument1 || vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000830 sanityCheckIRSB( irsb, "after instrumentation",
sewardjb9230752004-12-29 19:25:06 +0000831 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000832
sewardj9578a8b2004-11-04 19:44:48 +0000833 /* Do a post-instrumentation cleanup pass. */
sewardj17c7f952005-12-15 14:02:34 +0000834 if (vta->instrument1 || vta->instrument2) {
sewardjdd40fdf2006-12-24 02:20:24 +0000835 do_deadcode_BB( irsb );
836 irsb = cprop_BB( irsb );
837 do_deadcode_BB( irsb );
838 sanityCheckIRSB( irsb, "after post-instrumentation cleanup",
sewardjb9230752004-12-29 19:25:06 +0000839 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000840 }
841
sewardj2d6b14a2005-11-23 04:25:07 +0000842 vexAllocSanityCheck();
843
sewardj9578a8b2004-11-04 19:44:48 +0000844 if (vex_traceflags & VEX_TRACE_OPT2) {
845 vex_printf("\n------------------------"
846 " After post-instr IR optimisation "
847 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000848 ppIRSB ( irsb );
sewardj9578a8b2004-11-04 19:44:48 +0000849 vex_printf("\n");
850 }
851
sewardjf9517d02005-11-28 13:39:37 +0000852 /* Turn it into virtual-registerised code. Build trees -- this
853 also throws away any dead bindings. */
florian62140c12013-01-20 03:51:04 +0000854 max_ga = ado_treebuild_BB( irsb, preciseMemExnsFn );
sewardjf48ac192004-10-29 00:41:29 +0000855
sewardjbe1b6ff2007-08-28 06:06:27 +0000856 if (vta->finaltidy) {
857 irsb = vta->finaltidy(irsb);
858 }
859
sewardj2d6b14a2005-11-23 04:25:07 +0000860 vexAllocSanityCheck();
861
sewardjf48ac192004-10-29 00:41:29 +0000862 if (vex_traceflags & VEX_TRACE_TREES) {
863 vex_printf("\n------------------------"
864 " After tree-building "
865 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000866 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000867 vex_printf("\n");
868 }
869
sewardje908c422005-02-04 21:18:16 +0000870 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000871 if (0) {
872 *(vta->host_bytes_used) = 0;
873 res.status = VexTransOK; return res;
874 }
sewardje908c422005-02-04 21:18:16 +0000875 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000876
sewardjf48ac192004-10-29 00:41:29 +0000877 if (vex_traceflags & VEX_TRACE_VCODE)
878 vex_printf("\n------------------------"
879 " Instruction selection "
880 "------------------------\n");
881
sewardjc6f970f2012-04-02 21:54:49 +0000882 /* No guest has its IP field at offset zero. If this fails it
883 means some transformation pass somewhere failed to update/copy
884 irsb->offsIP properly. */
885 vassert(irsb->offsIP >= 16);
886
887 vcode = iselSB ( irsb, vta->arch_host,
888 &vta->archinfo_host,
889 &vta->abiinfo_both,
890 offB_HOST_EvC_COUNTER,
891 offB_HOST_EvC_FAILADDR,
892 chainingAllowed,
893 vta->addProfInc,
894 max_ga );
sewardjf13a16a2004-07-05 17:10:14 +0000895
sewardj2d6b14a2005-11-23 04:25:07 +0000896 vexAllocSanityCheck();
897
sewardjf48ac192004-10-29 00:41:29 +0000898 if (vex_traceflags & VEX_TRACE_VCODE)
899 vex_printf("\n");
900
sewardjf48ac192004-10-29 00:41:29 +0000901 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000902 for (i = 0; i < vcode->arr_used; i++) {
903 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000904 ppInstr(vcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000905 vex_printf("\n");
906 }
sewardjfbcaf332004-07-08 01:46:01 +0000907 vex_printf("\n");
908 }
sewardjfbcaf332004-07-08 01:46:01 +0000909
sewardjf13a16a2004-07-05 17:10:14 +0000910 /* Register allocate. */
911 rcode = doRegisterAllocation ( vcode, available_real_regs,
cerionf0de28c2005-12-13 20:21:11 +0000912 n_available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000913 isMove, getRegUsage, mapRegs,
sewardjfb7373a2007-08-25 21:29:03 +0000914 genSpill, genReload, directReload,
915 guest_sizeB,
cerion92b64362005-12-13 12:02:26 +0000916 ppInstr, ppReg, mode64 );
sewardjf13a16a2004-07-05 17:10:14 +0000917
sewardj2d6b14a2005-11-23 04:25:07 +0000918 vexAllocSanityCheck();
919
sewardjf48ac192004-10-29 00:41:29 +0000920 if (vex_traceflags & VEX_TRACE_RCODE) {
921 vex_printf("\n------------------------"
922 " Register-allocated code "
923 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000924 for (i = 0; i < rcode->arr_used; i++) {
925 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000926 ppInstr(rcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000927 vex_printf("\n");
928 }
sewardjfbcaf332004-07-08 01:46:01 +0000929 vex_printf("\n");
930 }
sewardjfbcaf332004-07-08 01:46:01 +0000931
sewardje908c422005-02-04 21:18:16 +0000932 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000933 if (0) {
934 *(vta->host_bytes_used) = 0;
935 res.status = VexTransOK; return res;
936 }
sewardje908c422005-02-04 21:18:16 +0000937 /* end HACK */
938
sewardj81bd5502004-07-21 18:49:27 +0000939 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000940 if (vex_traceflags & VEX_TRACE_ASM) {
941 vex_printf("\n------------------------"
942 " Assembly "
943 "------------------------\n\n");
944 }
945
sewardj81bd5502004-07-21 18:49:27 +0000946 out_used = 0; /* tracks along the host_bytes array */
947 for (i = 0; i < rcode->arr_used; i++) {
sewardjc6f970f2012-04-02 21:54:49 +0000948 HInstr* hi = rcode->arr[i];
949 Bool hi_isProfInc = False;
950 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
951 ppInstr(hi, mode64);
sewardjbad34a92004-07-22 01:14:11 +0000952 vex_printf("\n");
953 }
sewardjc6f970f2012-04-02 21:54:49 +0000954 j = emit( &hi_isProfInc,
sewardj9b769162014-07-24 12:42:03 +0000955 insn_bytes, sizeof insn_bytes, hi,
956 mode64, vta->archinfo_host.endness,
sewardjc6f970f2012-04-02 21:54:49 +0000957 vta->disp_cp_chain_me_to_slowEP,
958 vta->disp_cp_chain_me_to_fastEP,
959 vta->disp_cp_xindir,
960 vta->disp_cp_xassisted );
961 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
sewardjbad34a92004-07-22 01:14:11 +0000962 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000963 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000964 vex_printf("0%x ", (UInt)insn_bytes[k]);
965 else
966 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000967 vex_printf("\n\n");
968 }
sewardjc6f970f2012-04-02 21:54:49 +0000969 if (UNLIKELY(out_used + j > vta->host_bytes_size)) {
sewardj2d6b14a2005-11-23 04:25:07 +0000970 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000971 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000972 res.status = VexTransOutputFull;
973 return res;
sewardj81bd5502004-07-21 18:49:27 +0000974 }
sewardjc6f970f2012-04-02 21:54:49 +0000975 if (UNLIKELY(hi_isProfInc)) {
976 vassert(vta->addProfInc); /* else where did it come from? */
977 vassert(res.offs_profInc == -1); /* there can be only one (tm) */
978 vassert(out_used >= 0);
979 res.offs_profInc = out_used;
980 }
981 { UChar* dst = &vta->host_bytes[out_used];
982 for (k = 0; k < j; k++) {
983 dst[k] = insn_bytes[k];
984 }
985 out_used += j;
sewardj81bd5502004-07-21 18:49:27 +0000986 }
sewardj17c7f952005-12-15 14:02:34 +0000987 vassert(out_used <= vta->host_bytes_size);
sewardj81bd5502004-07-21 18:49:27 +0000988 }
sewardj17c7f952005-12-15 14:02:34 +0000989 *(vta->host_bytes_used) = out_used;
sewardj81bd5502004-07-21 18:49:27 +0000990
sewardj2d6b14a2005-11-23 04:25:07 +0000991 vexAllocSanityCheck();
992
993 vexSetAllocModeTEMP_and_clear();
sewardjf13a16a2004-07-05 17:10:14 +0000994
sewardj65ea17e2012-12-28 09:01:59 +0000995 if (vex_traceflags) {
996 /* Print the expansion ratio for this SB. */
997 j = 0; /* total guest bytes */
998 for (i = 0; i < vta->guest_extents->n_used; i++) {
999 j += vta->guest_extents->len[i];
1000 }
1001 if (1) vex_printf("VexExpansionRatio %d %d %d :10\n\n",
1002 j, out_used, (10 * out_used) / (j == 0 ? 1 : j));
1003 }
1004
sewardjf48ac192004-10-29 00:41:29 +00001005 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +00001006 res.status = VexTransOK;
1007 return res;
sewardj35421a32004-07-05 13:12:34 +00001008}
1009
1010
sewardjc6f970f2012-04-02 21:54:49 +00001011/* --------- Chain/Unchain XDirects. --------- */
1012
florian7d6f81d2014-09-22 21:43:37 +00001013VexInvalRange LibVEX_Chain ( VexArch arch_host,
1014 VexEndness endness_host,
1015 void* place_to_chain,
1016 const void* disp_cp_chain_me_EXPECTED,
1017 const void* place_to_jump_to )
sewardjc6f970f2012-04-02 21:54:49 +00001018{
sewardjc6f970f2012-04-02 21:54:49 +00001019 switch (arch_host) {
1020 case VexArchX86:
florian7d6f81d2014-09-22 21:43:37 +00001021 return chainXDirect_X86(endness_host,
1022 place_to_chain,
1023 disp_cp_chain_me_EXPECTED,
1024 place_to_jump_to);
sewardjc6f970f2012-04-02 21:54:49 +00001025 case VexArchAMD64:
florian7d6f81d2014-09-22 21:43:37 +00001026 return chainXDirect_AMD64(endness_host,
1027 place_to_chain,
1028 disp_cp_chain_me_EXPECTED,
1029 place_to_jump_to);
sewardjc6f970f2012-04-02 21:54:49 +00001030 case VexArchARM:
florian7d6f81d2014-09-22 21:43:37 +00001031 return chainXDirect_ARM(endness_host,
1032 place_to_chain,
1033 disp_cp_chain_me_EXPECTED,
1034 place_to_jump_to);
sewardjbbcf1882014-01-12 12:49:10 +00001035 case VexArchARM64:
florian7d6f81d2014-09-22 21:43:37 +00001036 return chainXDirect_ARM64(endness_host,
1037 place_to_chain,
1038 disp_cp_chain_me_EXPECTED,
1039 place_to_jump_to);
florian8844a632012-04-13 04:04:06 +00001040 case VexArchS390X:
florian7d6f81d2014-09-22 21:43:37 +00001041 return chainXDirect_S390(endness_host,
1042 place_to_chain,
1043 disp_cp_chain_me_EXPECTED,
1044 place_to_jump_to);
sewardj3dee8492012-04-20 00:13:28 +00001045 case VexArchPPC32:
sewardj9b769162014-07-24 12:42:03 +00001046 return chainXDirect_PPC(endness_host,
1047 place_to_chain,
sewardj3dee8492012-04-20 00:13:28 +00001048 disp_cp_chain_me_EXPECTED,
1049 place_to_jump_to, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +00001050 case VexArchPPC64:
sewardj9b769162014-07-24 12:42:03 +00001051 return chainXDirect_PPC(endness_host,
1052 place_to_chain,
sewardjf252de52012-04-20 10:42:24 +00001053 disp_cp_chain_me_EXPECTED,
1054 place_to_jump_to, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +00001055 case VexArchMIPS32:
sewardj9b769162014-07-24 12:42:03 +00001056 return chainXDirect_MIPS(endness_host,
1057 place_to_chain,
sewardjd0e5fe72012-06-07 08:51:02 +00001058 disp_cp_chain_me_EXPECTED,
1059 place_to_jump_to, False/*!mode64*/);
petarjb92a9542013-02-27 22:57:17 +00001060 case VexArchMIPS64:
sewardj9b769162014-07-24 12:42:03 +00001061 return chainXDirect_MIPS(endness_host,
1062 place_to_chain,
petarjb92a9542013-02-27 22:57:17 +00001063 disp_cp_chain_me_EXPECTED,
1064 place_to_jump_to, True/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +00001065 default:
1066 vassert(0);
1067 }
sewardjc6f970f2012-04-02 21:54:49 +00001068}
1069
florian7d6f81d2014-09-22 21:43:37 +00001070VexInvalRange LibVEX_UnChain ( VexArch arch_host,
1071 VexEndness endness_host,
1072 void* place_to_unchain,
1073 const void* place_to_jump_to_EXPECTED,
1074 const void* disp_cp_chain_me )
sewardjc6f970f2012-04-02 21:54:49 +00001075{
sewardjc6f970f2012-04-02 21:54:49 +00001076 switch (arch_host) {
1077 case VexArchX86:
florian7d6f81d2014-09-22 21:43:37 +00001078 return unchainXDirect_X86(endness_host,
1079 place_to_unchain,
1080 place_to_jump_to_EXPECTED,
1081 disp_cp_chain_me);
sewardjc6f970f2012-04-02 21:54:49 +00001082 case VexArchAMD64:
florian7d6f81d2014-09-22 21:43:37 +00001083 return unchainXDirect_AMD64(endness_host,
1084 place_to_unchain,
1085 place_to_jump_to_EXPECTED,
1086 disp_cp_chain_me);
sewardjc6f970f2012-04-02 21:54:49 +00001087 case VexArchARM:
florian7d6f81d2014-09-22 21:43:37 +00001088 return unchainXDirect_ARM(endness_host,
1089 place_to_unchain,
1090 place_to_jump_to_EXPECTED,
1091 disp_cp_chain_me);
sewardjc6acaa42014-02-19 17:42:59 +00001092 case VexArchARM64:
florian7d6f81d2014-09-22 21:43:37 +00001093 return unchainXDirect_ARM64(endness_host,
1094 place_to_unchain,
1095 place_to_jump_to_EXPECTED,
1096 disp_cp_chain_me);
florian8844a632012-04-13 04:04:06 +00001097 case VexArchS390X:
florian7d6f81d2014-09-22 21:43:37 +00001098 return unchainXDirect_S390(endness_host,
1099 place_to_unchain,
1100 place_to_jump_to_EXPECTED,
1101 disp_cp_chain_me);
sewardj3dee8492012-04-20 00:13:28 +00001102 case VexArchPPC32:
sewardj9b769162014-07-24 12:42:03 +00001103 return unchainXDirect_PPC(endness_host,
1104 place_to_unchain,
sewardj3dee8492012-04-20 00:13:28 +00001105 place_to_jump_to_EXPECTED,
1106 disp_cp_chain_me, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +00001107 case VexArchPPC64:
sewardj9b769162014-07-24 12:42:03 +00001108 return unchainXDirect_PPC(endness_host,
1109 place_to_unchain,
sewardjf252de52012-04-20 10:42:24 +00001110 place_to_jump_to_EXPECTED,
1111 disp_cp_chain_me, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +00001112 case VexArchMIPS32:
sewardj9b769162014-07-24 12:42:03 +00001113 return unchainXDirect_MIPS(endness_host,
1114 place_to_unchain,
petarjb92a9542013-02-27 22:57:17 +00001115 place_to_jump_to_EXPECTED,
1116 disp_cp_chain_me, False/*!mode64*/);
1117 case VexArchMIPS64:
sewardj9b769162014-07-24 12:42:03 +00001118 return unchainXDirect_MIPS(endness_host,
1119 place_to_unchain,
petarjb92a9542013-02-27 22:57:17 +00001120 place_to_jump_to_EXPECTED,
1121 disp_cp_chain_me, True/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +00001122 default:
1123 vassert(0);
1124 }
sewardjc6f970f2012-04-02 21:54:49 +00001125}
1126
sewardj9b769162014-07-24 12:42:03 +00001127Int LibVEX_evCheckSzB ( VexArch arch_host,
1128 VexEndness endness_host )
sewardjc6f970f2012-04-02 21:54:49 +00001129{
1130 static Int cached = 0; /* DO NOT MAKE NON-STATIC */
1131 if (UNLIKELY(cached == 0)) {
1132 switch (arch_host) {
1133 case VexArchX86:
sewardj9b769162014-07-24 12:42:03 +00001134 cached = evCheckSzB_X86(endness_host); break;
sewardjc6f970f2012-04-02 21:54:49 +00001135 case VexArchAMD64:
sewardj9b769162014-07-24 12:42:03 +00001136 cached = evCheckSzB_AMD64(endness_host); break;
sewardjc6f970f2012-04-02 21:54:49 +00001137 case VexArchARM:
sewardj9b769162014-07-24 12:42:03 +00001138 cached = evCheckSzB_ARM(endness_host); break;
sewardjbbcf1882014-01-12 12:49:10 +00001139 case VexArchARM64:
sewardj9b769162014-07-24 12:42:03 +00001140 cached = evCheckSzB_ARM64(endness_host); break;
florian8844a632012-04-13 04:04:06 +00001141 case VexArchS390X:
sewardj9b769162014-07-24 12:42:03 +00001142 cached = evCheckSzB_S390(endness_host); break;
sewardj3dee8492012-04-20 00:13:28 +00001143 case VexArchPPC32:
sewardjf252de52012-04-20 10:42:24 +00001144 case VexArchPPC64:
sewardj9b769162014-07-24 12:42:03 +00001145 cached = evCheckSzB_PPC(endness_host); break;
sewardjd0e5fe72012-06-07 08:51:02 +00001146 case VexArchMIPS32:
petarjb92a9542013-02-27 22:57:17 +00001147 case VexArchMIPS64:
sewardj9b769162014-07-24 12:42:03 +00001148 cached = evCheckSzB_MIPS(endness_host); break;
sewardjc6f970f2012-04-02 21:54:49 +00001149 default:
1150 vassert(0);
1151 }
1152 }
1153 return cached;
1154}
1155
sewardj9b769162014-07-24 12:42:03 +00001156VexInvalRange LibVEX_PatchProfInc ( VexArch arch_host,
1157 VexEndness endness_host,
1158 void* place_to_patch,
florian7d6f81d2014-09-22 21:43:37 +00001159 const ULong* location_of_counter )
sewardjc6f970f2012-04-02 21:54:49 +00001160{
sewardjc6f970f2012-04-02 21:54:49 +00001161 switch (arch_host) {
1162 case VexArchX86:
florian7d6f81d2014-09-22 21:43:37 +00001163 return patchProfInc_X86(endness_host, place_to_patch,
1164 location_of_counter);
sewardjc6f970f2012-04-02 21:54:49 +00001165 case VexArchAMD64:
florian7d6f81d2014-09-22 21:43:37 +00001166 return patchProfInc_AMD64(endness_host, place_to_patch,
1167 location_of_counter);
sewardjc6f970f2012-04-02 21:54:49 +00001168 case VexArchARM:
florian7d6f81d2014-09-22 21:43:37 +00001169 return patchProfInc_ARM(endness_host, place_to_patch,
1170 location_of_counter);
sewardj0ad37a92014-08-29 21:58:03 +00001171 case VexArchARM64:
florian7d6f81d2014-09-22 21:43:37 +00001172 return patchProfInc_ARM64(endness_host, place_to_patch,
1173 location_of_counter);
florian8844a632012-04-13 04:04:06 +00001174 case VexArchS390X:
florian7d6f81d2014-09-22 21:43:37 +00001175 return patchProfInc_S390(endness_host, place_to_patch,
1176 location_of_counter);
sewardj3dee8492012-04-20 00:13:28 +00001177 case VexArchPPC32:
sewardj9b769162014-07-24 12:42:03 +00001178 return patchProfInc_PPC(endness_host, place_to_patch,
sewardj3dee8492012-04-20 00:13:28 +00001179 location_of_counter, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +00001180 case VexArchPPC64:
sewardj9b769162014-07-24 12:42:03 +00001181 return patchProfInc_PPC(endness_host, place_to_patch,
sewardjf252de52012-04-20 10:42:24 +00001182 location_of_counter, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +00001183 case VexArchMIPS32:
sewardj9b769162014-07-24 12:42:03 +00001184 return patchProfInc_MIPS(endness_host, place_to_patch,
sewardjd0e5fe72012-06-07 08:51:02 +00001185 location_of_counter, False/*!mode64*/);
petarjb92a9542013-02-27 22:57:17 +00001186 case VexArchMIPS64:
sewardj9b769162014-07-24 12:42:03 +00001187 return patchProfInc_MIPS(endness_host, place_to_patch,
petarjb92a9542013-02-27 22:57:17 +00001188 location_of_counter, True/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +00001189 default:
1190 vassert(0);
1191 }
sewardjc6f970f2012-04-02 21:54:49 +00001192}
1193
1194
sewardj893aada2004-11-29 19:57:54 +00001195/* --------- Emulation warnings. --------- */
1196
florian1ff47562012-10-21 02:09:51 +00001197const HChar* LibVEX_EmNote_string ( VexEmNote ew )
sewardj893aada2004-11-29 19:57:54 +00001198{
1199 switch (ew) {
florian6ef84be2012-08-26 03:20:07 +00001200 case EmNote_NONE:
sewardj893aada2004-11-29 19:57:54 +00001201 return "none";
1202 case EmWarn_X86_x87exns:
1203 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +00001204 case EmWarn_X86_x87precision:
1205 return "Selection of non-80-bit x87 FP precision";
1206 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +00001207 return "Unmasking SSE FP exceptions";
1208 case EmWarn_X86_fz:
1209 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
1210 case EmWarn_X86_daz:
1211 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +00001212 case EmWarn_X86_acFlag:
1213 return "Setting %eflags.ac (setting noted but ignored)";
sewardj9dd9cf12006-01-20 14:13:55 +00001214 case EmWarn_PPCexns:
1215 return "Unmasking PPC32/64 FP exceptions";
1216 case EmWarn_PPC64_redir_overflow:
1217 return "PPC64 function redirection stack overflow";
1218 case EmWarn_PPC64_redir_underflow:
1219 return "PPC64 function redirection stack underflow";
florian4b8efad2012-09-02 18:07:08 +00001220 case EmWarn_S390X_fpext_rounding:
1221 return "The specified rounding mode cannot be supported. That\n"
1222 " feature requires the floating point extension facility.\n"
1223 " which is not available on this host. Continuing using\n"
1224 " the rounding mode from FPC. Results may differ!";
florianf0fa1be2012-09-18 20:24:38 +00001225 case EmWarn_S390X_invalid_rounding:
1226 return "The specified rounding mode is invalid.\n"
1227 " Continuing using 'round to nearest'. Results may differ!";
floriane75dafa2012-09-01 17:54:09 +00001228 case EmFail_S390X_stfle:
florian4e0083e2012-08-26 03:41:56 +00001229 return "Instruction stfle is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001230 case EmFail_S390X_stckf:
florianc5c669b2012-08-26 14:32:28 +00001231 return "Instruction stckf is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001232 case EmFail_S390X_ecag:
florian8c88cb62012-08-26 18:58:13 +00001233 return "Instruction ecag is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001234 case EmFail_S390X_fpext:
1235 return "Encountered an instruction that requires the floating "
1236 "point extension facility.\n"
1237 " That facility is not available on this host";
florian78d5ef72013-05-11 15:02:58 +00001238 case EmFail_S390X_invalid_PFPO_rounding_mode:
1239 return "The rounding mode specified in GPR 0 for PFPO instruction"
1240 " is invalid";
1241 case EmFail_S390X_invalid_PFPO_function:
1242 return "The function code specified in GPR 0 for PFPO instruction"
1243 " is invalid";
sewardj893aada2004-11-29 19:57:54 +00001244 default:
florian6ef84be2012-08-26 03:20:07 +00001245 vpanic("LibVEX_EmNote_string: unknown warning");
sewardj893aada2004-11-29 19:57:54 +00001246 }
1247}
sewardj35421a32004-07-05 13:12:34 +00001248
sewardj5117ce12006-01-27 21:20:15 +00001249/* ------------------ Arch/HwCaps stuff. ------------------ */
sewardjbef170b2004-12-21 01:23:00 +00001250
1251const HChar* LibVEX_ppVexArch ( VexArch arch )
1252{
1253 switch (arch) {
1254 case VexArch_INVALID: return "INVALID";
1255 case VexArchX86: return "X86";
1256 case VexArchAMD64: return "AMD64";
1257 case VexArchARM: return "ARM";
sewardjbbcf1882014-01-12 12:49:10 +00001258 case VexArchARM64: return "ARM64";
sewardj0ec57c52005-02-01 15:24:10 +00001259 case VexArchPPC32: return "PPC32";
cerionf0de28c2005-12-13 20:21:11 +00001260 case VexArchPPC64: return "PPC64";
sewardj2019a972011-03-07 16:04:07 +00001261 case VexArchS390X: return "S390X";
sewardjd0e5fe72012-06-07 08:51:02 +00001262 case VexArchMIPS32: return "MIPS32";
petarjb92a9542013-02-27 22:57:17 +00001263 case VexArchMIPS64: return "MIPS64";
sewardjbef170b2004-12-21 01:23:00 +00001264 default: return "VexArch???";
1265 }
1266}
1267
sewardj9b769162014-07-24 12:42:03 +00001268const HChar* LibVEX_ppVexEndness ( VexEndness endness )
1269{
1270 switch (endness) {
1271 case VexEndness_INVALID: return "INVALID";
1272 case VexEndnessLE: return "LittleEndian";
1273 case VexEndnessBE: return "BigEndian";
1274 default: return "VexEndness???";
1275 }
1276}
1277
sewardj5117ce12006-01-27 21:20:15 +00001278const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
sewardjbef170b2004-12-21 01:23:00 +00001279{
florian55085f82012-11-21 00:36:55 +00001280 const HChar* str = show_hwcaps(arch,hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001281 return str ? str : "INVALID";
sewardjbef170b2004-12-21 01:23:00 +00001282}
1283
sewardj5117ce12006-01-27 21:20:15 +00001284
sewardj27e1dd62005-06-30 11:49:14 +00001285/* Write default settings info *vai. */
1286void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
1287{
sewardj65902992014-05-03 21:20:56 +00001288 vex_bzero(vai, sizeof(*vai));
sewardj9b769162014-07-24 12:42:03 +00001289 vai->hwcaps = 0;
1290 vai->endness = VexEndness_INVALID;
1291 vai->ppc_icache_line_szB = 0;
1292 vai->ppc_dcbz_szB = 0;
1293 vai->ppc_dcbzl_szB = 0;
sewardj65902992014-05-03 21:20:56 +00001294 vai->arm64_dMinLine_lg2_szB = 0;
1295 vai->arm64_iMinLine_lg2_szB = 0;
florianf192a392012-10-07 19:44:40 +00001296 vai->hwcache_info.num_levels = 0;
1297 vai->hwcache_info.num_caches = 0;
sewardj65902992014-05-03 21:20:56 +00001298 vai->hwcache_info.caches = NULL;
florianf192a392012-10-07 19:44:40 +00001299 vai->hwcache_info.icaches_maintain_coherence = True; // whatever
sewardj27e1dd62005-06-30 11:49:14 +00001300}
1301
sewardjdd40fdf2006-12-24 02:20:24 +00001302/* Write default settings info *vbi. */
1303void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
sewardjaca070a2006-10-17 00:28:22 +00001304{
sewardj65902992014-05-03 21:20:56 +00001305 vex_bzero(vbi, sizeof(*vbi));
sewardjdd40fdf2006-12-24 02:20:24 +00001306 vbi->guest_stack_redzone_size = 0;
sewardj2e28ac42008-12-04 00:05:12 +00001307 vbi->guest_amd64_assume_fs_is_zero = False;
1308 vbi->guest_amd64_assume_gs_is_0x60 = False;
sewardjdd40fdf2006-12-24 02:20:24 +00001309 vbi->guest_ppc_zap_RZ_at_blr = False;
1310 vbi->guest_ppc_zap_RZ_at_bl = NULL;
sewardjdd40fdf2006-12-24 02:20:24 +00001311 vbi->host_ppc_calls_use_fndescrs = False;
sewardjaca070a2006-10-17 00:28:22 +00001312}
1313
sewardj27e1dd62005-06-30 11:49:14 +00001314
sewardj5117ce12006-01-27 21:20:15 +00001315/* Return a string showing the hwcaps in a nice way. The string will
1316 be NULL for invalid combinations of flags, so these functions also
1317 serve as a way to validate hwcaps values. */
1318
florian55085f82012-11-21 00:36:55 +00001319static const HChar* show_hwcaps_x86 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001320{
mjw6c65c122013-08-27 10:19:03 +00001321 /* Monotonic, LZCNT > SSE3 > SSE2 > SSE1 > MMXEXT > baseline. */
sewardj536fbab2010-07-29 15:39:05 +00001322 switch (hwcaps) {
1323 case 0:
1324 return "x86-sse0";
mjw6c65c122013-08-27 10:19:03 +00001325 case VEX_HWCAPS_X86_MMXEXT:
1326 return "x86-mmxext";
1327 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1:
1328 return "x86-mmxext-sse1";
1329 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2:
1330 return "x86-mmxext-sse1-sse2";
1331 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
sewardj536fbab2010-07-29 15:39:05 +00001332 | VEX_HWCAPS_X86_LZCNT:
mjw6c65c122013-08-27 10:19:03 +00001333 return "x86-mmxext-sse1-sse2-lzcnt";
1334 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
sewardj536fbab2010-07-29 15:39:05 +00001335 | VEX_HWCAPS_X86_SSE3:
mjw6c65c122013-08-27 10:19:03 +00001336 return "x86-mmxext-sse1-sse2-sse3";
1337 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
sewardj536fbab2010-07-29 15:39:05 +00001338 | VEX_HWCAPS_X86_SSE3 | VEX_HWCAPS_X86_LZCNT:
mjw6c65c122013-08-27 10:19:03 +00001339 return "x86-mmxext-sse1-sse2-sse3-lzcnt";
sewardj536fbab2010-07-29 15:39:05 +00001340 default:
1341 return NULL;
1342 }
sewardj5117ce12006-01-27 21:20:15 +00001343}
1344
florian55085f82012-11-21 00:36:55 +00001345static const HChar* show_hwcaps_amd64 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001346{
sewardje9d8a262009-07-01 08:06:34 +00001347 /* SSE3 and CX16 are orthogonal and > baseline, although we really
1348 don't expect to come across anything which can do SSE3 but can't
sewardj536fbab2010-07-29 15:39:05 +00001349 do CX16. Still, we can handle that case. LZCNT is similarly
sewardj818c7302013-03-26 13:53:18 +00001350 orthogonal. */
1351
1352 /* Throw out obviously stupid cases: */
sewardj818c7302013-03-26 13:53:18 +00001353 Bool have_sse3 = (hwcaps & VEX_HWCAPS_AMD64_SSE3) != 0;
1354 Bool have_avx = (hwcaps & VEX_HWCAPS_AMD64_AVX) != 0;
sewardjcc3d2192013-03-27 11:37:33 +00001355 Bool have_bmi = (hwcaps & VEX_HWCAPS_AMD64_BMI) != 0;
1356 Bool have_avx2 = (hwcaps & VEX_HWCAPS_AMD64_AVX2) != 0;
1357 /* AVX without SSE3 */
sewardj818c7302013-03-26 13:53:18 +00001358 if (have_avx && !have_sse3)
1359 return NULL;
sewardjcc3d2192013-03-27 11:37:33 +00001360 /* AVX2 or BMI without AVX */
1361 if ((have_avx2 || have_bmi) && !have_avx)
1362 return NULL;
sewardj818c7302013-03-26 13:53:18 +00001363
1364 /* This isn't threadsafe. We might need to fix it at some point. */
1365 static HChar buf[100] = { 0 };
1366 if (buf[0] != 0) return buf; /* already constructed */
1367
1368 vex_bzero(buf, sizeof(buf));
1369
1370 HChar* p = &buf[0];
1371
1372 p = p + vex_sprintf(p, "%s", "amd64");
1373 if (hwcaps == 0) {
1374 /* special-case the baseline case */
1375 p = p + vex_sprintf(p, "%s", "-sse2");
1376 goto out;
sewardj536fbab2010-07-29 15:39:05 +00001377 }
sewardj818c7302013-03-26 13:53:18 +00001378 if (hwcaps & VEX_HWCAPS_AMD64_CX16) {
1379 p = p + vex_sprintf(p, "%s", "-cx16");
1380 }
1381 if (hwcaps & VEX_HWCAPS_AMD64_LZCNT) {
1382 p = p + vex_sprintf(p, "%s", "-lzcnt");
1383 }
1384 if (hwcaps & VEX_HWCAPS_AMD64_RDTSCP) {
1385 p = p + vex_sprintf(p, "%s", "-rdtscp");
1386 }
1387 if (hwcaps & VEX_HWCAPS_AMD64_SSE3) {
1388 p = p + vex_sprintf(p, "%s", "-sse3");
1389 }
1390 if (hwcaps & VEX_HWCAPS_AMD64_AVX) {
1391 p = p + vex_sprintf(p, "%s", "-avx");
1392 }
sewardjcc3d2192013-03-27 11:37:33 +00001393 if (hwcaps & VEX_HWCAPS_AMD64_AVX2) {
1394 p = p + vex_sprintf(p, "%s", "-avx2");
1395 }
1396 if (hwcaps & VEX_HWCAPS_AMD64_BMI) {
1397 p = p + vex_sprintf(p, "%s", "-bmi");
1398 }
sewardj818c7302013-03-26 13:53:18 +00001399
1400 out:
1401 vassert(buf[sizeof(buf)-1] == 0);
1402 return buf;
sewardj5117ce12006-01-27 21:20:15 +00001403}
1404
florian55085f82012-11-21 00:36:55 +00001405static const HChar* show_hwcaps_ppc32 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001406{
1407 /* Monotonic with complications. Basically V > F > baseline,
1408 but once you have F then you can have FX or GX too. */
1409 const UInt F = VEX_HWCAPS_PPC32_F;
1410 const UInt V = VEX_HWCAPS_PPC32_V;
1411 const UInt FX = VEX_HWCAPS_PPC32_FX;
1412 const UInt GX = VEX_HWCAPS_PPC32_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001413 const UInt VX = VEX_HWCAPS_PPC32_VX;
sewardjc66d6fa2012-04-02 21:24:12 +00001414 const UInt DFP = VEX_HWCAPS_PPC32_DFP;
carll0c74bb52013-08-12 18:01:40 +00001415 const UInt ISA2_07 = VEX_HWCAPS_PPC32_ISA2_07;
sewardj5117ce12006-01-27 21:20:15 +00001416 UInt c = hwcaps;
1417 if (c == 0) return "ppc32-int";
1418 if (c == F) return "ppc32-int-flt";
1419 if (c == (F|FX)) return "ppc32-int-flt-FX";
1420 if (c == (F|GX)) return "ppc32-int-flt-GX";
1421 if (c == (F|FX|GX)) return "ppc32-int-flt-FX-GX";
1422 if (c == (F|V)) return "ppc32-int-flt-vmx";
1423 if (c == (F|V|FX)) return "ppc32-int-flt-vmx-FX";
1424 if (c == (F|V|GX)) return "ppc32-int-flt-vmx-GX";
1425 if (c == (F|V|FX|GX)) return "ppc32-int-flt-vmx-FX-GX";
sewardjc66d6fa2012-04-02 21:24:12 +00001426 if (c == (F|V|FX|GX|DFP)) return "ppc32-int-flt-vmx-FX-GX-DFP";
1427 if (c == (F|V|FX|GX|VX|DFP)) return "ppc32-int-flt-vmx-FX-GX-VX-DFP";
carll0c74bb52013-08-12 18:01:40 +00001428 if (c == (F|V|FX|GX|VX|DFP|ISA2_07))
1429 return "ppc32-int-flt-vmx-FX-GX-VX-DFP-ISA2_07";
1430
sewardj5117ce12006-01-27 21:20:15 +00001431 return NULL;
1432}
1433
florian55085f82012-11-21 00:36:55 +00001434static const HChar* show_hwcaps_ppc64 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001435{
1436 /* Monotonic with complications. Basically V > baseline(==F),
1437 but once you have F then you can have FX or GX too. */
sewardj3fd39672006-01-27 22:05:55 +00001438 const UInt V = VEX_HWCAPS_PPC64_V;
1439 const UInt FX = VEX_HWCAPS_PPC64_FX;
1440 const UInt GX = VEX_HWCAPS_PPC64_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001441 const UInt VX = VEX_HWCAPS_PPC64_VX;
sewardjc66d6fa2012-04-02 21:24:12 +00001442 const UInt DFP = VEX_HWCAPS_PPC64_DFP;
carll0c74bb52013-08-12 18:01:40 +00001443 const UInt ISA2_07 = VEX_HWCAPS_PPC64_ISA2_07;
sewardj5117ce12006-01-27 21:20:15 +00001444 UInt c = hwcaps;
1445 if (c == 0) return "ppc64-int-flt";
1446 if (c == FX) return "ppc64-int-flt-FX";
1447 if (c == GX) return "ppc64-int-flt-GX";
1448 if (c == (FX|GX)) return "ppc64-int-flt-FX-GX";
1449 if (c == V) return "ppc64-int-flt-vmx";
1450 if (c == (V|FX)) return "ppc64-int-flt-vmx-FX";
1451 if (c == (V|GX)) return "ppc64-int-flt-vmx-GX";
1452 if (c == (V|FX|GX)) return "ppc64-int-flt-vmx-FX-GX";
sewardjc66d6fa2012-04-02 21:24:12 +00001453 if (c == (V|FX|GX|DFP)) return "ppc64-int-flt-vmx-FX-GX-DFP";
1454 if (c == (V|FX|GX|VX|DFP)) return "ppc64-int-flt-vmx-FX-GX-VX-DFP";
carll0c74bb52013-08-12 18:01:40 +00001455 if (c == (V|FX|GX|VX|DFP|ISA2_07))
1456 return "ppc64-int-flt-vmx-FX-GX-VX-DFP-ISA2_07";
sewardj5117ce12006-01-27 21:20:15 +00001457 return NULL;
1458}
1459
florian55085f82012-11-21 00:36:55 +00001460static const HChar* show_hwcaps_arm ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001461{
sewardjec0d9a02010-08-22 12:54:56 +00001462 Bool N = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0);
1463 Bool vfp = ((hwcaps & (VEX_HWCAPS_ARM_VFP |
1464 VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3)) != 0);
1465 switch (VEX_ARM_ARCHLEVEL(hwcaps)) {
1466 case 5:
1467 if (N)
1468 return NULL;
1469 if (vfp)
1470 return "ARMv5-vfp";
1471 else
1472 return "ARMv5";
1473 return NULL;
1474 case 6:
1475 if (N)
1476 return NULL;
1477 if (vfp)
1478 return "ARMv6-vfp";
1479 else
1480 return "ARMv6";
1481 return NULL;
1482 case 7:
1483 if (vfp) {
1484 if (N)
1485 return "ARMv7-vfp-neon";
1486 else
1487 return "ARMv7-vfp";
1488 } else {
1489 if (N)
1490 return "ARMv7-neon";
1491 else
1492 return "ARMv7";
1493 }
1494 default:
1495 return NULL;
1496 }
sewardj5117ce12006-01-27 21:20:15 +00001497 return NULL;
1498}
1499
sewardjbbcf1882014-01-12 12:49:10 +00001500static const HChar* show_hwcaps_arm64 ( UInt hwcaps )
1501{
1502 /* Since there are no variants, just insist that hwcaps is zero,
1503 and declare it invalid otherwise. */
1504 if (hwcaps == 0)
1505 return "baseline";
1506 return NULL;
1507}
1508
florian55085f82012-11-21 00:36:55 +00001509static const HChar* show_hwcaps_s390x ( UInt hwcaps )
sewardj2019a972011-03-07 16:04:07 +00001510{
sewardjd07b8562011-04-27 11:58:22 +00001511 static const HChar prefix[] = "s390x";
florian9061eb32012-12-09 17:53:45 +00001512 static const struct {
1513 UInt hwcaps_bit;
1514 HChar name[6];
1515 } hwcaps_list[] = {
1516 { VEX_HWCAPS_S390X_LDISP, "ldisp" },
1517 { VEX_HWCAPS_S390X_EIMM, "eimm" },
1518 { VEX_HWCAPS_S390X_GIE, "gie" },
1519 { VEX_HWCAPS_S390X_DFP, "dfp" },
1520 { VEX_HWCAPS_S390X_FGX, "fgx" },
1521 { VEX_HWCAPS_S390X_STFLE, "stfle" },
1522 { VEX_HWCAPS_S390X_ETF2, "etf2" },
1523 { VEX_HWCAPS_S390X_ETF3, "etf3" },
1524 { VEX_HWCAPS_S390X_STCKF, "stckf" },
1525 { VEX_HWCAPS_S390X_FPEXT, "fpext" },
1526 { VEX_HWCAPS_S390X_LSC, "lsc" },
florian78d5ef72013-05-11 15:02:58 +00001527 { VEX_HWCAPS_S390X_PFPO, "pfpo" },
sewardjd07b8562011-04-27 11:58:22 +00001528 };
florian9061eb32012-12-09 17:53:45 +00001529#define NUM_HWCAPS (sizeof hwcaps_list / sizeof hwcaps_list[0])
1530 static HChar buf[sizeof prefix +
1531 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) +
1532 1]; // '\0'
1533 HChar *p;
1534 UInt i;
sewardjd07b8562011-04-27 11:58:22 +00001535
1536 if (buf[0] != '\0') return buf; /* already constructed */
sewardj2019a972011-03-07 16:04:07 +00001537
sewardj652b56a2011-04-13 15:38:17 +00001538 hwcaps = VEX_HWCAPS_S390X(hwcaps);
1539
sewardjd07b8562011-04-27 11:58:22 +00001540 p = buf + vex_sprintf(buf, "%s", prefix);
florian9061eb32012-12-09 17:53:45 +00001541 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1542 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1543 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1544 }
sewardj2019a972011-03-07 16:04:07 +00001545
sewardjd07b8562011-04-27 11:58:22 +00001546 /* If there are no facilities, add "zarch" */
1547 if (hwcaps == 0)
1548 vex_sprintf(p, "-%s", "zarch");
1549
1550 return buf;
sewardj2019a972011-03-07 16:04:07 +00001551}
1552
florian55085f82012-11-21 00:36:55 +00001553static const HChar* show_hwcaps_mips32 ( UInt hwcaps )
sewardjd0e5fe72012-06-07 08:51:02 +00001554{
dejanjc3fee0d2013-07-25 09:08:03 +00001555 /* MIPS baseline. */
petarjbc7d6f42013-09-16 18:11:59 +00001556 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_MIPS) {
dejanjc3fee0d2013-07-25 09:08:03 +00001557 /* MIPS baseline with dspr2. */
petarjbc7d6f42013-09-16 18:11:59 +00001558 if (VEX_MIPS_PROC_DSP2(hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +00001559 return "MIPS-baseline-dspr2";
1560 }
1561 /* MIPS baseline with dsp. */
petarjbc7d6f42013-09-16 18:11:59 +00001562 if (VEX_MIPS_PROC_DSP(hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +00001563 return "MIPS-baseline-dsp";
1564 }
1565 return "MIPS-baseline";
1566 }
1567
1568 /* Broadcom baseline. */
petarjbc7d6f42013-09-16 18:11:59 +00001569 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_BROADCOM) {
dejanjc3fee0d2013-07-25 09:08:03 +00001570 return "Broadcom-baseline";
1571 }
1572
1573 /* Netlogic baseline. */
petarjbc7d6f42013-09-16 18:11:59 +00001574 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_NETLOGIC) {
dejanjc3fee0d2013-07-25 09:08:03 +00001575 return "Netlogic-baseline";
1576 }
1577
petarjbc7d6f42013-09-16 18:11:59 +00001578 /* Cavium baseline. */
1579 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_CAVIUM) {
1580 return "Cavium-baseline";
1581 }
1582
sewardjd0e5fe72012-06-07 08:51:02 +00001583 return NULL;
1584}
1585
petarjb92a9542013-02-27 22:57:17 +00001586static const HChar* show_hwcaps_mips64 ( UInt hwcaps )
1587{
1588 return "mips64-baseline";
1589}
1590
sewardj5117ce12006-01-27 21:20:15 +00001591/* ---- */
florian55085f82012-11-21 00:36:55 +00001592static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001593{
1594 switch (arch) {
sewardjd0e5fe72012-06-07 08:51:02 +00001595 case VexArchX86: return show_hwcaps_x86(hwcaps);
1596 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
1597 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
1598 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
1599 case VexArchARM: return show_hwcaps_arm(hwcaps);
sewardjbbcf1882014-01-12 12:49:10 +00001600 case VexArchARM64: return show_hwcaps_arm64(hwcaps);
sewardjd0e5fe72012-06-07 08:51:02 +00001601 case VexArchS390X: return show_hwcaps_s390x(hwcaps);
1602 case VexArchMIPS32: return show_hwcaps_mips32(hwcaps);
petarjb92a9542013-02-27 22:57:17 +00001603 case VexArchMIPS64: return show_hwcaps_mips64(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001604 default: return NULL;
1605 }
1606}
1607
1608static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps )
1609{
1610 return show_hwcaps(arch,hwcaps) != NULL;
1611}
1612
1613
sewardj35421a32004-07-05 13:12:34 +00001614/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +00001615/*--- end main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +00001616/*---------------------------------------------------------------*/