blob: 93ca478cced1a1c46fc9580cc1506b1e7ed66a0f [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{
95 vcon->iropt_verbosity = 0;
96 vcon->iropt_level = 2;
philippec8e2f982012-08-01 22:04:13 +000097 vcon->iropt_register_updates = VexRegUpdUnwindregsAtMemAccess;
sewardj08613742004-10-25 13:01:45 +000098 vcon->iropt_unroll_thresh = 120;
sewardj18b4bb72005-03-29 21:32:41 +000099 vcon->guest_max_insns = 60;
sewardj08613742004-10-25 13:01:45 +0000100 vcon->guest_chase_thresh = 10;
sewardj984d9b12010-01-15 10:53:21 +0000101 vcon->guest_chase_cond = False;
sewardj08613742004-10-25 13:01:45 +0000102}
103
104
105/* Exported to library client. */
106
sewardj887a11a2004-07-05 17:26:47 +0000107void LibVEX_Init (
sewardj35421a32004-07-05 13:12:34 +0000108 /* failure exit function */
sewardj2b515872004-07-05 20:50:45 +0000109 __attribute__ ((noreturn))
sewardj35421a32004-07-05 13:12:34 +0000110 void (*failure_exit) ( void ),
111 /* logging output function */
sewardjd9763622005-02-07 03:12:19 +0000112 void (*log_bytes) ( HChar*, Int nbytes ),
sewardj35421a32004-07-05 13:12:34 +0000113 /* debug paranoia level */
114 Int debuglevel,
sewardj35421a32004-07-05 13:12:34 +0000115 /* Are we supporting valgrind checking? */
116 Bool valgrind_support,
sewardj08613742004-10-25 13:01:45 +0000117 /* Control ... */
118 /*READONLY*/VexControl* vcon
sewardj35421a32004-07-05 13:12:34 +0000119)
120{
sewardj08613742004-10-25 13:01:45 +0000121 /* First off, do enough minimal setup so that the following
122 assertions can fail in a sane fashion, if need be. */
sewardjea602bc2004-10-14 21:40:12 +0000123 vex_failure_exit = failure_exit;
124 vex_log_bytes = log_bytes;
125
126 /* Now it's safe to check parameters for sanity. */
sewardj35421a32004-07-05 13:12:34 +0000127 vassert(!vex_initdone);
128 vassert(failure_exit);
sewardj35421a32004-07-05 13:12:34 +0000129 vassert(log_bytes);
sewardj35421a32004-07-05 13:12:34 +0000130 vassert(debuglevel >= 0);
sewardj08613742004-10-25 13:01:45 +0000131
132 vassert(vcon->iropt_verbosity >= 0);
133 vassert(vcon->iropt_level >= 0);
134 vassert(vcon->iropt_level <= 2);
135 vassert(vcon->iropt_unroll_thresh >= 0);
136 vassert(vcon->iropt_unroll_thresh <= 400);
137 vassert(vcon->guest_max_insns >= 1);
138 vassert(vcon->guest_max_insns <= 100);
139 vassert(vcon->guest_chase_thresh >= 0);
140 vassert(vcon->guest_chase_thresh < vcon->guest_max_insns);
sewardj984d9b12010-01-15 10:53:21 +0000141 vassert(vcon->guest_chase_cond == True
142 || vcon->guest_chase_cond == False);
sewardj443cd9d2004-07-18 23:06:45 +0000143
sewardjea602bc2004-10-14 21:40:12 +0000144 /* Check that Vex has been built with sizes of basic types as
145 stated in priv/libvex_basictypes.h. Failure of any of these is
146 a serious configuration error and should be corrected
147 immediately. If any of these assertions fail you can fully
148 expect Vex not to work properly, if at all. */
149
150 vassert(1 == sizeof(UChar));
151 vassert(1 == sizeof(Char));
152 vassert(2 == sizeof(UShort));
153 vassert(2 == sizeof(Short));
154 vassert(4 == sizeof(UInt));
155 vassert(4 == sizeof(Int));
156 vassert(8 == sizeof(ULong));
157 vassert(8 == sizeof(Long));
158 vassert(4 == sizeof(Float));
159 vassert(8 == sizeof(Double));
160 vassert(1 == sizeof(Bool));
161 vassert(4 == sizeof(Addr32));
162 vassert(8 == sizeof(Addr64));
sewardjc9a43662004-11-30 18:51:59 +0000163 vassert(16 == sizeof(U128));
sewardj69d98e32010-06-18 08:17:41 +0000164 vassert(16 == sizeof(V128));
sewardjc9069f22012-06-01 16:09:50 +0000165 vassert(32 == sizeof(U256));
sewardjea602bc2004-10-14 21:40:12 +0000166
167 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
168 vassert(sizeof(void*) == sizeof(int*));
169 vassert(sizeof(void*) == sizeof(HWord));
170
sewardj97e87932005-02-07 00:00:50 +0000171 vassert(VEX_HOST_WORDSIZE == sizeof(void*));
172 vassert(VEX_HOST_WORDSIZE == sizeof(HWord));
173
sewardjc6f970f2012-04-02 21:54:49 +0000174 /* These take a lot of space, so make sure we don't have
175 any unnoticed size regressions. */
176 if (VEX_HOST_WORDSIZE == 4) {
florian420bfa92012-06-02 20:29:22 +0000177 vassert(sizeof(IRExpr) == 16);
sewardjc6f970f2012-04-02 21:54:49 +0000178 vassert(sizeof(IRStmt) == 20 /* x86 */
179 || sizeof(IRStmt) == 24 /* arm */);
180 } else {
florian420bfa92012-06-02 20:29:22 +0000181 vassert(sizeof(IRExpr) == 32);
floriand6f38b32012-05-31 15:46:18 +0000182 vassert(sizeof(IRStmt) == 32);
sewardjc6f970f2012-04-02 21:54:49 +0000183 }
184
sewardj8bde7f12013-04-11 13:57:43 +0000185 /* Check that signed integer division on the host rounds towards
186 zero. If not, h_calc_sdiv32_w_arm_semantics() won't work
187 correctly. */
188 /* 100.0 / 7.0 == 14.2857 */
189 vassert(udiv32(100, 7) == 14);
190 vassert(sdiv32(100, 7) == 14);
191 vassert(sdiv32(-100, 7) == -14); /* and not -15 */
192 vassert(sdiv32(100, -7) == -14); /* ditto */
193 vassert(sdiv32(-100, -7) == 14); /* not sure what this proves */
194
sewardjea602bc2004-10-14 21:40:12 +0000195 /* Really start up .. */
sewardj443cd9d2004-07-18 23:06:45 +0000196 vex_debuglevel = debuglevel;
sewardj443cd9d2004-07-18 23:06:45 +0000197 vex_valgrind_support = valgrind_support;
sewardj08613742004-10-25 13:01:45 +0000198 vex_control = *vcon;
sewardj443cd9d2004-07-18 23:06:45 +0000199 vex_initdone = True;
sewardjd887b862005-01-17 18:34:34 +0000200 vexSetAllocMode ( VexAllocModeTEMP );
sewardj35421a32004-07-05 13:12:34 +0000201}
202
203
204/* --------- Make a translation. --------- */
205
206/* Exported to library client. */
207
sewardj17c7f952005-12-15 14:02:34 +0000208VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
sewardj35421a32004-07-05 13:12:34 +0000209{
sewardj81bd5502004-07-21 18:49:27 +0000210 /* This the bundle of functions we need to do the back-end stuff
211 (insn selection, reg-alloc, assembly) whilst being insulated
212 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +0000213 HReg* available_real_regs;
214 Int n_available_real_regs;
sewardjfb7373a2007-08-25 21:29:03 +0000215 Bool (*isMove) ( HInstr*, HReg*, HReg* );
216 void (*getRegUsage) ( HRegUsage*, HInstr*, Bool );
217 void (*mapRegs) ( HRegRemap*, HInstr*, Bool );
sewardj6c299f32009-12-31 18:00:12 +0000218 void (*genSpill) ( HInstr**, HInstr**, HReg, Int, Bool );
219 void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool );
sewardjfb7373a2007-08-25 21:29:03 +0000220 HInstr* (*directReload) ( HInstr*, HReg, Short );
221 void (*ppInstr) ( HInstr*, Bool );
222 void (*ppReg) ( HReg );
sewardjc6f970f2012-04-02 21:54:49 +0000223 HInstrArray* (*iselSB) ( IRSB*, VexArch, VexArchInfo*, VexAbiInfo*,
224 Int, Int, Bool, Bool, Addr64 );
225 Int (*emit) ( /*MB_MOD*/Bool*,
226 UChar*, Int, HInstr*, Bool,
227 void*, void*, void*, void* );
florian1ff47562012-10-21 02:09:51 +0000228 IRExpr* (*specHelper) ( const HChar*, IRExpr**, IRStmt**, Int );
sewardj8d2291c2004-10-25 14:50:21 +0000229 Bool (*preciseMemExnsFn) ( Int, Int );
sewardjf13a16a2004-07-05 17:10:14 +0000230
sewardj9e6491a2005-07-02 19:24:10 +0000231 DisOneInstrFn disInstrFn;
232
sewardjeeac8412004-11-02 00:26:55 +0000233 VexGuestLayout* guest_layout;
234 Bool host_is_bigendian = False;
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;
sewardjc6f970f2012-04-02 21:54:49 +0000239 Int offB_TISTART, offB_TILEN, offB_GUEST_IP, szB_GUEST_IP;
240 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;
sewardjdb4738a2005-07-07 01:32:16 +0000265 offB_TISTART = 0;
266 offB_TILEN = 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;
sewardjc6f970f2012-04-02 21:54:49 +0000313 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
314 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000315 emit_X86Instr;
sewardj72c72812005-01-19 11:49:45 +0000316 host_is_bigendian = False;
sewardjcf787902004-11-03 09:08:33 +0000317 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000318 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_host.hwcaps));
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;
sewardjc6f970f2012-04-02 21:54:49 +0000336 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
337 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000338 emit_AMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000339 host_is_bigendian = False;
340 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000341 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_host.hwcaps));
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;
sewardj3dee8492012-04-20 00:13:28 +0000356 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
357 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000358 emit_PPCInstr;
cerion487e4c92005-02-04 16:28:19 +0000359 host_is_bigendian = True;
360 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000361 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_host.hwcaps));
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;
sewardj9e1cf152012-04-20 02:18:31 +0000376 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
377 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000378 emit_PPCInstr;
cerionf0de28c2005-12-13 20:21:11 +0000379 host_is_bigendian = True;
380 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000381 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_host.hwcaps));
cerionf0de28c2005-12-13 20:21:11 +0000382 break;
383
sewardj2019a972011-03-07 16:04:07 +0000384 case VexArchS390X:
385 mode64 = True;
386 getAllocableRegs_S390 ( &n_available_real_regs,
387 &available_real_regs, mode64 );
388 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_S390Instr;
389 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_S390Instr;
390 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_S390Instr;
391 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_S390;
392 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_S390;
393 ppInstr = (void(*)(HInstr*, Bool)) ppS390Instr;
394 ppReg = (void(*)(HReg)) ppHRegS390;
395 iselSB = iselSB_S390;
florian8844a632012-04-13 04:04:06 +0000396 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
397 void*,void*,void*,void*)) emit_S390Instr;
sewardj2019a972011-03-07 16:04:07 +0000398 host_is_bigendian = True;
399 host_word_type = Ity_I64;
400 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_host.hwcaps));
sewardj2019a972011-03-07 16:04:07 +0000401 break;
402
sewardj6c299f32009-12-31 18:00:12 +0000403 case VexArchARM:
sewardj2a1ed8e2009-12-31 19:26:03 +0000404 mode64 = False;
sewardj6c299f32009-12-31 18:00:12 +0000405 getAllocableRegs_ARM ( &n_available_real_regs,
406 &available_real_regs );
sewardj2a1ed8e2009-12-31 19:26:03 +0000407 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARMInstr;
408 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_ARMInstr;
409 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_ARMInstr;
410 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_ARM;
411 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_ARM;
412 ppInstr = (void(*)(HInstr*, Bool)) ppARMInstr;
413 ppReg = (void(*)(HReg)) ppHRegARM;
414 iselSB = iselSB_ARM;
sewardjc6f970f2012-04-02 21:54:49 +0000415 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
416 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000417 emit_ARMInstr;
sewardj6c299f32009-12-31 18:00:12 +0000418 host_is_bigendian = False;
419 host_word_type = Ity_I32;
420 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_host.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000421 break;
422
sewardjbbcf1882014-01-12 12:49:10 +0000423 case VexArchARM64:
424 mode64 = True;
425 getAllocableRegs_ARM64 ( &n_available_real_regs,
426 &available_real_regs );
427 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARM64Instr;
428 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
429 getRegUsage_ARM64Instr;
430 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool))
431 mapRegs_ARM64Instr;
432 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
433 genSpill_ARM64;
434 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
435 genReload_ARM64;
436 ppInstr = (void(*)(HInstr*, Bool)) ppARM64Instr;
437 ppReg = (void(*)(HReg)) ppHRegARM64;
438 iselSB = iselSB_ARM64;
439 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
440 void*,void*,void*,void*))
441 emit_ARM64Instr;
442 host_is_bigendian = False;
443 host_word_type = Ity_I64;
444 vassert(are_valid_hwcaps(VexArchARM64, vta->archinfo_host.hwcaps));
445 break;
446
sewardjd0e5fe72012-06-07 08:51:02 +0000447 case VexArchMIPS32:
448 mode64 = False;
449 getAllocableRegs_MIPS ( &n_available_real_regs,
450 &available_real_regs, mode64 );
451 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_MIPSInstr;
452 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_MIPSInstr;
453 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_MIPSInstr;
454 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_MIPS;
455 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_MIPS;
456 ppInstr = (void(*)(HInstr*, Bool)) ppMIPSInstr;
457 ppReg = (void(*)(HReg)) ppHRegMIPS;
458 iselSB = iselSB_MIPS;
459 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
460 void*,void*,void*,void*))
461 emit_MIPSInstr;
sewardj74142b82013-08-08 10:28:59 +0000462# if defined(VKI_LITTLE_ENDIAN)
sewardjd0e5fe72012-06-07 08:51:02 +0000463 host_is_bigendian = False;
sewardj74142b82013-08-08 10:28:59 +0000464# elif defined(VKI_BIG_ENDIAN)
sewardjd0e5fe72012-06-07 08:51:02 +0000465 host_is_bigendian = True;
sewardj74142b82013-08-08 10:28:59 +0000466# endif
sewardjd0e5fe72012-06-07 08:51:02 +0000467 host_word_type = Ity_I32;
468 vassert(are_valid_hwcaps(VexArchMIPS32, vta->archinfo_host.hwcaps));
469 break;
470
petarjb92a9542013-02-27 22:57:17 +0000471 case VexArchMIPS64:
472 mode64 = True;
473 getAllocableRegs_MIPS ( &n_available_real_regs,
474 &available_real_regs, mode64 );
475 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_MIPSInstr;
476 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_MIPSInstr;
477 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_MIPSInstr;
478 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_MIPS;
479 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_MIPS;
480 ppInstr = (void(*)(HInstr*, Bool)) ppMIPSInstr;
481 ppReg = (void(*)(HReg)) ppHRegMIPS;
482 iselSB = iselSB_MIPS;
483 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
484 void*,void*,void*,void*))
485 emit_MIPSInstr;
sewardj74142b82013-08-08 10:28:59 +0000486# if defined(VKI_LITTLE_ENDIAN)
petarjb92a9542013-02-27 22:57:17 +0000487 host_is_bigendian = False;
sewardj74142b82013-08-08 10:28:59 +0000488# elif defined(VKI_BIG_ENDIAN)
petarjb92a9542013-02-27 22:57:17 +0000489 host_is_bigendian = True;
sewardj74142b82013-08-08 10:28:59 +0000490# endif
petarjb92a9542013-02-27 22:57:17 +0000491 host_word_type = Ity_I64;
492 vassert(are_valid_hwcaps(VexArchMIPS64, vta->archinfo_host.hwcaps));
493 break;
494
sewardjf13a16a2004-07-05 17:10:14 +0000495 default:
sewardj6c299f32009-12-31 18:00:12 +0000496 vpanic("LibVEX_Translate: unsupported host insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000497 }
498
sewardj2a9ad022004-11-25 02:46:58 +0000499
sewardj17c7f952005-12-15 14:02:34 +0000500 switch (vta->arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000501
sewardjbef170b2004-12-21 01:23:00 +0000502 case VexArchX86:
sewardjc6f970f2012-04-02 21:54:49 +0000503 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
504 disInstrFn = disInstr_X86;
505 specHelper = guest_x86_spechelper;
506 guest_sizeB = sizeof(VexGuestX86State);
507 guest_word_type = Ity_I32;
508 guest_layout = &x86guest_layout;
509 offB_TISTART = offsetof(VexGuestX86State,guest_TISTART);
510 offB_TILEN = offsetof(VexGuestX86State,guest_TILEN);
511 offB_GUEST_IP = offsetof(VexGuestX86State,guest_EIP);
512 szB_GUEST_IP = sizeof( ((VexGuestX86State*)0)->guest_EIP );
513 offB_HOST_EvC_COUNTER = offsetof(VexGuestX86State,host_EvC_COUNTER);
514 offB_HOST_EvC_FAILADDR = offsetof(VexGuestX86State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000515 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000516 vassert(0 == sizeof(VexGuestX86State) % 16);
sewardjce02aa72006-01-12 12:27:58 +0000517 vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART) == 4);
518 vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
519 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000520 break;
sewardj2a9ad022004-11-25 02:46:58 +0000521
sewardj44d494d2005-01-20 20:26:33 +0000522 case VexArchAMD64:
sewardjc6f970f2012-04-02 21:54:49 +0000523 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
524 disInstrFn = disInstr_AMD64;
525 specHelper = guest_amd64_spechelper;
526 guest_sizeB = sizeof(VexGuestAMD64State);
527 guest_word_type = Ity_I64;
528 guest_layout = &amd64guest_layout;
529 offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART);
530 offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN);
531 offB_GUEST_IP = offsetof(VexGuestAMD64State,guest_RIP);
532 szB_GUEST_IP = sizeof( ((VexGuestAMD64State*)0)->guest_RIP );
533 offB_HOST_EvC_COUNTER = offsetof(VexGuestAMD64State,host_EvC_COUNTER);
534 offB_HOST_EvC_FAILADDR = offsetof(VexGuestAMD64State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000535 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000536 vassert(0 == sizeof(VexGuestAMD64State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000537 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8);
sewardjce02aa72006-01-12 12:27:58 +0000538 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
539 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000540 break;
541
cerionaabdfbf2005-01-29 12:56:15 +0000542 case VexArchPPC32:
sewardj3dee8492012-04-20 00:13:28 +0000543 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
544 disInstrFn = disInstr_PPC;
545 specHelper = guest_ppc32_spechelper;
546 guest_sizeB = sizeof(VexGuestPPC32State);
547 guest_word_type = Ity_I32;
548 guest_layout = &ppc32Guest_layout;
549 offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART);
550 offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN);
551 offB_GUEST_IP = offsetof(VexGuestPPC32State,guest_CIA);
552 szB_GUEST_IP = sizeof( ((VexGuestPPC32State*)0)->guest_CIA );
553 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC32State,host_EvC_COUNTER);
554 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC32State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000555 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000556 vassert(0 == sizeof(VexGuestPPC32State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000557 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000558 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
559 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000560 break;
561
cerionf0de28c2005-12-13 20:21:11 +0000562 case VexArchPPC64:
sewardj9e1cf152012-04-20 02:18:31 +0000563 preciseMemExnsFn = guest_ppc64_state_requires_precise_mem_exns;
564 disInstrFn = disInstr_PPC;
565 specHelper = guest_ppc64_spechelper;
566 guest_sizeB = sizeof(VexGuestPPC64State);
567 guest_word_type = Ity_I64;
568 guest_layout = &ppc64Guest_layout;
569 offB_TISTART = offsetof(VexGuestPPC64State,guest_TISTART);
570 offB_TILEN = offsetof(VexGuestPPC64State,guest_TILEN);
571 offB_GUEST_IP = offsetof(VexGuestPPC64State,guest_CIA);
572 szB_GUEST_IP = sizeof( ((VexGuestPPC64State*)0)->guest_CIA );
573 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC64State,host_EvC_COUNTER);
574 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC64State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000575 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_guest.hwcaps));
cerionf0de28c2005-12-13 20:21:11 +0000576 vassert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj3fd39672006-01-27 22:05:55 +0000577 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TISTART ) == 8);
578 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TILEN ) == 8);
579 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;
590 offB_TISTART = offsetof(VexGuestS390XState,guest_TISTART);
591 offB_TILEN = offsetof(VexGuestS390XState,guest_TILEN);
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));
597 vassert(0 == sizeof(VexGuestS390XState) % 16);
598 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TISTART ) == 8);
599 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TILEN ) == 8);
600 vassert(sizeof( ((VexGuestS390XState*)0)->guest_NRADDR ) == 8);
601 break;
602
sewardj6c299f32009-12-31 18:00:12 +0000603 case VexArchARM:
sewardjc6f970f2012-04-02 21:54:49 +0000604 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
605 disInstrFn = disInstr_ARM;
606 specHelper = guest_arm_spechelper;
607 guest_sizeB = sizeof(VexGuestARMState);
608 guest_word_type = Ity_I32;
609 guest_layout = &armGuest_layout;
610 offB_TISTART = offsetof(VexGuestARMState,guest_TISTART);
611 offB_TILEN = offsetof(VexGuestARMState,guest_TILEN);
612 offB_GUEST_IP = offsetof(VexGuestARMState,guest_R15T);
613 szB_GUEST_IP = sizeof( ((VexGuestARMState*)0)->guest_R15T );
614 offB_HOST_EvC_COUNTER = offsetof(VexGuestARMState,host_EvC_COUNTER);
615 offB_HOST_EvC_FAILADDR = offsetof(VexGuestARMState,host_EvC_FAILADDR);
sewardj6c299f32009-12-31 18:00:12 +0000616 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_guest.hwcaps));
617 vassert(0 == sizeof(VexGuestARMState) % 16);
618 vassert(sizeof( ((VexGuestARMState*)0)->guest_TISTART) == 4);
619 vassert(sizeof( ((VexGuestARMState*)0)->guest_TILEN ) == 4);
620 vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4);
621 break;
622
sewardjbbcf1882014-01-12 12:49:10 +0000623 case VexArchARM64:
624 preciseMemExnsFn = guest_arm64_state_requires_precise_mem_exns;
625 disInstrFn = disInstr_ARM64;
626 specHelper = guest_arm64_spechelper;
627 guest_sizeB = sizeof(VexGuestARM64State);
628 guest_word_type = Ity_I64;
629 guest_layout = &arm64Guest_layout;
630 offB_TISTART = offsetof(VexGuestARM64State,guest_TISTART);
631 offB_TILEN = offsetof(VexGuestARM64State,guest_TILEN);
632 offB_GUEST_IP = offsetof(VexGuestARM64State,guest_PC);
633 szB_GUEST_IP = sizeof( ((VexGuestARM64State*)0)->guest_PC );
634 offB_HOST_EvC_COUNTER = offsetof(VexGuestARM64State,host_EvC_COUNTER);
635 offB_HOST_EvC_FAILADDR = offsetof(VexGuestARM64State,host_EvC_FAILADDR);
636 vassert(are_valid_hwcaps(VexArchARM64, vta->archinfo_guest.hwcaps));
637 vassert(0 == sizeof(VexGuestARM64State) % 16);
638 vassert(sizeof( ((VexGuestARM64State*)0)->guest_TISTART) == 8);
639 vassert(sizeof( ((VexGuestARM64State*)0)->guest_TILEN ) == 8);
640 vassert(sizeof( ((VexGuestARM64State*)0)->guest_NRADDR ) == 8);
641 break;
642
sewardjd0e5fe72012-06-07 08:51:02 +0000643 case VexArchMIPS32:
644 preciseMemExnsFn = guest_mips32_state_requires_precise_mem_exns;
645 disInstrFn = disInstr_MIPS;
646 specHelper = guest_mips32_spechelper;
647 guest_sizeB = sizeof(VexGuestMIPS32State);
648 guest_word_type = Ity_I32;
649 guest_layout = &mips32Guest_layout;
650 offB_TISTART = offsetof(VexGuestMIPS32State,guest_TISTART);
651 offB_TILEN = offsetof(VexGuestMIPS32State,guest_TILEN);
652 offB_GUEST_IP = offsetof(VexGuestMIPS32State,guest_PC);
653 szB_GUEST_IP = sizeof( ((VexGuestMIPS32State*)0)->guest_PC );
654 offB_HOST_EvC_COUNTER = offsetof(VexGuestMIPS32State,host_EvC_COUNTER);
655 offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS32State,host_EvC_FAILADDR);
656 vassert(are_valid_hwcaps(VexArchMIPS32, vta->archinfo_guest.hwcaps));
657 vassert(0 == sizeof(VexGuestMIPS32State) % 16);
658 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_TISTART) == 4);
659 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_TILEN ) == 4);
660 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_NRADDR ) == 4);
661 break;
662
petarjb92a9542013-02-27 22:57:17 +0000663 case VexArchMIPS64:
664 preciseMemExnsFn = guest_mips64_state_requires_precise_mem_exns;
665 disInstrFn = disInstr_MIPS;
666 specHelper = guest_mips64_spechelper;
667 guest_sizeB = sizeof(VexGuestMIPS64State);
668 guest_word_type = Ity_I64;
669 guest_layout = &mips64Guest_layout;
670 offB_TISTART = offsetof(VexGuestMIPS64State,guest_TISTART);
671 offB_TILEN = offsetof(VexGuestMIPS64State,guest_TILEN);
672 offB_GUEST_IP = offsetof(VexGuestMIPS64State,guest_PC);
673 szB_GUEST_IP = sizeof( ((VexGuestMIPS64State*)0)->guest_PC );
674 offB_HOST_EvC_COUNTER = offsetof(VexGuestMIPS64State,host_EvC_COUNTER);
675 offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS64State,host_EvC_FAILADDR);
676 vassert(are_valid_hwcaps(VexArchMIPS64, vta->archinfo_guest.hwcaps));
677 vassert(0 == sizeof(VexGuestMIPS64State) % 16);
678 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_TISTART) == 8);
679 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_TILEN ) == 8);
680 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_NRADDR ) == 8);
681 break;
682
sewardjf13a16a2004-07-05 17:10:14 +0000683 default:
sewardj887a11a2004-07-05 17:26:47 +0000684 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000685 }
686
sewardjbc161a42011-06-07 21:28:38 +0000687 /* Set up result struct. */
688 VexTranslateResult res;
sewardjfadbbe22012-04-24 11:49:03 +0000689 res.status = VexTransOK;
690 res.n_sc_extents = 0;
691 res.offs_profInc = -1;
692 res.n_guest_instrs = 0;
sewardjbc161a42011-06-07 21:28:38 +0000693
sewardj9df271d2004-12-31 22:37:42 +0000694 /* yet more sanity checks ... */
sewardj17c7f952005-12-15 14:02:34 +0000695 if (vta->arch_guest == vta->arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000696 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000697 we are simulating one flavour of an architecture a different
698 flavour of the same architecture, which is pretty strange. */
sewardj5117ce12006-01-27 21:20:15 +0000699 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps);
sewardj9df271d2004-12-31 22:37:42 +0000700 }
sewardj2a9ad022004-11-25 02:46:58 +0000701
sewardj2d6b14a2005-11-23 04:25:07 +0000702 vexAllocSanityCheck();
703
sewardjf48ac192004-10-29 00:41:29 +0000704 if (vex_traceflags & VEX_TRACE_FE)
705 vex_printf("\n------------------------"
706 " Front end "
707 "------------------------\n\n");
708
sewardjdd40fdf2006-12-24 02:20:24 +0000709 irsb = bb_to_IR ( vta->guest_extents,
sewardjbc161a42011-06-07 21:28:38 +0000710 &res.n_sc_extents,
sewardjfadbbe22012-04-24 11:49:03 +0000711 &res.n_guest_instrs,
sewardjc716aea2006-01-17 01:48:46 +0000712 vta->callback_opaque,
sewardj9e6491a2005-07-02 19:24:10 +0000713 disInstrFn,
sewardj17c7f952005-12-15 14:02:34 +0000714 vta->guest_bytes,
715 vta->guest_bytes_addr,
716 vta->chase_into_ok,
sewardj9e6491a2005-07-02 19:24:10 +0000717 host_is_bigendian,
sewardj442e51a2012-12-06 18:08:04 +0000718 vta->sigill_diag,
sewardja5f55da2006-04-30 23:37:32 +0000719 vta->arch_guest,
sewardj17c7f952005-12-15 14:02:34 +0000720 &vta->archinfo_guest,
sewardjdd40fdf2006-12-24 02:20:24 +0000721 &vta->abiinfo_both,
sewardjdb4738a2005-07-07 01:32:16 +0000722 guest_word_type,
sewardjbc161a42011-06-07 21:28:38 +0000723 vta->needs_self_check,
sewardjc716aea2006-01-17 01:48:46 +0000724 vta->preamble_function,
sewardjdb4738a2005-07-07 01:32:16 +0000725 offB_TISTART,
sewardjc6f970f2012-04-02 21:54:49 +0000726 offB_TILEN,
727 offB_GUEST_IP,
728 szB_GUEST_IP );
sewardjf13a16a2004-07-05 17:10:14 +0000729
sewardj2d6b14a2005-11-23 04:25:07 +0000730 vexAllocSanityCheck();
731
sewardjdd40fdf2006-12-24 02:20:24 +0000732 if (irsb == NULL) {
sewardjf13a16a2004-07-05 17:10:14 +0000733 /* Access failure. */
sewardj2d6b14a2005-11-23 04:25:07 +0000734 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000735 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000736 res.status = VexTransAccessFail; return res;
sewardjf13a16a2004-07-05 17:10:14 +0000737 }
sewardjaa59f942004-10-09 09:34:36 +0000738
sewardj17c7f952005-12-15 14:02:34 +0000739 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3);
740 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr);
741 for (i = 0; i < vta->guest_extents->n_used; i++) {
742 vassert(vta->guest_extents->len[i] < 10000); /* sanity */
sewardj72c72812005-01-19 11:49:45 +0000743 }
744
sewardjaa59f942004-10-09 09:34:36 +0000745 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000746 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj17c7f952005-12-15 14:02:34 +0000747 if (vta->guest_extents->n_used > 1) {
sewardj72c72812005-01-19 11:49:45 +0000748 vex_printf("can't show code due to extents > 1\n");
749 } else {
750 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000751 UChar* p = (UChar*)vta->guest_bytes;
sewardj01f8cce2009-08-31 08:50:02 +0000752 UInt sum = 0;
sewardj17c7f952005-12-15 14:02:34 +0000753 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0];
sewardj01f8cce2009-08-31 08:50:02 +0000754 vex_printf("GuestBytes %llx %u ", vta->guest_bytes_addr,
755 guest_bytes_read );
756 for (i = 0; i < guest_bytes_read; i++) {
757 UInt b = (UInt)p[i];
758 vex_printf(" %02x", b );
759 sum = (sum << 1) ^ b;
760 }
761 vex_printf(" %08x\n\n", sum);
sewardj72c72812005-01-19 11:49:45 +0000762 }
sewardjaa59f942004-10-09 09:34:36 +0000763 }
764
765 /* Sanity check the initial IR. */
sewardjdd40fdf2006-12-24 02:20:24 +0000766 sanityCheckIRSB( irsb, "initial IR",
sewardjb9230752004-12-29 19:25:06 +0000767 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000768
sewardj2d6b14a2005-11-23 04:25:07 +0000769 vexAllocSanityCheck();
770
sewardjedf4d692004-08-17 13:52:58 +0000771 /* Clean it up, hopefully a lot. */
sewardjdd40fdf2006-12-24 02:20:24 +0000772 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn,
sewardjec0d9a02010-08-22 12:54:56 +0000773 vta->guest_bytes_addr,
774 vta->arch_guest );
sewardjdd40fdf2006-12-24 02:20:24 +0000775 sanityCheckIRSB( irsb, "after initial iropt",
sewardjb9230752004-12-29 19:25:06 +0000776 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000777
sewardjf48ac192004-10-29 00:41:29 +0000778 if (vex_traceflags & VEX_TRACE_OPT1) {
779 vex_printf("\n------------------------"
780 " After pre-instr IR optimisation "
781 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000782 ppIRSB ( irsb );
sewardjedf4d692004-08-17 13:52:58 +0000783 vex_printf("\n");
784 }
785
sewardj2d6b14a2005-11-23 04:25:07 +0000786 vexAllocSanityCheck();
787
sewardjf13a16a2004-07-05 17:10:14 +0000788 /* Get the thing instrumented. */
sewardj17c7f952005-12-15 14:02:34 +0000789 if (vta->instrument1)
sewardjdd40fdf2006-12-24 02:20:24 +0000790 irsb = vta->instrument1(vta->callback_opaque,
791 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000792 vta->guest_extents,
florian50481922012-10-07 21:58:07 +0000793 &vta->archinfo_host,
sewardj17c7f952005-12-15 14:02:34 +0000794 guest_word_type, host_word_type);
sewardj2d6b14a2005-11-23 04:25:07 +0000795 vexAllocSanityCheck();
796
sewardj17c7f952005-12-15 14:02:34 +0000797 if (vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000798 irsb = vta->instrument2(vta->callback_opaque,
799 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000800 vta->guest_extents,
florian50481922012-10-07 21:58:07 +0000801 &vta->archinfo_host,
sewardj17c7f952005-12-15 14:02:34 +0000802 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000803
sewardjf48ac192004-10-29 00:41:29 +0000804 if (vex_traceflags & VEX_TRACE_INST) {
805 vex_printf("\n------------------------"
806 " After instrumentation "
807 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000808 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000809 vex_printf("\n");
810 }
811
sewardj17c7f952005-12-15 14:02:34 +0000812 if (vta->instrument1 || vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000813 sanityCheckIRSB( irsb, "after instrumentation",
sewardjb9230752004-12-29 19:25:06 +0000814 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000815
sewardj9578a8b2004-11-04 19:44:48 +0000816 /* Do a post-instrumentation cleanup pass. */
sewardj17c7f952005-12-15 14:02:34 +0000817 if (vta->instrument1 || vta->instrument2) {
sewardjdd40fdf2006-12-24 02:20:24 +0000818 do_deadcode_BB( irsb );
819 irsb = cprop_BB( irsb );
820 do_deadcode_BB( irsb );
821 sanityCheckIRSB( irsb, "after post-instrumentation cleanup",
sewardjb9230752004-12-29 19:25:06 +0000822 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000823 }
824
sewardj2d6b14a2005-11-23 04:25:07 +0000825 vexAllocSanityCheck();
826
sewardj9578a8b2004-11-04 19:44:48 +0000827 if (vex_traceflags & VEX_TRACE_OPT2) {
828 vex_printf("\n------------------------"
829 " After post-instr IR optimisation "
830 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000831 ppIRSB ( irsb );
sewardj9578a8b2004-11-04 19:44:48 +0000832 vex_printf("\n");
833 }
834
sewardjf9517d02005-11-28 13:39:37 +0000835 /* Turn it into virtual-registerised code. Build trees -- this
836 also throws away any dead bindings. */
florian62140c12013-01-20 03:51:04 +0000837 max_ga = ado_treebuild_BB( irsb, preciseMemExnsFn );
sewardjf48ac192004-10-29 00:41:29 +0000838
sewardjbe1b6ff2007-08-28 06:06:27 +0000839 if (vta->finaltidy) {
840 irsb = vta->finaltidy(irsb);
841 }
842
sewardj2d6b14a2005-11-23 04:25:07 +0000843 vexAllocSanityCheck();
844
sewardjf48ac192004-10-29 00:41:29 +0000845 if (vex_traceflags & VEX_TRACE_TREES) {
846 vex_printf("\n------------------------"
847 " After tree-building "
848 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000849 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000850 vex_printf("\n");
851 }
852
sewardje908c422005-02-04 21:18:16 +0000853 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000854 if (0) {
855 *(vta->host_bytes_used) = 0;
856 res.status = VexTransOK; return res;
857 }
sewardje908c422005-02-04 21:18:16 +0000858 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000859
sewardjf48ac192004-10-29 00:41:29 +0000860 if (vex_traceflags & VEX_TRACE_VCODE)
861 vex_printf("\n------------------------"
862 " Instruction selection "
863 "------------------------\n");
864
sewardjc6f970f2012-04-02 21:54:49 +0000865 /* No guest has its IP field at offset zero. If this fails it
866 means some transformation pass somewhere failed to update/copy
867 irsb->offsIP properly. */
868 vassert(irsb->offsIP >= 16);
869
870 vcode = iselSB ( irsb, vta->arch_host,
871 &vta->archinfo_host,
872 &vta->abiinfo_both,
873 offB_HOST_EvC_COUNTER,
874 offB_HOST_EvC_FAILADDR,
875 chainingAllowed,
876 vta->addProfInc,
877 max_ga );
sewardjf13a16a2004-07-05 17:10:14 +0000878
sewardj2d6b14a2005-11-23 04:25:07 +0000879 vexAllocSanityCheck();
880
sewardjf48ac192004-10-29 00:41:29 +0000881 if (vex_traceflags & VEX_TRACE_VCODE)
882 vex_printf("\n");
883
sewardjf48ac192004-10-29 00:41:29 +0000884 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000885 for (i = 0; i < vcode->arr_used; i++) {
886 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000887 ppInstr(vcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000888 vex_printf("\n");
889 }
sewardjfbcaf332004-07-08 01:46:01 +0000890 vex_printf("\n");
891 }
sewardjfbcaf332004-07-08 01:46:01 +0000892
sewardjf13a16a2004-07-05 17:10:14 +0000893 /* Register allocate. */
894 rcode = doRegisterAllocation ( vcode, available_real_regs,
cerionf0de28c2005-12-13 20:21:11 +0000895 n_available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000896 isMove, getRegUsage, mapRegs,
sewardjfb7373a2007-08-25 21:29:03 +0000897 genSpill, genReload, directReload,
898 guest_sizeB,
cerion92b64362005-12-13 12:02:26 +0000899 ppInstr, ppReg, mode64 );
sewardjf13a16a2004-07-05 17:10:14 +0000900
sewardj2d6b14a2005-11-23 04:25:07 +0000901 vexAllocSanityCheck();
902
sewardjf48ac192004-10-29 00:41:29 +0000903 if (vex_traceflags & VEX_TRACE_RCODE) {
904 vex_printf("\n------------------------"
905 " Register-allocated code "
906 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000907 for (i = 0; i < rcode->arr_used; i++) {
908 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000909 ppInstr(rcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000910 vex_printf("\n");
911 }
sewardjfbcaf332004-07-08 01:46:01 +0000912 vex_printf("\n");
913 }
sewardjfbcaf332004-07-08 01:46:01 +0000914
sewardje908c422005-02-04 21:18:16 +0000915 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000916 if (0) {
917 *(vta->host_bytes_used) = 0;
918 res.status = VexTransOK; return res;
919 }
sewardje908c422005-02-04 21:18:16 +0000920 /* end HACK */
921
sewardj81bd5502004-07-21 18:49:27 +0000922 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000923 if (vex_traceflags & VEX_TRACE_ASM) {
924 vex_printf("\n------------------------"
925 " Assembly "
926 "------------------------\n\n");
927 }
928
sewardj81bd5502004-07-21 18:49:27 +0000929 out_used = 0; /* tracks along the host_bytes array */
930 for (i = 0; i < rcode->arr_used; i++) {
sewardjc6f970f2012-04-02 21:54:49 +0000931 HInstr* hi = rcode->arr[i];
932 Bool hi_isProfInc = False;
933 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
934 ppInstr(hi, mode64);
sewardjbad34a92004-07-22 01:14:11 +0000935 vex_printf("\n");
936 }
sewardjc6f970f2012-04-02 21:54:49 +0000937 j = emit( &hi_isProfInc,
938 insn_bytes, sizeof insn_bytes, hi, mode64,
939 vta->disp_cp_chain_me_to_slowEP,
940 vta->disp_cp_chain_me_to_fastEP,
941 vta->disp_cp_xindir,
942 vta->disp_cp_xassisted );
943 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
sewardjbad34a92004-07-22 01:14:11 +0000944 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000945 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000946 vex_printf("0%x ", (UInt)insn_bytes[k]);
947 else
948 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000949 vex_printf("\n\n");
950 }
sewardjc6f970f2012-04-02 21:54:49 +0000951 if (UNLIKELY(out_used + j > vta->host_bytes_size)) {
sewardj2d6b14a2005-11-23 04:25:07 +0000952 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000953 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000954 res.status = VexTransOutputFull;
955 return res;
sewardj81bd5502004-07-21 18:49:27 +0000956 }
sewardjc6f970f2012-04-02 21:54:49 +0000957 if (UNLIKELY(hi_isProfInc)) {
958 vassert(vta->addProfInc); /* else where did it come from? */
959 vassert(res.offs_profInc == -1); /* there can be only one (tm) */
960 vassert(out_used >= 0);
961 res.offs_profInc = out_used;
962 }
963 { UChar* dst = &vta->host_bytes[out_used];
964 for (k = 0; k < j; k++) {
965 dst[k] = insn_bytes[k];
966 }
967 out_used += j;
sewardj81bd5502004-07-21 18:49:27 +0000968 }
sewardj17c7f952005-12-15 14:02:34 +0000969 vassert(out_used <= vta->host_bytes_size);
sewardj81bd5502004-07-21 18:49:27 +0000970 }
sewardj17c7f952005-12-15 14:02:34 +0000971 *(vta->host_bytes_used) = out_used;
sewardj81bd5502004-07-21 18:49:27 +0000972
sewardj2d6b14a2005-11-23 04:25:07 +0000973 vexAllocSanityCheck();
974
975 vexSetAllocModeTEMP_and_clear();
sewardjf13a16a2004-07-05 17:10:14 +0000976
sewardj65ea17e2012-12-28 09:01:59 +0000977 if (vex_traceflags) {
978 /* Print the expansion ratio for this SB. */
979 j = 0; /* total guest bytes */
980 for (i = 0; i < vta->guest_extents->n_used; i++) {
981 j += vta->guest_extents->len[i];
982 }
983 if (1) vex_printf("VexExpansionRatio %d %d %d :10\n\n",
984 j, out_used, (10 * out_used) / (j == 0 ? 1 : j));
985 }
986
sewardjf48ac192004-10-29 00:41:29 +0000987 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000988 res.status = VexTransOK;
989 return res;
sewardj35421a32004-07-05 13:12:34 +0000990}
991
992
sewardjc6f970f2012-04-02 21:54:49 +0000993/* --------- Chain/Unchain XDirects. --------- */
994
995VexInvalRange LibVEX_Chain ( VexArch arch_host,
996 void* place_to_chain,
997 void* disp_cp_chain_me_EXPECTED,
998 void* place_to_jump_to )
999{
1000 VexInvalRange (*chainXDirect)(void*, void*, void*) = NULL;
1001 switch (arch_host) {
1002 case VexArchX86:
1003 chainXDirect = chainXDirect_X86; break;
1004 case VexArchAMD64:
1005 chainXDirect = chainXDirect_AMD64; break;
1006 case VexArchARM:
1007 chainXDirect = chainXDirect_ARM; break;
sewardjbbcf1882014-01-12 12:49:10 +00001008 case VexArchARM64:
1009 chainXDirect = chainXDirect_ARM64; break;
florian8844a632012-04-13 04:04:06 +00001010 case VexArchS390X:
1011 chainXDirect = chainXDirect_S390; break;
sewardj3dee8492012-04-20 00:13:28 +00001012 case VexArchPPC32:
1013 return chainXDirect_PPC(place_to_chain,
1014 disp_cp_chain_me_EXPECTED,
1015 place_to_jump_to, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +00001016 case VexArchPPC64:
1017 return chainXDirect_PPC(place_to_chain,
1018 disp_cp_chain_me_EXPECTED,
1019 place_to_jump_to, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +00001020 case VexArchMIPS32:
1021 return chainXDirect_MIPS(place_to_chain,
1022 disp_cp_chain_me_EXPECTED,
1023 place_to_jump_to, False/*!mode64*/);
petarjb92a9542013-02-27 22:57:17 +00001024 case VexArchMIPS64:
1025 return chainXDirect_MIPS(place_to_chain,
1026 disp_cp_chain_me_EXPECTED,
1027 place_to_jump_to, True/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +00001028 default:
1029 vassert(0);
1030 }
1031 vassert(chainXDirect);
1032 VexInvalRange vir
1033 = chainXDirect(place_to_chain, disp_cp_chain_me_EXPECTED,
1034 place_to_jump_to);
1035 return vir;
1036}
1037
1038VexInvalRange LibVEX_UnChain ( VexArch arch_host,
1039 void* place_to_unchain,
1040 void* place_to_jump_to_EXPECTED,
1041 void* disp_cp_chain_me )
1042{
1043 VexInvalRange (*unchainXDirect)(void*, void*, void*) = NULL;
1044 switch (arch_host) {
1045 case VexArchX86:
1046 unchainXDirect = unchainXDirect_X86; break;
1047 case VexArchAMD64:
1048 unchainXDirect = unchainXDirect_AMD64; break;
1049 case VexArchARM:
1050 unchainXDirect = unchainXDirect_ARM; break;
sewardjc6acaa42014-02-19 17:42:59 +00001051 case VexArchARM64:
1052 unchainXDirect = unchainXDirect_ARM64; break;
florian8844a632012-04-13 04:04:06 +00001053 case VexArchS390X:
1054 unchainXDirect = unchainXDirect_S390; break;
sewardj3dee8492012-04-20 00:13:28 +00001055 case VexArchPPC32:
1056 return unchainXDirect_PPC(place_to_unchain,
1057 place_to_jump_to_EXPECTED,
1058 disp_cp_chain_me, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +00001059 case VexArchPPC64:
1060 return unchainXDirect_PPC(place_to_unchain,
1061 place_to_jump_to_EXPECTED,
1062 disp_cp_chain_me, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +00001063 case VexArchMIPS32:
1064 return unchainXDirect_MIPS(place_to_unchain,
petarjb92a9542013-02-27 22:57:17 +00001065 place_to_jump_to_EXPECTED,
1066 disp_cp_chain_me, False/*!mode64*/);
1067 case VexArchMIPS64:
1068 return unchainXDirect_MIPS(place_to_unchain,
1069 place_to_jump_to_EXPECTED,
1070 disp_cp_chain_me, True/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +00001071 default:
1072 vassert(0);
1073 }
1074 vassert(unchainXDirect);
1075 VexInvalRange vir
1076 = unchainXDirect(place_to_unchain, place_to_jump_to_EXPECTED,
1077 disp_cp_chain_me);
1078 return vir;
1079}
1080
1081Int LibVEX_evCheckSzB ( VexArch arch_host )
1082{
1083 static Int cached = 0; /* DO NOT MAKE NON-STATIC */
1084 if (UNLIKELY(cached == 0)) {
1085 switch (arch_host) {
1086 case VexArchX86:
1087 cached = evCheckSzB_X86(); break;
1088 case VexArchAMD64:
1089 cached = evCheckSzB_AMD64(); break;
1090 case VexArchARM:
1091 cached = evCheckSzB_ARM(); break;
sewardjbbcf1882014-01-12 12:49:10 +00001092 case VexArchARM64:
1093 cached = evCheckSzB_ARM64(); break;
florian8844a632012-04-13 04:04:06 +00001094 case VexArchS390X:
1095 cached = evCheckSzB_S390(); break;
sewardj3dee8492012-04-20 00:13:28 +00001096 case VexArchPPC32:
sewardjf252de52012-04-20 10:42:24 +00001097 case VexArchPPC64:
sewardj3dee8492012-04-20 00:13:28 +00001098 cached = evCheckSzB_PPC(); break;
sewardjd0e5fe72012-06-07 08:51:02 +00001099 case VexArchMIPS32:
petarjb92a9542013-02-27 22:57:17 +00001100 case VexArchMIPS64:
sewardjd0e5fe72012-06-07 08:51:02 +00001101 cached = evCheckSzB_MIPS(); break;
sewardjc6f970f2012-04-02 21:54:49 +00001102 default:
1103 vassert(0);
1104 }
1105 }
1106 return cached;
1107}
1108
1109VexInvalRange LibVEX_PatchProfInc ( VexArch arch_host,
1110 void* place_to_patch,
1111 ULong* location_of_counter )
1112{
1113 VexInvalRange (*patchProfInc)(void*,ULong*) = NULL;
1114 switch (arch_host) {
1115 case VexArchX86:
1116 patchProfInc = patchProfInc_X86; break;
1117 case VexArchAMD64:
1118 patchProfInc = patchProfInc_AMD64; break;
1119 case VexArchARM:
1120 patchProfInc = patchProfInc_ARM; break;
florian8844a632012-04-13 04:04:06 +00001121 case VexArchS390X:
1122 patchProfInc = patchProfInc_S390; break;
sewardj3dee8492012-04-20 00:13:28 +00001123 case VexArchPPC32:
1124 return patchProfInc_PPC(place_to_patch,
1125 location_of_counter, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +00001126 case VexArchPPC64:
1127 return patchProfInc_PPC(place_to_patch,
1128 location_of_counter, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +00001129 case VexArchMIPS32:
1130 return patchProfInc_MIPS(place_to_patch,
1131 location_of_counter, False/*!mode64*/);
petarjb92a9542013-02-27 22:57:17 +00001132 case VexArchMIPS64:
1133 return patchProfInc_MIPS(place_to_patch,
1134 location_of_counter, True/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +00001135 default:
1136 vassert(0);
1137 }
1138 vassert(patchProfInc);
1139 VexInvalRange vir
1140 = patchProfInc(place_to_patch, location_of_counter);
1141 return vir;
1142}
1143
1144
sewardj893aada2004-11-29 19:57:54 +00001145/* --------- Emulation warnings. --------- */
1146
florian1ff47562012-10-21 02:09:51 +00001147const HChar* LibVEX_EmNote_string ( VexEmNote ew )
sewardj893aada2004-11-29 19:57:54 +00001148{
1149 switch (ew) {
florian6ef84be2012-08-26 03:20:07 +00001150 case EmNote_NONE:
sewardj893aada2004-11-29 19:57:54 +00001151 return "none";
1152 case EmWarn_X86_x87exns:
1153 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +00001154 case EmWarn_X86_x87precision:
1155 return "Selection of non-80-bit x87 FP precision";
1156 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +00001157 return "Unmasking SSE FP exceptions";
1158 case EmWarn_X86_fz:
1159 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
1160 case EmWarn_X86_daz:
1161 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +00001162 case EmWarn_X86_acFlag:
1163 return "Setting %eflags.ac (setting noted but ignored)";
sewardj9dd9cf12006-01-20 14:13:55 +00001164 case EmWarn_PPCexns:
1165 return "Unmasking PPC32/64 FP exceptions";
1166 case EmWarn_PPC64_redir_overflow:
1167 return "PPC64 function redirection stack overflow";
1168 case EmWarn_PPC64_redir_underflow:
1169 return "PPC64 function redirection stack underflow";
florian4b8efad2012-09-02 18:07:08 +00001170 case EmWarn_S390X_fpext_rounding:
1171 return "The specified rounding mode cannot be supported. That\n"
1172 " feature requires the floating point extension facility.\n"
1173 " which is not available on this host. Continuing using\n"
1174 " the rounding mode from FPC. Results may differ!";
florianf0fa1be2012-09-18 20:24:38 +00001175 case EmWarn_S390X_invalid_rounding:
1176 return "The specified rounding mode is invalid.\n"
1177 " Continuing using 'round to nearest'. Results may differ!";
floriane75dafa2012-09-01 17:54:09 +00001178 case EmFail_S390X_stfle:
florian4e0083e2012-08-26 03:41:56 +00001179 return "Instruction stfle is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001180 case EmFail_S390X_stckf:
florianc5c669b2012-08-26 14:32:28 +00001181 return "Instruction stckf is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001182 case EmFail_S390X_ecag:
florian8c88cb62012-08-26 18:58:13 +00001183 return "Instruction ecag is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001184 case EmFail_S390X_fpext:
1185 return "Encountered an instruction that requires the floating "
1186 "point extension facility.\n"
1187 " That facility is not available on this host";
florian78d5ef72013-05-11 15:02:58 +00001188 case EmFail_S390X_invalid_PFPO_rounding_mode:
1189 return "The rounding mode specified in GPR 0 for PFPO instruction"
1190 " is invalid";
1191 case EmFail_S390X_invalid_PFPO_function:
1192 return "The function code specified in GPR 0 for PFPO instruction"
1193 " is invalid";
sewardj893aada2004-11-29 19:57:54 +00001194 default:
florian6ef84be2012-08-26 03:20:07 +00001195 vpanic("LibVEX_EmNote_string: unknown warning");
sewardj893aada2004-11-29 19:57:54 +00001196 }
1197}
sewardj35421a32004-07-05 13:12:34 +00001198
sewardj5117ce12006-01-27 21:20:15 +00001199/* ------------------ Arch/HwCaps stuff. ------------------ */
sewardjbef170b2004-12-21 01:23:00 +00001200
1201const HChar* LibVEX_ppVexArch ( VexArch arch )
1202{
1203 switch (arch) {
1204 case VexArch_INVALID: return "INVALID";
1205 case VexArchX86: return "X86";
1206 case VexArchAMD64: return "AMD64";
1207 case VexArchARM: return "ARM";
sewardjbbcf1882014-01-12 12:49:10 +00001208 case VexArchARM64: return "ARM64";
sewardj0ec57c52005-02-01 15:24:10 +00001209 case VexArchPPC32: return "PPC32";
cerionf0de28c2005-12-13 20:21:11 +00001210 case VexArchPPC64: return "PPC64";
sewardj2019a972011-03-07 16:04:07 +00001211 case VexArchS390X: return "S390X";
sewardjd0e5fe72012-06-07 08:51:02 +00001212 case VexArchMIPS32: return "MIPS32";
petarjb92a9542013-02-27 22:57:17 +00001213 case VexArchMIPS64: return "MIPS64";
sewardjbef170b2004-12-21 01:23:00 +00001214 default: return "VexArch???";
1215 }
1216}
1217
sewardj5117ce12006-01-27 21:20:15 +00001218const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
sewardjbef170b2004-12-21 01:23:00 +00001219{
florian55085f82012-11-21 00:36:55 +00001220 const HChar* str = show_hwcaps(arch,hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001221 return str ? str : "INVALID";
sewardjbef170b2004-12-21 01:23:00 +00001222}
1223
sewardj5117ce12006-01-27 21:20:15 +00001224
sewardj27e1dd62005-06-30 11:49:14 +00001225/* Write default settings info *vai. */
1226void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
1227{
florian9138b172013-08-03 19:36:55 +00001228 vai->hwcaps = 0;
1229 vai->ppc_icache_line_szB = 0;
1230 vai->ppc_dcbz_szB = 0;
1231 vai->ppc_dcbzl_szB = 0;
sewardje971c6a2010-09-03 15:49:57 +00001232
florianf192a392012-10-07 19:44:40 +00001233 vai->hwcache_info.num_levels = 0;
1234 vai->hwcache_info.num_caches = 0;
1235 vai->hwcache_info.caches = NULL;
1236 vai->hwcache_info.icaches_maintain_coherence = True; // whatever
sewardj27e1dd62005-06-30 11:49:14 +00001237}
1238
sewardjdd40fdf2006-12-24 02:20:24 +00001239/* Write default settings info *vbi. */
1240void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
sewardjaca070a2006-10-17 00:28:22 +00001241{
sewardjdd40fdf2006-12-24 02:20:24 +00001242 vbi->guest_stack_redzone_size = 0;
sewardj2e28ac42008-12-04 00:05:12 +00001243 vbi->guest_amd64_assume_fs_is_zero = False;
1244 vbi->guest_amd64_assume_gs_is_0x60 = False;
sewardjdd40fdf2006-12-24 02:20:24 +00001245 vbi->guest_ppc_zap_RZ_at_blr = False;
1246 vbi->guest_ppc_zap_RZ_at_bl = NULL;
1247 vbi->guest_ppc_sc_continues_at_LR = False;
1248 vbi->host_ppc_calls_use_fndescrs = False;
1249 vbi->host_ppc32_regalign_int64_args = False;
sewardjaca070a2006-10-17 00:28:22 +00001250}
1251
sewardj27e1dd62005-06-30 11:49:14 +00001252
sewardj5117ce12006-01-27 21:20:15 +00001253/* Return a string showing the hwcaps in a nice way. The string will
1254 be NULL for invalid combinations of flags, so these functions also
1255 serve as a way to validate hwcaps values. */
1256
florian55085f82012-11-21 00:36:55 +00001257static const HChar* show_hwcaps_x86 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001258{
mjw6c65c122013-08-27 10:19:03 +00001259 /* Monotonic, LZCNT > SSE3 > SSE2 > SSE1 > MMXEXT > baseline. */
sewardj536fbab2010-07-29 15:39:05 +00001260 switch (hwcaps) {
1261 case 0:
1262 return "x86-sse0";
mjw6c65c122013-08-27 10:19:03 +00001263 case VEX_HWCAPS_X86_MMXEXT:
1264 return "x86-mmxext";
1265 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1:
1266 return "x86-mmxext-sse1";
1267 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2:
1268 return "x86-mmxext-sse1-sse2";
1269 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
sewardj536fbab2010-07-29 15:39:05 +00001270 | VEX_HWCAPS_X86_LZCNT:
mjw6c65c122013-08-27 10:19:03 +00001271 return "x86-mmxext-sse1-sse2-lzcnt";
1272 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
sewardj536fbab2010-07-29 15:39:05 +00001273 | VEX_HWCAPS_X86_SSE3:
mjw6c65c122013-08-27 10:19:03 +00001274 return "x86-mmxext-sse1-sse2-sse3";
1275 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
sewardj536fbab2010-07-29 15:39:05 +00001276 | VEX_HWCAPS_X86_SSE3 | VEX_HWCAPS_X86_LZCNT:
mjw6c65c122013-08-27 10:19:03 +00001277 return "x86-mmxext-sse1-sse2-sse3-lzcnt";
sewardj536fbab2010-07-29 15:39:05 +00001278 default:
1279 return NULL;
1280 }
sewardj5117ce12006-01-27 21:20:15 +00001281}
1282
florian55085f82012-11-21 00:36:55 +00001283static const HChar* show_hwcaps_amd64 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001284{
sewardje9d8a262009-07-01 08:06:34 +00001285 /* SSE3 and CX16 are orthogonal and > baseline, although we really
1286 don't expect to come across anything which can do SSE3 but can't
sewardj536fbab2010-07-29 15:39:05 +00001287 do CX16. Still, we can handle that case. LZCNT is similarly
sewardj818c7302013-03-26 13:53:18 +00001288 orthogonal. */
1289
1290 /* Throw out obviously stupid cases: */
sewardj818c7302013-03-26 13:53:18 +00001291 Bool have_sse3 = (hwcaps & VEX_HWCAPS_AMD64_SSE3) != 0;
1292 Bool have_avx = (hwcaps & VEX_HWCAPS_AMD64_AVX) != 0;
sewardjcc3d2192013-03-27 11:37:33 +00001293 Bool have_bmi = (hwcaps & VEX_HWCAPS_AMD64_BMI) != 0;
1294 Bool have_avx2 = (hwcaps & VEX_HWCAPS_AMD64_AVX2) != 0;
1295 /* AVX without SSE3 */
sewardj818c7302013-03-26 13:53:18 +00001296 if (have_avx && !have_sse3)
1297 return NULL;
sewardjcc3d2192013-03-27 11:37:33 +00001298 /* AVX2 or BMI without AVX */
1299 if ((have_avx2 || have_bmi) && !have_avx)
1300 return NULL;
sewardj818c7302013-03-26 13:53:18 +00001301
1302 /* This isn't threadsafe. We might need to fix it at some point. */
1303 static HChar buf[100] = { 0 };
1304 if (buf[0] != 0) return buf; /* already constructed */
1305
1306 vex_bzero(buf, sizeof(buf));
1307
1308 HChar* p = &buf[0];
1309
1310 p = p + vex_sprintf(p, "%s", "amd64");
1311 if (hwcaps == 0) {
1312 /* special-case the baseline case */
1313 p = p + vex_sprintf(p, "%s", "-sse2");
1314 goto out;
sewardj536fbab2010-07-29 15:39:05 +00001315 }
sewardj818c7302013-03-26 13:53:18 +00001316 if (hwcaps & VEX_HWCAPS_AMD64_CX16) {
1317 p = p + vex_sprintf(p, "%s", "-cx16");
1318 }
1319 if (hwcaps & VEX_HWCAPS_AMD64_LZCNT) {
1320 p = p + vex_sprintf(p, "%s", "-lzcnt");
1321 }
1322 if (hwcaps & VEX_HWCAPS_AMD64_RDTSCP) {
1323 p = p + vex_sprintf(p, "%s", "-rdtscp");
1324 }
1325 if (hwcaps & VEX_HWCAPS_AMD64_SSE3) {
1326 p = p + vex_sprintf(p, "%s", "-sse3");
1327 }
1328 if (hwcaps & VEX_HWCAPS_AMD64_AVX) {
1329 p = p + vex_sprintf(p, "%s", "-avx");
1330 }
sewardjcc3d2192013-03-27 11:37:33 +00001331 if (hwcaps & VEX_HWCAPS_AMD64_AVX2) {
1332 p = p + vex_sprintf(p, "%s", "-avx2");
1333 }
1334 if (hwcaps & VEX_HWCAPS_AMD64_BMI) {
1335 p = p + vex_sprintf(p, "%s", "-bmi");
1336 }
sewardj818c7302013-03-26 13:53:18 +00001337
1338 out:
1339 vassert(buf[sizeof(buf)-1] == 0);
1340 return buf;
sewardj5117ce12006-01-27 21:20:15 +00001341}
1342
florian55085f82012-11-21 00:36:55 +00001343static const HChar* show_hwcaps_ppc32 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001344{
1345 /* Monotonic with complications. Basically V > F > baseline,
1346 but once you have F then you can have FX or GX too. */
1347 const UInt F = VEX_HWCAPS_PPC32_F;
1348 const UInt V = VEX_HWCAPS_PPC32_V;
1349 const UInt FX = VEX_HWCAPS_PPC32_FX;
1350 const UInt GX = VEX_HWCAPS_PPC32_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001351 const UInt VX = VEX_HWCAPS_PPC32_VX;
sewardjc66d6fa2012-04-02 21:24:12 +00001352 const UInt DFP = VEX_HWCAPS_PPC32_DFP;
carll0c74bb52013-08-12 18:01:40 +00001353 const UInt ISA2_07 = VEX_HWCAPS_PPC32_ISA2_07;
sewardj5117ce12006-01-27 21:20:15 +00001354 UInt c = hwcaps;
1355 if (c == 0) return "ppc32-int";
1356 if (c == F) return "ppc32-int-flt";
1357 if (c == (F|FX)) return "ppc32-int-flt-FX";
1358 if (c == (F|GX)) return "ppc32-int-flt-GX";
1359 if (c == (F|FX|GX)) return "ppc32-int-flt-FX-GX";
1360 if (c == (F|V)) return "ppc32-int-flt-vmx";
1361 if (c == (F|V|FX)) return "ppc32-int-flt-vmx-FX";
1362 if (c == (F|V|GX)) return "ppc32-int-flt-vmx-GX";
1363 if (c == (F|V|FX|GX)) return "ppc32-int-flt-vmx-FX-GX";
sewardjc66d6fa2012-04-02 21:24:12 +00001364 if (c == (F|V|FX|GX|DFP)) return "ppc32-int-flt-vmx-FX-GX-DFP";
1365 if (c == (F|V|FX|GX|VX|DFP)) return "ppc32-int-flt-vmx-FX-GX-VX-DFP";
carll0c74bb52013-08-12 18:01:40 +00001366 if (c == (F|V|FX|GX|VX|DFP|ISA2_07))
1367 return "ppc32-int-flt-vmx-FX-GX-VX-DFP-ISA2_07";
1368
sewardj5117ce12006-01-27 21:20:15 +00001369 return NULL;
1370}
1371
florian55085f82012-11-21 00:36:55 +00001372static const HChar* show_hwcaps_ppc64 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001373{
1374 /* Monotonic with complications. Basically V > baseline(==F),
1375 but once you have F then you can have FX or GX too. */
sewardj3fd39672006-01-27 22:05:55 +00001376 const UInt V = VEX_HWCAPS_PPC64_V;
1377 const UInt FX = VEX_HWCAPS_PPC64_FX;
1378 const UInt GX = VEX_HWCAPS_PPC64_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001379 const UInt VX = VEX_HWCAPS_PPC64_VX;
sewardjc66d6fa2012-04-02 21:24:12 +00001380 const UInt DFP = VEX_HWCAPS_PPC64_DFP;
carll0c74bb52013-08-12 18:01:40 +00001381 const UInt ISA2_07 = VEX_HWCAPS_PPC64_ISA2_07;
sewardj5117ce12006-01-27 21:20:15 +00001382 UInt c = hwcaps;
1383 if (c == 0) return "ppc64-int-flt";
1384 if (c == FX) return "ppc64-int-flt-FX";
1385 if (c == GX) return "ppc64-int-flt-GX";
1386 if (c == (FX|GX)) return "ppc64-int-flt-FX-GX";
1387 if (c == V) return "ppc64-int-flt-vmx";
1388 if (c == (V|FX)) return "ppc64-int-flt-vmx-FX";
1389 if (c == (V|GX)) return "ppc64-int-flt-vmx-GX";
1390 if (c == (V|FX|GX)) return "ppc64-int-flt-vmx-FX-GX";
sewardjc66d6fa2012-04-02 21:24:12 +00001391 if (c == (V|FX|GX|DFP)) return "ppc64-int-flt-vmx-FX-GX-DFP";
1392 if (c == (V|FX|GX|VX|DFP)) return "ppc64-int-flt-vmx-FX-GX-VX-DFP";
carll0c74bb52013-08-12 18:01:40 +00001393 if (c == (V|FX|GX|VX|DFP|ISA2_07))
1394 return "ppc64-int-flt-vmx-FX-GX-VX-DFP-ISA2_07";
sewardj5117ce12006-01-27 21:20:15 +00001395 return NULL;
1396}
1397
florian55085f82012-11-21 00:36:55 +00001398static const HChar* show_hwcaps_arm ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001399{
sewardjec0d9a02010-08-22 12:54:56 +00001400 Bool N = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0);
1401 Bool vfp = ((hwcaps & (VEX_HWCAPS_ARM_VFP |
1402 VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3)) != 0);
1403 switch (VEX_ARM_ARCHLEVEL(hwcaps)) {
1404 case 5:
1405 if (N)
1406 return NULL;
1407 if (vfp)
1408 return "ARMv5-vfp";
1409 else
1410 return "ARMv5";
1411 return NULL;
1412 case 6:
1413 if (N)
1414 return NULL;
1415 if (vfp)
1416 return "ARMv6-vfp";
1417 else
1418 return "ARMv6";
1419 return NULL;
1420 case 7:
1421 if (vfp) {
1422 if (N)
1423 return "ARMv7-vfp-neon";
1424 else
1425 return "ARMv7-vfp";
1426 } else {
1427 if (N)
1428 return "ARMv7-neon";
1429 else
1430 return "ARMv7";
1431 }
1432 default:
1433 return NULL;
1434 }
sewardj5117ce12006-01-27 21:20:15 +00001435 return NULL;
1436}
1437
sewardjbbcf1882014-01-12 12:49:10 +00001438static const HChar* show_hwcaps_arm64 ( UInt hwcaps )
1439{
1440 /* Since there are no variants, just insist that hwcaps is zero,
1441 and declare it invalid otherwise. */
1442 if (hwcaps == 0)
1443 return "baseline";
1444 return NULL;
1445}
1446
florian55085f82012-11-21 00:36:55 +00001447static const HChar* show_hwcaps_s390x ( UInt hwcaps )
sewardj2019a972011-03-07 16:04:07 +00001448{
sewardjd07b8562011-04-27 11:58:22 +00001449 static const HChar prefix[] = "s390x";
florian9061eb32012-12-09 17:53:45 +00001450 static const struct {
1451 UInt hwcaps_bit;
1452 HChar name[6];
1453 } hwcaps_list[] = {
1454 { VEX_HWCAPS_S390X_LDISP, "ldisp" },
1455 { VEX_HWCAPS_S390X_EIMM, "eimm" },
1456 { VEX_HWCAPS_S390X_GIE, "gie" },
1457 { VEX_HWCAPS_S390X_DFP, "dfp" },
1458 { VEX_HWCAPS_S390X_FGX, "fgx" },
1459 { VEX_HWCAPS_S390X_STFLE, "stfle" },
1460 { VEX_HWCAPS_S390X_ETF2, "etf2" },
1461 { VEX_HWCAPS_S390X_ETF3, "etf3" },
1462 { VEX_HWCAPS_S390X_STCKF, "stckf" },
1463 { VEX_HWCAPS_S390X_FPEXT, "fpext" },
1464 { VEX_HWCAPS_S390X_LSC, "lsc" },
florian78d5ef72013-05-11 15:02:58 +00001465 { VEX_HWCAPS_S390X_PFPO, "pfpo" },
sewardjd07b8562011-04-27 11:58:22 +00001466 };
florian9061eb32012-12-09 17:53:45 +00001467#define NUM_HWCAPS (sizeof hwcaps_list / sizeof hwcaps_list[0])
1468 static HChar buf[sizeof prefix +
1469 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) +
1470 1]; // '\0'
1471 HChar *p;
1472 UInt i;
sewardjd07b8562011-04-27 11:58:22 +00001473
1474 if (buf[0] != '\0') return buf; /* already constructed */
sewardj2019a972011-03-07 16:04:07 +00001475
sewardj652b56a2011-04-13 15:38:17 +00001476 hwcaps = VEX_HWCAPS_S390X(hwcaps);
1477
sewardjd07b8562011-04-27 11:58:22 +00001478 p = buf + vex_sprintf(buf, "%s", prefix);
florian9061eb32012-12-09 17:53:45 +00001479 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1480 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1481 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1482 }
sewardj2019a972011-03-07 16:04:07 +00001483
sewardjd07b8562011-04-27 11:58:22 +00001484 /* If there are no facilities, add "zarch" */
1485 if (hwcaps == 0)
1486 vex_sprintf(p, "-%s", "zarch");
1487
1488 return buf;
sewardj2019a972011-03-07 16:04:07 +00001489}
1490
florian55085f82012-11-21 00:36:55 +00001491static const HChar* show_hwcaps_mips32 ( UInt hwcaps )
sewardjd0e5fe72012-06-07 08:51:02 +00001492{
dejanjc3fee0d2013-07-25 09:08:03 +00001493 /* MIPS baseline. */
petarjbc7d6f42013-09-16 18:11:59 +00001494 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_MIPS) {
dejanjc3fee0d2013-07-25 09:08:03 +00001495 /* MIPS baseline with dspr2. */
petarjbc7d6f42013-09-16 18:11:59 +00001496 if (VEX_MIPS_PROC_DSP2(hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +00001497 return "MIPS-baseline-dspr2";
1498 }
1499 /* MIPS baseline with dsp. */
petarjbc7d6f42013-09-16 18:11:59 +00001500 if (VEX_MIPS_PROC_DSP(hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +00001501 return "MIPS-baseline-dsp";
1502 }
1503 return "MIPS-baseline";
1504 }
1505
1506 /* Broadcom baseline. */
petarjbc7d6f42013-09-16 18:11:59 +00001507 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_BROADCOM) {
dejanjc3fee0d2013-07-25 09:08:03 +00001508 return "Broadcom-baseline";
1509 }
1510
1511 /* Netlogic baseline. */
petarjbc7d6f42013-09-16 18:11:59 +00001512 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_NETLOGIC) {
dejanjc3fee0d2013-07-25 09:08:03 +00001513 return "Netlogic-baseline";
1514 }
1515
petarjbc7d6f42013-09-16 18:11:59 +00001516 /* Cavium baseline. */
1517 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_CAVIUM) {
1518 return "Cavium-baseline";
1519 }
1520
sewardjd0e5fe72012-06-07 08:51:02 +00001521 return NULL;
1522}
1523
petarjb92a9542013-02-27 22:57:17 +00001524static const HChar* show_hwcaps_mips64 ( UInt hwcaps )
1525{
1526 return "mips64-baseline";
1527}
1528
sewardj5117ce12006-01-27 21:20:15 +00001529/* ---- */
florian55085f82012-11-21 00:36:55 +00001530static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001531{
1532 switch (arch) {
sewardjd0e5fe72012-06-07 08:51:02 +00001533 case VexArchX86: return show_hwcaps_x86(hwcaps);
1534 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
1535 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
1536 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
1537 case VexArchARM: return show_hwcaps_arm(hwcaps);
sewardjbbcf1882014-01-12 12:49:10 +00001538 case VexArchARM64: return show_hwcaps_arm64(hwcaps);
sewardjd0e5fe72012-06-07 08:51:02 +00001539 case VexArchS390X: return show_hwcaps_s390x(hwcaps);
1540 case VexArchMIPS32: return show_hwcaps_mips32(hwcaps);
petarjb92a9542013-02-27 22:57:17 +00001541 case VexArchMIPS64: return show_hwcaps_mips64(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001542 default: return NULL;
1543 }
1544}
1545
1546static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps )
1547{
1548 return show_hwcaps(arch,hwcaps) != NULL;
1549}
1550
1551
sewardj35421a32004-07-05 13:12:34 +00001552/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +00001553/*--- end main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +00001554/*---------------------------------------------------------------*/