blob: baa573a0558092ee17eb9d91e0d6ee8a056e2ebf [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"
sewardjf13a16a2004-07-05 17:10:14 +000045
sewardjcef7d3e2009-07-02 12:21:59 +000046#include "main_globals.h"
47#include "main_util.h"
48#include "host_generic_regs.h"
49#include "ir_opt.h"
sewardj35421a32004-07-05 13:12:34 +000050
sewardjcef7d3e2009-07-02 12:21:59 +000051#include "host_x86_defs.h"
52#include "host_amd64_defs.h"
53#include "host_ppc_defs.h"
sewardj6c299f32009-12-31 18:00:12 +000054#include "host_arm_defs.h"
sewardj2019a972011-03-07 16:04:07 +000055#include "host_s390_defs.h"
sewardjd0e5fe72012-06-07 08:51:02 +000056#include "host_mips_defs.h"
sewardj2a9ad022004-11-25 02:46:58 +000057
sewardjcef7d3e2009-07-02 12:21:59 +000058#include "guest_generic_bb_to_IR.h"
59#include "guest_x86_defs.h"
60#include "guest_amd64_defs.h"
61#include "guest_arm_defs.h"
62#include "guest_ppc_defs.h"
sewardj2019a972011-03-07 16:04:07 +000063#include "guest_s390_defs.h"
sewardjd0e5fe72012-06-07 08:51:02 +000064#include "guest_mips_defs.h"
sewardj2a9ad022004-11-25 02:46:58 +000065
sewardj69d98e32010-06-18 08:17:41 +000066#include "host_generic_simd128.h"
67
sewardj35421a32004-07-05 13:12:34 +000068
69/* This file contains the top level interface to the library. */
70
sewardj5117ce12006-01-27 21:20:15 +000071/* --------- fwds ... --------- */
72
73static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps );
florian55085f82012-11-21 00:36:55 +000074static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps );
sewardj5117ce12006-01-27 21:20:15 +000075
76
sewardj35421a32004-07-05 13:12:34 +000077/* --------- Initialise the library. --------- */
78
79/* Exported to library client. */
80
sewardj08613742004-10-25 13:01:45 +000081void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon )
82{
83 vcon->iropt_verbosity = 0;
84 vcon->iropt_level = 2;
philippec8e2f982012-08-01 22:04:13 +000085 vcon->iropt_register_updates = VexRegUpdUnwindregsAtMemAccess;
sewardj08613742004-10-25 13:01:45 +000086 vcon->iropt_unroll_thresh = 120;
sewardj18b4bb72005-03-29 21:32:41 +000087 vcon->guest_max_insns = 60;
sewardj08613742004-10-25 13:01:45 +000088 vcon->guest_chase_thresh = 10;
sewardj984d9b12010-01-15 10:53:21 +000089 vcon->guest_chase_cond = False;
sewardj08613742004-10-25 13:01:45 +000090}
91
92
93/* Exported to library client. */
94
sewardj887a11a2004-07-05 17:26:47 +000095void LibVEX_Init (
sewardj35421a32004-07-05 13:12:34 +000096 /* failure exit function */
sewardj2b515872004-07-05 20:50:45 +000097 __attribute__ ((noreturn))
sewardj35421a32004-07-05 13:12:34 +000098 void (*failure_exit) ( void ),
99 /* logging output function */
sewardjd9763622005-02-07 03:12:19 +0000100 void (*log_bytes) ( HChar*, Int nbytes ),
sewardj35421a32004-07-05 13:12:34 +0000101 /* debug paranoia level */
102 Int debuglevel,
sewardj35421a32004-07-05 13:12:34 +0000103 /* Are we supporting valgrind checking? */
104 Bool valgrind_support,
sewardj08613742004-10-25 13:01:45 +0000105 /* Control ... */
106 /*READONLY*/VexControl* vcon
sewardj35421a32004-07-05 13:12:34 +0000107)
108{
sewardj08613742004-10-25 13:01:45 +0000109 /* First off, do enough minimal setup so that the following
110 assertions can fail in a sane fashion, if need be. */
sewardjea602bc2004-10-14 21:40:12 +0000111 vex_failure_exit = failure_exit;
112 vex_log_bytes = log_bytes;
113
114 /* Now it's safe to check parameters for sanity. */
sewardj35421a32004-07-05 13:12:34 +0000115 vassert(!vex_initdone);
116 vassert(failure_exit);
sewardj35421a32004-07-05 13:12:34 +0000117 vassert(log_bytes);
sewardj35421a32004-07-05 13:12:34 +0000118 vassert(debuglevel >= 0);
sewardj08613742004-10-25 13:01:45 +0000119
120 vassert(vcon->iropt_verbosity >= 0);
121 vassert(vcon->iropt_level >= 0);
122 vassert(vcon->iropt_level <= 2);
123 vassert(vcon->iropt_unroll_thresh >= 0);
124 vassert(vcon->iropt_unroll_thresh <= 400);
125 vassert(vcon->guest_max_insns >= 1);
126 vassert(vcon->guest_max_insns <= 100);
127 vassert(vcon->guest_chase_thresh >= 0);
128 vassert(vcon->guest_chase_thresh < vcon->guest_max_insns);
sewardj984d9b12010-01-15 10:53:21 +0000129 vassert(vcon->guest_chase_cond == True
130 || vcon->guest_chase_cond == False);
sewardj443cd9d2004-07-18 23:06:45 +0000131
sewardjea602bc2004-10-14 21:40:12 +0000132 /* Check that Vex has been built with sizes of basic types as
133 stated in priv/libvex_basictypes.h. Failure of any of these is
134 a serious configuration error and should be corrected
135 immediately. If any of these assertions fail you can fully
136 expect Vex not to work properly, if at all. */
137
138 vassert(1 == sizeof(UChar));
139 vassert(1 == sizeof(Char));
140 vassert(2 == sizeof(UShort));
141 vassert(2 == sizeof(Short));
142 vassert(4 == sizeof(UInt));
143 vassert(4 == sizeof(Int));
144 vassert(8 == sizeof(ULong));
145 vassert(8 == sizeof(Long));
146 vassert(4 == sizeof(Float));
147 vassert(8 == sizeof(Double));
148 vassert(1 == sizeof(Bool));
149 vassert(4 == sizeof(Addr32));
150 vassert(8 == sizeof(Addr64));
sewardjc9a43662004-11-30 18:51:59 +0000151 vassert(16 == sizeof(U128));
sewardj69d98e32010-06-18 08:17:41 +0000152 vassert(16 == sizeof(V128));
sewardjc9069f22012-06-01 16:09:50 +0000153 vassert(32 == sizeof(U256));
sewardjea602bc2004-10-14 21:40:12 +0000154
155 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
156 vassert(sizeof(void*) == sizeof(int*));
157 vassert(sizeof(void*) == sizeof(HWord));
158
sewardj97e87932005-02-07 00:00:50 +0000159 vassert(VEX_HOST_WORDSIZE == sizeof(void*));
160 vassert(VEX_HOST_WORDSIZE == sizeof(HWord));
161
sewardjc6f970f2012-04-02 21:54:49 +0000162 /* These take a lot of space, so make sure we don't have
163 any unnoticed size regressions. */
164 if (VEX_HOST_WORDSIZE == 4) {
florian420bfa92012-06-02 20:29:22 +0000165 vassert(sizeof(IRExpr) == 16);
sewardjc6f970f2012-04-02 21:54:49 +0000166 vassert(sizeof(IRStmt) == 20 /* x86 */
167 || sizeof(IRStmt) == 24 /* arm */);
168 } else {
florian420bfa92012-06-02 20:29:22 +0000169 vassert(sizeof(IRExpr) == 32);
floriand6f38b32012-05-31 15:46:18 +0000170 vassert(sizeof(IRStmt) == 32);
sewardjc6f970f2012-04-02 21:54:49 +0000171 }
172
sewardjea602bc2004-10-14 21:40:12 +0000173 /* Really start up .. */
sewardj443cd9d2004-07-18 23:06:45 +0000174 vex_debuglevel = debuglevel;
sewardj443cd9d2004-07-18 23:06:45 +0000175 vex_valgrind_support = valgrind_support;
sewardj08613742004-10-25 13:01:45 +0000176 vex_control = *vcon;
sewardj443cd9d2004-07-18 23:06:45 +0000177 vex_initdone = True;
sewardjd887b862005-01-17 18:34:34 +0000178 vexSetAllocMode ( VexAllocModeTEMP );
sewardj35421a32004-07-05 13:12:34 +0000179}
180
181
182/* --------- Make a translation. --------- */
183
184/* Exported to library client. */
185
sewardj17c7f952005-12-15 14:02:34 +0000186VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
sewardj35421a32004-07-05 13:12:34 +0000187{
sewardj81bd5502004-07-21 18:49:27 +0000188 /* This the bundle of functions we need to do the back-end stuff
189 (insn selection, reg-alloc, assembly) whilst being insulated
190 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +0000191 HReg* available_real_regs;
192 Int n_available_real_regs;
sewardjfb7373a2007-08-25 21:29:03 +0000193 Bool (*isMove) ( HInstr*, HReg*, HReg* );
194 void (*getRegUsage) ( HRegUsage*, HInstr*, Bool );
195 void (*mapRegs) ( HRegRemap*, HInstr*, Bool );
sewardj6c299f32009-12-31 18:00:12 +0000196 void (*genSpill) ( HInstr**, HInstr**, HReg, Int, Bool );
197 void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool );
sewardjfb7373a2007-08-25 21:29:03 +0000198 HInstr* (*directReload) ( HInstr*, HReg, Short );
199 void (*ppInstr) ( HInstr*, Bool );
200 void (*ppReg) ( HReg );
sewardjc6f970f2012-04-02 21:54:49 +0000201 HInstrArray* (*iselSB) ( IRSB*, VexArch, VexArchInfo*, VexAbiInfo*,
202 Int, Int, Bool, Bool, Addr64 );
203 Int (*emit) ( /*MB_MOD*/Bool*,
204 UChar*, Int, HInstr*, Bool,
205 void*, void*, void*, void* );
florian1ff47562012-10-21 02:09:51 +0000206 IRExpr* (*specHelper) ( const HChar*, IRExpr**, IRStmt**, Int );
sewardj8d2291c2004-10-25 14:50:21 +0000207 Bool (*preciseMemExnsFn) ( Int, Int );
sewardjf13a16a2004-07-05 17:10:14 +0000208
sewardj9e6491a2005-07-02 19:24:10 +0000209 DisOneInstrFn disInstrFn;
210
sewardjeeac8412004-11-02 00:26:55 +0000211 VexGuestLayout* guest_layout;
212 Bool host_is_bigendian = False;
sewardjdd40fdf2006-12-24 02:20:24 +0000213 IRSB* irsb;
sewardjeeac8412004-11-02 00:26:55 +0000214 HInstrArray* vcode;
215 HInstrArray* rcode;
216 Int i, j, k, out_used, guest_sizeB;
sewardjc6f970f2012-04-02 21:54:49 +0000217 Int offB_TISTART, offB_TILEN, offB_GUEST_IP, szB_GUEST_IP;
218 Int offB_HOST_EvC_COUNTER, offB_HOST_EvC_FAILADDR;
219 UChar insn_bytes[64];
sewardjcf787902004-11-03 09:08:33 +0000220 IRType guest_word_type;
221 IRType host_word_type;
sewardjc6f970f2012-04-02 21:54:49 +0000222 Bool mode64, chainingAllowed;
223 Addr64 max_ga;
sewardjf13a16a2004-07-05 17:10:14 +0000224
sewardj49651f42004-10-28 22:11:04 +0000225 guest_layout = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000226 available_real_regs = NULL;
227 n_available_real_regs = 0;
228 isMove = NULL;
229 getRegUsage = NULL;
230 mapRegs = NULL;
231 genSpill = NULL;
232 genReload = NULL;
sewardjfb7373a2007-08-25 21:29:03 +0000233 directReload = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000234 ppInstr = NULL;
235 ppReg = NULL;
sewardjdd40fdf2006-12-24 02:20:24 +0000236 iselSB = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000237 emit = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000238 specHelper = NULL;
sewardj8d2291c2004-10-25 14:50:21 +0000239 preciseMemExnsFn = NULL;
sewardj9e6491a2005-07-02 19:24:10 +0000240 disInstrFn = NULL;
sewardjcf787902004-11-03 09:08:33 +0000241 guest_word_type = Ity_INVALID;
242 host_word_type = Ity_INVALID;
sewardjdb4738a2005-07-07 01:32:16 +0000243 offB_TISTART = 0;
244 offB_TILEN = 0;
sewardjc6f970f2012-04-02 21:54:49 +0000245 offB_GUEST_IP = 0;
246 szB_GUEST_IP = 0;
247 offB_HOST_EvC_COUNTER = 0;
248 offB_HOST_EvC_FAILADDR = 0;
cerion92b64362005-12-13 12:02:26 +0000249 mode64 = False;
sewardjc6f970f2012-04-02 21:54:49 +0000250 chainingAllowed = False;
sewardj36ca5132004-07-24 13:12:23 +0000251
sewardj17c7f952005-12-15 14:02:34 +0000252 vex_traceflags = vta->traceflags;
sewardj58800ff2004-07-28 01:51:10 +0000253
sewardj35421a32004-07-05 13:12:34 +0000254 vassert(vex_initdone);
sewardjc6f970f2012-04-02 21:54:49 +0000255 vassert(vta->needs_self_check != NULL);
256 vassert(vta->disp_cp_xassisted != NULL);
257 /* Both the chainers and the indir are either NULL or non-NULL. */
258 if (vta->disp_cp_chain_me_to_slowEP != NULL) {
259 vassert(vta->disp_cp_chain_me_to_fastEP != NULL);
260 vassert(vta->disp_cp_xindir != NULL);
261 chainingAllowed = True;
262 } else {
263 vassert(vta->disp_cp_chain_me_to_fastEP == NULL);
264 vassert(vta->disp_cp_xindir == NULL);
265 }
florian2eeeb9b2011-09-23 18:03:21 +0000266
sewardj2d6b14a2005-11-23 04:25:07 +0000267 vexSetAllocModeTEMP_and_clear();
268 vexAllocSanityCheck();
sewardj2a9ad022004-11-25 02:46:58 +0000269
sewardjf13a16a2004-07-05 17:10:14 +0000270 /* First off, check that the guest and host insn sets
271 are supported. */
sewardj2a9ad022004-11-25 02:46:58 +0000272
sewardj17c7f952005-12-15 14:02:34 +0000273 switch (vta->arch_host) {
sewardj2a9ad022004-11-25 02:46:58 +0000274
sewardjbef170b2004-12-21 01:23:00 +0000275 case VexArchX86:
sewardjfb7373a2007-08-25 21:29:03 +0000276 mode64 = False;
sewardjf13a16a2004-07-05 17:10:14 +0000277 getAllocableRegs_X86 ( &n_available_real_regs,
278 &available_real_regs );
sewardjfb7373a2007-08-25 21:29:03 +0000279 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000280 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
281 getRegUsage_X86Instr;
sewardjfb7373a2007-08-25 21:29:03 +0000282 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000283 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
284 genSpill_X86;
285 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
286 genReload_X86;
sewardjfb7373a2007-08-25 21:29:03 +0000287 directReload = (HInstr*(*)(HInstr*,HReg,Short)) directReload_X86;
288 ppInstr = (void(*)(HInstr*, Bool)) ppX86Instr;
289 ppReg = (void(*)(HReg)) ppHRegX86;
290 iselSB = iselSB_X86;
sewardjc6f970f2012-04-02 21:54:49 +0000291 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
292 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000293 emit_X86Instr;
sewardj72c72812005-01-19 11:49:45 +0000294 host_is_bigendian = False;
sewardjcf787902004-11-03 09:08:33 +0000295 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000296 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_host.hwcaps));
sewardjf13a16a2004-07-05 17:10:14 +0000297 break;
sewardj2a9ad022004-11-25 02:46:58 +0000298
sewardjc33671d2005-02-01 20:30:00 +0000299 case VexArchAMD64:
cerion92b64362005-12-13 12:02:26 +0000300 mode64 = True;
sewardjc33671d2005-02-01 20:30:00 +0000301 getAllocableRegs_AMD64 ( &n_available_real_regs,
302 &available_real_regs );
303 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000304 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
305 getRegUsage_AMD64Instr;
cerion92b64362005-12-13 12:02:26 +0000306 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000307 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
308 genSpill_AMD64;
309 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
310 genReload_AMD64;
cerion92b64362005-12-13 12:02:26 +0000311 ppInstr = (void(*)(HInstr*, Bool)) ppAMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000312 ppReg = (void(*)(HReg)) ppHRegAMD64;
sewardjdd40fdf2006-12-24 02:20:24 +0000313 iselSB = iselSB_AMD64;
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_AMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000317 host_is_bigendian = False;
318 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000319 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_host.hwcaps));
sewardjc33671d2005-02-01 20:30:00 +0000320 break;
321
cerion487e4c92005-02-04 16:28:19 +0000322 case VexArchPPC32:
cerion92b64362005-12-13 12:02:26 +0000323 mode64 = False;
cerion5b2325f2005-12-23 00:55:09 +0000324 getAllocableRegs_PPC ( &n_available_real_regs,
325 &available_real_regs, mode64 );
326 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
327 getRegUsage = (void(*)(HRegUsage*,HInstr*,Bool)) getRegUsage_PPCInstr;
328 mapRegs = (void(*)(HRegRemap*,HInstr*,Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000329 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
330 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000331 ppInstr = (void(*)(HInstr*,Bool)) ppPPCInstr;
332 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000333 iselSB = iselSB_PPC;
sewardj3dee8492012-04-20 00:13:28 +0000334 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
335 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000336 emit_PPCInstr;
cerion487e4c92005-02-04 16:28:19 +0000337 host_is_bigendian = True;
338 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000339 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_host.hwcaps));
cerion487e4c92005-02-04 16:28:19 +0000340 break;
341
cerionf0de28c2005-12-13 20:21:11 +0000342 case VexArchPPC64:
343 mode64 = True;
cerion5b2325f2005-12-23 00:55:09 +0000344 getAllocableRegs_PPC ( &n_available_real_regs,
345 &available_real_regs, mode64 );
346 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
347 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_PPCInstr;
348 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000349 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
350 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000351 ppInstr = (void(*)(HInstr*, Bool)) ppPPCInstr;
352 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000353 iselSB = iselSB_PPC;
sewardj9e1cf152012-04-20 02:18:31 +0000354 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
355 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000356 emit_PPCInstr;
cerionf0de28c2005-12-13 20:21:11 +0000357 host_is_bigendian = True;
358 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000359 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_host.hwcaps));
cerionf0de28c2005-12-13 20:21:11 +0000360 break;
361
sewardj2019a972011-03-07 16:04:07 +0000362 case VexArchS390X:
363 mode64 = True;
364 getAllocableRegs_S390 ( &n_available_real_regs,
365 &available_real_regs, mode64 );
366 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_S390Instr;
367 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_S390Instr;
368 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_S390Instr;
369 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_S390;
370 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_S390;
371 ppInstr = (void(*)(HInstr*, Bool)) ppS390Instr;
372 ppReg = (void(*)(HReg)) ppHRegS390;
373 iselSB = iselSB_S390;
florian8844a632012-04-13 04:04:06 +0000374 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
375 void*,void*,void*,void*)) emit_S390Instr;
sewardj2019a972011-03-07 16:04:07 +0000376 host_is_bigendian = True;
377 host_word_type = Ity_I64;
378 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_host.hwcaps));
sewardj2019a972011-03-07 16:04:07 +0000379 break;
380
sewardj6c299f32009-12-31 18:00:12 +0000381 case VexArchARM:
sewardj2a1ed8e2009-12-31 19:26:03 +0000382 mode64 = False;
sewardj6c299f32009-12-31 18:00:12 +0000383 getAllocableRegs_ARM ( &n_available_real_regs,
384 &available_real_regs );
sewardj2a1ed8e2009-12-31 19:26:03 +0000385 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARMInstr;
386 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_ARMInstr;
387 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_ARMInstr;
388 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_ARM;
389 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_ARM;
390 ppInstr = (void(*)(HInstr*, Bool)) ppARMInstr;
391 ppReg = (void(*)(HReg)) ppHRegARM;
392 iselSB = iselSB_ARM;
sewardjc6f970f2012-04-02 21:54:49 +0000393 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
394 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000395 emit_ARMInstr;
sewardj6c299f32009-12-31 18:00:12 +0000396 host_is_bigendian = False;
397 host_word_type = Ity_I32;
398 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_host.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000399 break;
400
sewardjd0e5fe72012-06-07 08:51:02 +0000401 case VexArchMIPS32:
402 mode64 = False;
403 getAllocableRegs_MIPS ( &n_available_real_regs,
404 &available_real_regs, mode64 );
405 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_MIPSInstr;
406 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_MIPSInstr;
407 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_MIPSInstr;
408 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_MIPS;
409 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_MIPS;
410 ppInstr = (void(*)(HInstr*, Bool)) ppMIPSInstr;
411 ppReg = (void(*)(HReg)) ppHRegMIPS;
412 iselSB = iselSB_MIPS;
413 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
414 void*,void*,void*,void*))
415 emit_MIPSInstr;
416#if defined(VKI_LITTLE_ENDIAN)
417 host_is_bigendian = False;
418#elif defined(VKI_BIG_ENDIAN)
419 host_is_bigendian = True;
420#endif
421 host_word_type = Ity_I32;
422 vassert(are_valid_hwcaps(VexArchMIPS32, vta->archinfo_host.hwcaps));
423 break;
424
sewardjf13a16a2004-07-05 17:10:14 +0000425 default:
sewardj6c299f32009-12-31 18:00:12 +0000426 vpanic("LibVEX_Translate: unsupported host insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000427 }
428
sewardj2a9ad022004-11-25 02:46:58 +0000429
sewardj17c7f952005-12-15 14:02:34 +0000430 switch (vta->arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000431
sewardjbef170b2004-12-21 01:23:00 +0000432 case VexArchX86:
sewardjc6f970f2012-04-02 21:54:49 +0000433 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
434 disInstrFn = disInstr_X86;
435 specHelper = guest_x86_spechelper;
436 guest_sizeB = sizeof(VexGuestX86State);
437 guest_word_type = Ity_I32;
438 guest_layout = &x86guest_layout;
439 offB_TISTART = offsetof(VexGuestX86State,guest_TISTART);
440 offB_TILEN = offsetof(VexGuestX86State,guest_TILEN);
441 offB_GUEST_IP = offsetof(VexGuestX86State,guest_EIP);
442 szB_GUEST_IP = sizeof( ((VexGuestX86State*)0)->guest_EIP );
443 offB_HOST_EvC_COUNTER = offsetof(VexGuestX86State,host_EvC_COUNTER);
444 offB_HOST_EvC_FAILADDR = offsetof(VexGuestX86State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000445 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000446 vassert(0 == sizeof(VexGuestX86State) % 16);
sewardjce02aa72006-01-12 12:27:58 +0000447 vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART) == 4);
448 vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
449 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000450 break;
sewardj2a9ad022004-11-25 02:46:58 +0000451
sewardj44d494d2005-01-20 20:26:33 +0000452 case VexArchAMD64:
sewardjc6f970f2012-04-02 21:54:49 +0000453 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
454 disInstrFn = disInstr_AMD64;
455 specHelper = guest_amd64_spechelper;
456 guest_sizeB = sizeof(VexGuestAMD64State);
457 guest_word_type = Ity_I64;
458 guest_layout = &amd64guest_layout;
459 offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART);
460 offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN);
461 offB_GUEST_IP = offsetof(VexGuestAMD64State,guest_RIP);
462 szB_GUEST_IP = sizeof( ((VexGuestAMD64State*)0)->guest_RIP );
463 offB_HOST_EvC_COUNTER = offsetof(VexGuestAMD64State,host_EvC_COUNTER);
464 offB_HOST_EvC_FAILADDR = offsetof(VexGuestAMD64State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000465 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000466 vassert(0 == sizeof(VexGuestAMD64State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000467 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8);
sewardjce02aa72006-01-12 12:27:58 +0000468 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
469 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000470 break;
471
cerionaabdfbf2005-01-29 12:56:15 +0000472 case VexArchPPC32:
sewardj3dee8492012-04-20 00:13:28 +0000473 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
474 disInstrFn = disInstr_PPC;
475 specHelper = guest_ppc32_spechelper;
476 guest_sizeB = sizeof(VexGuestPPC32State);
477 guest_word_type = Ity_I32;
478 guest_layout = &ppc32Guest_layout;
479 offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART);
480 offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN);
481 offB_GUEST_IP = offsetof(VexGuestPPC32State,guest_CIA);
482 szB_GUEST_IP = sizeof( ((VexGuestPPC32State*)0)->guest_CIA );
483 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC32State,host_EvC_COUNTER);
484 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC32State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000485 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000486 vassert(0 == sizeof(VexGuestPPC32State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000487 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000488 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
489 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000490 break;
491
cerionf0de28c2005-12-13 20:21:11 +0000492 case VexArchPPC64:
sewardj9e1cf152012-04-20 02:18:31 +0000493 preciseMemExnsFn = guest_ppc64_state_requires_precise_mem_exns;
494 disInstrFn = disInstr_PPC;
495 specHelper = guest_ppc64_spechelper;
496 guest_sizeB = sizeof(VexGuestPPC64State);
497 guest_word_type = Ity_I64;
498 guest_layout = &ppc64Guest_layout;
499 offB_TISTART = offsetof(VexGuestPPC64State,guest_TISTART);
500 offB_TILEN = offsetof(VexGuestPPC64State,guest_TILEN);
501 offB_GUEST_IP = offsetof(VexGuestPPC64State,guest_CIA);
502 szB_GUEST_IP = sizeof( ((VexGuestPPC64State*)0)->guest_CIA );
503 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC64State,host_EvC_COUNTER);
504 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC64State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000505 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_guest.hwcaps));
cerionf0de28c2005-12-13 20:21:11 +0000506 vassert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj3fd39672006-01-27 22:05:55 +0000507 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TISTART ) == 8);
508 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TILEN ) == 8);
509 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8);
510 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8);
cerionf0de28c2005-12-13 20:21:11 +0000511 break;
512
sewardj2019a972011-03-07 16:04:07 +0000513 case VexArchS390X:
514 preciseMemExnsFn = guest_s390x_state_requires_precise_mem_exns;
515 disInstrFn = disInstr_S390;
516 specHelper = guest_s390x_spechelper;
517 guest_sizeB = sizeof(VexGuestS390XState);
518 guest_word_type = Ity_I64;
519 guest_layout = &s390xGuest_layout;
520 offB_TISTART = offsetof(VexGuestS390XState,guest_TISTART);
521 offB_TILEN = offsetof(VexGuestS390XState,guest_TILEN);
florian8844a632012-04-13 04:04:06 +0000522 offB_GUEST_IP = offsetof(VexGuestS390XState,guest_IA);
523 szB_GUEST_IP = sizeof( ((VexGuestS390XState*)0)->guest_IA);
524 offB_HOST_EvC_COUNTER = offsetof(VexGuestS390XState,host_EvC_COUNTER);
525 offB_HOST_EvC_FAILADDR = offsetof(VexGuestS390XState,host_EvC_FAILADDR);
sewardj2019a972011-03-07 16:04:07 +0000526 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_guest.hwcaps));
527 vassert(0 == sizeof(VexGuestS390XState) % 16);
528 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TISTART ) == 8);
529 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TILEN ) == 8);
530 vassert(sizeof( ((VexGuestS390XState*)0)->guest_NRADDR ) == 8);
531 break;
532
sewardj6c299f32009-12-31 18:00:12 +0000533 case VexArchARM:
sewardjc6f970f2012-04-02 21:54:49 +0000534 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
535 disInstrFn = disInstr_ARM;
536 specHelper = guest_arm_spechelper;
537 guest_sizeB = sizeof(VexGuestARMState);
538 guest_word_type = Ity_I32;
539 guest_layout = &armGuest_layout;
540 offB_TISTART = offsetof(VexGuestARMState,guest_TISTART);
541 offB_TILEN = offsetof(VexGuestARMState,guest_TILEN);
542 offB_GUEST_IP = offsetof(VexGuestARMState,guest_R15T);
543 szB_GUEST_IP = sizeof( ((VexGuestARMState*)0)->guest_R15T );
544 offB_HOST_EvC_COUNTER = offsetof(VexGuestARMState,host_EvC_COUNTER);
545 offB_HOST_EvC_FAILADDR = offsetof(VexGuestARMState,host_EvC_FAILADDR);
sewardj6c299f32009-12-31 18:00:12 +0000546 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_guest.hwcaps));
547 vassert(0 == sizeof(VexGuestARMState) % 16);
548 vassert(sizeof( ((VexGuestARMState*)0)->guest_TISTART) == 4);
549 vassert(sizeof( ((VexGuestARMState*)0)->guest_TILEN ) == 4);
550 vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4);
551 break;
552
sewardjd0e5fe72012-06-07 08:51:02 +0000553 case VexArchMIPS32:
554 preciseMemExnsFn = guest_mips32_state_requires_precise_mem_exns;
555 disInstrFn = disInstr_MIPS;
556 specHelper = guest_mips32_spechelper;
557 guest_sizeB = sizeof(VexGuestMIPS32State);
558 guest_word_type = Ity_I32;
559 guest_layout = &mips32Guest_layout;
560 offB_TISTART = offsetof(VexGuestMIPS32State,guest_TISTART);
561 offB_TILEN = offsetof(VexGuestMIPS32State,guest_TILEN);
562 offB_GUEST_IP = offsetof(VexGuestMIPS32State,guest_PC);
563 szB_GUEST_IP = sizeof( ((VexGuestMIPS32State*)0)->guest_PC );
564 offB_HOST_EvC_COUNTER = offsetof(VexGuestMIPS32State,host_EvC_COUNTER);
565 offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS32State,host_EvC_FAILADDR);
566 vassert(are_valid_hwcaps(VexArchMIPS32, vta->archinfo_guest.hwcaps));
567 vassert(0 == sizeof(VexGuestMIPS32State) % 16);
568 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_TISTART) == 4);
569 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_TILEN ) == 4);
570 vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_NRADDR ) == 4);
571 break;
572
sewardjf13a16a2004-07-05 17:10:14 +0000573 default:
sewardj887a11a2004-07-05 17:26:47 +0000574 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000575 }
576
sewardjbc161a42011-06-07 21:28:38 +0000577 /* Set up result struct. */
578 VexTranslateResult res;
sewardjfadbbe22012-04-24 11:49:03 +0000579 res.status = VexTransOK;
580 res.n_sc_extents = 0;
581 res.offs_profInc = -1;
582 res.n_guest_instrs = 0;
sewardjbc161a42011-06-07 21:28:38 +0000583
sewardj9df271d2004-12-31 22:37:42 +0000584 /* yet more sanity checks ... */
sewardj17c7f952005-12-15 14:02:34 +0000585 if (vta->arch_guest == vta->arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000586 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000587 we are simulating one flavour of an architecture a different
588 flavour of the same architecture, which is pretty strange. */
sewardj5117ce12006-01-27 21:20:15 +0000589 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps);
sewardj9df271d2004-12-31 22:37:42 +0000590 }
sewardj2a9ad022004-11-25 02:46:58 +0000591
sewardj2d6b14a2005-11-23 04:25:07 +0000592 vexAllocSanityCheck();
593
sewardjf48ac192004-10-29 00:41:29 +0000594 if (vex_traceflags & VEX_TRACE_FE)
595 vex_printf("\n------------------------"
596 " Front end "
597 "------------------------\n\n");
598
sewardjdd40fdf2006-12-24 02:20:24 +0000599 irsb = bb_to_IR ( vta->guest_extents,
sewardjbc161a42011-06-07 21:28:38 +0000600 &res.n_sc_extents,
sewardjfadbbe22012-04-24 11:49:03 +0000601 &res.n_guest_instrs,
sewardjc716aea2006-01-17 01:48:46 +0000602 vta->callback_opaque,
sewardj9e6491a2005-07-02 19:24:10 +0000603 disInstrFn,
sewardj17c7f952005-12-15 14:02:34 +0000604 vta->guest_bytes,
605 vta->guest_bytes_addr,
606 vta->chase_into_ok,
sewardj9e6491a2005-07-02 19:24:10 +0000607 host_is_bigendian,
sewardj442e51a2012-12-06 18:08:04 +0000608 vta->sigill_diag,
sewardja5f55da2006-04-30 23:37:32 +0000609 vta->arch_guest,
sewardj17c7f952005-12-15 14:02:34 +0000610 &vta->archinfo_guest,
sewardjdd40fdf2006-12-24 02:20:24 +0000611 &vta->abiinfo_both,
sewardjdb4738a2005-07-07 01:32:16 +0000612 guest_word_type,
sewardjbc161a42011-06-07 21:28:38 +0000613 vta->needs_self_check,
sewardjc716aea2006-01-17 01:48:46 +0000614 vta->preamble_function,
sewardjdb4738a2005-07-07 01:32:16 +0000615 offB_TISTART,
sewardjc6f970f2012-04-02 21:54:49 +0000616 offB_TILEN,
617 offB_GUEST_IP,
618 szB_GUEST_IP );
sewardjf13a16a2004-07-05 17:10:14 +0000619
sewardj2d6b14a2005-11-23 04:25:07 +0000620 vexAllocSanityCheck();
621
sewardjdd40fdf2006-12-24 02:20:24 +0000622 if (irsb == NULL) {
sewardjf13a16a2004-07-05 17:10:14 +0000623 /* Access failure. */
sewardj2d6b14a2005-11-23 04:25:07 +0000624 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000625 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000626 res.status = VexTransAccessFail; return res;
sewardjf13a16a2004-07-05 17:10:14 +0000627 }
sewardjaa59f942004-10-09 09:34:36 +0000628
sewardj17c7f952005-12-15 14:02:34 +0000629 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3);
630 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr);
631 for (i = 0; i < vta->guest_extents->n_used; i++) {
632 vassert(vta->guest_extents->len[i] < 10000); /* sanity */
sewardj72c72812005-01-19 11:49:45 +0000633 }
634
sewardjaa59f942004-10-09 09:34:36 +0000635 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000636 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj17c7f952005-12-15 14:02:34 +0000637 if (vta->guest_extents->n_used > 1) {
sewardj72c72812005-01-19 11:49:45 +0000638 vex_printf("can't show code due to extents > 1\n");
639 } else {
640 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000641 UChar* p = (UChar*)vta->guest_bytes;
sewardj01f8cce2009-08-31 08:50:02 +0000642 UInt sum = 0;
sewardj17c7f952005-12-15 14:02:34 +0000643 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0];
sewardj01f8cce2009-08-31 08:50:02 +0000644 vex_printf("GuestBytes %llx %u ", vta->guest_bytes_addr,
645 guest_bytes_read );
646 for (i = 0; i < guest_bytes_read; i++) {
647 UInt b = (UInt)p[i];
648 vex_printf(" %02x", b );
649 sum = (sum << 1) ^ b;
650 }
651 vex_printf(" %08x\n\n", sum);
sewardj72c72812005-01-19 11:49:45 +0000652 }
sewardjaa59f942004-10-09 09:34:36 +0000653 }
654
655 /* Sanity check the initial IR. */
sewardjdd40fdf2006-12-24 02:20:24 +0000656 sanityCheckIRSB( irsb, "initial IR",
sewardjb9230752004-12-29 19:25:06 +0000657 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000658
sewardj2d6b14a2005-11-23 04:25:07 +0000659 vexAllocSanityCheck();
660
sewardjedf4d692004-08-17 13:52:58 +0000661 /* Clean it up, hopefully a lot. */
sewardjdd40fdf2006-12-24 02:20:24 +0000662 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn,
sewardjec0d9a02010-08-22 12:54:56 +0000663 vta->guest_bytes_addr,
664 vta->arch_guest );
sewardjdd40fdf2006-12-24 02:20:24 +0000665 sanityCheckIRSB( irsb, "after initial iropt",
sewardjb9230752004-12-29 19:25:06 +0000666 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000667
sewardjf48ac192004-10-29 00:41:29 +0000668 if (vex_traceflags & VEX_TRACE_OPT1) {
669 vex_printf("\n------------------------"
670 " After pre-instr IR optimisation "
671 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000672 ppIRSB ( irsb );
sewardjedf4d692004-08-17 13:52:58 +0000673 vex_printf("\n");
674 }
675
sewardj2d6b14a2005-11-23 04:25:07 +0000676 vexAllocSanityCheck();
677
sewardjf13a16a2004-07-05 17:10:14 +0000678 /* Get the thing instrumented. */
sewardj17c7f952005-12-15 14:02:34 +0000679 if (vta->instrument1)
sewardjdd40fdf2006-12-24 02:20:24 +0000680 irsb = vta->instrument1(vta->callback_opaque,
681 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000682 vta->guest_extents,
florian50481922012-10-07 21:58:07 +0000683 &vta->archinfo_host,
sewardj17c7f952005-12-15 14:02:34 +0000684 guest_word_type, host_word_type);
sewardj2d6b14a2005-11-23 04:25:07 +0000685 vexAllocSanityCheck();
686
sewardj17c7f952005-12-15 14:02:34 +0000687 if (vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000688 irsb = vta->instrument2(vta->callback_opaque,
689 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000690 vta->guest_extents,
florian50481922012-10-07 21:58:07 +0000691 &vta->archinfo_host,
sewardj17c7f952005-12-15 14:02:34 +0000692 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000693
sewardjf48ac192004-10-29 00:41:29 +0000694 if (vex_traceflags & VEX_TRACE_INST) {
695 vex_printf("\n------------------------"
696 " After instrumentation "
697 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000698 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000699 vex_printf("\n");
700 }
701
sewardj17c7f952005-12-15 14:02:34 +0000702 if (vta->instrument1 || vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000703 sanityCheckIRSB( irsb, "after instrumentation",
sewardjb9230752004-12-29 19:25:06 +0000704 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000705
sewardj9578a8b2004-11-04 19:44:48 +0000706 /* Do a post-instrumentation cleanup pass. */
sewardj17c7f952005-12-15 14:02:34 +0000707 if (vta->instrument1 || vta->instrument2) {
sewardjdd40fdf2006-12-24 02:20:24 +0000708 do_deadcode_BB( irsb );
709 irsb = cprop_BB( irsb );
710 do_deadcode_BB( irsb );
711 sanityCheckIRSB( irsb, "after post-instrumentation cleanup",
sewardjb9230752004-12-29 19:25:06 +0000712 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000713 }
714
sewardj2d6b14a2005-11-23 04:25:07 +0000715 vexAllocSanityCheck();
716
sewardj9578a8b2004-11-04 19:44:48 +0000717 if (vex_traceflags & VEX_TRACE_OPT2) {
718 vex_printf("\n------------------------"
719 " After post-instr IR optimisation "
720 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000721 ppIRSB ( irsb );
sewardj9578a8b2004-11-04 19:44:48 +0000722 vex_printf("\n");
723 }
724
sewardjf9517d02005-11-28 13:39:37 +0000725 /* Turn it into virtual-registerised code. Build trees -- this
726 also throws away any dead bindings. */
florian62140c12013-01-20 03:51:04 +0000727 max_ga = ado_treebuild_BB( irsb, preciseMemExnsFn );
sewardjf48ac192004-10-29 00:41:29 +0000728
sewardjbe1b6ff2007-08-28 06:06:27 +0000729 if (vta->finaltidy) {
730 irsb = vta->finaltidy(irsb);
731 }
732
sewardj2d6b14a2005-11-23 04:25:07 +0000733 vexAllocSanityCheck();
734
sewardjf48ac192004-10-29 00:41:29 +0000735 if (vex_traceflags & VEX_TRACE_TREES) {
736 vex_printf("\n------------------------"
737 " After tree-building "
738 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000739 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000740 vex_printf("\n");
741 }
742
sewardje908c422005-02-04 21:18:16 +0000743 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000744 if (0) {
745 *(vta->host_bytes_used) = 0;
746 res.status = VexTransOK; return res;
747 }
sewardje908c422005-02-04 21:18:16 +0000748 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000749
sewardjf48ac192004-10-29 00:41:29 +0000750 if (vex_traceflags & VEX_TRACE_VCODE)
751 vex_printf("\n------------------------"
752 " Instruction selection "
753 "------------------------\n");
754
sewardjc6f970f2012-04-02 21:54:49 +0000755 /* No guest has its IP field at offset zero. If this fails it
756 means some transformation pass somewhere failed to update/copy
757 irsb->offsIP properly. */
758 vassert(irsb->offsIP >= 16);
759
760 vcode = iselSB ( irsb, vta->arch_host,
761 &vta->archinfo_host,
762 &vta->abiinfo_both,
763 offB_HOST_EvC_COUNTER,
764 offB_HOST_EvC_FAILADDR,
765 chainingAllowed,
766 vta->addProfInc,
767 max_ga );
sewardjf13a16a2004-07-05 17:10:14 +0000768
sewardj2d6b14a2005-11-23 04:25:07 +0000769 vexAllocSanityCheck();
770
sewardjf48ac192004-10-29 00:41:29 +0000771 if (vex_traceflags & VEX_TRACE_VCODE)
772 vex_printf("\n");
773
sewardjf48ac192004-10-29 00:41:29 +0000774 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000775 for (i = 0; i < vcode->arr_used; i++) {
776 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000777 ppInstr(vcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000778 vex_printf("\n");
779 }
sewardjfbcaf332004-07-08 01:46:01 +0000780 vex_printf("\n");
781 }
sewardjfbcaf332004-07-08 01:46:01 +0000782
sewardjf13a16a2004-07-05 17:10:14 +0000783 /* Register allocate. */
784 rcode = doRegisterAllocation ( vcode, available_real_regs,
cerionf0de28c2005-12-13 20:21:11 +0000785 n_available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000786 isMove, getRegUsage, mapRegs,
sewardjfb7373a2007-08-25 21:29:03 +0000787 genSpill, genReload, directReload,
788 guest_sizeB,
cerion92b64362005-12-13 12:02:26 +0000789 ppInstr, ppReg, mode64 );
sewardjf13a16a2004-07-05 17:10:14 +0000790
sewardj2d6b14a2005-11-23 04:25:07 +0000791 vexAllocSanityCheck();
792
sewardjf48ac192004-10-29 00:41:29 +0000793 if (vex_traceflags & VEX_TRACE_RCODE) {
794 vex_printf("\n------------------------"
795 " Register-allocated code "
796 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000797 for (i = 0; i < rcode->arr_used; i++) {
798 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000799 ppInstr(rcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000800 vex_printf("\n");
801 }
sewardjfbcaf332004-07-08 01:46:01 +0000802 vex_printf("\n");
803 }
sewardjfbcaf332004-07-08 01:46:01 +0000804
sewardje908c422005-02-04 21:18:16 +0000805 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000806 if (0) {
807 *(vta->host_bytes_used) = 0;
808 res.status = VexTransOK; return res;
809 }
sewardje908c422005-02-04 21:18:16 +0000810 /* end HACK */
811
sewardj81bd5502004-07-21 18:49:27 +0000812 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000813 if (vex_traceflags & VEX_TRACE_ASM) {
814 vex_printf("\n------------------------"
815 " Assembly "
816 "------------------------\n\n");
817 }
818
sewardj81bd5502004-07-21 18:49:27 +0000819 out_used = 0; /* tracks along the host_bytes array */
820 for (i = 0; i < rcode->arr_used; i++) {
sewardjc6f970f2012-04-02 21:54:49 +0000821 HInstr* hi = rcode->arr[i];
822 Bool hi_isProfInc = False;
823 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
824 ppInstr(hi, mode64);
sewardjbad34a92004-07-22 01:14:11 +0000825 vex_printf("\n");
826 }
sewardjc6f970f2012-04-02 21:54:49 +0000827 j = emit( &hi_isProfInc,
828 insn_bytes, sizeof insn_bytes, hi, mode64,
829 vta->disp_cp_chain_me_to_slowEP,
830 vta->disp_cp_chain_me_to_fastEP,
831 vta->disp_cp_xindir,
832 vta->disp_cp_xassisted );
833 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
sewardjbad34a92004-07-22 01:14:11 +0000834 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000835 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000836 vex_printf("0%x ", (UInt)insn_bytes[k]);
837 else
838 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000839 vex_printf("\n\n");
840 }
sewardjc6f970f2012-04-02 21:54:49 +0000841 if (UNLIKELY(out_used + j > vta->host_bytes_size)) {
sewardj2d6b14a2005-11-23 04:25:07 +0000842 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000843 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000844 res.status = VexTransOutputFull;
845 return res;
sewardj81bd5502004-07-21 18:49:27 +0000846 }
sewardjc6f970f2012-04-02 21:54:49 +0000847 if (UNLIKELY(hi_isProfInc)) {
848 vassert(vta->addProfInc); /* else where did it come from? */
849 vassert(res.offs_profInc == -1); /* there can be only one (tm) */
850 vassert(out_used >= 0);
851 res.offs_profInc = out_used;
852 }
853 { UChar* dst = &vta->host_bytes[out_used];
854 for (k = 0; k < j; k++) {
855 dst[k] = insn_bytes[k];
856 }
857 out_used += j;
sewardj81bd5502004-07-21 18:49:27 +0000858 }
sewardj17c7f952005-12-15 14:02:34 +0000859 vassert(out_used <= vta->host_bytes_size);
sewardj81bd5502004-07-21 18:49:27 +0000860 }
sewardj17c7f952005-12-15 14:02:34 +0000861 *(vta->host_bytes_used) = out_used;
sewardj81bd5502004-07-21 18:49:27 +0000862
sewardj2d6b14a2005-11-23 04:25:07 +0000863 vexAllocSanityCheck();
864
865 vexSetAllocModeTEMP_and_clear();
sewardjf13a16a2004-07-05 17:10:14 +0000866
sewardj65ea17e2012-12-28 09:01:59 +0000867 if (vex_traceflags) {
868 /* Print the expansion ratio for this SB. */
869 j = 0; /* total guest bytes */
870 for (i = 0; i < vta->guest_extents->n_used; i++) {
871 j += vta->guest_extents->len[i];
872 }
873 if (1) vex_printf("VexExpansionRatio %d %d %d :10\n\n",
874 j, out_used, (10 * out_used) / (j == 0 ? 1 : j));
875 }
876
sewardjf48ac192004-10-29 00:41:29 +0000877 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000878 res.status = VexTransOK;
879 return res;
sewardj35421a32004-07-05 13:12:34 +0000880}
881
882
sewardjc6f970f2012-04-02 21:54:49 +0000883/* --------- Chain/Unchain XDirects. --------- */
884
885VexInvalRange LibVEX_Chain ( VexArch arch_host,
886 void* place_to_chain,
887 void* disp_cp_chain_me_EXPECTED,
888 void* place_to_jump_to )
889{
890 VexInvalRange (*chainXDirect)(void*, void*, void*) = NULL;
891 switch (arch_host) {
892 case VexArchX86:
893 chainXDirect = chainXDirect_X86; break;
894 case VexArchAMD64:
895 chainXDirect = chainXDirect_AMD64; break;
896 case VexArchARM:
897 chainXDirect = chainXDirect_ARM; break;
florian8844a632012-04-13 04:04:06 +0000898 case VexArchS390X:
899 chainXDirect = chainXDirect_S390; break;
sewardj3dee8492012-04-20 00:13:28 +0000900 case VexArchPPC32:
901 return chainXDirect_PPC(place_to_chain,
902 disp_cp_chain_me_EXPECTED,
903 place_to_jump_to, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +0000904 case VexArchPPC64:
905 return chainXDirect_PPC(place_to_chain,
906 disp_cp_chain_me_EXPECTED,
907 place_to_jump_to, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +0000908 case VexArchMIPS32:
909 return chainXDirect_MIPS(place_to_chain,
910 disp_cp_chain_me_EXPECTED,
911 place_to_jump_to, False/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +0000912 default:
913 vassert(0);
914 }
915 vassert(chainXDirect);
916 VexInvalRange vir
917 = chainXDirect(place_to_chain, disp_cp_chain_me_EXPECTED,
918 place_to_jump_to);
919 return vir;
920}
921
922VexInvalRange LibVEX_UnChain ( VexArch arch_host,
923 void* place_to_unchain,
924 void* place_to_jump_to_EXPECTED,
925 void* disp_cp_chain_me )
926{
927 VexInvalRange (*unchainXDirect)(void*, void*, void*) = NULL;
928 switch (arch_host) {
929 case VexArchX86:
930 unchainXDirect = unchainXDirect_X86; break;
931 case VexArchAMD64:
932 unchainXDirect = unchainXDirect_AMD64; break;
933 case VexArchARM:
934 unchainXDirect = unchainXDirect_ARM; break;
florian8844a632012-04-13 04:04:06 +0000935 case VexArchS390X:
936 unchainXDirect = unchainXDirect_S390; break;
sewardj3dee8492012-04-20 00:13:28 +0000937 case VexArchPPC32:
938 return unchainXDirect_PPC(place_to_unchain,
939 place_to_jump_to_EXPECTED,
940 disp_cp_chain_me, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +0000941 case VexArchPPC64:
942 return unchainXDirect_PPC(place_to_unchain,
943 place_to_jump_to_EXPECTED,
944 disp_cp_chain_me, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +0000945 case VexArchMIPS32:
946 return unchainXDirect_MIPS(place_to_unchain,
947 place_to_jump_to_EXPECTED,
948 disp_cp_chain_me, False/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +0000949 default:
950 vassert(0);
951 }
952 vassert(unchainXDirect);
953 VexInvalRange vir
954 = unchainXDirect(place_to_unchain, place_to_jump_to_EXPECTED,
955 disp_cp_chain_me);
956 return vir;
957}
958
959Int LibVEX_evCheckSzB ( VexArch arch_host )
960{
961 static Int cached = 0; /* DO NOT MAKE NON-STATIC */
962 if (UNLIKELY(cached == 0)) {
963 switch (arch_host) {
964 case VexArchX86:
965 cached = evCheckSzB_X86(); break;
966 case VexArchAMD64:
967 cached = evCheckSzB_AMD64(); break;
968 case VexArchARM:
969 cached = evCheckSzB_ARM(); break;
florian8844a632012-04-13 04:04:06 +0000970 case VexArchS390X:
971 cached = evCheckSzB_S390(); break;
sewardj3dee8492012-04-20 00:13:28 +0000972 case VexArchPPC32:
sewardjf252de52012-04-20 10:42:24 +0000973 case VexArchPPC64:
sewardj3dee8492012-04-20 00:13:28 +0000974 cached = evCheckSzB_PPC(); break;
sewardjd0e5fe72012-06-07 08:51:02 +0000975 case VexArchMIPS32:
976 cached = evCheckSzB_MIPS(); break;
sewardjc6f970f2012-04-02 21:54:49 +0000977 default:
978 vassert(0);
979 }
980 }
981 return cached;
982}
983
984VexInvalRange LibVEX_PatchProfInc ( VexArch arch_host,
985 void* place_to_patch,
986 ULong* location_of_counter )
987{
988 VexInvalRange (*patchProfInc)(void*,ULong*) = NULL;
989 switch (arch_host) {
990 case VexArchX86:
991 patchProfInc = patchProfInc_X86; break;
992 case VexArchAMD64:
993 patchProfInc = patchProfInc_AMD64; break;
994 case VexArchARM:
995 patchProfInc = patchProfInc_ARM; break;
florian8844a632012-04-13 04:04:06 +0000996 case VexArchS390X:
997 patchProfInc = patchProfInc_S390; break;
sewardj3dee8492012-04-20 00:13:28 +0000998 case VexArchPPC32:
999 return patchProfInc_PPC(place_to_patch,
1000 location_of_counter, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +00001001 case VexArchPPC64:
1002 return patchProfInc_PPC(place_to_patch,
1003 location_of_counter, True/*mode64*/);
sewardjd0e5fe72012-06-07 08:51:02 +00001004 case VexArchMIPS32:
1005 return patchProfInc_MIPS(place_to_patch,
1006 location_of_counter, False/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +00001007 default:
1008 vassert(0);
1009 }
1010 vassert(patchProfInc);
1011 VexInvalRange vir
1012 = patchProfInc(place_to_patch, location_of_counter);
1013 return vir;
1014}
1015
1016
sewardj893aada2004-11-29 19:57:54 +00001017/* --------- Emulation warnings. --------- */
1018
florian1ff47562012-10-21 02:09:51 +00001019const HChar* LibVEX_EmNote_string ( VexEmNote ew )
sewardj893aada2004-11-29 19:57:54 +00001020{
1021 switch (ew) {
florian6ef84be2012-08-26 03:20:07 +00001022 case EmNote_NONE:
sewardj893aada2004-11-29 19:57:54 +00001023 return "none";
1024 case EmWarn_X86_x87exns:
1025 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +00001026 case EmWarn_X86_x87precision:
1027 return "Selection of non-80-bit x87 FP precision";
1028 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +00001029 return "Unmasking SSE FP exceptions";
1030 case EmWarn_X86_fz:
1031 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
1032 case EmWarn_X86_daz:
1033 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +00001034 case EmWarn_X86_acFlag:
1035 return "Setting %eflags.ac (setting noted but ignored)";
sewardj9dd9cf12006-01-20 14:13:55 +00001036 case EmWarn_PPCexns:
1037 return "Unmasking PPC32/64 FP exceptions";
1038 case EmWarn_PPC64_redir_overflow:
1039 return "PPC64 function redirection stack overflow";
1040 case EmWarn_PPC64_redir_underflow:
1041 return "PPC64 function redirection stack underflow";
florian4b8efad2012-09-02 18:07:08 +00001042 case EmWarn_S390X_fpext_rounding:
1043 return "The specified rounding mode cannot be supported. That\n"
1044 " feature requires the floating point extension facility.\n"
1045 " which is not available on this host. Continuing using\n"
1046 " the rounding mode from FPC. Results may differ!";
florianf0fa1be2012-09-18 20:24:38 +00001047 case EmWarn_S390X_invalid_rounding:
1048 return "The specified rounding mode is invalid.\n"
1049 " Continuing using 'round to nearest'. Results may differ!";
floriane75dafa2012-09-01 17:54:09 +00001050 case EmFail_S390X_stfle:
florian4e0083e2012-08-26 03:41:56 +00001051 return "Instruction stfle is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001052 case EmFail_S390X_stckf:
florianc5c669b2012-08-26 14:32:28 +00001053 return "Instruction stckf is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001054 case EmFail_S390X_ecag:
florian8c88cb62012-08-26 18:58:13 +00001055 return "Instruction ecag is not supported on this host";
floriane75dafa2012-09-01 17:54:09 +00001056 case EmFail_S390X_fpext:
1057 return "Encountered an instruction that requires the floating "
1058 "point extension facility.\n"
1059 " That facility is not available on this host";
sewardj893aada2004-11-29 19:57:54 +00001060 default:
florian6ef84be2012-08-26 03:20:07 +00001061 vpanic("LibVEX_EmNote_string: unknown warning");
sewardj893aada2004-11-29 19:57:54 +00001062 }
1063}
sewardj35421a32004-07-05 13:12:34 +00001064
sewardj5117ce12006-01-27 21:20:15 +00001065/* ------------------ Arch/HwCaps stuff. ------------------ */
sewardjbef170b2004-12-21 01:23:00 +00001066
1067const HChar* LibVEX_ppVexArch ( VexArch arch )
1068{
1069 switch (arch) {
1070 case VexArch_INVALID: return "INVALID";
1071 case VexArchX86: return "X86";
1072 case VexArchAMD64: return "AMD64";
1073 case VexArchARM: return "ARM";
sewardj0ec57c52005-02-01 15:24:10 +00001074 case VexArchPPC32: return "PPC32";
cerionf0de28c2005-12-13 20:21:11 +00001075 case VexArchPPC64: return "PPC64";
sewardj2019a972011-03-07 16:04:07 +00001076 case VexArchS390X: return "S390X";
sewardjd0e5fe72012-06-07 08:51:02 +00001077 case VexArchMIPS32: return "MIPS32";
sewardjbef170b2004-12-21 01:23:00 +00001078 default: return "VexArch???";
1079 }
1080}
1081
sewardj5117ce12006-01-27 21:20:15 +00001082const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
sewardjbef170b2004-12-21 01:23:00 +00001083{
florian55085f82012-11-21 00:36:55 +00001084 const HChar* str = show_hwcaps(arch,hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001085 return str ? str : "INVALID";
sewardjbef170b2004-12-21 01:23:00 +00001086}
1087
sewardj5117ce12006-01-27 21:20:15 +00001088
sewardj27e1dd62005-06-30 11:49:14 +00001089/* Write default settings info *vai. */
1090void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
1091{
sewardj5117ce12006-01-27 21:20:15 +00001092 vai->hwcaps = 0;
cerion5b2325f2005-12-23 00:55:09 +00001093 vai->ppc_cache_line_szB = 0;
sewardje971c6a2010-09-03 15:49:57 +00001094 vai->ppc_dcbz_szB = 0;
1095 vai->ppc_dcbzl_szB = 0;
1096
florianf192a392012-10-07 19:44:40 +00001097 vai->hwcache_info.num_levels = 0;
1098 vai->hwcache_info.num_caches = 0;
1099 vai->hwcache_info.caches = NULL;
1100 vai->hwcache_info.icaches_maintain_coherence = True; // whatever
sewardj27e1dd62005-06-30 11:49:14 +00001101}
1102
sewardjdd40fdf2006-12-24 02:20:24 +00001103/* Write default settings info *vbi. */
1104void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
sewardjaca070a2006-10-17 00:28:22 +00001105{
sewardjdd40fdf2006-12-24 02:20:24 +00001106 vbi->guest_stack_redzone_size = 0;
sewardj2e28ac42008-12-04 00:05:12 +00001107 vbi->guest_amd64_assume_fs_is_zero = False;
1108 vbi->guest_amd64_assume_gs_is_0x60 = False;
sewardjdd40fdf2006-12-24 02:20:24 +00001109 vbi->guest_ppc_zap_RZ_at_blr = False;
1110 vbi->guest_ppc_zap_RZ_at_bl = NULL;
1111 vbi->guest_ppc_sc_continues_at_LR = False;
1112 vbi->host_ppc_calls_use_fndescrs = False;
1113 vbi->host_ppc32_regalign_int64_args = False;
sewardjaca070a2006-10-17 00:28:22 +00001114}
1115
sewardj27e1dd62005-06-30 11:49:14 +00001116
sewardj5117ce12006-01-27 21:20:15 +00001117/* Return a string showing the hwcaps in a nice way. The string will
1118 be NULL for invalid combinations of flags, so these functions also
1119 serve as a way to validate hwcaps values. */
1120
florian55085f82012-11-21 00:36:55 +00001121static const HChar* show_hwcaps_x86 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001122{
1123 /* Monotonic, SSE3 > SSE2 > SSE1 > baseline. */
sewardj536fbab2010-07-29 15:39:05 +00001124 switch (hwcaps) {
1125 case 0:
1126 return "x86-sse0";
1127 case VEX_HWCAPS_X86_SSE1:
1128 return "x86-sse1";
1129 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2:
1130 return "x86-sse1-sse2";
1131 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
1132 | VEX_HWCAPS_X86_LZCNT:
1133 return "x86-sse1-sse2-lzcnt";
1134 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
1135 | VEX_HWCAPS_X86_SSE3:
1136 return "x86-sse1-sse2-sse3";
1137 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
1138 | VEX_HWCAPS_X86_SSE3 | VEX_HWCAPS_X86_LZCNT:
1139 return "x86-sse1-sse2-sse3-lzcnt";
1140 default:
1141 return NULL;
1142 }
sewardj5117ce12006-01-27 21:20:15 +00001143}
1144
florian55085f82012-11-21 00:36:55 +00001145static const HChar* show_hwcaps_amd64 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001146{
sewardje9d8a262009-07-01 08:06:34 +00001147 /* SSE3 and CX16 are orthogonal and > baseline, although we really
1148 don't expect to come across anything which can do SSE3 but can't
sewardj536fbab2010-07-29 15:39:05 +00001149 do CX16. Still, we can handle that case. LZCNT is similarly
sewardjf350a422012-04-26 14:16:52 +00001150 orthogonal. AVX is technically orthogonal, but just add the
1151 cases we actually come across. (This scheme for printing is
1152 very stupid. We should add strings independently based on
1153 feature bits, but then it would be hard to return a string that
1154 didn't need deallocating by the caller.) */
sewardjc4530ae2012-05-21 10:18:49 +00001155 /* FIXME: show_hwcaps_s390x is a much better way to do this. */
sewardj536fbab2010-07-29 15:39:05 +00001156 switch (hwcaps) {
1157 case 0:
1158 return "amd64-sse2";
1159 case VEX_HWCAPS_AMD64_SSE3:
1160 return "amd64-sse3";
1161 case VEX_HWCAPS_AMD64_CX16:
1162 return "amd64-sse2-cx16";
1163 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16:
1164 return "amd64-sse3-cx16";
1165 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_LZCNT:
1166 return "amd64-sse3-lzcnt";
1167 case VEX_HWCAPS_AMD64_CX16 | VEX_HWCAPS_AMD64_LZCNT:
1168 return "amd64-sse2-cx16-lzcnt";
1169 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16
1170 | VEX_HWCAPS_AMD64_LZCNT:
1171 return "amd64-sse3-cx16-lzcnt";
sewardjf350a422012-04-26 14:16:52 +00001172 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16
1173 | VEX_HWCAPS_AMD64_AVX:
1174 return "amd64-sse3-cx16-avx";
sewardjb5e17b92012-05-21 16:16:13 +00001175 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16
1176 | VEX_HWCAPS_AMD64_LZCNT | VEX_HWCAPS_AMD64_AVX:
1177 return "amd64-sse3-cx16-lzcnt-avx";
sewardj536fbab2010-07-29 15:39:05 +00001178 default:
1179 return NULL;
1180 }
sewardj5117ce12006-01-27 21:20:15 +00001181}
1182
florian55085f82012-11-21 00:36:55 +00001183static const HChar* show_hwcaps_ppc32 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001184{
1185 /* Monotonic with complications. Basically V > F > baseline,
1186 but once you have F then you can have FX or GX too. */
1187 const UInt F = VEX_HWCAPS_PPC32_F;
1188 const UInt V = VEX_HWCAPS_PPC32_V;
1189 const UInt FX = VEX_HWCAPS_PPC32_FX;
1190 const UInt GX = VEX_HWCAPS_PPC32_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001191 const UInt VX = VEX_HWCAPS_PPC32_VX;
sewardjc66d6fa2012-04-02 21:24:12 +00001192 const UInt DFP = VEX_HWCAPS_PPC32_DFP;
sewardj5117ce12006-01-27 21:20:15 +00001193 UInt c = hwcaps;
1194 if (c == 0) return "ppc32-int";
1195 if (c == F) return "ppc32-int-flt";
1196 if (c == (F|FX)) return "ppc32-int-flt-FX";
1197 if (c == (F|GX)) return "ppc32-int-flt-GX";
1198 if (c == (F|FX|GX)) return "ppc32-int-flt-FX-GX";
1199 if (c == (F|V)) return "ppc32-int-flt-vmx";
1200 if (c == (F|V|FX)) return "ppc32-int-flt-vmx-FX";
1201 if (c == (F|V|GX)) return "ppc32-int-flt-vmx-GX";
1202 if (c == (F|V|FX|GX)) return "ppc32-int-flt-vmx-FX-GX";
sewardjc66d6fa2012-04-02 21:24:12 +00001203 if (c == (F|V|FX|GX|DFP)) return "ppc32-int-flt-vmx-FX-GX-DFP";
1204 if (c == (F|V|FX|GX|VX|DFP)) return "ppc32-int-flt-vmx-FX-GX-VX-DFP";
sewardj5117ce12006-01-27 21:20:15 +00001205 return NULL;
1206}
1207
florian55085f82012-11-21 00:36:55 +00001208static const HChar* show_hwcaps_ppc64 ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001209{
1210 /* Monotonic with complications. Basically V > baseline(==F),
1211 but once you have F then you can have FX or GX too. */
sewardj3fd39672006-01-27 22:05:55 +00001212 const UInt V = VEX_HWCAPS_PPC64_V;
1213 const UInt FX = VEX_HWCAPS_PPC64_FX;
1214 const UInt GX = VEX_HWCAPS_PPC64_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001215 const UInt VX = VEX_HWCAPS_PPC64_VX;
sewardjc66d6fa2012-04-02 21:24:12 +00001216 const UInt DFP = VEX_HWCAPS_PPC64_DFP;
sewardj5117ce12006-01-27 21:20:15 +00001217 UInt c = hwcaps;
1218 if (c == 0) return "ppc64-int-flt";
1219 if (c == FX) return "ppc64-int-flt-FX";
1220 if (c == GX) return "ppc64-int-flt-GX";
1221 if (c == (FX|GX)) return "ppc64-int-flt-FX-GX";
1222 if (c == V) return "ppc64-int-flt-vmx";
1223 if (c == (V|FX)) return "ppc64-int-flt-vmx-FX";
1224 if (c == (V|GX)) return "ppc64-int-flt-vmx-GX";
1225 if (c == (V|FX|GX)) return "ppc64-int-flt-vmx-FX-GX";
sewardjc66d6fa2012-04-02 21:24:12 +00001226 if (c == (V|FX|GX|DFP)) return "ppc64-int-flt-vmx-FX-GX-DFP";
1227 if (c == (V|FX|GX|VX|DFP)) return "ppc64-int-flt-vmx-FX-GX-VX-DFP";
sewardj5117ce12006-01-27 21:20:15 +00001228 return NULL;
1229}
1230
florian55085f82012-11-21 00:36:55 +00001231static const HChar* show_hwcaps_arm ( UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001232{
sewardjec0d9a02010-08-22 12:54:56 +00001233 Bool N = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0);
1234 Bool vfp = ((hwcaps & (VEX_HWCAPS_ARM_VFP |
1235 VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3)) != 0);
1236 switch (VEX_ARM_ARCHLEVEL(hwcaps)) {
1237 case 5:
1238 if (N)
1239 return NULL;
1240 if (vfp)
1241 return "ARMv5-vfp";
1242 else
1243 return "ARMv5";
1244 return NULL;
1245 case 6:
1246 if (N)
1247 return NULL;
1248 if (vfp)
1249 return "ARMv6-vfp";
1250 else
1251 return "ARMv6";
1252 return NULL;
1253 case 7:
1254 if (vfp) {
1255 if (N)
1256 return "ARMv7-vfp-neon";
1257 else
1258 return "ARMv7-vfp";
1259 } else {
1260 if (N)
1261 return "ARMv7-neon";
1262 else
1263 return "ARMv7";
1264 }
1265 default:
1266 return NULL;
1267 }
sewardj5117ce12006-01-27 21:20:15 +00001268 return NULL;
1269}
1270
florian55085f82012-11-21 00:36:55 +00001271static const HChar* show_hwcaps_s390x ( UInt hwcaps )
sewardj2019a972011-03-07 16:04:07 +00001272{
sewardjd07b8562011-04-27 11:58:22 +00001273 static const HChar prefix[] = "s390x";
florian9061eb32012-12-09 17:53:45 +00001274 static const struct {
1275 UInt hwcaps_bit;
1276 HChar name[6];
1277 } hwcaps_list[] = {
1278 { VEX_HWCAPS_S390X_LDISP, "ldisp" },
1279 { VEX_HWCAPS_S390X_EIMM, "eimm" },
1280 { VEX_HWCAPS_S390X_GIE, "gie" },
1281 { VEX_HWCAPS_S390X_DFP, "dfp" },
1282 { VEX_HWCAPS_S390X_FGX, "fgx" },
1283 { VEX_HWCAPS_S390X_STFLE, "stfle" },
1284 { VEX_HWCAPS_S390X_ETF2, "etf2" },
1285 { VEX_HWCAPS_S390X_ETF3, "etf3" },
1286 { VEX_HWCAPS_S390X_STCKF, "stckf" },
1287 { VEX_HWCAPS_S390X_FPEXT, "fpext" },
1288 { VEX_HWCAPS_S390X_LSC, "lsc" },
sewardjd07b8562011-04-27 11:58:22 +00001289 };
florian9061eb32012-12-09 17:53:45 +00001290#define NUM_HWCAPS (sizeof hwcaps_list / sizeof hwcaps_list[0])
1291 static HChar buf[sizeof prefix +
1292 NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) +
1293 1]; // '\0'
1294 HChar *p;
1295 UInt i;
sewardjd07b8562011-04-27 11:58:22 +00001296
1297 if (buf[0] != '\0') return buf; /* already constructed */
sewardj2019a972011-03-07 16:04:07 +00001298
sewardj652b56a2011-04-13 15:38:17 +00001299 hwcaps = VEX_HWCAPS_S390X(hwcaps);
1300
sewardjd07b8562011-04-27 11:58:22 +00001301 p = buf + vex_sprintf(buf, "%s", prefix);
florian9061eb32012-12-09 17:53:45 +00001302 for (i = 0 ; i < NUM_HWCAPS; ++i) {
1303 if (hwcaps & hwcaps_list[i].hwcaps_bit)
1304 p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
1305 }
sewardj2019a972011-03-07 16:04:07 +00001306
sewardjd07b8562011-04-27 11:58:22 +00001307 /* If there are no facilities, add "zarch" */
1308 if (hwcaps == 0)
1309 vex_sprintf(p, "-%s", "zarch");
1310
1311 return buf;
sewardj2019a972011-03-07 16:04:07 +00001312}
1313
florian55085f82012-11-21 00:36:55 +00001314static const HChar* show_hwcaps_mips32 ( UInt hwcaps )
sewardjd0e5fe72012-06-07 08:51:02 +00001315{
1316 if (hwcaps == 0x00010000) return "MIPS-baseline";
1317 if (hwcaps == 0x00020000) return "Broadcom-baseline";
1318 return NULL;
1319}
1320
sewardj5117ce12006-01-27 21:20:15 +00001321/* ---- */
florian55085f82012-11-21 00:36:55 +00001322static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
sewardj5117ce12006-01-27 21:20:15 +00001323{
1324 switch (arch) {
sewardjd0e5fe72012-06-07 08:51:02 +00001325 case VexArchX86: return show_hwcaps_x86(hwcaps);
1326 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
1327 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
1328 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
1329 case VexArchARM: return show_hwcaps_arm(hwcaps);
1330 case VexArchS390X: return show_hwcaps_s390x(hwcaps);
1331 case VexArchMIPS32: return show_hwcaps_mips32(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001332 default: return NULL;
1333 }
1334}
1335
1336static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps )
1337{
1338 return show_hwcaps(arch,hwcaps) != NULL;
1339}
1340
1341
sewardj35421a32004-07-05 13:12:34 +00001342/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +00001343/*--- end main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +00001344/*---------------------------------------------------------------*/