blob: ebb8d41af9c8fd013809ae400a7e23dc1401f15b [file] [log] [blame]
sewardj35421a32004-07-05 13:12:34 +00001
2/*---------------------------------------------------------------*/
sewardj752f9062010-05-03 21:38:49 +00003/*--- begin main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +00004/*---------------------------------------------------------------*/
5
sewardjf8ed9d82004-11-12 17:40:23 +00006/*
sewardj752f9062010-05-03 21:38:49 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjf8ed9d82004-11-12 17:40:23 +00009
sewardj89ae8472013-10-18 14:12:58 +000010 Copyright (C) 2004-2013 OpenWorks LLP
sewardj752f9062010-05-03 21:38:49 +000011 info@open-works.net
sewardjf8ed9d82004-11-12 17:40:23 +000012
sewardj752f9062010-05-03 21:38:49 +000013 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
sewardjf8ed9d82004-11-12 17:40:23 +000017
sewardj752f9062010-05-03 21:38:49 +000018 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
sewardj7bd6ffe2005-08-03 16:07:36 +000026 02110-1301, USA.
27
sewardj752f9062010-05-03 21:38:49 +000028 The GNU General Public License is contained in the file COPYING.
sewardjf8ed9d82004-11-12 17:40:23 +000029
30 Neither the names of the U.S. Department of Energy nor the
31 University of California nor the names of its contributors may be
32 used to endorse or promote products derived from this software
33 without prior written permission.
sewardjf8ed9d82004-11-12 17:40:23 +000034*/
35
sewardj887a11a2004-07-05 17:26:47 +000036#include "libvex.h"
florian33b02432012-08-25 21:48:04 +000037#include "libvex_emnote.h"
sewardj81ec4182004-10-25 23:15:52 +000038#include "libvex_guest_x86.h"
sewardj44d494d2005-01-20 20:26:33 +000039#include "libvex_guest_amd64.h"
sewardj2a9ad022004-11-25 02:46:58 +000040#include "libvex_guest_arm.h"
sewardjbbcf1882014-01-12 12:49:10 +000041#include "libvex_guest_arm64.h"
cerionaabdfbf2005-01-29 12:56:15 +000042#include "libvex_guest_ppc32.h"
cerionf0de28c2005-12-13 20:21:11 +000043#include "libvex_guest_ppc64.h"
sewardj2019a972011-03-07 16:04:07 +000044#include "libvex_guest_s390x.h"
sewardjd0e5fe72012-06-07 08:51:02 +000045#include "libvex_guest_mips32.h"
petarjb92a9542013-02-27 22:57:17 +000046#include "libvex_guest_mips64.h"
sewardjf13a16a2004-07-05 17:10:14 +000047
sewardjcef7d3e2009-07-02 12:21:59 +000048#include "main_globals.h"
49#include "main_util.h"
50#include "host_generic_regs.h"
51#include "ir_opt.h"
sewardj35421a32004-07-05 13:12:34 +000052
sewardjcef7d3e2009-07-02 12:21:59 +000053#include "host_x86_defs.h"
54#include "host_amd64_defs.h"
55#include "host_ppc_defs.h"
sewardj6c299f32009-12-31 18:00:12 +000056#include "host_arm_defs.h"
sewardjbbcf1882014-01-12 12:49:10 +000057#include "host_arm64_defs.h"
sewardj2019a972011-03-07 16:04:07 +000058#include "host_s390_defs.h"
sewardjd0e5fe72012-06-07 08:51:02 +000059#include "host_mips_defs.h"
sewardj2a9ad022004-11-25 02:46:58 +000060
sewardjcef7d3e2009-07-02 12:21:59 +000061#include "guest_generic_bb_to_IR.h"
62#include "guest_x86_defs.h"
63#include "guest_amd64_defs.h"
64#include "guest_arm_defs.h"
sewardjbbcf1882014-01-12 12:49:10 +000065#include "guest_arm64_defs.h"
sewardjcef7d3e2009-07-02 12:21:59 +000066#include "guest_ppc_defs.h"
sewardj2019a972011-03-07 16:04:07 +000067#include "guest_s390_defs.h"
sewardjd0e5fe72012-06-07 08:51:02 +000068#include "guest_mips_defs.h"
sewardj2a9ad022004-11-25 02:46:58 +000069
sewardj69d98e32010-06-18 08:17:41 +000070#include "host_generic_simd128.h"
71
sewardj35421a32004-07-05 13:12:34 +000072
73/* This file contains the top level interface to the library. */
74
sewardj5117ce12006-01-27 21:20:15 +000075/* --------- fwds ... --------- */
76
77static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps );
florian55085f82012-11-21 00:36:55 +000078static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps );
sewardj5117ce12006-01-27 21:20:15 +000079
80
sewardj8bde7f12013-04-11 13:57:43 +000081/* --------- helpers --------- */
82
83__attribute__((noinline))
84static UInt udiv32 ( UInt x, UInt y ) { return x/y; }
85__attribute__((noinline))
86static Int sdiv32 ( Int x, Int y ) { return x/y; }
87
88
sewardj35421a32004-07-05 13:12:34 +000089/* --------- Initialise the library. --------- */
90
91/* Exported to library client. */
92
sewardj08613742004-10-25 13:01:45 +000093void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon )
94{
sewardj65902992014-05-03 21:20:56 +000095 vex_bzero(vcon, sizeof(*vcon));
sewardj08613742004-10-25 13:01:45 +000096 vcon->iropt_verbosity = 0;
97 vcon->iropt_level = 2;
philippec8e2f982012-08-01 22:04:13 +000098 vcon->iropt_register_updates = VexRegUpdUnwindregsAtMemAccess;
sewardj08613742004-10-25 13:01:45 +000099 vcon->iropt_unroll_thresh = 120;
sewardj18b4bb72005-03-29 21:32:41 +0000100 vcon->guest_max_insns = 60;
sewardj08613742004-10-25 13:01:45 +0000101 vcon->guest_chase_thresh = 10;
sewardj984d9b12010-01-15 10:53:21 +0000102 vcon->guest_chase_cond = False;
sewardj08613742004-10-25 13:01:45 +0000103}
104
105
106/* Exported to library client. */
107
sewardj887a11a2004-07-05 17:26:47 +0000108void LibVEX_Init (
sewardj35421a32004-07-05 13:12:34 +0000109 /* failure exit function */
sewardj2b515872004-07-05 20:50:45 +0000110 __attribute__ ((noreturn))
sewardj35421a32004-07-05 13:12:34 +0000111 void (*failure_exit) ( void ),
112 /* logging output function */
sewardjd9763622005-02-07 03:12:19 +0000113 void (*log_bytes) ( HChar*, Int nbytes ),
sewardj35421a32004-07-05 13:12:34 +0000114 /* debug paranoia level */
115 Int debuglevel,
sewardj35421a32004-07-05 13:12:34 +0000116 /* Are we supporting valgrind checking? */
117 Bool valgrind_support,
sewardj08613742004-10-25 13:01:45 +0000118 /* Control ... */
119 /*READONLY*/VexControl* vcon
sewardj35421a32004-07-05 13:12:34 +0000120)
121{
sewardj08613742004-10-25 13:01:45 +0000122 /* First off, do enough minimal setup so that the following
123 assertions can fail in a sane fashion, if need be. */
sewardjea602bc2004-10-14 21:40:12 +0000124 vex_failure_exit = failure_exit;
125 vex_log_bytes = log_bytes;
126
127 /* Now it's safe to check parameters for sanity. */
sewardj35421a32004-07-05 13:12:34 +0000128 vassert(!vex_initdone);
129 vassert(failure_exit);
sewardj35421a32004-07-05 13:12:34 +0000130 vassert(log_bytes);
sewardj35421a32004-07-05 13:12:34 +0000131 vassert(debuglevel >= 0);
sewardj08613742004-10-25 13:01:45 +0000132
133 vassert(vcon->iropt_verbosity >= 0);
134 vassert(vcon->iropt_level >= 0);
135 vassert(vcon->iropt_level <= 2);
136 vassert(vcon->iropt_unroll_thresh >= 0);
137 vassert(vcon->iropt_unroll_thresh <= 400);
138 vassert(vcon->guest_max_insns >= 1);
139 vassert(vcon->guest_max_insns <= 100);
140 vassert(vcon->guest_chase_thresh >= 0);
141 vassert(vcon->guest_chase_thresh < vcon->guest_max_insns);
sewardj984d9b12010-01-15 10:53:21 +0000142 vassert(vcon->guest_chase_cond == True
143 || vcon->guest_chase_cond == False);
sewardj443cd9d2004-07-18 23:06:45 +0000144
sewardjea602bc2004-10-14 21:40:12 +0000145 /* Check that Vex has been built with sizes of basic types as
146 stated in priv/libvex_basictypes.h. Failure of any of these is
147 a serious configuration error and should be corrected
148 immediately. If any of these assertions fail you can fully
149 expect Vex not to work properly, if at all. */
150
151 vassert(1 == sizeof(UChar));
152 vassert(1 == sizeof(Char));
153 vassert(2 == sizeof(UShort));
154 vassert(2 == sizeof(Short));
155 vassert(4 == sizeof(UInt));
156 vassert(4 == sizeof(Int));
157 vassert(8 == sizeof(ULong));
158 vassert(8 == sizeof(Long));
159 vassert(4 == sizeof(Float));
160 vassert(8 == sizeof(Double));
161 vassert(1 == sizeof(Bool));
162 vassert(4 == sizeof(Addr32));
163 vassert(8 == sizeof(Addr64));
sewardjc9a43662004-11-30 18:51:59 +0000164 vassert(16 == sizeof(U128));
sewardj69d98e32010-06-18 08:17:41 +0000165 vassert(16 == sizeof(V128));
sewardjc9069f22012-06-01 16:09:50 +0000166 vassert(32 == sizeof(U256));
sewardjea602bc2004-10-14 21:40:12 +0000167
168 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
169 vassert(sizeof(void*) == sizeof(int*));
170 vassert(sizeof(void*) == sizeof(HWord));
171
sewardj97e87932005-02-07 00:00:50 +0000172 vassert(VEX_HOST_WORDSIZE == sizeof(void*));
173 vassert(VEX_HOST_WORDSIZE == sizeof(HWord));
174
sewardjc6f970f2012-04-02 21:54:49 +0000175 /* These take a lot of space, so make sure we don't have
176 any unnoticed size regressions. */
177 if (VEX_HOST_WORDSIZE == 4) {
florian420bfa92012-06-02 20:29:22 +0000178 vassert(sizeof(IRExpr) == 16);
sewardjc6f970f2012-04-02 21:54:49 +0000179 vassert(sizeof(IRStmt) == 20 /* x86 */
180 || sizeof(IRStmt) == 24 /* arm */);
181 } else {
florian420bfa92012-06-02 20:29:22 +0000182 vassert(sizeof(IRExpr) == 32);
floriand6f38b32012-05-31 15:46:18 +0000183 vassert(sizeof(IRStmt) == 32);
sewardjc6f970f2012-04-02 21:54:49 +0000184 }
185
sewardj8bde7f12013-04-11 13:57:43 +0000186 /* Check that signed integer division on the host rounds towards
187 zero. If not, h_calc_sdiv32_w_arm_semantics() won't work
188 correctly. */
189 /* 100.0 / 7.0 == 14.2857 */
190 vassert(udiv32(100, 7) == 14);
191 vassert(sdiv32(100, 7) == 14);
192 vassert(sdiv32(-100, 7) == -14); /* and not -15 */
193 vassert(sdiv32(100, -7) == -14); /* ditto */
194 vassert(sdiv32(-100, -7) == 14); /* not sure what this proves */
195
sewardjea602bc2004-10-14 21:40:12 +0000196 /* Really start up .. */
sewardj443cd9d2004-07-18 23:06:45 +0000197 vex_debuglevel = debuglevel;
sewardj443cd9d2004-07-18 23:06:45 +0000198 vex_valgrind_support = valgrind_support;
sewardj08613742004-10-25 13:01:45 +0000199 vex_control = *vcon;
sewardj443cd9d2004-07-18 23:06:45 +0000200 vex_initdone = True;
sewardjd887b862005-01-17 18:34:34 +0000201 vexSetAllocMode ( VexAllocModeTEMP );
sewardj35421a32004-07-05 13:12:34 +0000202}
203
204
205/* --------- Make a translation. --------- */
206
207/* Exported to library client. */
208
sewardj17c7f952005-12-15 14:02:34 +0000209VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
sewardj35421a32004-07-05 13:12:34 +0000210{
sewardj81bd5502004-07-21 18:49:27 +0000211 /* This the bundle of functions we need to do the back-end stuff
212 (insn selection, reg-alloc, assembly) whilst being insulated
213 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +0000214 HReg* available_real_regs;
215 Int n_available_real_regs;
sewardjfb7373a2007-08-25 21:29:03 +0000216 Bool (*isMove) ( HInstr*, HReg*, HReg* );
217 void (*getRegUsage) ( HRegUsage*, HInstr*, Bool );
218 void (*mapRegs) ( HRegRemap*, HInstr*, Bool );
sewardj6c299f32009-12-31 18:00:12 +0000219 void (*genSpill) ( HInstr**, HInstr**, HReg, Int, Bool );
220 void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool );
sewardjfb7373a2007-08-25 21:29:03 +0000221 HInstr* (*directReload) ( HInstr*, HReg, Short );
222 void (*ppInstr) ( HInstr*, Bool );
223 void (*ppReg) ( HReg );
sewardjc6f970f2012-04-02 21:54:49 +0000224 HInstrArray* (*iselSB) ( IRSB*, VexArch, VexArchInfo*, VexAbiInfo*,
225 Int, Int, Bool, Bool, Addr64 );
226 Int (*emit) ( /*MB_MOD*/Bool*,
227 UChar*, Int, HInstr*, Bool,
228 void*, void*, void*, void* );
florian1ff47562012-10-21 02:09:51 +0000229 IRExpr* (*specHelper) ( const HChar*, IRExpr**, IRStmt**, Int );
sewardj8d2291c2004-10-25 14:50:21 +0000230 Bool (*preciseMemExnsFn) ( Int, Int );
sewardjf13a16a2004-07-05 17:10:14 +0000231
sewardj9e6491a2005-07-02 19:24:10 +0000232 DisOneInstrFn disInstrFn;
233
sewardjeeac8412004-11-02 00:26:55 +0000234 VexGuestLayout* guest_layout;
235 Bool host_is_bigendian = False;
sewardjdd40fdf2006-12-24 02:20:24 +0000236 IRSB* irsb;
sewardjeeac8412004-11-02 00:26:55 +0000237 HInstrArray* vcode;
238 HInstrArray* rcode;
239 Int i, j, k, out_used, guest_sizeB;
sewardjc6f970f2012-04-02 21:54:49 +0000240 Int offB_TISTART, offB_TILEN, offB_GUEST_IP, szB_GUEST_IP;
241 Int offB_HOST_EvC_COUNTER, offB_HOST_EvC_FAILADDR;
petarjb92a9542013-02-27 22:57:17 +0000242 UChar insn_bytes[128];
sewardjcf787902004-11-03 09:08:33 +0000243 IRType guest_word_type;
244 IRType host_word_type;
sewardjc6f970f2012-04-02 21:54:49 +0000245 Bool mode64, chainingAllowed;
246 Addr64 max_ga;
sewardjf13a16a2004-07-05 17:10:14 +0000247
sewardj49651f42004-10-28 22:11:04 +0000248 guest_layout = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000249 available_real_regs = NULL;
250 n_available_real_regs = 0;
251 isMove = NULL;
252 getRegUsage = NULL;
253 mapRegs = NULL;
254 genSpill = NULL;
255 genReload = NULL;
sewardjfb7373a2007-08-25 21:29:03 +0000256 directReload = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000257 ppInstr = NULL;
258 ppReg = NULL;
sewardjdd40fdf2006-12-24 02:20:24 +0000259 iselSB = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000260 emit = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000261 specHelper = NULL;
sewardj8d2291c2004-10-25 14:50:21 +0000262 preciseMemExnsFn = NULL;
sewardj9e6491a2005-07-02 19:24:10 +0000263 disInstrFn = NULL;
sewardjcf787902004-11-03 09:08:33 +0000264 guest_word_type = Ity_INVALID;
265 host_word_type = Ity_INVALID;
sewardjdb4738a2005-07-07 01:32:16 +0000266 offB_TISTART = 0;
267 offB_TILEN = 0;
sewardjc6f970f2012-04-02 21:54:49 +0000268 offB_GUEST_IP = 0;
269 szB_GUEST_IP = 0;
270 offB_HOST_EvC_COUNTER = 0;
271 offB_HOST_EvC_FAILADDR = 0;
cerion92b64362005-12-13 12:02:26 +0000272 mode64 = False;
sewardjc6f970f2012-04-02 21:54:49 +0000273 chainingAllowed = False;
sewardj36ca5132004-07-24 13:12:23 +0000274
sewardj17c7f952005-12-15 14:02:34 +0000275 vex_traceflags = vta->traceflags;
sewardj58800ff2004-07-28 01:51:10 +0000276
sewardj35421a32004-07-05 13:12:34 +0000277 vassert(vex_initdone);
sewardjc6f970f2012-04-02 21:54:49 +0000278 vassert(vta->needs_self_check != NULL);
279 vassert(vta->disp_cp_xassisted != NULL);
280 /* Both the chainers and the indir are either NULL or non-NULL. */
281 if (vta->disp_cp_chain_me_to_slowEP != NULL) {
282 vassert(vta->disp_cp_chain_me_to_fastEP != NULL);
283 vassert(vta->disp_cp_xindir != NULL);
284 chainingAllowed = True;
285 } else {
286 vassert(vta->disp_cp_chain_me_to_fastEP == NULL);
287 vassert(vta->disp_cp_xindir == NULL);
288 }
florian2eeeb9b2011-09-23 18:03:21 +0000289
sewardj2d6b14a2005-11-23 04:25:07 +0000290 vexSetAllocModeTEMP_and_clear();
291 vexAllocSanityCheck();
sewardj2a9ad022004-11-25 02:46:58 +0000292
sewardjf13a16a2004-07-05 17:10:14 +0000293 /* First off, check that the guest and host insn sets
294 are supported. */
sewardj2a9ad022004-11-25 02:46:58 +0000295
sewardj17c7f952005-12-15 14:02:34 +0000296 switch (vta->arch_host) {
sewardj2a9ad022004-11-25 02:46:58 +0000297
sewardjbef170b2004-12-21 01:23:00 +0000298 case VexArchX86:
sewardjfb7373a2007-08-25 21:29:03 +0000299 mode64 = False;
sewardjf13a16a2004-07-05 17:10:14 +0000300 getAllocableRegs_X86 ( &n_available_real_regs,
301 &available_real_regs );
sewardjfb7373a2007-08-25 21:29:03 +0000302 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000303 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
304 getRegUsage_X86Instr;
sewardjfb7373a2007-08-25 21:29:03 +0000305 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000306 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
307 genSpill_X86;
308 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
309 genReload_X86;
sewardjfb7373a2007-08-25 21:29:03 +0000310 directReload = (HInstr*(*)(HInstr*,HReg,Short)) directReload_X86;
311 ppInstr = (void(*)(HInstr*, Bool)) ppX86Instr;
312 ppReg = (void(*)(HReg)) ppHRegX86;
313 iselSB = iselSB_X86;
sewardjc6f970f2012-04-02 21:54:49 +0000314 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
315 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000316 emit_X86Instr;
sewardj72c72812005-01-19 11:49:45 +0000317 host_is_bigendian = False;
sewardjcf787902004-11-03 09:08:33 +0000318 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000319 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_host.hwcaps));
sewardjf13a16a2004-07-05 17:10:14 +0000320 break;
sewardj2a9ad022004-11-25 02:46:58 +0000321
sewardjc33671d2005-02-01 20:30:00 +0000322 case VexArchAMD64:
cerion92b64362005-12-13 12:02:26 +0000323 mode64 = True;
sewardjc33671d2005-02-01 20:30:00 +0000324 getAllocableRegs_AMD64 ( &n_available_real_regs,
325 &available_real_regs );
326 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000327 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
328 getRegUsage_AMD64Instr;
cerion92b64362005-12-13 12:02:26 +0000329 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000330 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
331 genSpill_AMD64;
332 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
333 genReload_AMD64;
cerion92b64362005-12-13 12:02:26 +0000334 ppInstr = (void(*)(HInstr*, Bool)) ppAMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000335 ppReg = (void(*)(HReg)) ppHRegAMD64;
sewardjdd40fdf2006-12-24 02:20:24 +0000336 iselSB = iselSB_AMD64;
sewardjc6f970f2012-04-02 21:54:49 +0000337 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
338 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000339 emit_AMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000340 host_is_bigendian = False;
341 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000342 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_host.hwcaps));
sewardjc33671d2005-02-01 20:30:00 +0000343 break;
344
cerion487e4c92005-02-04 16:28:19 +0000345 case VexArchPPC32:
cerion92b64362005-12-13 12:02:26 +0000346 mode64 = False;
cerion5b2325f2005-12-23 00:55:09 +0000347 getAllocableRegs_PPC ( &n_available_real_regs,
348 &available_real_regs, mode64 );
349 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
350 getRegUsage = (void(*)(HRegUsage*,HInstr*,Bool)) getRegUsage_PPCInstr;
351 mapRegs = (void(*)(HRegRemap*,HInstr*,Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000352 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
353 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000354 ppInstr = (void(*)(HInstr*,Bool)) ppPPCInstr;
355 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000356 iselSB = iselSB_PPC;
sewardj3dee8492012-04-20 00:13:28 +0000357 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
358 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000359 emit_PPCInstr;
cerion487e4c92005-02-04 16:28:19 +0000360 host_is_bigendian = True;
361 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000362 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_host.hwcaps));
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;
sewardj9e1cf152012-04-20 02:18:31 +0000377 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
378 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000379 emit_PPCInstr;
cerionf0de28c2005-12-13 20:21:11 +0000380 host_is_bigendian = True;
381 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000382 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_host.hwcaps));
cerionf0de28c2005-12-13 20:21:11 +0000383 break;
384
sewardj2019a972011-03-07 16:04:07 +0000385 case VexArchS390X:
386 mode64 = True;
387 getAllocableRegs_S390 ( &n_available_real_regs,
388 &available_real_regs, mode64 );
389 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_S390Instr;
390 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_S390Instr;
391 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_S390Instr;
392 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_S390;
393 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_S390;
394 ppInstr = (void(*)(HInstr*, Bool)) ppS390Instr;
395 ppReg = (void(*)(HReg)) ppHRegS390;
396 iselSB = iselSB_S390;
florian8844a632012-04-13 04:04:06 +0000397 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
398 void*,void*,void*,void*)) emit_S390Instr;
sewardj2019a972011-03-07 16:04:07 +0000399 host_is_bigendian = True;
400 host_word_type = Ity_I64;
401 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_host.hwcaps));
sewardj2019a972011-03-07 16:04:07 +0000402 break;
403
sewardj6c299f32009-12-31 18:00:12 +0000404 case VexArchARM:
sewardj2a1ed8e2009-12-31 19:26:03 +0000405 mode64 = False;
sewardj6c299f32009-12-31 18:00:12 +0000406 getAllocableRegs_ARM ( &n_available_real_regs,
407 &available_real_regs );
sewardj2a1ed8e2009-12-31 19:26:03 +0000408 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARMInstr;
409 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_ARMInstr;
410 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_ARMInstr;
411 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_ARM;
412 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_ARM;
413 ppInstr = (void(*)(HInstr*, Bool)) ppARMInstr;
414 ppReg = (void(*)(HReg)) ppHRegARM;
415 iselSB = iselSB_ARM;
sewardjc6f970f2012-04-02 21:54:49 +0000416 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
417 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000418 emit_ARMInstr;
sewardj6c299f32009-12-31 18:00:12 +0000419 host_is_bigendian = False;
420 host_word_type = Ity_I32;
421 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_host.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000422 break;
423
sewardjbbcf1882014-01-12 12:49:10 +0000424 case VexArchARM64:
425 mode64 = True;
426 getAllocableRegs_ARM64 ( &n_available_real_regs,
427 &available_real_regs );
428 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARM64Instr;
429 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
430 getRegUsage_ARM64Instr;
431 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool))
432 mapRegs_ARM64Instr;
433 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
434 genSpill_ARM64;
435 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
436 genReload_ARM64;
437 ppInstr = (void(*)(HInstr*, Bool)) ppARM64Instr;
438 ppReg = (void(*)(HReg)) ppHRegARM64;
439 iselSB = iselSB_ARM64;
440 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
441 void*,void*,void*,void*))
442 emit_ARM64Instr;
443 host_is_bigendian = False;
444 host_word_type = Ity_I64;
445 vassert(are_valid_hwcaps(VexArchARM64, vta->archinfo_host.hwcaps));
446 break;
447
sewardjd0e5fe72012-06-07 08:51:02 +0000448 case VexArchMIPS32:
449 mode64 = False;
450 getAllocableRegs_MIPS ( &n_available_real_regs,
451 &available_real_regs, mode64 );
452 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_MIPSInstr;
453 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_MIPSInstr;
454 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_MIPSInstr;
455 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_MIPS;
456 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_MIPS;
457 ppInstr = (void(*)(HInstr*, Bool)) ppMIPSInstr;
458 ppReg = (void(*)(HReg)) ppHRegMIPS;
459 iselSB = iselSB_MIPS;
460 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
461 void*,void*,void*,void*))
462 emit_MIPSInstr;
sewardj74142b82013-08-08 10:28:59 +0000463# if defined(VKI_LITTLE_ENDIAN)
sewardjd0e5fe72012-06-07 08:51:02 +0000464 host_is_bigendian = False;
sewardj74142b82013-08-08 10:28:59 +0000465# elif defined(VKI_BIG_ENDIAN)
sewardjd0e5fe72012-06-07 08:51:02 +0000466 host_is_bigendian = True;
sewardj74142b82013-08-08 10:28:59 +0000467# endif
sewardjd0e5fe72012-06-07 08:51:02 +0000468 host_word_type = Ity_I32;
469 vassert(are_valid_hwcaps(VexArchMIPS32, vta->archinfo_host.hwcaps));
470 break;
471
petarjb92a9542013-02-27 22:57:17 +0000472 case VexArchMIPS64:
473 mode64 = True;
474 getAllocableRegs_MIPS ( &n_available_real_regs,
475 &available_real_regs, mode64 );
476 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_MIPSInstr;
477 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_MIPSInstr;
478 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_MIPSInstr;
479 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_MIPS;
480 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_MIPS;
481 ppInstr = (void(*)(HInstr*, Bool)) ppMIPSInstr;
482 ppReg = (void(*)(HReg)) ppHRegMIPS;
483 iselSB = iselSB_MIPS;
484 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
485 void*,void*,void*,void*))
486 emit_MIPSInstr;
sewardj74142b82013-08-08 10:28:59 +0000487# if defined(VKI_LITTLE_ENDIAN)
petarjb92a9542013-02-27 22:57:17 +0000488 host_is_bigendian = False;
sewardj74142b82013-08-08 10:28:59 +0000489# elif defined(VKI_BIG_ENDIAN)
petarjb92a9542013-02-27 22:57:17 +0000490 host_is_bigendian = True;
sewardj74142b82013-08-08 10:28:59 +0000491# endif
petarjb92a9542013-02-27 22:57:17 +0000492 host_word_type = Ity_I64;
493 vassert(are_valid_hwcaps(VexArchMIPS64, vta->archinfo_host.hwcaps));
494 break;
495
sewardjf13a16a2004-07-05 17:10:14 +0000496 default:
sewardj6c299f32009-12-31 18:00:12 +0000497 vpanic("LibVEX_Translate: unsupported host insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000498 }
499
sewardj2a9ad022004-11-25 02:46:58 +0000500
sewardj17c7f952005-12-15 14:02:34 +0000501 switch (vta->arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000502
sewardjbef170b2004-12-21 01:23:00 +0000503 case VexArchX86:
sewardjc6f970f2012-04-02 21:54:49 +0000504 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
505 disInstrFn = disInstr_X86;
506 specHelper = guest_x86_spechelper;
507 guest_sizeB = sizeof(VexGuestX86State);
508 guest_word_type = Ity_I32;
509 guest_layout = &x86guest_layout;
510 offB_TISTART = offsetof(VexGuestX86State,guest_TISTART);
511 offB_TILEN = offsetof(VexGuestX86State,guest_TILEN);
512 offB_GUEST_IP = offsetof(VexGuestX86State,guest_EIP);
513 szB_GUEST_IP = sizeof( ((VexGuestX86State*)0)->guest_EIP );
514 offB_HOST_EvC_COUNTER = offsetof(VexGuestX86State,host_EvC_COUNTER);
515 offB_HOST_EvC_FAILADDR = offsetof(VexGuestX86State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000516 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000517 vassert(0 == sizeof(VexGuestX86State) % 16);
sewardjce02aa72006-01-12 12:27:58 +0000518 vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART) == 4);
519 vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
520 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000521 break;
sewardj2a9ad022004-11-25 02:46:58 +0000522
sewardj44d494d2005-01-20 20:26:33 +0000523 case VexArchAMD64:
sewardjc6f970f2012-04-02 21:54:49 +0000524 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
525 disInstrFn = disInstr_AMD64;
526 specHelper = guest_amd64_spechelper;
527 guest_sizeB = sizeof(VexGuestAMD64State);
528 guest_word_type = Ity_I64;
529 guest_layout = &amd64guest_layout;
530 offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART);
531 offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN);
532 offB_GUEST_IP = offsetof(VexGuestAMD64State,guest_RIP);
533 szB_GUEST_IP = sizeof( ((VexGuestAMD64State*)0)->guest_RIP );
534 offB_HOST_EvC_COUNTER = offsetof(VexGuestAMD64State,host_EvC_COUNTER);
535 offB_HOST_EvC_FAILADDR = offsetof(VexGuestAMD64State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000536 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000537 vassert(0 == sizeof(VexGuestAMD64State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000538 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8);
sewardjce02aa72006-01-12 12:27:58 +0000539 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
540 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000541 break;
542
cerionaabdfbf2005-01-29 12:56:15 +0000543 case VexArchPPC32:
sewardj3dee8492012-04-20 00:13:28 +0000544 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
545 disInstrFn = disInstr_PPC;
546 specHelper = guest_ppc32_spechelper;
547 guest_sizeB = sizeof(VexGuestPPC32State);
548 guest_word_type = Ity_I32;
549 guest_layout = &ppc32Guest_layout;
550 offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART);
551 offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN);
552 offB_GUEST_IP = offsetof(VexGuestPPC32State,guest_CIA);
553 szB_GUEST_IP = sizeof( ((VexGuestPPC32State*)0)->guest_CIA );
554 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC32State,host_EvC_COUNTER);
555 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC32State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000556 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000557 vassert(0 == sizeof(VexGuestPPC32State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000558 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000559 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
560 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000561 break;
562
cerionf0de28c2005-12-13 20:21:11 +0000563 case VexArchPPC64:
sewardj9e1cf152012-04-20 02:18:31 +0000564 preciseMemExnsFn = guest_ppc64_state_requires_precise_mem_exns;
565 disInstrFn = disInstr_PPC;
566 specHelper = guest_ppc64_spechelper;
567 guest_sizeB = sizeof(VexGuestPPC64State);
568 guest_word_type = Ity_I64;
569 guest_layout = &ppc64Guest_layout;
570 offB_TISTART = offsetof(VexGuestPPC64State,guest_TISTART);
571 offB_TILEN = offsetof(VexGuestPPC64State,guest_TILEN);
572 offB_GUEST_IP = offsetof(VexGuestPPC64State,guest_CIA);
573 szB_GUEST_IP = sizeof( ((VexGuestPPC64State*)0)->guest_CIA );
574 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC64State,host_EvC_COUNTER);
575 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC64State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000576 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_guest.hwcaps));
cerionf0de28c2005-12-13 20:21:11 +0000577 vassert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj3fd39672006-01-27 22:05:55 +0000578 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TISTART ) == 8);
579 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TILEN ) == 8);
580 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8);
581 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8);
cerionf0de28c2005-12-13 20:21:11 +0000582 break;
583
sewardj2019a972011-03-07 16:04:07 +0000584 case VexArchS390X:
585 preciseMemExnsFn = guest_s390x_state_requires_precise_mem_exns;
586 disInstrFn = disInstr_S390;
587 specHelper = guest_s390x_spechelper;
588 guest_sizeB = sizeof(VexGuestS390XState);
589 guest_word_type = Ity_I64;
590 guest_layout = &s390xGuest_layout;
591 offB_TISTART = offsetof(VexGuestS390XState,guest_TISTART);
592 offB_TILEN = offsetof(VexGuestS390XState,guest_TILEN);
florian8844a632012-04-13 04:04:06 +0000593 offB_GUEST_IP = offsetof(VexGuestS390XState,guest_IA);
594 szB_GUEST_IP = sizeof( ((VexGuestS390XState*)0)->guest_IA);
595 offB_HOST_EvC_COUNTER = offsetof(VexGuestS390XState,host_EvC_COUNTER);
596 offB_HOST_EvC_FAILADDR = offsetof(VexGuestS390XState,host_EvC_FAILADDR);
sewardj2019a972011-03-07 16:04:07 +0000597 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_guest.hwcaps));
598 vassert(0 == sizeof(VexGuestS390XState) % 16);
599 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TISTART ) == 8);
600 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TILEN ) == 8);
601 vassert(sizeof( ((VexGuestS390XState*)0)->guest_NRADDR ) == 8);
602 break;
603
sewardj6c299f32009-12-31 18:00:12 +0000604 case VexArchARM:
sewardjc6f970f2012-04-02 21:54:49 +0000605 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
606 disInstrFn = disInstr_ARM;
607 specHelper = guest_arm_spechelper;
608 guest_sizeB = sizeof(VexGuestARMState);
609 guest_word_type = Ity_I32;
610 guest_layout = &armGuest_layout;
611 offB_TISTART = offsetof(VexGuestARMState,guest_TISTART);
612 offB_TILEN = offsetof(VexGuestARMState,guest_TILEN);
613 offB_GUEST_IP = offsetof(VexGuestARMState,guest_R15T);
614 szB_GUEST_IP = sizeof( ((VexGuestARMState*)0)->guest_R15T );
615 offB_HOST_EvC_COUNTER = offsetof(VexGuestARMState,host_EvC_COUNTER);
616 offB_HOST_EvC_FAILADDR = offsetof(VexGuestARMState,host_EvC_FAILADDR);
sewardj6c299f32009-12-31 18:00:12 +0000617 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_guest.hwcaps));
618 vassert(0 == sizeof(VexGuestARMState) % 16);
619 vassert(sizeof( ((VexGuestARMState*)0)->guest_TISTART) == 4);
620 vassert(sizeof( ((VexGuestARMState*)0)->guest_TILEN ) == 4);
621 vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4);
622 break;
623
sewardjbbcf1882014-01-12 12:49:10 +0000624 case VexArchARM64:
625 preciseMemExnsFn = guest_arm64_state_requires_precise_mem_exns;
626 disInstrFn = disInstr_ARM64;
627 specHelper = guest_arm64_spechelper;
628 guest_sizeB = sizeof(VexGuestARM64State);
629 guest_word_type = Ity_I64;
630 guest_layout = &arm64Guest_layout;
631 offB_TISTART = offsetof(VexGuestARM64State,guest_TISTART);
632 offB_TILEN = offsetof(VexGuestARM64State,guest_TILEN);
633 offB_GUEST_IP = offsetof(VexGuestARM64State,guest_PC);
634 szB_GUEST_IP = sizeof( ((VexGuestARM64State*)0)->guest_PC );
635 offB_HOST_EvC_COUNTER = offsetof(VexGuestARM64State,host_EvC_COUNTER);
636 offB_HOST_EvC_FAILADDR = offsetof(VexGuestARM64State,host_EvC_FAILADDR);
637 vassert(are_valid_hwcaps(VexArchARM64, vta->archinfo_guest.hwcaps));
638 vassert(0 == sizeof(VexGuestARM64State) % 16);
639 vassert(sizeof( ((VexGuestARM64State*)0)->guest_TISTART) == 8);
640 vassert(sizeof( ((VexGuestARM64State*)0)->guest_TILEN ) == 8);
641 vassert(sizeof( ((VexGuestARM64State*)0)->guest_NRADDR ) == 8);
642 break;
643
sewardjd0e5fe72012-06-07 08:51:02 +0000644 case VexArchMIPS32:
645 preciseMemExnsFn = guest_mips32_state_requires_precise_mem_exns;
646 disInstrFn = disInstr_MIPS;
647 specHelper = guest_mips32_spechelper;
648 guest_sizeB = sizeof(VexGuestMIPS32State);
649 guest_word_type = Ity_I32;
650 guest_layout = &mips32Guest_layout;
651 offB_TISTART = offsetof(VexGuestMIPS32State,guest_TISTART);
652 offB_TILEN = offsetof(VexGuestMIPS32State,guest_TILEN);
653 offB_GUEST_IP = offsetof(VexGuestMIPS32State,guest_PC);
654 szB_GUEST_IP = sizeof( ((VexGuestMIPS32State*)0)->guest_PC );
655 offB_HOST_EvC_COUNTER = offsetof(VexGuestMIPS32State,host_EvC_COUNTER);
656 offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS32State,host_EvC_FAILADDR);
657 vassert(are_valid_hwcaps(VexArchMIPS32, vta->archinfo_guest.hwcaps));
658 vassert(0 == sizeof(VexGuestMIPS32State) % 16);
659 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_TISTART) == 4);
660 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_TILEN ) == 4);
661 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_NRADDR ) == 4);
662 break;
663
petarjb92a9542013-02-27 22:57:17 +0000664 case VexArchMIPS64:
665 preciseMemExnsFn = guest_mips64_state_requires_precise_mem_exns;
666 disInstrFn = disInstr_MIPS;
667 specHelper = guest_mips64_spechelper;
668 guest_sizeB = sizeof(VexGuestMIPS64State);
669 guest_word_type = Ity_I64;
670 guest_layout = &mips64Guest_layout;
671 offB_TISTART = offsetof(VexGuestMIPS64State,guest_TISTART);
672 offB_TILEN = offsetof(VexGuestMIPS64State,guest_TILEN);
673 offB_GUEST_IP = offsetof(VexGuestMIPS64State,guest_PC);
674 szB_GUEST_IP = sizeof( ((VexGuestMIPS64State*)0)->guest_PC );
675 offB_HOST_EvC_COUNTER = offsetof(VexGuestMIPS64State,host_EvC_COUNTER);
676 offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS64State,host_EvC_FAILADDR);
677 vassert(are_valid_hwcaps(VexArchMIPS64, vta->archinfo_guest.hwcaps));
678 vassert(0 == sizeof(VexGuestMIPS64State) % 16);
679 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_TISTART) == 8);
680 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_TILEN ) == 8);
681 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_NRADDR ) == 8);
682 break;
683
sewardjf13a16a2004-07-05 17:10:14 +0000684 default:
sewardj887a11a2004-07-05 17:26:47 +0000685 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000686 }
687
sewardjbc161a42011-06-07 21:28:38 +0000688 /* Set up result struct. */
689 VexTranslateResult res;
sewardjfadbbe22012-04-24 11:49:03 +0000690 res.status = VexTransOK;
691 res.n_sc_extents = 0;
692 res.offs_profInc = -1;
693 res.n_guest_instrs = 0;
sewardjbc161a42011-06-07 21:28:38 +0000694
sewardj9df271d2004-12-31 22:37:42 +0000695 /* yet more sanity checks ... */
sewardj17c7f952005-12-15 14:02:34 +0000696 if (vta->arch_guest == vta->arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000697 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000698 we are simulating one flavour of an architecture a different
699 flavour of the same architecture, which is pretty strange. */
sewardj5117ce12006-01-27 21:20:15 +0000700 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps);
sewardj9df271d2004-12-31 22:37:42 +0000701 }
sewardj2a9ad022004-11-25 02:46:58 +0000702
sewardj2d6b14a2005-11-23 04:25:07 +0000703 vexAllocSanityCheck();
704
sewardjf48ac192004-10-29 00:41:29 +0000705 if (vex_traceflags & VEX_TRACE_FE)
706 vex_printf("\n------------------------"
707 " Front end "
708 "------------------------\n\n");
709
sewardjdd40fdf2006-12-24 02:20:24 +0000710 irsb = bb_to_IR ( vta->guest_extents,
sewardjbc161a42011-06-07 21:28:38 +0000711 &res.n_sc_extents,
sewardjfadbbe22012-04-24 11:49:03 +0000712 &res.n_guest_instrs,
sewardjc716aea2006-01-17 01:48:46 +0000713 vta->callback_opaque,
sewardj9e6491a2005-07-02 19:24:10 +0000714 disInstrFn,
sewardj17c7f952005-12-15 14:02:34 +0000715 vta->guest_bytes,
716 vta->guest_bytes_addr,
717 vta->chase_into_ok,
sewardj9e6491a2005-07-02 19:24:10 +0000718 host_is_bigendian,
sewardj442e51a2012-12-06 18:08:04 +0000719 vta->sigill_diag,
sewardja5f55da2006-04-30 23:37:32 +0000720 vta->arch_guest,
sewardj17c7f952005-12-15 14:02:34 +0000721 &vta->archinfo_guest,
sewardjdd40fdf2006-12-24 02:20:24 +0000722 &vta->abiinfo_both,
sewardjdb4738a2005-07-07 01:32:16 +0000723 guest_word_type,
sewardjbc161a42011-06-07 21:28:38 +0000724 vta->needs_self_check,
sewardjc716aea2006-01-17 01:48:46 +0000725 vta->preamble_function,
sewardjdb4738a2005-07-07 01:32:16 +0000726 offB_TISTART,
sewardjc6f970f2012-04-02 21:54:49 +0000727 offB_TILEN,
728 offB_GUEST_IP,
729 szB_GUEST_IP );
sewardjf13a16a2004-07-05 17:10:14 +0000730
sewardj2d6b14a2005-11-23 04:25:07 +0000731 vexAllocSanityCheck();
732
sewardjdd40fdf2006-12-24 02:20:24 +0000733 if (irsb == NULL) {
sewardjf13a16a2004-07-05 17:10:14 +0000734 /* Access failure. */
sewardj2d6b14a2005-11-23 04:25:07 +0000735 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000736 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000737 res.status = VexTransAccessFail; return res;
sewardjf13a16a2004-07-05 17:10:14 +0000738 }
sewardjaa59f942004-10-09 09:34:36 +0000739
sewardj17c7f952005-12-15 14:02:34 +0000740 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3);
741 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr);
742 for (i = 0; i < vta->guest_extents->n_used; i++) {
743 vassert(vta->guest_extents->len[i] < 10000); /* sanity */
sewardj72c72812005-01-19 11:49:45 +0000744 }
745
sewardjaa59f942004-10-09 09:34:36 +0000746 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000747 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj17c7f952005-12-15 14:02:34 +0000748 if (vta->guest_extents->n_used > 1) {
sewardj72c72812005-01-19 11:49:45 +0000749 vex_printf("can't show code due to extents > 1\n");
750 } else {
751 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000752 UChar* p = (UChar*)vta->guest_bytes;
sewardj01f8cce2009-08-31 08:50:02 +0000753 UInt sum = 0;
sewardj17c7f952005-12-15 14:02:34 +0000754 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0];
sewardj01f8cce2009-08-31 08:50:02 +0000755 vex_printf("GuestBytes %llx %u ", vta->guest_bytes_addr,
756 guest_bytes_read );
757 for (i = 0; i < guest_bytes_read; i++) {
758 UInt b = (UInt)p[i];
759 vex_printf(" %02x", b );
760 sum = (sum << 1) ^ b;
761 }
762 vex_printf(" %08x\n\n", sum);
sewardj72c72812005-01-19 11:49:45 +0000763 }
sewardjaa59f942004-10-09 09:34:36 +0000764 }
765
766 /* Sanity check the initial IR. */
sewardjdd40fdf2006-12-24 02:20:24 +0000767 sanityCheckIRSB( irsb, "initial IR",
sewardjb9230752004-12-29 19:25:06 +0000768 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000769
sewardj2d6b14a2005-11-23 04:25:07 +0000770 vexAllocSanityCheck();
771
sewardjedf4d692004-08-17 13:52:58 +0000772 /* Clean it up, hopefully a lot. */
sewardjdd40fdf2006-12-24 02:20:24 +0000773 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn,
sewardjec0d9a02010-08-22 12:54:56 +0000774 vta->guest_bytes_addr,
775 vta->arch_guest );
sewardjdd40fdf2006-12-24 02:20:24 +0000776 sanityCheckIRSB( irsb, "after initial iropt",
sewardjb9230752004-12-29 19:25:06 +0000777 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000778
sewardjf48ac192004-10-29 00:41:29 +0000779 if (vex_traceflags & VEX_TRACE_OPT1) {
780 vex_printf("\n------------------------"
781 " After pre-instr IR optimisation "
782 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000783 ppIRSB ( irsb );
sewardjedf4d692004-08-17 13:52:58 +0000784 vex_printf("\n");
785 }
786
sewardj2d6b14a2005-11-23 04:25:07 +0000787 vexAllocSanityCheck();
788
sewardjf13a16a2004-07-05 17:10:14 +0000789 /* Get the thing instrumented. */
sewardj17c7f952005-12-15 14:02:34 +0000790 if (vta->instrument1)
sewardjdd40fdf2006-12-24 02:20:24 +0000791 irsb = vta->instrument1(vta->callback_opaque,
792 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000793 vta->guest_extents,
florian50481922012-10-07 21:58:07 +0000794 &vta->archinfo_host,
sewardj17c7f952005-12-15 14:02:34 +0000795 guest_word_type, host_word_type);
sewardj2d6b14a2005-11-23 04:25:07 +0000796 vexAllocSanityCheck();
797
sewardj17c7f952005-12-15 14:02:34 +0000798 if (vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000799 irsb = vta->instrument2(vta->callback_opaque,
800 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000801 vta->guest_extents,
florian50481922012-10-07 21:58:07 +0000802 &vta->archinfo_host,
sewardj17c7f952005-12-15 14:02:34 +0000803 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000804
sewardjf48ac192004-10-29 00:41:29 +0000805 if (vex_traceflags & VEX_TRACE_INST) {
806 vex_printf("\n------------------------"
807 " After instrumentation "
808 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000809 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000810 vex_printf("\n");
811 }
812
sewardj17c7f952005-12-15 14:02:34 +0000813 if (vta->instrument1 || vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000814 sanityCheckIRSB( irsb, "after instrumentation",
sewardjb9230752004-12-29 19:25:06 +0000815 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000816
sewardj9578a8b2004-11-04 19:44:48 +0000817 /* Do a post-instrumentation cleanup pass. */
sewardj17c7f952005-12-15 14:02:34 +0000818 if (vta->instrument1 || vta->instrument2) {
sewardjdd40fdf2006-12-24 02:20:24 +0000819 do_deadcode_BB( irsb );
820 irsb = cprop_BB( irsb );
821 do_deadcode_BB( irsb );
822 sanityCheckIRSB( irsb, "after post-instrumentation cleanup",
sewardjb9230752004-12-29 19:25:06 +0000823 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000824 }
825
sewardj2d6b14a2005-11-23 04:25:07 +0000826 vexAllocSanityCheck();
827
sewardj9578a8b2004-11-04 19:44:48 +0000828 if (vex_traceflags & VEX_TRACE_OPT2) {
829 vex_printf("\n------------------------"
830 " After post-instr IR optimisation "
831 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000832 ppIRSB ( irsb );
sewardj9578a8b2004-11-04 19:44:48 +0000833 vex_printf("\n");
834 }
835
sewardjf9517d02005-11-28 13:39:37 +0000836 /* Turn it into virtual-registerised code. Build trees -- this
837 also throws away any dead bindings. */
florian62140c12013-01-20 03:51:04 +0000838 max_ga = ado_treebuild_BB( irsb, preciseMemExnsFn );
sewardjf48ac192004-10-29 00:41:29 +0000839
sewardjbe1b6ff2007-08-28 06:06:27 +0000840 if (vta->finaltidy) {
841 irsb = vta->finaltidy(irsb);
842 }
843
sewardj2d6b14a2005-11-23 04:25:07 +0000844 vexAllocSanityCheck();
845
sewardjf48ac192004-10-29 00:41:29 +0000846 if (vex_traceflags & VEX_TRACE_TREES) {
847 vex_printf("\n------------------------"
848 " After tree-building "
849 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000850 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000851 vex_printf("\n");
852 }
853
sewardje908c422005-02-04 21:18:16 +0000854 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000855 if (0) {
856 *(vta->host_bytes_used) = 0;
857 res.status = VexTransOK; return res;
858 }
sewardje908c422005-02-04 21:18:16 +0000859 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000860
sewardjf48ac192004-10-29 00:41:29 +0000861 if (vex_traceflags & VEX_TRACE_VCODE)
862 vex_printf("\n------------------------"
863 " Instruction selection "
864 "------------------------\n");
865
sewardjc6f970f2012-04-02 21:54:49 +0000866 /* No guest has its IP field at offset zero. If this fails it
867 means some transformation pass somewhere failed to update/copy
868 irsb->offsIP properly. */
869 vassert(irsb->offsIP >= 16);
870
871 vcode = iselSB ( irsb, vta->arch_host,
872 &vta->archinfo_host,
873 &vta->abiinfo_both,
874 offB_HOST_EvC_COUNTER,
875 offB_HOST_EvC_FAILADDR,
876 chainingAllowed,
877 vta->addProfInc,
878 max_ga );
sewardjf13a16a2004-07-05 17:10:14 +0000879
sewardj2d6b14a2005-11-23 04:25:07 +0000880 vexAllocSanityCheck();
881
sewardjf48ac192004-10-29 00:41:29 +0000882 if (vex_traceflags & VEX_TRACE_VCODE)
883 vex_printf("\n");
884
sewardjf48ac192004-10-29 00:41:29 +0000885 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000886 for (i = 0; i < vcode->arr_used; i++) {
887 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000888 ppInstr(vcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000889 vex_printf("\n");
890 }
sewardjfbcaf332004-07-08 01:46:01 +0000891 vex_printf("\n");
892 }
sewardjfbcaf332004-07-08 01:46:01 +0000893
sewardjf13a16a2004-07-05 17:10:14 +0000894 /* Register allocate. */
895 rcode = doRegisterAllocation ( vcode, available_real_regs,
cerionf0de28c2005-12-13 20:21:11 +0000896 n_available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000897 isMove, getRegUsage, mapRegs,
sewardjfb7373a2007-08-25 21:29:03 +0000898 genSpill, genReload, directReload,
899 guest_sizeB,
cerion92b64362005-12-13 12:02:26 +0000900 ppInstr, ppReg, mode64 );
sewardjf13a16a2004-07-05 17:10:14 +0000901
sewardj2d6b14a2005-11-23 04:25:07 +0000902 vexAllocSanityCheck();
903
sewardjf48ac192004-10-29 00:41:29 +0000904 if (vex_traceflags & VEX_TRACE_RCODE) {
905 vex_printf("\n------------------------"
906 " Register-allocated code "
907 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000908 for (i = 0; i < rcode->arr_used; i++) {
909 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000910 ppInstr(rcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000911 vex_printf("\n");
912 }
sewardjfbcaf332004-07-08 01:46:01 +0000913 vex_printf("\n");
914 }
sewardjfbcaf332004-07-08 01:46:01 +0000915
sewardje908c422005-02-04 21:18:16 +0000916 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000917 if (0) {
918 *(vta->host_bytes_used) = 0;
919 res.status = VexTransOK; return res;
920 }
sewardje908c422005-02-04 21:18:16 +0000921 /* end HACK */
922
sewardj81bd5502004-07-21 18:49:27 +0000923 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000924 if (vex_traceflags & VEX_TRACE_ASM) {
925 vex_printf("\n------------------------"
926 " Assembly "
927 "------------------------\n\n");
928 }
929
sewardj81bd5502004-07-21 18:49:27 +0000930 out_used = 0; /* tracks along the host_bytes array */
931 for (i = 0; i < rcode->arr_used; i++) {
sewardjc6f970f2012-04-02 21:54:49 +0000932 HInstr* hi = rcode->arr[i];
933 Bool hi_isProfInc = False;
934 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
935 ppInstr(hi, mode64);
sewardjbad34a92004-07-22 01:14:11 +0000936 vex_printf("\n");
937 }
sewardjc6f970f2012-04-02 21:54:49 +0000938 j = emit( &hi_isProfInc,
939 insn_bytes, sizeof insn_bytes, hi, mode64,
940 vta->disp_cp_chain_me_to_slowEP,
941 vta->disp_cp_chain_me_to_fastEP,
942 vta->disp_cp_xindir,
943 vta->disp_cp_xassisted );
944 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
sewardjbad34a92004-07-22 01:14:11 +0000945 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000946 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000947 vex_printf("0%x ", (UInt)insn_bytes[k]);
948 else
949 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000950 vex_printf("\n\n");
951 }
sewardjc6f970f2012-04-02 21:54:49 +0000952 if (UNLIKELY(out_used + j > vta->host_bytes_size)) {
sewardj2d6b14a2005-11-23 04:25:07 +0000953 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000954 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000955 res.status = VexTransOutputFull;
956 return res;
sewardj81bd5502004-07-21 18:49:27 +0000957 }
sewardjc6f970f2012-04-02 21:54:49 +0000958 if (UNLIKELY(hi_isProfInc)) {
959 vassert(vta->addProfInc); /* else where did it come from? */
960 vassert(res.offs_profInc == -1); /* there can be only one (tm) */
961 vassert(out_used >= 0);
962 res.offs_profInc = out_used;
963 }
964 { UChar* dst = &vta->host_bytes[out_used];
965 for (k = 0; k < j; k++) {
966 dst[k] = insn_bytes[k];
967 }
968 out_used += j;
sewardj81bd5502004-07-21 18:49:27 +0000969 }
sewardj17c7f952005-12-15 14:02:34 +0000970 vassert(out_used <= vta->host_bytes_size);
sewardj81bd5502004-07-21 18:49:27 +0000971 }
sewardj17c7f952005-12-15 14:02:34 +0000972 *(vta->host_bytes_used) = out_used;
sewardj81bd5502004-07-21 18:49:27 +0000973
sewardj2d6b14a2005-11-23 04:25:07 +0000974 vexAllocSanityCheck();
975
976 vexSetAllocModeTEMP_and_clear();
sewardjf13a16a2004-07-05 17:10:14 +0000977
sewardj65ea17e2012-12-28 09:01:59 +0000978 if (vex_traceflags) {
979 /* Print the expansion ratio for this SB. */
980 j = 0; /* total guest bytes */
981 for (i = 0; i < vta->guest_extents->n_used; i++) {
982 j += vta->guest_extents->len[i];
983 }
984 if (1) vex_printf("VexExpansionRatio %d %d %d :10\n\n",
985 j, out_used, (10 * out_used) / (j == 0 ? 1 : j));
986 }
987
sewardjf48ac192004-10-29 00:41:29 +0000988 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000989 res.status = VexTransOK;
990 return res;
sewardj35421a32004-07-05 13:12:34 +0000991}
992
993
sewardjc6f970f2012-04-02 21:54:49 +0000994/* --------- Chain/Unchain XDirects. --------- */
995
996VexInvalRange LibVEX_Chain ( VexArch arch_host,
997 void* place_to_chain,
998 void* disp_cp_chain_me_EXPECTED,
999 void* place_to_jump_to )
1000{
1001 VexInvalRange (*chainXDirect)(void*, void*, void*) = NULL;
1002 switch (arch_host) {
1003 case VexArchX86:
1004 chainXDirect = chainXDirect_X86; break;
1005 case VexArchAMD64:
1006 chainXDirect = chainXDirect_AMD64; break;
1007 case VexArchARM:
1008 chainXDirect = chainXDirect_ARM; break;
sewardjbbcf1882014-01-12 12:49:10 +00001009 case VexArchARM64:
1010 chainXDirect = chainXDirect_ARM64; break;
florian8844a632012-04-13 04:04:06 +00001011 case VexArchS390X:
1012 chainXDirect = chainXDirect_S390; break;
sewardj3dee8492012-04-20 00:13:28 +00001013 case VexArchPPC32:
1014 return chainXDirect_PPC(place_to_chain,
1015 disp_cp_chain_me_EXPECTED,
1016 place_to_jump_to, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +00001017 case VexArchPPC64:
1018 return chainXDirect_PPC(place_to_chain,
1019 disp_cp_chain_me_EXPECTED,
1020 place_to_jump_to, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +00001021 case VexArchMIPS32:
1022 return chainXDirect_MIPS(place_to_chain,
1023 disp_cp_chain_me_EXPECTED,
1024 place_to_jump_to, False/*!mode64*/);
petarjb92a9542013-02-27 22:57:17 +00001025 case VexArchMIPS64:
1026 return chainXDirect_MIPS(place_to_chain,
1027 disp_cp_chain_me_EXPECTED,
1028 place_to_jump_to, True/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +00001029 default:
1030 vassert(0);
1031 }
1032 vassert(chainXDirect);
1033 VexInvalRange vir
1034 = chainXDirect(place_to_chain, disp_cp_chain_me_EXPECTED,
1035 place_to_jump_to);
1036 return vir;
1037}
1038
1039VexInvalRange LibVEX_UnChain ( VexArch arch_host,
1040 void* place_to_unchain,
1041 void* place_to_jump_to_EXPECTED,
1042 void* disp_cp_chain_me )
1043{
1044 VexInvalRange (*unchainXDirect)(void*, void*, void*) = NULL;
1045 switch (arch_host) {
1046 case VexArchX86:
1047 unchainXDirect = unchainXDirect_X86; break;
1048 case VexArchAMD64:
1049 unchainXDirect = unchainXDirect_AMD64; break;
1050 case VexArchARM:
1051 unchainXDirect = unchainXDirect_ARM; break;
sewardjc6acaa42014-02-19 17:42:59 +00001052 case VexArchARM64:
1053 unchainXDirect = unchainXDirect_ARM64; break;
florian8844a632012-04-13 04:04:06 +00001054 case VexArchS390X:
1055 unchainXDirect = unchainXDirect_S390; break;
sewardj3dee8492012-04-20 00:13:28 +00001056 case VexArchPPC32:
1057 return unchainXDirect_PPC(place_to_unchain,
1058 place_to_jump_to_EXPECTED,
1059 disp_cp_chain_me, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +00001060 case VexArchPPC64:
1061 return unchainXDirect_PPC(place_to_unchain,
1062 place_to_jump_to_EXPECTED,
1063 disp_cp_chain_me, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +00001064 case VexArchMIPS32:
1065 return unchainXDirect_MIPS(place_to_unchain,
petarjb92a9542013-02-27 22:57:17 +00001066 place_to_jump_to_EXPECTED,
1067 disp_cp_chain_me, False/*!mode64*/);
1068 case VexArchMIPS64:
1069 return unchainXDirect_MIPS(place_to_unchain,
1070 place_to_jump_to_EXPECTED,
1071 disp_cp_chain_me, True/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +00001072 default:
1073 vassert(0);
1074 }
1075 vassert(unchainXDirect);
1076 VexInvalRange vir
1077 = unchainXDirect(place_to_unchain, place_to_jump_to_EXPECTED,
1078 disp_cp_chain_me);
1079 return vir;
1080}
1081
1082Int LibVEX_evCheckSzB ( VexArch arch_host )
1083{
1084 static Int cached = 0; /* DO NOT MAKE NON-STATIC */
1085 if (UNLIKELY(cached == 0)) {
1086 switch (arch_host) {
1087 case VexArchX86:
1088 cached = evCheckSzB_X86(); break;
1089 case VexArchAMD64:
1090 cached = evCheckSzB_AMD64(); break;
1091 case VexArchARM:
1092 cached = evCheckSzB_ARM(); break;
sewardjbbcf1882014-01-12 12:49:10 +00001093 case VexArchARM64:
1094 cached = evCheckSzB_ARM64(); break;
florian8844a632012-04-13 04:04:06 +00001095 case VexArchS390X:
1096 cached = evCheckSzB_S390(); break;
sewardj3dee8492012-04-20 00:13:28 +00001097 case VexArchPPC32:
sewardjf252de52012-04-20 10:42:24 +00001098 case VexArchPPC64:
sewardj3dee8492012-04-20 00:13:28 +00001099 cached = evCheckSzB_PPC(); break;
sewardjd0e5fe72012-06-07 08:51:02 +00001100 case VexArchMIPS32:
petarjb92a9542013-02-27 22:57:17 +00001101 case VexArchMIPS64:
sewardjd0e5fe72012-06-07 08:51:02 +00001102 cached = evCheckSzB_MIPS(); break;
sewardjc6f970f2012-04-02 21:54:49 +00001103 default:
1104 vassert(0);
1105 }
1106 }
1107 return cached;
1108}
1109
1110VexInvalRange LibVEX_PatchProfInc ( VexArch arch_host,
1111 void* place_to_patch,
1112 ULong* location_of_counter )
1113{
1114 VexInvalRange (*patchProfInc)(void*,ULong*) = NULL;
1115 switch (arch_host) {
1116 case VexArchX86:
1117 patchProfInc = patchProfInc_X86; break;
1118 case VexArchAMD64:
1119 patchProfInc = patchProfInc_AMD64; break;
1120 case VexArchARM:
1121 patchProfInc = patchProfInc_ARM; break;
florian8844a632012-04-13 04:04:06 +00001122 case VexArchS390X:
1123 patchProfInc = patchProfInc_S390; break;
sewardj3dee8492012-04-20 00:13:28 +00001124 case VexArchPPC32:
1125 return patchProfInc_PPC(place_to_patch,
1126 location_of_counter, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +00001127 case VexArchPPC64:
1128 return patchProfInc_PPC(place_to_patch,
1129 location_of_counter, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +00001130 case VexArchMIPS32:
1131 return patchProfInc_MIPS(place_to_patch,
1132 location_of_counter, False/*!mode64*/);
petarjb92a9542013-02-27 22:57:17 +00001133 case VexArchMIPS64:
1134 return patchProfInc_MIPS(place_to_patch,
1135 location_of_counter, True/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +00001136 default:
1137 vassert(0);
1138 }
1139 vassert(patchProfInc);
1140 VexInvalRange vir
1141 = patchProfInc(place_to_patch, location_of_counter);
1142 return vir;
1143}
1144
1145
sewardj893aada2004-11-29 19:57:54 +00001146/* --------- Emulation warnings. --------- */
1147
florian1ff47562012-10-21 02:09:51 +00001148const HChar* LibVEX_EmNote_string ( VexEmNote ew )
sewardj893aada2004-11-29 19:57:54 +00001149{
1150 switch (ew) {
florian6ef84be2012-08-26 03:20:07 +00001151 case EmNote_NONE:
sewardj893aada2004-11-29 19:57:54 +00001152 return "none";
1153 case EmWarn_X86_x87exns:
1154 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +00001155 case EmWarn_X86_x87precision:
1156 return "Selection of non-80-bit x87 FP precision";
1157 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +00001158 return "Unmasking SSE FP exceptions";
1159 case EmWarn_X86_fz:
1160 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
1161 case EmWarn_X86_daz:
1162 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +00001163 case EmWarn_X86_acFlag:
1164 return "Setting %eflags.ac (setting noted but ignored)";
sewardj9dd9cf12006-01-20 14:13:55 +00001165 case EmWarn_PPCexns:
1166 return "Unmasking PPC32/64 FP exceptions";
1167 case EmWarn_PPC64_redir_overflow:
1168 return "PPC64 function redirection stack overflow";
1169 case EmWarn_PPC64_redir_underflow:
1170 return "PPC64 function redirection stack underflow";
florian4b8efad2012-09-02 18:07:08 +00001171 case EmWarn_S390X_fpext_rounding:
1172 return "The specified rounding mode cannot be supported. That\n"
1173 " feature requires the floating point extension facility.\n"
1174 " which is not available on this host. Continuing using\n"
1175 " the rounding mode from FPC. Results may differ!";
florianf0fa1be2012-09-18 20:24:38 +00001176 case EmWarn_S390X_invalid_rounding:
1177 return "The specified rounding mode is invalid.\n"
1178 " Continuing using 'round to nearest'. Results may differ!";
floriane75dafa2012-09-01 17:54:09 +00001179 case EmFail_S390X_stfle:
florian4e0083e2012-08-26 03:41:56 +00001180 return "Instruction stfle is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001181 case EmFail_S390X_stckf:
florianc5c669b2012-08-26 14:32:28 +00001182 return "Instruction stckf is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001183 case EmFail_S390X_ecag:
florian8c88cb62012-08-26 18:58:13 +00001184 return "Instruction ecag is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001185 case EmFail_S390X_fpext:
1186 return "Encountered an instruction that requires the floating "
1187 "point extension facility.\n"
1188 " That facility is not available on this host";
florian78d5ef72013-05-11 15:02:58 +00001189 case EmFail_S390X_invalid_PFPO_rounding_mode:
1190 return "The rounding mode specified in GPR 0 for PFPO instruction"
1191 " is invalid";
1192 case EmFail_S390X_invalid_PFPO_function:
1193 return "The function code specified in GPR 0 for PFPO instruction"
1194 " is invalid";
sewardj893aada2004-11-29 19:57:54 +00001195 default:
florian6ef84be2012-08-26 03:20:07 +00001196 vpanic("LibVEX_EmNote_string: unknown warning");
sewardj893aada2004-11-29 19:57:54 +00001197 }
1198}
sewardj35421a32004-07-05 13:12:34 +00001199
sewardj5117ce12006-01-27 21:20:15 +00001200/* ------------------ Arch/HwCaps stuff. ------------------ */
sewardjbef170b2004-12-21 01:23:00 +00001201
1202const HChar* LibVEX_ppVexArch ( VexArch arch )
1203{
1204 switch (arch) {
1205 case VexArch_INVALID: return "INVALID";
1206 case VexArchX86: return "X86";
1207 case VexArchAMD64: return "AMD64";
1208 case VexArchARM: return "ARM";
sewardjbbcf1882014-01-12 12:49:10 +00001209 case VexArchARM64: return "ARM64";
sewardj0ec57c52005-02-01 15:24:10 +00001210 case VexArchPPC32: return "PPC32";
cerionf0de28c2005-12-13 20:21:11 +00001211 case VexArchPPC64: return "PPC64";
sewardj2019a972011-03-07 16:04:07 +00001212 case VexArchS390X: return "S390X";
sewardjd0e5fe72012-06-07 08:51:02 +00001213 case VexArchMIPS32: return "MIPS32";
petarjb92a9542013-02-27 22:57:17 +00001214 case VexArchMIPS64: return "MIPS64";
sewardjbef170b2004-12-21 01:23:00 +00001215 default: return "VexArch???";
1216 }
1217}
1218
sewardj5117ce12006-01-27 21:20:15 +00001219const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
sewardjbef170b2004-12-21 01:23:00 +00001220{
florian55085f82012-11-21 00:36:55 +00001221 const HChar* str = show_hwcaps(arch,hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001222 return str ? str : "INVALID";
sewardjbef170b2004-12-21 01:23:00 +00001223}
1224
sewardj5117ce12006-01-27 21:20:15 +00001225
sewardj27e1dd62005-06-30 11:49:14 +00001226/* Write default settings info *vai. */
1227void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
1228{
sewardj65902992014-05-03 21:20:56 +00001229 vex_bzero(vai, sizeof(*vai));
florian9138b172013-08-03 19:36:55 +00001230 vai->hwcaps = 0;
1231 vai->ppc_icache_line_szB = 0;
1232 vai->ppc_dcbz_szB = 0;
1233 vai->ppc_dcbzl_szB = 0;
sewardj65902992014-05-03 21:20:56 +00001234 vai->arm64_dMinLine_lg2_szB = 0;
1235 vai->arm64_iMinLine_lg2_szB = 0;
florianf192a392012-10-07 19:44:40 +00001236 vai->hwcache_info.num_levels = 0;
1237 vai->hwcache_info.num_caches = 0;
sewardj65902992014-05-03 21:20:56 +00001238 vai->hwcache_info.caches = NULL;
florianf192a392012-10-07 19:44:40 +00001239 vai->hwcache_info.icaches_maintain_coherence = True; // whatever
sewardj27e1dd62005-06-30 11:49:14 +00001240}
1241
sewardjdd40fdf2006-12-24 02:20:24 +00001242/* Write default settings info *vbi. */
1243void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
sewardjaca070a2006-10-17 00:28:22 +00001244{
sewardj65902992014-05-03 21:20:56 +00001245 vex_bzero(vbi, sizeof(*vbi));
sewardjdd40fdf2006-12-24 02:20:24 +00001246 vbi->guest_stack_redzone_size = 0;
sewardj2e28ac42008-12-04 00:05:12 +00001247 vbi->guest_amd64_assume_fs_is_zero = False;
1248 vbi->guest_amd64_assume_gs_is_0x60 = False;
sewardjdd40fdf2006-12-24 02:20:24 +00001249 vbi->guest_ppc_zap_RZ_at_blr = False;
1250 vbi->guest_ppc_zap_RZ_at_bl = NULL;
1251 vbi->guest_ppc_sc_continues_at_LR = False;
1252 vbi->host_ppc_calls_use_fndescrs = False;
1253 vbi->host_ppc32_regalign_int64_args = False;
sewardjaca070a2006-10-17 00:28:22 +00001254}
1255
sewardj27e1dd62005-06-30 11:49:14 +00001256
sewardj5117ce12006-01-27 21:20:15 +00001257/* Return a string showing the hwcaps in a nice way. The string will
1258 be NULL for invalid combinations of flags, so these functions also
1259 serve as a way to validate hwcaps values. */
1260
florian55085f82012-11-21 00:36:55 +00001261static const HChar* show_hwcaps_x86 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001262{
mjw6c65c122013-08-27 10:19:03 +00001263 /* Monotonic, LZCNT > SSE3 > SSE2 > SSE1 > MMXEXT > baseline. */
sewardj536fbab2010-07-29 15:39:05 +00001264 switch (hwcaps) {
1265 case 0:
1266 return "x86-sse0";
mjw6c65c122013-08-27 10:19:03 +00001267 case VEX_HWCAPS_X86_MMXEXT:
1268 return "x86-mmxext";
1269 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1:
1270 return "x86-mmxext-sse1";
1271 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2:
1272 return "x86-mmxext-sse1-sse2";
1273 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
sewardj536fbab2010-07-29 15:39:05 +00001274 | VEX_HWCAPS_X86_LZCNT:
mjw6c65c122013-08-27 10:19:03 +00001275 return "x86-mmxext-sse1-sse2-lzcnt";
1276 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
sewardj536fbab2010-07-29 15:39:05 +00001277 | VEX_HWCAPS_X86_SSE3:
mjw6c65c122013-08-27 10:19:03 +00001278 return "x86-mmxext-sse1-sse2-sse3";
1279 case VEX_HWCAPS_X86_MMXEXT | VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
sewardj536fbab2010-07-29 15:39:05 +00001280 | VEX_HWCAPS_X86_SSE3 | VEX_HWCAPS_X86_LZCNT:
mjw6c65c122013-08-27 10:19:03 +00001281 return "x86-mmxext-sse1-sse2-sse3-lzcnt";
sewardj536fbab2010-07-29 15:39:05 +00001282 default:
1283 return NULL;
1284 }
sewardj5117ce12006-01-27 21:20:15 +00001285}
1286
florian55085f82012-11-21 00:36:55 +00001287static const HChar* show_hwcaps_amd64 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001288{
sewardje9d8a262009-07-01 08:06:34 +00001289 /* SSE3 and CX16 are orthogonal and > baseline, although we really
1290 don't expect to come across anything which can do SSE3 but can't
sewardj536fbab2010-07-29 15:39:05 +00001291 do CX16. Still, we can handle that case. LZCNT is similarly
sewardj818c7302013-03-26 13:53:18 +00001292 orthogonal. */
1293
1294 /* Throw out obviously stupid cases: */
sewardj818c7302013-03-26 13:53:18 +00001295 Bool have_sse3 = (hwcaps & VEX_HWCAPS_AMD64_SSE3) != 0;
1296 Bool have_avx = (hwcaps & VEX_HWCAPS_AMD64_AVX) != 0;
sewardjcc3d2192013-03-27 11:37:33 +00001297 Bool have_bmi = (hwcaps & VEX_HWCAPS_AMD64_BMI) != 0;
1298 Bool have_avx2 = (hwcaps & VEX_HWCAPS_AMD64_AVX2) != 0;
1299 /* AVX without SSE3 */
sewardj818c7302013-03-26 13:53:18 +00001300 if (have_avx && !have_sse3)
1301 return NULL;
sewardjcc3d2192013-03-27 11:37:33 +00001302 /* AVX2 or BMI without AVX */
1303 if ((have_avx2 || have_bmi) && !have_avx)
1304 return NULL;
sewardj818c7302013-03-26 13:53:18 +00001305
1306 /* This isn't threadsafe. We might need to fix it at some point. */
1307 static HChar buf[100] = { 0 };
1308 if (buf[0] != 0) return buf; /* already constructed */
1309
1310 vex_bzero(buf, sizeof(buf));
1311
1312 HChar* p = &buf[0];
1313
1314 p = p + vex_sprintf(p, "%s", "amd64");
1315 if (hwcaps == 0) {
1316 /* special-case the baseline case */
1317 p = p + vex_sprintf(p, "%s", "-sse2");
1318 goto out;
sewardj536fbab2010-07-29 15:39:05 +00001319 }
sewardj818c7302013-03-26 13:53:18 +00001320 if (hwcaps & VEX_HWCAPS_AMD64_CX16) {
1321 p = p + vex_sprintf(p, "%s", "-cx16");
1322 }
1323 if (hwcaps & VEX_HWCAPS_AMD64_LZCNT) {
1324 p = p + vex_sprintf(p, "%s", "-lzcnt");
1325 }
1326 if (hwcaps & VEX_HWCAPS_AMD64_RDTSCP) {
1327 p = p + vex_sprintf(p, "%s", "-rdtscp");
1328 }
1329 if (hwcaps & VEX_HWCAPS_AMD64_SSE3) {
1330 p = p + vex_sprintf(p, "%s", "-sse3");
1331 }
1332 if (hwcaps & VEX_HWCAPS_AMD64_AVX) {
1333 p = p + vex_sprintf(p, "%s", "-avx");
1334 }
sewardjcc3d2192013-03-27 11:37:33 +00001335 if (hwcaps & VEX_HWCAPS_AMD64_AVX2) {
1336 p = p + vex_sprintf(p, "%s", "-avx2");
1337 }
1338 if (hwcaps & VEX_HWCAPS_AMD64_BMI) {
1339 p = p + vex_sprintf(p, "%s", "-bmi");
1340 }
sewardj818c7302013-03-26 13:53:18 +00001341
1342 out:
1343 vassert(buf[sizeof(buf)-1] == 0);
1344 return buf;
sewardj5117ce12006-01-27 21:20:15 +00001345}
1346
florian55085f82012-11-21 00:36:55 +00001347static const HChar* show_hwcaps_ppc32 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001348{
1349 /* Monotonic with complications. Basically V > F > baseline,
1350 but once you have F then you can have FX or GX too. */
1351 const UInt F = VEX_HWCAPS_PPC32_F;
1352 const UInt V = VEX_HWCAPS_PPC32_V;
1353 const UInt FX = VEX_HWCAPS_PPC32_FX;
1354 const UInt GX = VEX_HWCAPS_PPC32_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001355 const UInt VX = VEX_HWCAPS_PPC32_VX;
sewardjc66d6fa2012-04-02 21:24:12 +00001356 const UInt DFP = VEX_HWCAPS_PPC32_DFP;
carll0c74bb52013-08-12 18:01:40 +00001357 const UInt ISA2_07 = VEX_HWCAPS_PPC32_ISA2_07;
sewardj5117ce12006-01-27 21:20:15 +00001358 UInt c = hwcaps;
1359 if (c == 0) return "ppc32-int";
1360 if (c == F) return "ppc32-int-flt";
1361 if (c == (F|FX)) return "ppc32-int-flt-FX";
1362 if (c == (F|GX)) return "ppc32-int-flt-GX";
1363 if (c == (F|FX|GX)) return "ppc32-int-flt-FX-GX";
1364 if (c == (F|V)) return "ppc32-int-flt-vmx";
1365 if (c == (F|V|FX)) return "ppc32-int-flt-vmx-FX";
1366 if (c == (F|V|GX)) return "ppc32-int-flt-vmx-GX";
1367 if (c == (F|V|FX|GX)) return "ppc32-int-flt-vmx-FX-GX";
sewardjc66d6fa2012-04-02 21:24:12 +00001368 if (c == (F|V|FX|GX|DFP)) return "ppc32-int-flt-vmx-FX-GX-DFP";
1369 if (c == (F|V|FX|GX|VX|DFP)) return "ppc32-int-flt-vmx-FX-GX-VX-DFP";
carll0c74bb52013-08-12 18:01:40 +00001370 if (c == (F|V|FX|GX|VX|DFP|ISA2_07))
1371 return "ppc32-int-flt-vmx-FX-GX-VX-DFP-ISA2_07";
1372
sewardj5117ce12006-01-27 21:20:15 +00001373 return NULL;
1374}
1375
florian55085f82012-11-21 00:36:55 +00001376static const HChar* show_hwcaps_ppc64 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001377{
1378 /* Monotonic with complications. Basically V > baseline(==F),
1379 but once you have F then you can have FX or GX too. */
sewardj3fd39672006-01-27 22:05:55 +00001380 const UInt V = VEX_HWCAPS_PPC64_V;
1381 const UInt FX = VEX_HWCAPS_PPC64_FX;
1382 const UInt GX = VEX_HWCAPS_PPC64_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001383 const UInt VX = VEX_HWCAPS_PPC64_VX;
sewardjc66d6fa2012-04-02 21:24:12 +00001384 const UInt DFP = VEX_HWCAPS_PPC64_DFP;
carll0c74bb52013-08-12 18:01:40 +00001385 const UInt ISA2_07 = VEX_HWCAPS_PPC64_ISA2_07;
sewardj5117ce12006-01-27 21:20:15 +00001386 UInt c = hwcaps;
1387 if (c == 0) return "ppc64-int-flt";
1388 if (c == FX) return "ppc64-int-flt-FX";
1389 if (c == GX) return "ppc64-int-flt-GX";
1390 if (c == (FX|GX)) return "ppc64-int-flt-FX-GX";
1391 if (c == V) return "ppc64-int-flt-vmx";
1392 if (c == (V|FX)) return "ppc64-int-flt-vmx-FX";
1393 if (c == (V|GX)) return "ppc64-int-flt-vmx-GX";
1394 if (c == (V|FX|GX)) return "ppc64-int-flt-vmx-FX-GX";
sewardjc66d6fa2012-04-02 21:24:12 +00001395 if (c == (V|FX|GX|DFP)) return "ppc64-int-flt-vmx-FX-GX-DFP";
1396 if (c == (V|FX|GX|VX|DFP)) return "ppc64-int-flt-vmx-FX-GX-VX-DFP";
carll0c74bb52013-08-12 18:01:40 +00001397 if (c == (V|FX|GX|VX|DFP|ISA2_07))
1398 return "ppc64-int-flt-vmx-FX-GX-VX-DFP-ISA2_07";
sewardj5117ce12006-01-27 21:20:15 +00001399 return NULL;
1400}
1401
florian55085f82012-11-21 00:36:55 +00001402static const HChar* show_hwcaps_arm ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001403{
sewardjec0d9a02010-08-22 12:54:56 +00001404 Bool N = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0);
1405 Bool vfp = ((hwcaps & (VEX_HWCAPS_ARM_VFP |
1406 VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3)) != 0);
1407 switch (VEX_ARM_ARCHLEVEL(hwcaps)) {
1408 case 5:
1409 if (N)
1410 return NULL;
1411 if (vfp)
1412 return "ARMv5-vfp";
1413 else
1414 return "ARMv5";
1415 return NULL;
1416 case 6:
1417 if (N)
1418 return NULL;
1419 if (vfp)
1420 return "ARMv6-vfp";
1421 else
1422 return "ARMv6";
1423 return NULL;
1424 case 7:
1425 if (vfp) {
1426 if (N)
1427 return "ARMv7-vfp-neon";
1428 else
1429 return "ARMv7-vfp";
1430 } else {
1431 if (N)
1432 return "ARMv7-neon";
1433 else
1434 return "ARMv7";
1435 }
1436 default:
1437 return NULL;
1438 }
sewardj5117ce12006-01-27 21:20:15 +00001439 return NULL;
1440}
1441
sewardjbbcf1882014-01-12 12:49:10 +00001442static const HChar* show_hwcaps_arm64 ( UInt hwcaps )
1443{
1444 /* Since there are no variants, just insist that hwcaps is zero,
1445 and declare it invalid otherwise. */
1446 if (hwcaps == 0)
1447 return "baseline";
1448 return NULL;
1449}
1450
florian55085f82012-11-21 00:36:55 +00001451static const HChar* show_hwcaps_s390x ( UInt hwcaps )
sewardj2019a972011-03-07 16:04:07 +00001452{
sewardjd07b8562011-04-27 11:58:22 +00001453 static const HChar prefix[] = "s390x";
florian9061eb32012-12-09 17:53:45 +00001454 static const struct {
1455 UInt hwcaps_bit;
1456 HChar name[6];
1457 } hwcaps_list[] = {
1458 { VEX_HWCAPS_S390X_LDISP, "ldisp" },
1459 { VEX_HWCAPS_S390X_EIMM, "eimm" },
1460 { VEX_HWCAPS_S390X_GIE, "gie" },
1461 { VEX_HWCAPS_S390X_DFP, "dfp" },
1462 { VEX_HWCAPS_S390X_FGX, "fgx" },
1463 { VEX_HWCAPS_S390X_STFLE, "stfle" },
1464 { VEX_HWCAPS_S390X_ETF2, "etf2" },
1465 { VEX_HWCAPS_S390X_ETF3, "etf3" },
1466 { VEX_HWCAPS_S390X_STCKF, "stckf" },
1467 { VEX_HWCAPS_S390X_FPEXT, "fpext" },
1468 { VEX_HWCAPS_S390X_LSC, "lsc" },
florian78d5ef72013-05-11 15:02:58 +00001469 { VEX_HWCAPS_S390X_PFPO, "pfpo" },
sewardjd07b8562011-04-27 11:58:22 +00001470 };
florian9061eb32012-12-09 17:53:45 +00001471#define NUM_HWCAPS (sizeof hwcaps_list / sizeof hwcaps_list[0])
1472 static HChar buf[sizeof prefix +
1473 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) +
1474 1]; // '\0'
1475 HChar *p;
1476 UInt i;
sewardjd07b8562011-04-27 11:58:22 +00001477
1478 if (buf[0] != '\0') return buf; /* already constructed */
sewardj2019a972011-03-07 16:04:07 +00001479
sewardj652b56a2011-04-13 15:38:17 +00001480 hwcaps = VEX_HWCAPS_S390X(hwcaps);
1481
sewardjd07b8562011-04-27 11:58:22 +00001482 p = buf + vex_sprintf(buf, "%s", prefix);
florian9061eb32012-12-09 17:53:45 +00001483 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1484 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1485 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1486 }
sewardj2019a972011-03-07 16:04:07 +00001487
sewardjd07b8562011-04-27 11:58:22 +00001488 /* If there are no facilities, add "zarch" */
1489 if (hwcaps == 0)
1490 vex_sprintf(p, "-%s", "zarch");
1491
1492 return buf;
sewardj2019a972011-03-07 16:04:07 +00001493}
1494
florian55085f82012-11-21 00:36:55 +00001495static const HChar* show_hwcaps_mips32 ( UInt hwcaps )
sewardjd0e5fe72012-06-07 08:51:02 +00001496{
dejanjc3fee0d2013-07-25 09:08:03 +00001497 /* MIPS baseline. */
petarjbc7d6f42013-09-16 18:11:59 +00001498 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_MIPS) {
dejanjc3fee0d2013-07-25 09:08:03 +00001499 /* MIPS baseline with dspr2. */
petarjbc7d6f42013-09-16 18:11:59 +00001500 if (VEX_MIPS_PROC_DSP2(hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +00001501 return "MIPS-baseline-dspr2";
1502 }
1503 /* MIPS baseline with dsp. */
petarjbc7d6f42013-09-16 18:11:59 +00001504 if (VEX_MIPS_PROC_DSP(hwcaps)) {
dejanjc3fee0d2013-07-25 09:08:03 +00001505 return "MIPS-baseline-dsp";
1506 }
1507 return "MIPS-baseline";
1508 }
1509
1510 /* Broadcom baseline. */
petarjbc7d6f42013-09-16 18:11:59 +00001511 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_BROADCOM) {
dejanjc3fee0d2013-07-25 09:08:03 +00001512 return "Broadcom-baseline";
1513 }
1514
1515 /* Netlogic baseline. */
petarjbc7d6f42013-09-16 18:11:59 +00001516 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_NETLOGIC) {
dejanjc3fee0d2013-07-25 09:08:03 +00001517 return "Netlogic-baseline";
1518 }
1519
petarjbc7d6f42013-09-16 18:11:59 +00001520 /* Cavium baseline. */
1521 if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_CAVIUM) {
1522 return "Cavium-baseline";
1523 }
1524
sewardjd0e5fe72012-06-07 08:51:02 +00001525 return NULL;
1526}
1527
petarjb92a9542013-02-27 22:57:17 +00001528static const HChar* show_hwcaps_mips64 ( UInt hwcaps )
1529{
1530 return "mips64-baseline";
1531}
1532
sewardj5117ce12006-01-27 21:20:15 +00001533/* ---- */
florian55085f82012-11-21 00:36:55 +00001534static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001535{
1536 switch (arch) {
sewardjd0e5fe72012-06-07 08:51:02 +00001537 case VexArchX86: return show_hwcaps_x86(hwcaps);
1538 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
1539 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
1540 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
1541 case VexArchARM: return show_hwcaps_arm(hwcaps);
sewardjbbcf1882014-01-12 12:49:10 +00001542 case VexArchARM64: return show_hwcaps_arm64(hwcaps);
sewardjd0e5fe72012-06-07 08:51:02 +00001543 case VexArchS390X: return show_hwcaps_s390x(hwcaps);
1544 case VexArchMIPS32: return show_hwcaps_mips32(hwcaps);
petarjb92a9542013-02-27 22:57:17 +00001545 case VexArchMIPS64: return show_hwcaps_mips64(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001546 default: return NULL;
1547 }
1548}
1549
1550static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps )
1551{
1552 return show_hwcaps(arch,hwcaps) != NULL;
1553}
1554
1555
sewardj35421a32004-07-05 13:12:34 +00001556/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +00001557/*--- end main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +00001558/*---------------------------------------------------------------*/