blob: aa45d11efb823ff450978fa16902cdf287f1fda4 [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
sewardj25e54732012-08-05 15:36:51 +000010 Copyright (C) 2004-2012 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"
cerionaabdfbf2005-01-29 12:56:15 +000041#include "libvex_guest_ppc32.h"
cerionf0de28c2005-12-13 20:21:11 +000042#include "libvex_guest_ppc64.h"
sewardj2019a972011-03-07 16:04:07 +000043#include "libvex_guest_s390x.h"
sewardjd0e5fe72012-06-07 08:51:02 +000044#include "libvex_guest_mips32.h"
petarjb92a9542013-02-27 22:57:17 +000045#include "libvex_guest_mips64.h"
sewardjf13a16a2004-07-05 17:10:14 +000046
sewardjcef7d3e2009-07-02 12:21:59 +000047#include "main_globals.h"
48#include "main_util.h"
49#include "host_generic_regs.h"
50#include "ir_opt.h"
sewardj35421a32004-07-05 13:12:34 +000051
sewardjcef7d3e2009-07-02 12:21:59 +000052#include "host_x86_defs.h"
53#include "host_amd64_defs.h"
54#include "host_ppc_defs.h"
sewardj6c299f32009-12-31 18:00:12 +000055#include "host_arm_defs.h"
sewardj2019a972011-03-07 16:04:07 +000056#include "host_s390_defs.h"
sewardjd0e5fe72012-06-07 08:51:02 +000057#include "host_mips_defs.h"
sewardj2a9ad022004-11-25 02:46:58 +000058
sewardjcef7d3e2009-07-02 12:21:59 +000059#include "guest_generic_bb_to_IR.h"
60#include "guest_x86_defs.h"
61#include "guest_amd64_defs.h"
62#include "guest_arm_defs.h"
63#include "guest_ppc_defs.h"
sewardj2019a972011-03-07 16:04:07 +000064#include "guest_s390_defs.h"
sewardjd0e5fe72012-06-07 08:51:02 +000065#include "guest_mips_defs.h"
sewardj2a9ad022004-11-25 02:46:58 +000066
sewardj69d98e32010-06-18 08:17:41 +000067#include "host_generic_simd128.h"
68
sewardj35421a32004-07-05 13:12:34 +000069
70/* This file contains the top level interface to the library. */
71
sewardj5117ce12006-01-27 21:20:15 +000072/* --------- fwds ... --------- */
73
74static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps );
florian55085f82012-11-21 00:36:55 +000075static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps );
sewardj5117ce12006-01-27 21:20:15 +000076
77
sewardj35421a32004-07-05 13:12:34 +000078/* --------- Initialise the library. --------- */
79
80/* Exported to library client. */
81
sewardj08613742004-10-25 13:01:45 +000082void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon )
83{
84 vcon->iropt_verbosity = 0;
85 vcon->iropt_level = 2;
philippec8e2f982012-08-01 22:04:13 +000086 vcon->iropt_register_updates = VexRegUpdUnwindregsAtMemAccess;
sewardj08613742004-10-25 13:01:45 +000087 vcon->iropt_unroll_thresh = 120;
sewardj18b4bb72005-03-29 21:32:41 +000088 vcon->guest_max_insns = 60;
sewardj08613742004-10-25 13:01:45 +000089 vcon->guest_chase_thresh = 10;
sewardj984d9b12010-01-15 10:53:21 +000090 vcon->guest_chase_cond = False;
sewardj08613742004-10-25 13:01:45 +000091}
92
93
94/* Exported to library client. */
95
sewardj887a11a2004-07-05 17:26:47 +000096void LibVEX_Init (
sewardj35421a32004-07-05 13:12:34 +000097 /* failure exit function */
sewardj2b515872004-07-05 20:50:45 +000098 __attribute__ ((noreturn))
sewardj35421a32004-07-05 13:12:34 +000099 void (*failure_exit) ( void ),
100 /* logging output function */
sewardjd9763622005-02-07 03:12:19 +0000101 void (*log_bytes) ( HChar*, Int nbytes ),
sewardj35421a32004-07-05 13:12:34 +0000102 /* debug paranoia level */
103 Int debuglevel,
sewardj35421a32004-07-05 13:12:34 +0000104 /* Are we supporting valgrind checking? */
105 Bool valgrind_support,
sewardj08613742004-10-25 13:01:45 +0000106 /* Control ... */
107 /*READONLY*/VexControl* vcon
sewardj35421a32004-07-05 13:12:34 +0000108)
109{
sewardj08613742004-10-25 13:01:45 +0000110 /* First off, do enough minimal setup so that the following
111 assertions can fail in a sane fashion, if need be. */
sewardjea602bc2004-10-14 21:40:12 +0000112 vex_failure_exit = failure_exit;
113 vex_log_bytes = log_bytes;
114
115 /* Now it's safe to check parameters for sanity. */
sewardj35421a32004-07-05 13:12:34 +0000116 vassert(!vex_initdone);
117 vassert(failure_exit);
sewardj35421a32004-07-05 13:12:34 +0000118 vassert(log_bytes);
sewardj35421a32004-07-05 13:12:34 +0000119 vassert(debuglevel >= 0);
sewardj08613742004-10-25 13:01:45 +0000120
121 vassert(vcon->iropt_verbosity >= 0);
122 vassert(vcon->iropt_level >= 0);
123 vassert(vcon->iropt_level <= 2);
124 vassert(vcon->iropt_unroll_thresh >= 0);
125 vassert(vcon->iropt_unroll_thresh <= 400);
126 vassert(vcon->guest_max_insns >= 1);
127 vassert(vcon->guest_max_insns <= 100);
128 vassert(vcon->guest_chase_thresh >= 0);
129 vassert(vcon->guest_chase_thresh < vcon->guest_max_insns);
sewardj984d9b12010-01-15 10:53:21 +0000130 vassert(vcon->guest_chase_cond == True
131 || vcon->guest_chase_cond == False);
sewardj443cd9d2004-07-18 23:06:45 +0000132
sewardjea602bc2004-10-14 21:40:12 +0000133 /* Check that Vex has been built with sizes of basic types as
134 stated in priv/libvex_basictypes.h. Failure of any of these is
135 a serious configuration error and should be corrected
136 immediately. If any of these assertions fail you can fully
137 expect Vex not to work properly, if at all. */
138
139 vassert(1 == sizeof(UChar));
140 vassert(1 == sizeof(Char));
141 vassert(2 == sizeof(UShort));
142 vassert(2 == sizeof(Short));
143 vassert(4 == sizeof(UInt));
144 vassert(4 == sizeof(Int));
145 vassert(8 == sizeof(ULong));
146 vassert(8 == sizeof(Long));
147 vassert(4 == sizeof(Float));
148 vassert(8 == sizeof(Double));
149 vassert(1 == sizeof(Bool));
150 vassert(4 == sizeof(Addr32));
151 vassert(8 == sizeof(Addr64));
sewardjc9a43662004-11-30 18:51:59 +0000152 vassert(16 == sizeof(U128));
sewardj69d98e32010-06-18 08:17:41 +0000153 vassert(16 == sizeof(V128));
sewardjc9069f22012-06-01 16:09:50 +0000154 vassert(32 == sizeof(U256));
sewardjea602bc2004-10-14 21:40:12 +0000155
156 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
157 vassert(sizeof(void*) == sizeof(int*));
158 vassert(sizeof(void*) == sizeof(HWord));
159
sewardj97e87932005-02-07 00:00:50 +0000160 vassert(VEX_HOST_WORDSIZE == sizeof(void*));
161 vassert(VEX_HOST_WORDSIZE == sizeof(HWord));
162
sewardjc6f970f2012-04-02 21:54:49 +0000163 /* These take a lot of space, so make sure we don't have
164 any unnoticed size regressions. */
165 if (VEX_HOST_WORDSIZE == 4) {
florian420bfa92012-06-02 20:29:22 +0000166 vassert(sizeof(IRExpr) == 16);
sewardjc6f970f2012-04-02 21:54:49 +0000167 vassert(sizeof(IRStmt) == 20 /* x86 */
168 || sizeof(IRStmt) == 24 /* arm */);
169 } else {
florian420bfa92012-06-02 20:29:22 +0000170 vassert(sizeof(IRExpr) == 32);
floriand6f38b32012-05-31 15:46:18 +0000171 vassert(sizeof(IRStmt) == 32);
sewardjc6f970f2012-04-02 21:54:49 +0000172 }
173
sewardjea602bc2004-10-14 21:40:12 +0000174 /* Really start up .. */
sewardj443cd9d2004-07-18 23:06:45 +0000175 vex_debuglevel = debuglevel;
sewardj443cd9d2004-07-18 23:06:45 +0000176 vex_valgrind_support = valgrind_support;
sewardj08613742004-10-25 13:01:45 +0000177 vex_control = *vcon;
sewardj443cd9d2004-07-18 23:06:45 +0000178 vex_initdone = True;
sewardjd887b862005-01-17 18:34:34 +0000179 vexSetAllocMode ( VexAllocModeTEMP );
sewardj35421a32004-07-05 13:12:34 +0000180}
181
182
183/* --------- Make a translation. --------- */
184
185/* Exported to library client. */
186
sewardj17c7f952005-12-15 14:02:34 +0000187VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
sewardj35421a32004-07-05 13:12:34 +0000188{
sewardj81bd5502004-07-21 18:49:27 +0000189 /* This the bundle of functions we need to do the back-end stuff
190 (insn selection, reg-alloc, assembly) whilst being insulated
191 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +0000192 HReg* available_real_regs;
193 Int n_available_real_regs;
sewardjfb7373a2007-08-25 21:29:03 +0000194 Bool (*isMove) ( HInstr*, HReg*, HReg* );
195 void (*getRegUsage) ( HRegUsage*, HInstr*, Bool );
196 void (*mapRegs) ( HRegRemap*, HInstr*, Bool );
sewardj6c299f32009-12-31 18:00:12 +0000197 void (*genSpill) ( HInstr**, HInstr**, HReg, Int, Bool );
198 void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool );
sewardjfb7373a2007-08-25 21:29:03 +0000199 HInstr* (*directReload) ( HInstr*, HReg, Short );
200 void (*ppInstr) ( HInstr*, Bool );
201 void (*ppReg) ( HReg );
sewardjc6f970f2012-04-02 21:54:49 +0000202 HInstrArray* (*iselSB) ( IRSB*, VexArch, VexArchInfo*, VexAbiInfo*,
203 Int, Int, Bool, Bool, Addr64 );
204 Int (*emit) ( /*MB_MOD*/Bool*,
205 UChar*, Int, HInstr*, Bool,
206 void*, void*, void*, void* );
florian1ff47562012-10-21 02:09:51 +0000207 IRExpr* (*specHelper) ( const HChar*, IRExpr**, IRStmt**, Int );
sewardj8d2291c2004-10-25 14:50:21 +0000208 Bool (*preciseMemExnsFn) ( Int, Int );
sewardjf13a16a2004-07-05 17:10:14 +0000209
sewardj9e6491a2005-07-02 19:24:10 +0000210 DisOneInstrFn disInstrFn;
211
sewardjeeac8412004-11-02 00:26:55 +0000212 VexGuestLayout* guest_layout;
213 Bool host_is_bigendian = False;
sewardjdd40fdf2006-12-24 02:20:24 +0000214 IRSB* irsb;
sewardjeeac8412004-11-02 00:26:55 +0000215 HInstrArray* vcode;
216 HInstrArray* rcode;
217 Int i, j, k, out_used, guest_sizeB;
sewardjc6f970f2012-04-02 21:54:49 +0000218 Int offB_TISTART, offB_TILEN, offB_GUEST_IP, szB_GUEST_IP;
219 Int offB_HOST_EvC_COUNTER, offB_HOST_EvC_FAILADDR;
petarjb92a9542013-02-27 22:57:17 +0000220 UChar insn_bytes[128];
sewardjcf787902004-11-03 09:08:33 +0000221 IRType guest_word_type;
222 IRType host_word_type;
sewardjc6f970f2012-04-02 21:54:49 +0000223 Bool mode64, chainingAllowed;
224 Addr64 max_ga;
sewardjf13a16a2004-07-05 17:10:14 +0000225
sewardj49651f42004-10-28 22:11:04 +0000226 guest_layout = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000227 available_real_regs = NULL;
228 n_available_real_regs = 0;
229 isMove = NULL;
230 getRegUsage = NULL;
231 mapRegs = NULL;
232 genSpill = NULL;
233 genReload = NULL;
sewardjfb7373a2007-08-25 21:29:03 +0000234 directReload = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000235 ppInstr = NULL;
236 ppReg = NULL;
sewardjdd40fdf2006-12-24 02:20:24 +0000237 iselSB = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000238 emit = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000239 specHelper = NULL;
sewardj8d2291c2004-10-25 14:50:21 +0000240 preciseMemExnsFn = NULL;
sewardj9e6491a2005-07-02 19:24:10 +0000241 disInstrFn = NULL;
sewardjcf787902004-11-03 09:08:33 +0000242 guest_word_type = Ity_INVALID;
243 host_word_type = Ity_INVALID;
sewardjdb4738a2005-07-07 01:32:16 +0000244 offB_TISTART = 0;
245 offB_TILEN = 0;
sewardjc6f970f2012-04-02 21:54:49 +0000246 offB_GUEST_IP = 0;
247 szB_GUEST_IP = 0;
248 offB_HOST_EvC_COUNTER = 0;
249 offB_HOST_EvC_FAILADDR = 0;
cerion92b64362005-12-13 12:02:26 +0000250 mode64 = False;
sewardjc6f970f2012-04-02 21:54:49 +0000251 chainingAllowed = False;
sewardj36ca5132004-07-24 13:12:23 +0000252
sewardj17c7f952005-12-15 14:02:34 +0000253 vex_traceflags = vta->traceflags;
sewardj58800ff2004-07-28 01:51:10 +0000254
sewardj35421a32004-07-05 13:12:34 +0000255 vassert(vex_initdone);
sewardjc6f970f2012-04-02 21:54:49 +0000256 vassert(vta->needs_self_check != NULL);
257 vassert(vta->disp_cp_xassisted != NULL);
258 /* Both the chainers and the indir are either NULL or non-NULL. */
259 if (vta->disp_cp_chain_me_to_slowEP != NULL) {
260 vassert(vta->disp_cp_chain_me_to_fastEP != NULL);
261 vassert(vta->disp_cp_xindir != NULL);
262 chainingAllowed = True;
263 } else {
264 vassert(vta->disp_cp_chain_me_to_fastEP == NULL);
265 vassert(vta->disp_cp_xindir == NULL);
266 }
florian2eeeb9b2011-09-23 18:03:21 +0000267
sewardj2d6b14a2005-11-23 04:25:07 +0000268 vexSetAllocModeTEMP_and_clear();
269 vexAllocSanityCheck();
sewardj2a9ad022004-11-25 02:46:58 +0000270
sewardjf13a16a2004-07-05 17:10:14 +0000271 /* First off, check that the guest and host insn sets
272 are supported. */
sewardj2a9ad022004-11-25 02:46:58 +0000273
sewardj17c7f952005-12-15 14:02:34 +0000274 switch (vta->arch_host) {
sewardj2a9ad022004-11-25 02:46:58 +0000275
sewardjbef170b2004-12-21 01:23:00 +0000276 case VexArchX86:
sewardjfb7373a2007-08-25 21:29:03 +0000277 mode64 = False;
sewardjf13a16a2004-07-05 17:10:14 +0000278 getAllocableRegs_X86 ( &n_available_real_regs,
279 &available_real_regs );
sewardjfb7373a2007-08-25 21:29:03 +0000280 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000281 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
282 getRegUsage_X86Instr;
sewardjfb7373a2007-08-25 21:29:03 +0000283 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000284 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
285 genSpill_X86;
286 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
287 genReload_X86;
sewardjfb7373a2007-08-25 21:29:03 +0000288 directReload = (HInstr*(*)(HInstr*,HReg,Short)) directReload_X86;
289 ppInstr = (void(*)(HInstr*, Bool)) ppX86Instr;
290 ppReg = (void(*)(HReg)) ppHRegX86;
291 iselSB = iselSB_X86;
sewardjc6f970f2012-04-02 21:54:49 +0000292 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
293 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000294 emit_X86Instr;
sewardj72c72812005-01-19 11:49:45 +0000295 host_is_bigendian = False;
sewardjcf787902004-11-03 09:08:33 +0000296 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000297 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_host.hwcaps));
sewardjf13a16a2004-07-05 17:10:14 +0000298 break;
sewardj2a9ad022004-11-25 02:46:58 +0000299
sewardjc33671d2005-02-01 20:30:00 +0000300 case VexArchAMD64:
cerion92b64362005-12-13 12:02:26 +0000301 mode64 = True;
sewardjc33671d2005-02-01 20:30:00 +0000302 getAllocableRegs_AMD64 ( &n_available_real_regs,
303 &available_real_regs );
304 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000305 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
306 getRegUsage_AMD64Instr;
cerion92b64362005-12-13 12:02:26 +0000307 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000308 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
309 genSpill_AMD64;
310 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
311 genReload_AMD64;
cerion92b64362005-12-13 12:02:26 +0000312 ppInstr = (void(*)(HInstr*, Bool)) ppAMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000313 ppReg = (void(*)(HReg)) ppHRegAMD64;
sewardjdd40fdf2006-12-24 02:20:24 +0000314 iselSB = iselSB_AMD64;
sewardjc6f970f2012-04-02 21:54:49 +0000315 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
316 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000317 emit_AMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000318 host_is_bigendian = False;
319 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000320 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_host.hwcaps));
sewardjc33671d2005-02-01 20:30:00 +0000321 break;
322
cerion487e4c92005-02-04 16:28:19 +0000323 case VexArchPPC32:
cerion92b64362005-12-13 12:02:26 +0000324 mode64 = False;
cerion5b2325f2005-12-23 00:55:09 +0000325 getAllocableRegs_PPC ( &n_available_real_regs,
326 &available_real_regs, mode64 );
327 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
328 getRegUsage = (void(*)(HRegUsage*,HInstr*,Bool)) getRegUsage_PPCInstr;
329 mapRegs = (void(*)(HRegRemap*,HInstr*,Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000330 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
331 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000332 ppInstr = (void(*)(HInstr*,Bool)) ppPPCInstr;
333 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000334 iselSB = iselSB_PPC;
sewardj3dee8492012-04-20 00:13:28 +0000335 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
336 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000337 emit_PPCInstr;
cerion487e4c92005-02-04 16:28:19 +0000338 host_is_bigendian = True;
339 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000340 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_host.hwcaps));
cerion487e4c92005-02-04 16:28:19 +0000341 break;
342
cerionf0de28c2005-12-13 20:21:11 +0000343 case VexArchPPC64:
344 mode64 = True;
cerion5b2325f2005-12-23 00:55:09 +0000345 getAllocableRegs_PPC ( &n_available_real_regs,
346 &available_real_regs, mode64 );
347 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
348 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_PPCInstr;
349 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000350 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
351 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000352 ppInstr = (void(*)(HInstr*, Bool)) ppPPCInstr;
353 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000354 iselSB = iselSB_PPC;
sewardj9e1cf152012-04-20 02:18:31 +0000355 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
356 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000357 emit_PPCInstr;
cerionf0de28c2005-12-13 20:21:11 +0000358 host_is_bigendian = True;
359 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000360 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_host.hwcaps));
cerionf0de28c2005-12-13 20:21:11 +0000361 break;
362
sewardj2019a972011-03-07 16:04:07 +0000363 case VexArchS390X:
364 mode64 = True;
365 getAllocableRegs_S390 ( &n_available_real_regs,
366 &available_real_regs, mode64 );
367 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_S390Instr;
368 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_S390Instr;
369 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_S390Instr;
370 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_S390;
371 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_S390;
372 ppInstr = (void(*)(HInstr*, Bool)) ppS390Instr;
373 ppReg = (void(*)(HReg)) ppHRegS390;
374 iselSB = iselSB_S390;
florian8844a632012-04-13 04:04:06 +0000375 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
376 void*,void*,void*,void*)) emit_S390Instr;
sewardj2019a972011-03-07 16:04:07 +0000377 host_is_bigendian = True;
378 host_word_type = Ity_I64;
379 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_host.hwcaps));
sewardj2019a972011-03-07 16:04:07 +0000380 break;
381
sewardj6c299f32009-12-31 18:00:12 +0000382 case VexArchARM:
sewardj2a1ed8e2009-12-31 19:26:03 +0000383 mode64 = False;
sewardj6c299f32009-12-31 18:00:12 +0000384 getAllocableRegs_ARM ( &n_available_real_regs,
385 &available_real_regs );
sewardj2a1ed8e2009-12-31 19:26:03 +0000386 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARMInstr;
387 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_ARMInstr;
388 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_ARMInstr;
389 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_ARM;
390 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_ARM;
391 ppInstr = (void(*)(HInstr*, Bool)) ppARMInstr;
392 ppReg = (void(*)(HReg)) ppHRegARM;
393 iselSB = iselSB_ARM;
sewardjc6f970f2012-04-02 21:54:49 +0000394 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
395 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000396 emit_ARMInstr;
sewardj6c299f32009-12-31 18:00:12 +0000397 host_is_bigendian = False;
398 host_word_type = Ity_I32;
399 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_host.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000400 break;
401
sewardjd0e5fe72012-06-07 08:51:02 +0000402 case VexArchMIPS32:
403 mode64 = False;
404 getAllocableRegs_MIPS ( &n_available_real_regs,
405 &available_real_regs, mode64 );
406 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_MIPSInstr;
407 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_MIPSInstr;
408 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_MIPSInstr;
409 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_MIPS;
410 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_MIPS;
411 ppInstr = (void(*)(HInstr*, Bool)) ppMIPSInstr;
412 ppReg = (void(*)(HReg)) ppHRegMIPS;
413 iselSB = iselSB_MIPS;
414 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
415 void*,void*,void*,void*))
416 emit_MIPSInstr;
417#if defined(VKI_LITTLE_ENDIAN)
418 host_is_bigendian = False;
419#elif defined(VKI_BIG_ENDIAN)
420 host_is_bigendian = True;
421#endif
422 host_word_type = Ity_I32;
423 vassert(are_valid_hwcaps(VexArchMIPS32, vta->archinfo_host.hwcaps));
424 break;
425
petarjb92a9542013-02-27 22:57:17 +0000426 case VexArchMIPS64:
427 mode64 = True;
428 getAllocableRegs_MIPS ( &n_available_real_regs,
429 &available_real_regs, mode64 );
430 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_MIPSInstr;
431 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_MIPSInstr;
432 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_MIPSInstr;
433 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_MIPS;
434 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_MIPS;
435 ppInstr = (void(*)(HInstr*, Bool)) ppMIPSInstr;
436 ppReg = (void(*)(HReg)) ppHRegMIPS;
437 iselSB = iselSB_MIPS;
438 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
439 void*,void*,void*,void*))
440 emit_MIPSInstr;
441#if defined(VKI_LITTLE_ENDIAN)
442 host_is_bigendian = False;
443#elif defined(VKI_BIG_ENDIAN)
444 host_is_bigendian = True;
445#endif
446 host_word_type = Ity_I64;
447 vassert(are_valid_hwcaps(VexArchMIPS64, vta->archinfo_host.hwcaps));
448 break;
449
sewardjf13a16a2004-07-05 17:10:14 +0000450 default:
sewardj6c299f32009-12-31 18:00:12 +0000451 vpanic("LibVEX_Translate: unsupported host insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000452 }
453
sewardj2a9ad022004-11-25 02:46:58 +0000454
sewardj17c7f952005-12-15 14:02:34 +0000455 switch (vta->arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000456
sewardjbef170b2004-12-21 01:23:00 +0000457 case VexArchX86:
sewardjc6f970f2012-04-02 21:54:49 +0000458 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
459 disInstrFn = disInstr_X86;
460 specHelper = guest_x86_spechelper;
461 guest_sizeB = sizeof(VexGuestX86State);
462 guest_word_type = Ity_I32;
463 guest_layout = &x86guest_layout;
464 offB_TISTART = offsetof(VexGuestX86State,guest_TISTART);
465 offB_TILEN = offsetof(VexGuestX86State,guest_TILEN);
466 offB_GUEST_IP = offsetof(VexGuestX86State,guest_EIP);
467 szB_GUEST_IP = sizeof( ((VexGuestX86State*)0)->guest_EIP );
468 offB_HOST_EvC_COUNTER = offsetof(VexGuestX86State,host_EvC_COUNTER);
469 offB_HOST_EvC_FAILADDR = offsetof(VexGuestX86State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000470 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000471 vassert(0 == sizeof(VexGuestX86State) % 16);
sewardjce02aa72006-01-12 12:27:58 +0000472 vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART) == 4);
473 vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
474 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000475 break;
sewardj2a9ad022004-11-25 02:46:58 +0000476
sewardj44d494d2005-01-20 20:26:33 +0000477 case VexArchAMD64:
sewardjc6f970f2012-04-02 21:54:49 +0000478 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
479 disInstrFn = disInstr_AMD64;
480 specHelper = guest_amd64_spechelper;
481 guest_sizeB = sizeof(VexGuestAMD64State);
482 guest_word_type = Ity_I64;
483 guest_layout = &amd64guest_layout;
484 offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART);
485 offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN);
486 offB_GUEST_IP = offsetof(VexGuestAMD64State,guest_RIP);
487 szB_GUEST_IP = sizeof( ((VexGuestAMD64State*)0)->guest_RIP );
488 offB_HOST_EvC_COUNTER = offsetof(VexGuestAMD64State,host_EvC_COUNTER);
489 offB_HOST_EvC_FAILADDR = offsetof(VexGuestAMD64State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000490 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000491 vassert(0 == sizeof(VexGuestAMD64State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000492 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8);
sewardjce02aa72006-01-12 12:27:58 +0000493 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
494 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000495 break;
496
cerionaabdfbf2005-01-29 12:56:15 +0000497 case VexArchPPC32:
sewardj3dee8492012-04-20 00:13:28 +0000498 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
499 disInstrFn = disInstr_PPC;
500 specHelper = guest_ppc32_spechelper;
501 guest_sizeB = sizeof(VexGuestPPC32State);
502 guest_word_type = Ity_I32;
503 guest_layout = &ppc32Guest_layout;
504 offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART);
505 offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN);
506 offB_GUEST_IP = offsetof(VexGuestPPC32State,guest_CIA);
507 szB_GUEST_IP = sizeof( ((VexGuestPPC32State*)0)->guest_CIA );
508 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC32State,host_EvC_COUNTER);
509 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC32State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000510 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000511 vassert(0 == sizeof(VexGuestPPC32State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000512 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000513 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
514 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000515 break;
516
cerionf0de28c2005-12-13 20:21:11 +0000517 case VexArchPPC64:
sewardj9e1cf152012-04-20 02:18:31 +0000518 preciseMemExnsFn = guest_ppc64_state_requires_precise_mem_exns;
519 disInstrFn = disInstr_PPC;
520 specHelper = guest_ppc64_spechelper;
521 guest_sizeB = sizeof(VexGuestPPC64State);
522 guest_word_type = Ity_I64;
523 guest_layout = &ppc64Guest_layout;
524 offB_TISTART = offsetof(VexGuestPPC64State,guest_TISTART);
525 offB_TILEN = offsetof(VexGuestPPC64State,guest_TILEN);
526 offB_GUEST_IP = offsetof(VexGuestPPC64State,guest_CIA);
527 szB_GUEST_IP = sizeof( ((VexGuestPPC64State*)0)->guest_CIA );
528 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC64State,host_EvC_COUNTER);
529 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC64State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000530 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_guest.hwcaps));
cerionf0de28c2005-12-13 20:21:11 +0000531 vassert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj3fd39672006-01-27 22:05:55 +0000532 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TISTART ) == 8);
533 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TILEN ) == 8);
534 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8);
535 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8);
cerionf0de28c2005-12-13 20:21:11 +0000536 break;
537
sewardj2019a972011-03-07 16:04:07 +0000538 case VexArchS390X:
539 preciseMemExnsFn = guest_s390x_state_requires_precise_mem_exns;
540 disInstrFn = disInstr_S390;
541 specHelper = guest_s390x_spechelper;
542 guest_sizeB = sizeof(VexGuestS390XState);
543 guest_word_type = Ity_I64;
544 guest_layout = &s390xGuest_layout;
545 offB_TISTART = offsetof(VexGuestS390XState,guest_TISTART);
546 offB_TILEN = offsetof(VexGuestS390XState,guest_TILEN);
florian8844a632012-04-13 04:04:06 +0000547 offB_GUEST_IP = offsetof(VexGuestS390XState,guest_IA);
548 szB_GUEST_IP = sizeof( ((VexGuestS390XState*)0)->guest_IA);
549 offB_HOST_EvC_COUNTER = offsetof(VexGuestS390XState,host_EvC_COUNTER);
550 offB_HOST_EvC_FAILADDR = offsetof(VexGuestS390XState,host_EvC_FAILADDR);
sewardj2019a972011-03-07 16:04:07 +0000551 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_guest.hwcaps));
552 vassert(0 == sizeof(VexGuestS390XState) % 16);
553 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TISTART ) == 8);
554 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TILEN ) == 8);
555 vassert(sizeof( ((VexGuestS390XState*)0)->guest_NRADDR ) == 8);
556 break;
557
sewardj6c299f32009-12-31 18:00:12 +0000558 case VexArchARM:
sewardjc6f970f2012-04-02 21:54:49 +0000559 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
560 disInstrFn = disInstr_ARM;
561 specHelper = guest_arm_spechelper;
562 guest_sizeB = sizeof(VexGuestARMState);
563 guest_word_type = Ity_I32;
564 guest_layout = &armGuest_layout;
565 offB_TISTART = offsetof(VexGuestARMState,guest_TISTART);
566 offB_TILEN = offsetof(VexGuestARMState,guest_TILEN);
567 offB_GUEST_IP = offsetof(VexGuestARMState,guest_R15T);
568 szB_GUEST_IP = sizeof( ((VexGuestARMState*)0)->guest_R15T );
569 offB_HOST_EvC_COUNTER = offsetof(VexGuestARMState,host_EvC_COUNTER);
570 offB_HOST_EvC_FAILADDR = offsetof(VexGuestARMState,host_EvC_FAILADDR);
sewardj6c299f32009-12-31 18:00:12 +0000571 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_guest.hwcaps));
572 vassert(0 == sizeof(VexGuestARMState) % 16);
573 vassert(sizeof( ((VexGuestARMState*)0)->guest_TISTART) == 4);
574 vassert(sizeof( ((VexGuestARMState*)0)->guest_TILEN ) == 4);
575 vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4);
576 break;
577
sewardjd0e5fe72012-06-07 08:51:02 +0000578 case VexArchMIPS32:
579 preciseMemExnsFn = guest_mips32_state_requires_precise_mem_exns;
580 disInstrFn = disInstr_MIPS;
581 specHelper = guest_mips32_spechelper;
582 guest_sizeB = sizeof(VexGuestMIPS32State);
583 guest_word_type = Ity_I32;
584 guest_layout = &mips32Guest_layout;
585 offB_TISTART = offsetof(VexGuestMIPS32State,guest_TISTART);
586 offB_TILEN = offsetof(VexGuestMIPS32State,guest_TILEN);
587 offB_GUEST_IP = offsetof(VexGuestMIPS32State,guest_PC);
588 szB_GUEST_IP = sizeof( ((VexGuestMIPS32State*)0)->guest_PC );
589 offB_HOST_EvC_COUNTER = offsetof(VexGuestMIPS32State,host_EvC_COUNTER);
590 offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS32State,host_EvC_FAILADDR);
591 vassert(are_valid_hwcaps(VexArchMIPS32, vta->archinfo_guest.hwcaps));
592 vassert(0 == sizeof(VexGuestMIPS32State) % 16);
593 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_TISTART) == 4);
594 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_TILEN ) == 4);
595 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_NRADDR ) == 4);
596 break;
597
petarjb92a9542013-02-27 22:57:17 +0000598 case VexArchMIPS64:
599 preciseMemExnsFn = guest_mips64_state_requires_precise_mem_exns;
600 disInstrFn = disInstr_MIPS;
601 specHelper = guest_mips64_spechelper;
602 guest_sizeB = sizeof(VexGuestMIPS64State);
603 guest_word_type = Ity_I64;
604 guest_layout = &mips64Guest_layout;
605 offB_TISTART = offsetof(VexGuestMIPS64State,guest_TISTART);
606 offB_TILEN = offsetof(VexGuestMIPS64State,guest_TILEN);
607 offB_GUEST_IP = offsetof(VexGuestMIPS64State,guest_PC);
608 szB_GUEST_IP = sizeof( ((VexGuestMIPS64State*)0)->guest_PC );
609 offB_HOST_EvC_COUNTER = offsetof(VexGuestMIPS64State,host_EvC_COUNTER);
610 offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS64State,host_EvC_FAILADDR);
611 vassert(are_valid_hwcaps(VexArchMIPS64, vta->archinfo_guest.hwcaps));
612 vassert(0 == sizeof(VexGuestMIPS64State) % 16);
613 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_TISTART) == 8);
614 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_TILEN ) == 8);
615 vassert(sizeof( ((VexGuestMIPS64State*)0)->guest_NRADDR ) == 8);
616 break;
617
sewardjf13a16a2004-07-05 17:10:14 +0000618 default:
sewardj887a11a2004-07-05 17:26:47 +0000619 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000620 }
621
sewardjbc161a42011-06-07 21:28:38 +0000622 /* Set up result struct. */
623 VexTranslateResult res;
sewardjfadbbe22012-04-24 11:49:03 +0000624 res.status = VexTransOK;
625 res.n_sc_extents = 0;
626 res.offs_profInc = -1;
627 res.n_guest_instrs = 0;
sewardjbc161a42011-06-07 21:28:38 +0000628
sewardj9df271d2004-12-31 22:37:42 +0000629 /* yet more sanity checks ... */
sewardj17c7f952005-12-15 14:02:34 +0000630 if (vta->arch_guest == vta->arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000631 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000632 we are simulating one flavour of an architecture a different
633 flavour of the same architecture, which is pretty strange. */
sewardj5117ce12006-01-27 21:20:15 +0000634 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps);
sewardj9df271d2004-12-31 22:37:42 +0000635 }
sewardj2a9ad022004-11-25 02:46:58 +0000636
sewardj2d6b14a2005-11-23 04:25:07 +0000637 vexAllocSanityCheck();
638
sewardjf48ac192004-10-29 00:41:29 +0000639 if (vex_traceflags & VEX_TRACE_FE)
640 vex_printf("\n------------------------"
641 " Front end "
642 "------------------------\n\n");
643
sewardjdd40fdf2006-12-24 02:20:24 +0000644 irsb = bb_to_IR ( vta->guest_extents,
sewardjbc161a42011-06-07 21:28:38 +0000645 &res.n_sc_extents,
sewardjfadbbe22012-04-24 11:49:03 +0000646 &res.n_guest_instrs,
sewardjc716aea2006-01-17 01:48:46 +0000647 vta->callback_opaque,
sewardj9e6491a2005-07-02 19:24:10 +0000648 disInstrFn,
sewardj17c7f952005-12-15 14:02:34 +0000649 vta->guest_bytes,
650 vta->guest_bytes_addr,
651 vta->chase_into_ok,
sewardj9e6491a2005-07-02 19:24:10 +0000652 host_is_bigendian,
sewardj442e51a2012-12-06 18:08:04 +0000653 vta->sigill_diag,
sewardja5f55da2006-04-30 23:37:32 +0000654 vta->arch_guest,
sewardj17c7f952005-12-15 14:02:34 +0000655 &vta->archinfo_guest,
sewardjdd40fdf2006-12-24 02:20:24 +0000656 &vta->abiinfo_both,
sewardjdb4738a2005-07-07 01:32:16 +0000657 guest_word_type,
sewardjbc161a42011-06-07 21:28:38 +0000658 vta->needs_self_check,
sewardjc716aea2006-01-17 01:48:46 +0000659 vta->preamble_function,
sewardjdb4738a2005-07-07 01:32:16 +0000660 offB_TISTART,
sewardjc6f970f2012-04-02 21:54:49 +0000661 offB_TILEN,
662 offB_GUEST_IP,
663 szB_GUEST_IP );
sewardjf13a16a2004-07-05 17:10:14 +0000664
sewardj2d6b14a2005-11-23 04:25:07 +0000665 vexAllocSanityCheck();
666
sewardjdd40fdf2006-12-24 02:20:24 +0000667 if (irsb == NULL) {
sewardjf13a16a2004-07-05 17:10:14 +0000668 /* Access failure. */
sewardj2d6b14a2005-11-23 04:25:07 +0000669 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000670 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000671 res.status = VexTransAccessFail; return res;
sewardjf13a16a2004-07-05 17:10:14 +0000672 }
sewardjaa59f942004-10-09 09:34:36 +0000673
sewardj17c7f952005-12-15 14:02:34 +0000674 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3);
675 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr);
676 for (i = 0; i < vta->guest_extents->n_used; i++) {
677 vassert(vta->guest_extents->len[i] < 10000); /* sanity */
sewardj72c72812005-01-19 11:49:45 +0000678 }
679
sewardjaa59f942004-10-09 09:34:36 +0000680 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000681 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj17c7f952005-12-15 14:02:34 +0000682 if (vta->guest_extents->n_used > 1) {
sewardj72c72812005-01-19 11:49:45 +0000683 vex_printf("can't show code due to extents > 1\n");
684 } else {
685 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000686 UChar* p = (UChar*)vta->guest_bytes;
sewardj01f8cce2009-08-31 08:50:02 +0000687 UInt sum = 0;
sewardj17c7f952005-12-15 14:02:34 +0000688 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0];
sewardj01f8cce2009-08-31 08:50:02 +0000689 vex_printf("GuestBytes %llx %u ", vta->guest_bytes_addr,
690 guest_bytes_read );
691 for (i = 0; i < guest_bytes_read; i++) {
692 UInt b = (UInt)p[i];
693 vex_printf(" %02x", b );
694 sum = (sum << 1) ^ b;
695 }
696 vex_printf(" %08x\n\n", sum);
sewardj72c72812005-01-19 11:49:45 +0000697 }
sewardjaa59f942004-10-09 09:34:36 +0000698 }
699
700 /* Sanity check the initial IR. */
sewardjdd40fdf2006-12-24 02:20:24 +0000701 sanityCheckIRSB( irsb, "initial IR",
sewardjb9230752004-12-29 19:25:06 +0000702 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000703
sewardj2d6b14a2005-11-23 04:25:07 +0000704 vexAllocSanityCheck();
705
sewardjedf4d692004-08-17 13:52:58 +0000706 /* Clean it up, hopefully a lot. */
sewardjdd40fdf2006-12-24 02:20:24 +0000707 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn,
sewardjec0d9a02010-08-22 12:54:56 +0000708 vta->guest_bytes_addr,
709 vta->arch_guest );
sewardjdd40fdf2006-12-24 02:20:24 +0000710 sanityCheckIRSB( irsb, "after initial iropt",
sewardjb9230752004-12-29 19:25:06 +0000711 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000712
sewardjf48ac192004-10-29 00:41:29 +0000713 if (vex_traceflags & VEX_TRACE_OPT1) {
714 vex_printf("\n------------------------"
715 " After pre-instr IR optimisation "
716 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000717 ppIRSB ( irsb );
sewardjedf4d692004-08-17 13:52:58 +0000718 vex_printf("\n");
719 }
720
sewardj2d6b14a2005-11-23 04:25:07 +0000721 vexAllocSanityCheck();
722
sewardjf13a16a2004-07-05 17:10:14 +0000723 /* Get the thing instrumented. */
sewardj17c7f952005-12-15 14:02:34 +0000724 if (vta->instrument1)
sewardjdd40fdf2006-12-24 02:20:24 +0000725 irsb = vta->instrument1(vta->callback_opaque,
726 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000727 vta->guest_extents,
florian50481922012-10-07 21:58:07 +0000728 &vta->archinfo_host,
sewardj17c7f952005-12-15 14:02:34 +0000729 guest_word_type, host_word_type);
sewardj2d6b14a2005-11-23 04:25:07 +0000730 vexAllocSanityCheck();
731
sewardj17c7f952005-12-15 14:02:34 +0000732 if (vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000733 irsb = vta->instrument2(vta->callback_opaque,
734 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000735 vta->guest_extents,
florian50481922012-10-07 21:58:07 +0000736 &vta->archinfo_host,
sewardj17c7f952005-12-15 14:02:34 +0000737 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000738
sewardjf48ac192004-10-29 00:41:29 +0000739 if (vex_traceflags & VEX_TRACE_INST) {
740 vex_printf("\n------------------------"
741 " After instrumentation "
742 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000743 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000744 vex_printf("\n");
745 }
746
sewardj17c7f952005-12-15 14:02:34 +0000747 if (vta->instrument1 || vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000748 sanityCheckIRSB( irsb, "after instrumentation",
sewardjb9230752004-12-29 19:25:06 +0000749 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000750
sewardj9578a8b2004-11-04 19:44:48 +0000751 /* Do a post-instrumentation cleanup pass. */
sewardj17c7f952005-12-15 14:02:34 +0000752 if (vta->instrument1 || vta->instrument2) {
sewardjdd40fdf2006-12-24 02:20:24 +0000753 do_deadcode_BB( irsb );
754 irsb = cprop_BB( irsb );
755 do_deadcode_BB( irsb );
756 sanityCheckIRSB( irsb, "after post-instrumentation cleanup",
sewardjb9230752004-12-29 19:25:06 +0000757 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000758 }
759
sewardj2d6b14a2005-11-23 04:25:07 +0000760 vexAllocSanityCheck();
761
sewardj9578a8b2004-11-04 19:44:48 +0000762 if (vex_traceflags & VEX_TRACE_OPT2) {
763 vex_printf("\n------------------------"
764 " After post-instr IR optimisation "
765 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000766 ppIRSB ( irsb );
sewardj9578a8b2004-11-04 19:44:48 +0000767 vex_printf("\n");
768 }
769
sewardjf9517d02005-11-28 13:39:37 +0000770 /* Turn it into virtual-registerised code. Build trees -- this
771 also throws away any dead bindings. */
florian62140c12013-01-20 03:51:04 +0000772 max_ga = ado_treebuild_BB( irsb, preciseMemExnsFn );
sewardjf48ac192004-10-29 00:41:29 +0000773
sewardjbe1b6ff2007-08-28 06:06:27 +0000774 if (vta->finaltidy) {
775 irsb = vta->finaltidy(irsb);
776 }
777
sewardj2d6b14a2005-11-23 04:25:07 +0000778 vexAllocSanityCheck();
779
sewardjf48ac192004-10-29 00:41:29 +0000780 if (vex_traceflags & VEX_TRACE_TREES) {
781 vex_printf("\n------------------------"
782 " After tree-building "
783 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000784 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000785 vex_printf("\n");
786 }
787
sewardje908c422005-02-04 21:18:16 +0000788 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000789 if (0) {
790 *(vta->host_bytes_used) = 0;
791 res.status = VexTransOK; return res;
792 }
sewardje908c422005-02-04 21:18:16 +0000793 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000794
sewardjf48ac192004-10-29 00:41:29 +0000795 if (vex_traceflags & VEX_TRACE_VCODE)
796 vex_printf("\n------------------------"
797 " Instruction selection "
798 "------------------------\n");
799
sewardjc6f970f2012-04-02 21:54:49 +0000800 /* No guest has its IP field at offset zero. If this fails it
801 means some transformation pass somewhere failed to update/copy
802 irsb->offsIP properly. */
803 vassert(irsb->offsIP >= 16);
804
805 vcode = iselSB ( irsb, vta->arch_host,
806 &vta->archinfo_host,
807 &vta->abiinfo_both,
808 offB_HOST_EvC_COUNTER,
809 offB_HOST_EvC_FAILADDR,
810 chainingAllowed,
811 vta->addProfInc,
812 max_ga );
sewardjf13a16a2004-07-05 17:10:14 +0000813
sewardj2d6b14a2005-11-23 04:25:07 +0000814 vexAllocSanityCheck();
815
sewardjf48ac192004-10-29 00:41:29 +0000816 if (vex_traceflags & VEX_TRACE_VCODE)
817 vex_printf("\n");
818
sewardjf48ac192004-10-29 00:41:29 +0000819 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000820 for (i = 0; i < vcode->arr_used; i++) {
821 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000822 ppInstr(vcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000823 vex_printf("\n");
824 }
sewardjfbcaf332004-07-08 01:46:01 +0000825 vex_printf("\n");
826 }
sewardjfbcaf332004-07-08 01:46:01 +0000827
sewardjf13a16a2004-07-05 17:10:14 +0000828 /* Register allocate. */
829 rcode = doRegisterAllocation ( vcode, available_real_regs,
cerionf0de28c2005-12-13 20:21:11 +0000830 n_available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000831 isMove, getRegUsage, mapRegs,
sewardjfb7373a2007-08-25 21:29:03 +0000832 genSpill, genReload, directReload,
833 guest_sizeB,
cerion92b64362005-12-13 12:02:26 +0000834 ppInstr, ppReg, mode64 );
sewardjf13a16a2004-07-05 17:10:14 +0000835
sewardj2d6b14a2005-11-23 04:25:07 +0000836 vexAllocSanityCheck();
837
sewardjf48ac192004-10-29 00:41:29 +0000838 if (vex_traceflags & VEX_TRACE_RCODE) {
839 vex_printf("\n------------------------"
840 " Register-allocated code "
841 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000842 for (i = 0; i < rcode->arr_used; i++) {
843 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000844 ppInstr(rcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000845 vex_printf("\n");
846 }
sewardjfbcaf332004-07-08 01:46:01 +0000847 vex_printf("\n");
848 }
sewardjfbcaf332004-07-08 01:46:01 +0000849
sewardje908c422005-02-04 21:18:16 +0000850 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000851 if (0) {
852 *(vta->host_bytes_used) = 0;
853 res.status = VexTransOK; return res;
854 }
sewardje908c422005-02-04 21:18:16 +0000855 /* end HACK */
856
sewardj81bd5502004-07-21 18:49:27 +0000857 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000858 if (vex_traceflags & VEX_TRACE_ASM) {
859 vex_printf("\n------------------------"
860 " Assembly "
861 "------------------------\n\n");
862 }
863
sewardj81bd5502004-07-21 18:49:27 +0000864 out_used = 0; /* tracks along the host_bytes array */
865 for (i = 0; i < rcode->arr_used; i++) {
sewardjc6f970f2012-04-02 21:54:49 +0000866 HInstr* hi = rcode->arr[i];
867 Bool hi_isProfInc = False;
868 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
869 ppInstr(hi, mode64);
sewardjbad34a92004-07-22 01:14:11 +0000870 vex_printf("\n");
871 }
sewardjc6f970f2012-04-02 21:54:49 +0000872 j = emit( &hi_isProfInc,
873 insn_bytes, sizeof insn_bytes, hi, mode64,
874 vta->disp_cp_chain_me_to_slowEP,
875 vta->disp_cp_chain_me_to_fastEP,
876 vta->disp_cp_xindir,
877 vta->disp_cp_xassisted );
878 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
sewardjbad34a92004-07-22 01:14:11 +0000879 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000880 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000881 vex_printf("0%x ", (UInt)insn_bytes[k]);
882 else
883 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000884 vex_printf("\n\n");
885 }
sewardjc6f970f2012-04-02 21:54:49 +0000886 if (UNLIKELY(out_used + j > vta->host_bytes_size)) {
sewardj2d6b14a2005-11-23 04:25:07 +0000887 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000888 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000889 res.status = VexTransOutputFull;
890 return res;
sewardj81bd5502004-07-21 18:49:27 +0000891 }
sewardjc6f970f2012-04-02 21:54:49 +0000892 if (UNLIKELY(hi_isProfInc)) {
893 vassert(vta->addProfInc); /* else where did it come from? */
894 vassert(res.offs_profInc == -1); /* there can be only one (tm) */
895 vassert(out_used >= 0);
896 res.offs_profInc = out_used;
897 }
898 { UChar* dst = &vta->host_bytes[out_used];
899 for (k = 0; k < j; k++) {
900 dst[k] = insn_bytes[k];
901 }
902 out_used += j;
sewardj81bd5502004-07-21 18:49:27 +0000903 }
sewardj17c7f952005-12-15 14:02:34 +0000904 vassert(out_used <= vta->host_bytes_size);
sewardj81bd5502004-07-21 18:49:27 +0000905 }
sewardj17c7f952005-12-15 14:02:34 +0000906 *(vta->host_bytes_used) = out_used;
sewardj81bd5502004-07-21 18:49:27 +0000907
sewardj2d6b14a2005-11-23 04:25:07 +0000908 vexAllocSanityCheck();
909
910 vexSetAllocModeTEMP_and_clear();
sewardjf13a16a2004-07-05 17:10:14 +0000911
sewardj65ea17e2012-12-28 09:01:59 +0000912 if (vex_traceflags) {
913 /* Print the expansion ratio for this SB. */
914 j = 0; /* total guest bytes */
915 for (i = 0; i < vta->guest_extents->n_used; i++) {
916 j += vta->guest_extents->len[i];
917 }
918 if (1) vex_printf("VexExpansionRatio %d %d %d :10\n\n",
919 j, out_used, (10 * out_used) / (j == 0 ? 1 : j));
920 }
921
sewardjf48ac192004-10-29 00:41:29 +0000922 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000923 res.status = VexTransOK;
924 return res;
sewardj35421a32004-07-05 13:12:34 +0000925}
926
927
sewardjc6f970f2012-04-02 21:54:49 +0000928/* --------- Chain/Unchain XDirects. --------- */
929
930VexInvalRange LibVEX_Chain ( VexArch arch_host,
931 void* place_to_chain,
932 void* disp_cp_chain_me_EXPECTED,
933 void* place_to_jump_to )
934{
935 VexInvalRange (*chainXDirect)(void*, void*, void*) = NULL;
936 switch (arch_host) {
937 case VexArchX86:
938 chainXDirect = chainXDirect_X86; break;
939 case VexArchAMD64:
940 chainXDirect = chainXDirect_AMD64; break;
941 case VexArchARM:
942 chainXDirect = chainXDirect_ARM; break;
florian8844a632012-04-13 04:04:06 +0000943 case VexArchS390X:
944 chainXDirect = chainXDirect_S390; break;
sewardj3dee8492012-04-20 00:13:28 +0000945 case VexArchPPC32:
946 return chainXDirect_PPC(place_to_chain,
947 disp_cp_chain_me_EXPECTED,
948 place_to_jump_to, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +0000949 case VexArchPPC64:
950 return chainXDirect_PPC(place_to_chain,
951 disp_cp_chain_me_EXPECTED,
952 place_to_jump_to, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +0000953 case VexArchMIPS32:
954 return chainXDirect_MIPS(place_to_chain,
955 disp_cp_chain_me_EXPECTED,
956 place_to_jump_to, False/*!mode64*/);
petarjb92a9542013-02-27 22:57:17 +0000957 case VexArchMIPS64:
958 return chainXDirect_MIPS(place_to_chain,
959 disp_cp_chain_me_EXPECTED,
960 place_to_jump_to, True/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +0000961 default:
962 vassert(0);
963 }
964 vassert(chainXDirect);
965 VexInvalRange vir
966 = chainXDirect(place_to_chain, disp_cp_chain_me_EXPECTED,
967 place_to_jump_to);
968 return vir;
969}
970
971VexInvalRange LibVEX_UnChain ( VexArch arch_host,
972 void* place_to_unchain,
973 void* place_to_jump_to_EXPECTED,
974 void* disp_cp_chain_me )
975{
976 VexInvalRange (*unchainXDirect)(void*, void*, void*) = NULL;
977 switch (arch_host) {
978 case VexArchX86:
979 unchainXDirect = unchainXDirect_X86; break;
980 case VexArchAMD64:
981 unchainXDirect = unchainXDirect_AMD64; break;
982 case VexArchARM:
983 unchainXDirect = unchainXDirect_ARM; break;
florian8844a632012-04-13 04:04:06 +0000984 case VexArchS390X:
985 unchainXDirect = unchainXDirect_S390; break;
sewardj3dee8492012-04-20 00:13:28 +0000986 case VexArchPPC32:
987 return unchainXDirect_PPC(place_to_unchain,
988 place_to_jump_to_EXPECTED,
989 disp_cp_chain_me, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +0000990 case VexArchPPC64:
991 return unchainXDirect_PPC(place_to_unchain,
992 place_to_jump_to_EXPECTED,
993 disp_cp_chain_me, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +0000994 case VexArchMIPS32:
995 return unchainXDirect_MIPS(place_to_unchain,
petarjb92a9542013-02-27 22:57:17 +0000996 place_to_jump_to_EXPECTED,
997 disp_cp_chain_me, False/*!mode64*/);
998 case VexArchMIPS64:
999 return unchainXDirect_MIPS(place_to_unchain,
1000 place_to_jump_to_EXPECTED,
1001 disp_cp_chain_me, True/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +00001002 default:
1003 vassert(0);
1004 }
1005 vassert(unchainXDirect);
1006 VexInvalRange vir
1007 = unchainXDirect(place_to_unchain, place_to_jump_to_EXPECTED,
1008 disp_cp_chain_me);
1009 return vir;
1010}
1011
1012Int LibVEX_evCheckSzB ( VexArch arch_host )
1013{
1014 static Int cached = 0; /* DO NOT MAKE NON-STATIC */
1015 if (UNLIKELY(cached == 0)) {
1016 switch (arch_host) {
1017 case VexArchX86:
1018 cached = evCheckSzB_X86(); break;
1019 case VexArchAMD64:
1020 cached = evCheckSzB_AMD64(); break;
1021 case VexArchARM:
1022 cached = evCheckSzB_ARM(); break;
florian8844a632012-04-13 04:04:06 +00001023 case VexArchS390X:
1024 cached = evCheckSzB_S390(); break;
sewardj3dee8492012-04-20 00:13:28 +00001025 case VexArchPPC32:
sewardjf252de52012-04-20 10:42:24 +00001026 case VexArchPPC64:
sewardj3dee8492012-04-20 00:13:28 +00001027 cached = evCheckSzB_PPC(); break;
sewardjd0e5fe72012-06-07 08:51:02 +00001028 case VexArchMIPS32:
petarjb92a9542013-02-27 22:57:17 +00001029 case VexArchMIPS64:
sewardjd0e5fe72012-06-07 08:51:02 +00001030 cached = evCheckSzB_MIPS(); break;
sewardjc6f970f2012-04-02 21:54:49 +00001031 default:
1032 vassert(0);
1033 }
1034 }
1035 return cached;
1036}
1037
1038VexInvalRange LibVEX_PatchProfInc ( VexArch arch_host,
1039 void* place_to_patch,
1040 ULong* location_of_counter )
1041{
1042 VexInvalRange (*patchProfInc)(void*,ULong*) = NULL;
1043 switch (arch_host) {
1044 case VexArchX86:
1045 patchProfInc = patchProfInc_X86; break;
1046 case VexArchAMD64:
1047 patchProfInc = patchProfInc_AMD64; break;
1048 case VexArchARM:
1049 patchProfInc = patchProfInc_ARM; break;
florian8844a632012-04-13 04:04:06 +00001050 case VexArchS390X:
1051 patchProfInc = patchProfInc_S390; break;
sewardj3dee8492012-04-20 00:13:28 +00001052 case VexArchPPC32:
1053 return patchProfInc_PPC(place_to_patch,
1054 location_of_counter, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +00001055 case VexArchPPC64:
1056 return patchProfInc_PPC(place_to_patch,
1057 location_of_counter, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +00001058 case VexArchMIPS32:
1059 return patchProfInc_MIPS(place_to_patch,
1060 location_of_counter, False/*!mode64*/);
petarjb92a9542013-02-27 22:57:17 +00001061 case VexArchMIPS64:
1062 return patchProfInc_MIPS(place_to_patch,
1063 location_of_counter, True/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +00001064 default:
1065 vassert(0);
1066 }
1067 vassert(patchProfInc);
1068 VexInvalRange vir
1069 = patchProfInc(place_to_patch, location_of_counter);
1070 return vir;
1071}
1072
1073
sewardj893aada2004-11-29 19:57:54 +00001074/* --------- Emulation warnings. --------- */
1075
florian1ff47562012-10-21 02:09:51 +00001076const HChar* LibVEX_EmNote_string ( VexEmNote ew )
sewardj893aada2004-11-29 19:57:54 +00001077{
1078 switch (ew) {
florian6ef84be2012-08-26 03:20:07 +00001079 case EmNote_NONE:
sewardj893aada2004-11-29 19:57:54 +00001080 return "none";
1081 case EmWarn_X86_x87exns:
1082 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +00001083 case EmWarn_X86_x87precision:
1084 return "Selection of non-80-bit x87 FP precision";
1085 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +00001086 return "Unmasking SSE FP exceptions";
1087 case EmWarn_X86_fz:
1088 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
1089 case EmWarn_X86_daz:
1090 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +00001091 case EmWarn_X86_acFlag:
1092 return "Setting %eflags.ac (setting noted but ignored)";
sewardj9dd9cf12006-01-20 14:13:55 +00001093 case EmWarn_PPCexns:
1094 return "Unmasking PPC32/64 FP exceptions";
1095 case EmWarn_PPC64_redir_overflow:
1096 return "PPC64 function redirection stack overflow";
1097 case EmWarn_PPC64_redir_underflow:
1098 return "PPC64 function redirection stack underflow";
florian4b8efad2012-09-02 18:07:08 +00001099 case EmWarn_S390X_fpext_rounding:
1100 return "The specified rounding mode cannot be supported. That\n"
1101 " feature requires the floating point extension facility.\n"
1102 " which is not available on this host. Continuing using\n"
1103 " the rounding mode from FPC. Results may differ!";
florianf0fa1be2012-09-18 20:24:38 +00001104 case EmWarn_S390X_invalid_rounding:
1105 return "The specified rounding mode is invalid.\n"
1106 " Continuing using 'round to nearest'. Results may differ!";
floriane75dafa2012-09-01 17:54:09 +00001107 case EmFail_S390X_stfle:
florian4e0083e2012-08-26 03:41:56 +00001108 return "Instruction stfle is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001109 case EmFail_S390X_stckf:
florianc5c669b2012-08-26 14:32:28 +00001110 return "Instruction stckf is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001111 case EmFail_S390X_ecag:
florian8c88cb62012-08-26 18:58:13 +00001112 return "Instruction ecag is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001113 case EmFail_S390X_fpext:
1114 return "Encountered an instruction that requires the floating "
1115 "point extension facility.\n"
1116 " That facility is not available on this host";
sewardj893aada2004-11-29 19:57:54 +00001117 default:
florian6ef84be2012-08-26 03:20:07 +00001118 vpanic("LibVEX_EmNote_string: unknown warning");
sewardj893aada2004-11-29 19:57:54 +00001119 }
1120}
sewardj35421a32004-07-05 13:12:34 +00001121
sewardj5117ce12006-01-27 21:20:15 +00001122/* ------------------ Arch/HwCaps stuff. ------------------ */
sewardjbef170b2004-12-21 01:23:00 +00001123
1124const HChar* LibVEX_ppVexArch ( VexArch arch )
1125{
1126 switch (arch) {
1127 case VexArch_INVALID: return "INVALID";
1128 case VexArchX86: return "X86";
1129 case VexArchAMD64: return "AMD64";
1130 case VexArchARM: return "ARM";
sewardj0ec57c52005-02-01 15:24:10 +00001131 case VexArchPPC32: return "PPC32";
cerionf0de28c2005-12-13 20:21:11 +00001132 case VexArchPPC64: return "PPC64";
sewardj2019a972011-03-07 16:04:07 +00001133 case VexArchS390X: return "S390X";
sewardjd0e5fe72012-06-07 08:51:02 +00001134 case VexArchMIPS32: return "MIPS32";
petarjb92a9542013-02-27 22:57:17 +00001135 case VexArchMIPS64: return "MIPS64";
sewardjbef170b2004-12-21 01:23:00 +00001136 default: return "VexArch???";
1137 }
1138}
1139
sewardj5117ce12006-01-27 21:20:15 +00001140const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
sewardjbef170b2004-12-21 01:23:00 +00001141{
florian55085f82012-11-21 00:36:55 +00001142 const HChar* str = show_hwcaps(arch,hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001143 return str ? str : "INVALID";
sewardjbef170b2004-12-21 01:23:00 +00001144}
1145
sewardj5117ce12006-01-27 21:20:15 +00001146
sewardj27e1dd62005-06-30 11:49:14 +00001147/* Write default settings info *vai. */
1148void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
1149{
sewardj5117ce12006-01-27 21:20:15 +00001150 vai->hwcaps = 0;
cerion5b2325f2005-12-23 00:55:09 +00001151 vai->ppc_cache_line_szB = 0;
sewardje971c6a2010-09-03 15:49:57 +00001152 vai->ppc_dcbz_szB = 0;
1153 vai->ppc_dcbzl_szB = 0;
1154
florianf192a392012-10-07 19:44:40 +00001155 vai->hwcache_info.num_levels = 0;
1156 vai->hwcache_info.num_caches = 0;
1157 vai->hwcache_info.caches = NULL;
1158 vai->hwcache_info.icaches_maintain_coherence = True; // whatever
sewardj27e1dd62005-06-30 11:49:14 +00001159}
1160
sewardjdd40fdf2006-12-24 02:20:24 +00001161/* Write default settings info *vbi. */
1162void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
sewardjaca070a2006-10-17 00:28:22 +00001163{
sewardjdd40fdf2006-12-24 02:20:24 +00001164 vbi->guest_stack_redzone_size = 0;
sewardj2e28ac42008-12-04 00:05:12 +00001165 vbi->guest_amd64_assume_fs_is_zero = False;
1166 vbi->guest_amd64_assume_gs_is_0x60 = False;
sewardjdd40fdf2006-12-24 02:20:24 +00001167 vbi->guest_ppc_zap_RZ_at_blr = False;
1168 vbi->guest_ppc_zap_RZ_at_bl = NULL;
1169 vbi->guest_ppc_sc_continues_at_LR = False;
1170 vbi->host_ppc_calls_use_fndescrs = False;
1171 vbi->host_ppc32_regalign_int64_args = False;
sewardjaca070a2006-10-17 00:28:22 +00001172}
1173
sewardj27e1dd62005-06-30 11:49:14 +00001174
sewardj5117ce12006-01-27 21:20:15 +00001175/* Return a string showing the hwcaps in a nice way. The string will
1176 be NULL for invalid combinations of flags, so these functions also
1177 serve as a way to validate hwcaps values. */
1178
florian55085f82012-11-21 00:36:55 +00001179static const HChar* show_hwcaps_x86 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001180{
1181 /* Monotonic, SSE3 > SSE2 > SSE1 > baseline. */
sewardj536fbab2010-07-29 15:39:05 +00001182 switch (hwcaps) {
1183 case 0:
1184 return "x86-sse0";
1185 case VEX_HWCAPS_X86_SSE1:
1186 return "x86-sse1";
1187 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2:
1188 return "x86-sse1-sse2";
1189 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
1190 | VEX_HWCAPS_X86_LZCNT:
1191 return "x86-sse1-sse2-lzcnt";
1192 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
1193 | VEX_HWCAPS_X86_SSE3:
1194 return "x86-sse1-sse2-sse3";
1195 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
1196 | VEX_HWCAPS_X86_SSE3 | VEX_HWCAPS_X86_LZCNT:
1197 return "x86-sse1-sse2-sse3-lzcnt";
1198 default:
1199 return NULL;
1200 }
sewardj5117ce12006-01-27 21:20:15 +00001201}
1202
florian55085f82012-11-21 00:36:55 +00001203static const HChar* show_hwcaps_amd64 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001204{
sewardje9d8a262009-07-01 08:06:34 +00001205 /* SSE3 and CX16 are orthogonal and > baseline, although we really
1206 don't expect to come across anything which can do SSE3 but can't
sewardj536fbab2010-07-29 15:39:05 +00001207 do CX16. Still, we can handle that case. LZCNT is similarly
sewardj818c7302013-03-26 13:53:18 +00001208 orthogonal. */
1209
1210 /* Throw out obviously stupid cases: */
1211 /* AVX without SSE3 */
1212 Bool have_sse3 = (hwcaps & VEX_HWCAPS_AMD64_SSE3) != 0;
1213 Bool have_avx = (hwcaps & VEX_HWCAPS_AMD64_AVX) != 0;
1214 if (have_avx && !have_sse3)
1215 return NULL;
1216
1217 /* This isn't threadsafe. We might need to fix it at some point. */
1218 static HChar buf[100] = { 0 };
1219 if (buf[0] != 0) return buf; /* already constructed */
1220
1221 vex_bzero(buf, sizeof(buf));
1222
1223 HChar* p = &buf[0];
1224
1225 p = p + vex_sprintf(p, "%s", "amd64");
1226 if (hwcaps == 0) {
1227 /* special-case the baseline case */
1228 p = p + vex_sprintf(p, "%s", "-sse2");
1229 goto out;
sewardj536fbab2010-07-29 15:39:05 +00001230 }
sewardj818c7302013-03-26 13:53:18 +00001231 if (hwcaps & VEX_HWCAPS_AMD64_CX16) {
1232 p = p + vex_sprintf(p, "%s", "-cx16");
1233 }
1234 if (hwcaps & VEX_HWCAPS_AMD64_LZCNT) {
1235 p = p + vex_sprintf(p, "%s", "-lzcnt");
1236 }
1237 if (hwcaps & VEX_HWCAPS_AMD64_RDTSCP) {
1238 p = p + vex_sprintf(p, "%s", "-rdtscp");
1239 }
1240 if (hwcaps & VEX_HWCAPS_AMD64_SSE3) {
1241 p = p + vex_sprintf(p, "%s", "-sse3");
1242 }
1243 if (hwcaps & VEX_HWCAPS_AMD64_AVX) {
1244 p = p + vex_sprintf(p, "%s", "-avx");
1245 }
1246
1247 out:
1248 vassert(buf[sizeof(buf)-1] == 0);
1249 return buf;
sewardj5117ce12006-01-27 21:20:15 +00001250}
1251
florian55085f82012-11-21 00:36:55 +00001252static const HChar* show_hwcaps_ppc32 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001253{
1254 /* Monotonic with complications. Basically V > F > baseline,
1255 but once you have F then you can have FX or GX too. */
1256 const UInt F = VEX_HWCAPS_PPC32_F;
1257 const UInt V = VEX_HWCAPS_PPC32_V;
1258 const UInt FX = VEX_HWCAPS_PPC32_FX;
1259 const UInt GX = VEX_HWCAPS_PPC32_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001260 const UInt VX = VEX_HWCAPS_PPC32_VX;
sewardjc66d6fa2012-04-02 21:24:12 +00001261 const UInt DFP = VEX_HWCAPS_PPC32_DFP;
sewardj5117ce12006-01-27 21:20:15 +00001262 UInt c = hwcaps;
1263 if (c == 0) return "ppc32-int";
1264 if (c == F) return "ppc32-int-flt";
1265 if (c == (F|FX)) return "ppc32-int-flt-FX";
1266 if (c == (F|GX)) return "ppc32-int-flt-GX";
1267 if (c == (F|FX|GX)) return "ppc32-int-flt-FX-GX";
1268 if (c == (F|V)) return "ppc32-int-flt-vmx";
1269 if (c == (F|V|FX)) return "ppc32-int-flt-vmx-FX";
1270 if (c == (F|V|GX)) return "ppc32-int-flt-vmx-GX";
1271 if (c == (F|V|FX|GX)) return "ppc32-int-flt-vmx-FX-GX";
sewardjc66d6fa2012-04-02 21:24:12 +00001272 if (c == (F|V|FX|GX|DFP)) return "ppc32-int-flt-vmx-FX-GX-DFP";
1273 if (c == (F|V|FX|GX|VX|DFP)) return "ppc32-int-flt-vmx-FX-GX-VX-DFP";
sewardj5117ce12006-01-27 21:20:15 +00001274 return NULL;
1275}
1276
florian55085f82012-11-21 00:36:55 +00001277static const HChar* show_hwcaps_ppc64 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001278{
1279 /* Monotonic with complications. Basically V > baseline(==F),
1280 but once you have F then you can have FX or GX too. */
sewardj3fd39672006-01-27 22:05:55 +00001281 const UInt V = VEX_HWCAPS_PPC64_V;
1282 const UInt FX = VEX_HWCAPS_PPC64_FX;
1283 const UInt GX = VEX_HWCAPS_PPC64_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001284 const UInt VX = VEX_HWCAPS_PPC64_VX;
sewardjc66d6fa2012-04-02 21:24:12 +00001285 const UInt DFP = VEX_HWCAPS_PPC64_DFP;
sewardj5117ce12006-01-27 21:20:15 +00001286 UInt c = hwcaps;
1287 if (c == 0) return "ppc64-int-flt";
1288 if (c == FX) return "ppc64-int-flt-FX";
1289 if (c == GX) return "ppc64-int-flt-GX";
1290 if (c == (FX|GX)) return "ppc64-int-flt-FX-GX";
1291 if (c == V) return "ppc64-int-flt-vmx";
1292 if (c == (V|FX)) return "ppc64-int-flt-vmx-FX";
1293 if (c == (V|GX)) return "ppc64-int-flt-vmx-GX";
1294 if (c == (V|FX|GX)) return "ppc64-int-flt-vmx-FX-GX";
sewardjc66d6fa2012-04-02 21:24:12 +00001295 if (c == (V|FX|GX|DFP)) return "ppc64-int-flt-vmx-FX-GX-DFP";
1296 if (c == (V|FX|GX|VX|DFP)) return "ppc64-int-flt-vmx-FX-GX-VX-DFP";
sewardj5117ce12006-01-27 21:20:15 +00001297 return NULL;
1298}
1299
florian55085f82012-11-21 00:36:55 +00001300static const HChar* show_hwcaps_arm ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001301{
sewardjec0d9a02010-08-22 12:54:56 +00001302 Bool N = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0);
1303 Bool vfp = ((hwcaps & (VEX_HWCAPS_ARM_VFP |
1304 VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3)) != 0);
1305 switch (VEX_ARM_ARCHLEVEL(hwcaps)) {
1306 case 5:
1307 if (N)
1308 return NULL;
1309 if (vfp)
1310 return "ARMv5-vfp";
1311 else
1312 return "ARMv5";
1313 return NULL;
1314 case 6:
1315 if (N)
1316 return NULL;
1317 if (vfp)
1318 return "ARMv6-vfp";
1319 else
1320 return "ARMv6";
1321 return NULL;
1322 case 7:
1323 if (vfp) {
1324 if (N)
1325 return "ARMv7-vfp-neon";
1326 else
1327 return "ARMv7-vfp";
1328 } else {
1329 if (N)
1330 return "ARMv7-neon";
1331 else
1332 return "ARMv7";
1333 }
1334 default:
1335 return NULL;
1336 }
sewardj5117ce12006-01-27 21:20:15 +00001337 return NULL;
1338}
1339
florian55085f82012-11-21 00:36:55 +00001340static const HChar* show_hwcaps_s390x ( UInt hwcaps )
sewardj2019a972011-03-07 16:04:07 +00001341{
sewardjd07b8562011-04-27 11:58:22 +00001342 static const HChar prefix[] = "s390x";
florian9061eb32012-12-09 17:53:45 +00001343 static const struct {
1344 UInt hwcaps_bit;
1345 HChar name[6];
1346 } hwcaps_list[] = {
1347 { VEX_HWCAPS_S390X_LDISP, "ldisp" },
1348 { VEX_HWCAPS_S390X_EIMM, "eimm" },
1349 { VEX_HWCAPS_S390X_GIE, "gie" },
1350 { VEX_HWCAPS_S390X_DFP, "dfp" },
1351 { VEX_HWCAPS_S390X_FGX, "fgx" },
1352 { VEX_HWCAPS_S390X_STFLE, "stfle" },
1353 { VEX_HWCAPS_S390X_ETF2, "etf2" },
1354 { VEX_HWCAPS_S390X_ETF3, "etf3" },
1355 { VEX_HWCAPS_S390X_STCKF, "stckf" },
1356 { VEX_HWCAPS_S390X_FPEXT, "fpext" },
1357 { VEX_HWCAPS_S390X_LSC, "lsc" },
sewardjd07b8562011-04-27 11:58:22 +00001358 };
florian9061eb32012-12-09 17:53:45 +00001359#define NUM_HWCAPS (sizeof hwcaps_list / sizeof hwcaps_list[0])
1360 static HChar buf[sizeof prefix +
1361 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) +
1362 1]; // '\0'
1363 HChar *p;
1364 UInt i;
sewardjd07b8562011-04-27 11:58:22 +00001365
1366 if (buf[0] != '\0') return buf; /* already constructed */
sewardj2019a972011-03-07 16:04:07 +00001367
sewardj652b56a2011-04-13 15:38:17 +00001368 hwcaps = VEX_HWCAPS_S390X(hwcaps);
1369
sewardjd07b8562011-04-27 11:58:22 +00001370 p = buf + vex_sprintf(buf, "%s", prefix);
florian9061eb32012-12-09 17:53:45 +00001371 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1372 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1373 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1374 }
sewardj2019a972011-03-07 16:04:07 +00001375
sewardjd07b8562011-04-27 11:58:22 +00001376 /* If there are no facilities, add "zarch" */
1377 if (hwcaps == 0)
1378 vex_sprintf(p, "-%s", "zarch");
1379
1380 return buf;
sewardj2019a972011-03-07 16:04:07 +00001381}
1382
florian55085f82012-11-21 00:36:55 +00001383static const HChar* show_hwcaps_mips32 ( UInt hwcaps )
sewardjd0e5fe72012-06-07 08:51:02 +00001384{
1385 if (hwcaps == 0x00010000) return "MIPS-baseline";
1386 if (hwcaps == 0x00020000) return "Broadcom-baseline";
1387 return NULL;
1388}
1389
petarjb92a9542013-02-27 22:57:17 +00001390static const HChar* show_hwcaps_mips64 ( UInt hwcaps )
1391{
1392 return "mips64-baseline";
1393}
1394
sewardj5117ce12006-01-27 21:20:15 +00001395/* ---- */
florian55085f82012-11-21 00:36:55 +00001396static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001397{
1398 switch (arch) {
sewardjd0e5fe72012-06-07 08:51:02 +00001399 case VexArchX86: return show_hwcaps_x86(hwcaps);
1400 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
1401 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
1402 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
1403 case VexArchARM: return show_hwcaps_arm(hwcaps);
1404 case VexArchS390X: return show_hwcaps_s390x(hwcaps);
1405 case VexArchMIPS32: return show_hwcaps_mips32(hwcaps);
petarjb92a9542013-02-27 22:57:17 +00001406 case VexArchMIPS64: return show_hwcaps_mips64(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001407 default: return NULL;
1408 }
1409}
1410
1411static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps )
1412{
1413 return show_hwcaps(arch,hwcaps) != NULL;
1414}
1415
1416
sewardj35421a32004-07-05 13:12:34 +00001417/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +00001418/*--- end main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +00001419/*---------------------------------------------------------------*/