blob: c73c5d291af5451fa5324e5183126d00632d09f2 [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
sewardje6c53e02011-10-23 07:33:43 +000010 Copyright (C) 2004-2011 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"
sewardj893aada2004-11-29 19:57:54 +000037#include "libvex_emwarn.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"
sewardjf13a16a2004-07-05 17:10:14 +000044
sewardjcef7d3e2009-07-02 12:21:59 +000045#include "main_globals.h"
46#include "main_util.h"
47#include "host_generic_regs.h"
48#include "ir_opt.h"
sewardj35421a32004-07-05 13:12:34 +000049
sewardjcef7d3e2009-07-02 12:21:59 +000050#include "host_x86_defs.h"
51#include "host_amd64_defs.h"
52#include "host_ppc_defs.h"
sewardj6c299f32009-12-31 18:00:12 +000053#include "host_arm_defs.h"
sewardj2019a972011-03-07 16:04:07 +000054#include "host_s390_defs.h"
sewardj2a9ad022004-11-25 02:46:58 +000055
sewardjcef7d3e2009-07-02 12:21:59 +000056#include "guest_generic_bb_to_IR.h"
57#include "guest_x86_defs.h"
58#include "guest_amd64_defs.h"
59#include "guest_arm_defs.h"
60#include "guest_ppc_defs.h"
sewardj2019a972011-03-07 16:04:07 +000061#include "guest_s390_defs.h"
sewardj2a9ad022004-11-25 02:46:58 +000062
sewardj69d98e32010-06-18 08:17:41 +000063#include "host_generic_simd128.h"
64
sewardj35421a32004-07-05 13:12:34 +000065
66/* This file contains the top level interface to the library. */
67
sewardj5117ce12006-01-27 21:20:15 +000068/* --------- fwds ... --------- */
69
70static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps );
71static HChar* show_hwcaps ( VexArch arch, UInt hwcaps );
72
73
sewardj35421a32004-07-05 13:12:34 +000074/* --------- Initialise the library. --------- */
75
76/* Exported to library client. */
77
sewardj08613742004-10-25 13:01:45 +000078void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon )
79{
80 vcon->iropt_verbosity = 0;
81 vcon->iropt_level = 2;
82 vcon->iropt_precise_memory_exns = False;
83 vcon->iropt_unroll_thresh = 120;
sewardj18b4bb72005-03-29 21:32:41 +000084 vcon->guest_max_insns = 60;
sewardj08613742004-10-25 13:01:45 +000085 vcon->guest_chase_thresh = 10;
sewardj984d9b12010-01-15 10:53:21 +000086 vcon->guest_chase_cond = False;
sewardj08613742004-10-25 13:01:45 +000087}
88
89
90/* Exported to library client. */
91
sewardj887a11a2004-07-05 17:26:47 +000092void LibVEX_Init (
sewardj35421a32004-07-05 13:12:34 +000093 /* failure exit function */
sewardj2b515872004-07-05 20:50:45 +000094 __attribute__ ((noreturn))
sewardj35421a32004-07-05 13:12:34 +000095 void (*failure_exit) ( void ),
96 /* logging output function */
sewardjd9763622005-02-07 03:12:19 +000097 void (*log_bytes) ( HChar*, Int nbytes ),
sewardj35421a32004-07-05 13:12:34 +000098 /* debug paranoia level */
99 Int debuglevel,
sewardj35421a32004-07-05 13:12:34 +0000100 /* Are we supporting valgrind checking? */
101 Bool valgrind_support,
sewardj08613742004-10-25 13:01:45 +0000102 /* Control ... */
103 /*READONLY*/VexControl* vcon
sewardj35421a32004-07-05 13:12:34 +0000104)
105{
sewardj08613742004-10-25 13:01:45 +0000106 /* First off, do enough minimal setup so that the following
107 assertions can fail in a sane fashion, if need be. */
sewardjea602bc2004-10-14 21:40:12 +0000108 vex_failure_exit = failure_exit;
109 vex_log_bytes = log_bytes;
110
111 /* Now it's safe to check parameters for sanity. */
sewardj35421a32004-07-05 13:12:34 +0000112 vassert(!vex_initdone);
113 vassert(failure_exit);
sewardj35421a32004-07-05 13:12:34 +0000114 vassert(log_bytes);
sewardj35421a32004-07-05 13:12:34 +0000115 vassert(debuglevel >= 0);
sewardj08613742004-10-25 13:01:45 +0000116
117 vassert(vcon->iropt_verbosity >= 0);
118 vassert(vcon->iropt_level >= 0);
119 vassert(vcon->iropt_level <= 2);
120 vassert(vcon->iropt_unroll_thresh >= 0);
121 vassert(vcon->iropt_unroll_thresh <= 400);
122 vassert(vcon->guest_max_insns >= 1);
123 vassert(vcon->guest_max_insns <= 100);
124 vassert(vcon->guest_chase_thresh >= 0);
125 vassert(vcon->guest_chase_thresh < vcon->guest_max_insns);
sewardj984d9b12010-01-15 10:53:21 +0000126 vassert(vcon->guest_chase_cond == True
127 || vcon->guest_chase_cond == False);
sewardj443cd9d2004-07-18 23:06:45 +0000128
sewardjea602bc2004-10-14 21:40:12 +0000129 /* Check that Vex has been built with sizes of basic types as
130 stated in priv/libvex_basictypes.h. Failure of any of these is
131 a serious configuration error and should be corrected
132 immediately. If any of these assertions fail you can fully
133 expect Vex not to work properly, if at all. */
134
135 vassert(1 == sizeof(UChar));
136 vassert(1 == sizeof(Char));
137 vassert(2 == sizeof(UShort));
138 vassert(2 == sizeof(Short));
139 vassert(4 == sizeof(UInt));
140 vassert(4 == sizeof(Int));
141 vassert(8 == sizeof(ULong));
142 vassert(8 == sizeof(Long));
143 vassert(4 == sizeof(Float));
144 vassert(8 == sizeof(Double));
145 vassert(1 == sizeof(Bool));
146 vassert(4 == sizeof(Addr32));
147 vassert(8 == sizeof(Addr64));
sewardjc9a43662004-11-30 18:51:59 +0000148 vassert(16 == sizeof(U128));
sewardj69d98e32010-06-18 08:17:41 +0000149 vassert(16 == sizeof(V128));
sewardjea602bc2004-10-14 21:40:12 +0000150
151 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
152 vassert(sizeof(void*) == sizeof(int*));
153 vassert(sizeof(void*) == sizeof(HWord));
154
sewardj97e87932005-02-07 00:00:50 +0000155 vassert(VEX_HOST_WORDSIZE == sizeof(void*));
156 vassert(VEX_HOST_WORDSIZE == sizeof(HWord));
157
sewardjc6f970f2012-04-02 21:54:49 +0000158 /* These take a lot of space, so make sure we don't have
159 any unnoticed size regressions. */
160 if (VEX_HOST_WORDSIZE == 4) {
161 vassert(sizeof(IRExpr) == 24);
162 vassert(sizeof(IRStmt) == 20 /* x86 */
163 || sizeof(IRStmt) == 24 /* arm */);
164 } else {
165 vassert(sizeof(IRExpr) == 48);
166 vassert(sizeof(IRStmt) == 40);
167 }
168
sewardjea602bc2004-10-14 21:40:12 +0000169 /* Really start up .. */
sewardj443cd9d2004-07-18 23:06:45 +0000170 vex_debuglevel = debuglevel;
sewardj443cd9d2004-07-18 23:06:45 +0000171 vex_valgrind_support = valgrind_support;
sewardj08613742004-10-25 13:01:45 +0000172 vex_control = *vcon;
sewardj443cd9d2004-07-18 23:06:45 +0000173 vex_initdone = True;
sewardjd887b862005-01-17 18:34:34 +0000174 vexSetAllocMode ( VexAllocModeTEMP );
sewardj35421a32004-07-05 13:12:34 +0000175}
176
177
178/* --------- Make a translation. --------- */
179
180/* Exported to library client. */
181
sewardj17c7f952005-12-15 14:02:34 +0000182VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
sewardj35421a32004-07-05 13:12:34 +0000183{
sewardj81bd5502004-07-21 18:49:27 +0000184 /* This the bundle of functions we need to do the back-end stuff
185 (insn selection, reg-alloc, assembly) whilst being insulated
186 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +0000187 HReg* available_real_regs;
188 Int n_available_real_regs;
sewardjfb7373a2007-08-25 21:29:03 +0000189 Bool (*isMove) ( HInstr*, HReg*, HReg* );
190 void (*getRegUsage) ( HRegUsage*, HInstr*, Bool );
191 void (*mapRegs) ( HRegRemap*, HInstr*, Bool );
sewardj6c299f32009-12-31 18:00:12 +0000192 void (*genSpill) ( HInstr**, HInstr**, HReg, Int, Bool );
193 void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool );
sewardjfb7373a2007-08-25 21:29:03 +0000194 HInstr* (*directReload) ( HInstr*, HReg, Short );
195 void (*ppInstr) ( HInstr*, Bool );
196 void (*ppReg) ( HReg );
sewardjc6f970f2012-04-02 21:54:49 +0000197 HInstrArray* (*iselSB) ( IRSB*, VexArch, VexArchInfo*, VexAbiInfo*,
198 Int, Int, Bool, Bool, Addr64 );
199 Int (*emit) ( /*MB_MOD*/Bool*,
200 UChar*, Int, HInstr*, Bool,
201 void*, void*, void*, void* );
sewardjec0d9a02010-08-22 12:54:56 +0000202 IRExpr* (*specHelper) ( HChar*, IRExpr**, IRStmt**, Int );
sewardj8d2291c2004-10-25 14:50:21 +0000203 Bool (*preciseMemExnsFn) ( Int, Int );
sewardjf13a16a2004-07-05 17:10:14 +0000204
sewardj9e6491a2005-07-02 19:24:10 +0000205 DisOneInstrFn disInstrFn;
206
sewardjeeac8412004-11-02 00:26:55 +0000207 VexGuestLayout* guest_layout;
208 Bool host_is_bigendian = False;
sewardjdd40fdf2006-12-24 02:20:24 +0000209 IRSB* irsb;
sewardjeeac8412004-11-02 00:26:55 +0000210 HInstrArray* vcode;
211 HInstrArray* rcode;
212 Int i, j, k, out_used, guest_sizeB;
sewardjc6f970f2012-04-02 21:54:49 +0000213 Int offB_TISTART, offB_TILEN, offB_GUEST_IP, szB_GUEST_IP;
214 Int offB_HOST_EvC_COUNTER, offB_HOST_EvC_FAILADDR;
215 UChar insn_bytes[64];
sewardjcf787902004-11-03 09:08:33 +0000216 IRType guest_word_type;
217 IRType host_word_type;
sewardjc6f970f2012-04-02 21:54:49 +0000218 Bool mode64, chainingAllowed;
219 Addr64 max_ga;
sewardjf13a16a2004-07-05 17:10:14 +0000220
sewardj49651f42004-10-28 22:11:04 +0000221 guest_layout = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000222 available_real_regs = NULL;
223 n_available_real_regs = 0;
224 isMove = NULL;
225 getRegUsage = NULL;
226 mapRegs = NULL;
227 genSpill = NULL;
228 genReload = NULL;
sewardjfb7373a2007-08-25 21:29:03 +0000229 directReload = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000230 ppInstr = NULL;
231 ppReg = NULL;
sewardjdd40fdf2006-12-24 02:20:24 +0000232 iselSB = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000233 emit = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000234 specHelper = NULL;
sewardj8d2291c2004-10-25 14:50:21 +0000235 preciseMemExnsFn = NULL;
sewardj9e6491a2005-07-02 19:24:10 +0000236 disInstrFn = NULL;
sewardjcf787902004-11-03 09:08:33 +0000237 guest_word_type = Ity_INVALID;
238 host_word_type = Ity_INVALID;
sewardjdb4738a2005-07-07 01:32:16 +0000239 offB_TISTART = 0;
240 offB_TILEN = 0;
sewardjc6f970f2012-04-02 21:54:49 +0000241 offB_GUEST_IP = 0;
242 szB_GUEST_IP = 0;
243 offB_HOST_EvC_COUNTER = 0;
244 offB_HOST_EvC_FAILADDR = 0;
cerion92b64362005-12-13 12:02:26 +0000245 mode64 = False;
sewardjc6f970f2012-04-02 21:54:49 +0000246 chainingAllowed = False;
sewardj36ca5132004-07-24 13:12:23 +0000247
sewardj17c7f952005-12-15 14:02:34 +0000248 vex_traceflags = vta->traceflags;
sewardj58800ff2004-07-28 01:51:10 +0000249
sewardj35421a32004-07-05 13:12:34 +0000250 vassert(vex_initdone);
sewardjc6f970f2012-04-02 21:54:49 +0000251 vassert(vta->needs_self_check != NULL);
252 vassert(vta->disp_cp_xassisted != NULL);
253 /* Both the chainers and the indir are either NULL or non-NULL. */
254 if (vta->disp_cp_chain_me_to_slowEP != NULL) {
255 vassert(vta->disp_cp_chain_me_to_fastEP != NULL);
256 vassert(vta->disp_cp_xindir != NULL);
257 chainingAllowed = True;
258 } else {
259 vassert(vta->disp_cp_chain_me_to_fastEP == NULL);
260 vassert(vta->disp_cp_xindir == NULL);
261 }
florian2eeeb9b2011-09-23 18:03:21 +0000262
sewardj2d6b14a2005-11-23 04:25:07 +0000263 vexSetAllocModeTEMP_and_clear();
264 vexAllocSanityCheck();
sewardj2a9ad022004-11-25 02:46:58 +0000265
sewardjf13a16a2004-07-05 17:10:14 +0000266 /* First off, check that the guest and host insn sets
267 are supported. */
sewardj2a9ad022004-11-25 02:46:58 +0000268
sewardj17c7f952005-12-15 14:02:34 +0000269 switch (vta->arch_host) {
sewardj2a9ad022004-11-25 02:46:58 +0000270
sewardjbef170b2004-12-21 01:23:00 +0000271 case VexArchX86:
sewardjfb7373a2007-08-25 21:29:03 +0000272 mode64 = False;
sewardjf13a16a2004-07-05 17:10:14 +0000273 getAllocableRegs_X86 ( &n_available_real_regs,
274 &available_real_regs );
sewardjfb7373a2007-08-25 21:29:03 +0000275 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000276 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
277 getRegUsage_X86Instr;
sewardjfb7373a2007-08-25 21:29:03 +0000278 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000279 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
280 genSpill_X86;
281 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
282 genReload_X86;
sewardjfb7373a2007-08-25 21:29:03 +0000283 directReload = (HInstr*(*)(HInstr*,HReg,Short)) directReload_X86;
284 ppInstr = (void(*)(HInstr*, Bool)) ppX86Instr;
285 ppReg = (void(*)(HReg)) ppHRegX86;
286 iselSB = iselSB_X86;
sewardjc6f970f2012-04-02 21:54:49 +0000287 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
288 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000289 emit_X86Instr;
sewardj72c72812005-01-19 11:49:45 +0000290 host_is_bigendian = False;
sewardjcf787902004-11-03 09:08:33 +0000291 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000292 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_host.hwcaps));
sewardjf13a16a2004-07-05 17:10:14 +0000293 break;
sewardj2a9ad022004-11-25 02:46:58 +0000294
sewardjc33671d2005-02-01 20:30:00 +0000295 case VexArchAMD64:
cerion92b64362005-12-13 12:02:26 +0000296 mode64 = True;
sewardjc33671d2005-02-01 20:30:00 +0000297 getAllocableRegs_AMD64 ( &n_available_real_regs,
298 &available_real_regs );
299 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000300 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
301 getRegUsage_AMD64Instr;
cerion92b64362005-12-13 12:02:26 +0000302 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000303 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
304 genSpill_AMD64;
305 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
306 genReload_AMD64;
cerion92b64362005-12-13 12:02:26 +0000307 ppInstr = (void(*)(HInstr*, Bool)) ppAMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000308 ppReg = (void(*)(HReg)) ppHRegAMD64;
sewardjdd40fdf2006-12-24 02:20:24 +0000309 iselSB = iselSB_AMD64;
sewardjc6f970f2012-04-02 21:54:49 +0000310 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
311 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000312 emit_AMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000313 host_is_bigendian = False;
314 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000315 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_host.hwcaps));
sewardjc33671d2005-02-01 20:30:00 +0000316 break;
317
cerion487e4c92005-02-04 16:28:19 +0000318 case VexArchPPC32:
cerion92b64362005-12-13 12:02:26 +0000319 mode64 = False;
cerion5b2325f2005-12-23 00:55:09 +0000320 getAllocableRegs_PPC ( &n_available_real_regs,
321 &available_real_regs, mode64 );
322 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
323 getRegUsage = (void(*)(HRegUsage*,HInstr*,Bool)) getRegUsage_PPCInstr;
324 mapRegs = (void(*)(HRegRemap*,HInstr*,Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000325 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
326 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000327 ppInstr = (void(*)(HInstr*,Bool)) ppPPCInstr;
328 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000329 iselSB = iselSB_PPC;
sewardj3dee8492012-04-20 00:13:28 +0000330 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
331 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000332 emit_PPCInstr;
cerion487e4c92005-02-04 16:28:19 +0000333 host_is_bigendian = True;
334 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000335 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_host.hwcaps));
cerion487e4c92005-02-04 16:28:19 +0000336 break;
337
cerionf0de28c2005-12-13 20:21:11 +0000338 case VexArchPPC64:
339 mode64 = True;
cerion5b2325f2005-12-23 00:55:09 +0000340 getAllocableRegs_PPC ( &n_available_real_regs,
341 &available_real_regs, mode64 );
342 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
343 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_PPCInstr;
344 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000345 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
346 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000347 ppInstr = (void(*)(HInstr*, Bool)) ppPPCInstr;
348 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000349 iselSB = iselSB_PPC;
sewardj9e1cf152012-04-20 02:18:31 +0000350 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
351 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000352 emit_PPCInstr;
cerionf0de28c2005-12-13 20:21:11 +0000353 host_is_bigendian = True;
354 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000355 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_host.hwcaps));
cerionf0de28c2005-12-13 20:21:11 +0000356 break;
357
sewardj2019a972011-03-07 16:04:07 +0000358 case VexArchS390X:
359 mode64 = True;
360 getAllocableRegs_S390 ( &n_available_real_regs,
361 &available_real_regs, mode64 );
362 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_S390Instr;
363 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_S390Instr;
364 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_S390Instr;
365 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_S390;
366 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_S390;
367 ppInstr = (void(*)(HInstr*, Bool)) ppS390Instr;
368 ppReg = (void(*)(HReg)) ppHRegS390;
369 iselSB = iselSB_S390;
florian8844a632012-04-13 04:04:06 +0000370 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
371 void*,void*,void*,void*)) emit_S390Instr;
sewardj2019a972011-03-07 16:04:07 +0000372 host_is_bigendian = True;
373 host_word_type = Ity_I64;
374 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_host.hwcaps));
sewardj2019a972011-03-07 16:04:07 +0000375 break;
376
sewardj6c299f32009-12-31 18:00:12 +0000377 case VexArchARM:
sewardj2a1ed8e2009-12-31 19:26:03 +0000378 mode64 = False;
sewardj6c299f32009-12-31 18:00:12 +0000379 getAllocableRegs_ARM ( &n_available_real_regs,
380 &available_real_regs );
sewardj2a1ed8e2009-12-31 19:26:03 +0000381 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARMInstr;
382 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_ARMInstr;
383 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_ARMInstr;
384 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_ARM;
385 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_ARM;
386 ppInstr = (void(*)(HInstr*, Bool)) ppARMInstr;
387 ppReg = (void(*)(HReg)) ppHRegARM;
388 iselSB = iselSB_ARM;
sewardjc6f970f2012-04-02 21:54:49 +0000389 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
390 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000391 emit_ARMInstr;
sewardj6c299f32009-12-31 18:00:12 +0000392 host_is_bigendian = False;
393 host_word_type = Ity_I32;
394 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_host.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000395 break;
396
sewardjf13a16a2004-07-05 17:10:14 +0000397 default:
sewardj6c299f32009-12-31 18:00:12 +0000398 vpanic("LibVEX_Translate: unsupported host insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000399 }
400
sewardj2a9ad022004-11-25 02:46:58 +0000401
sewardj17c7f952005-12-15 14:02:34 +0000402 switch (vta->arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000403
sewardjbef170b2004-12-21 01:23:00 +0000404 case VexArchX86:
sewardjc6f970f2012-04-02 21:54:49 +0000405 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
406 disInstrFn = disInstr_X86;
407 specHelper = guest_x86_spechelper;
408 guest_sizeB = sizeof(VexGuestX86State);
409 guest_word_type = Ity_I32;
410 guest_layout = &x86guest_layout;
411 offB_TISTART = offsetof(VexGuestX86State,guest_TISTART);
412 offB_TILEN = offsetof(VexGuestX86State,guest_TILEN);
413 offB_GUEST_IP = offsetof(VexGuestX86State,guest_EIP);
414 szB_GUEST_IP = sizeof( ((VexGuestX86State*)0)->guest_EIP );
415 offB_HOST_EvC_COUNTER = offsetof(VexGuestX86State,host_EvC_COUNTER);
416 offB_HOST_EvC_FAILADDR = offsetof(VexGuestX86State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000417 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000418 vassert(0 == sizeof(VexGuestX86State) % 16);
sewardjce02aa72006-01-12 12:27:58 +0000419 vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART) == 4);
420 vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
421 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000422 break;
sewardj2a9ad022004-11-25 02:46:58 +0000423
sewardj44d494d2005-01-20 20:26:33 +0000424 case VexArchAMD64:
sewardjc6f970f2012-04-02 21:54:49 +0000425 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
426 disInstrFn = disInstr_AMD64;
427 specHelper = guest_amd64_spechelper;
428 guest_sizeB = sizeof(VexGuestAMD64State);
429 guest_word_type = Ity_I64;
430 guest_layout = &amd64guest_layout;
431 offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART);
432 offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN);
433 offB_GUEST_IP = offsetof(VexGuestAMD64State,guest_RIP);
434 szB_GUEST_IP = sizeof( ((VexGuestAMD64State*)0)->guest_RIP );
435 offB_HOST_EvC_COUNTER = offsetof(VexGuestAMD64State,host_EvC_COUNTER);
436 offB_HOST_EvC_FAILADDR = offsetof(VexGuestAMD64State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000437 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000438 vassert(0 == sizeof(VexGuestAMD64State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000439 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8);
sewardjce02aa72006-01-12 12:27:58 +0000440 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
441 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000442 break;
443
cerionaabdfbf2005-01-29 12:56:15 +0000444 case VexArchPPC32:
sewardj3dee8492012-04-20 00:13:28 +0000445 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
446 disInstrFn = disInstr_PPC;
447 specHelper = guest_ppc32_spechelper;
448 guest_sizeB = sizeof(VexGuestPPC32State);
449 guest_word_type = Ity_I32;
450 guest_layout = &ppc32Guest_layout;
451 offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART);
452 offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN);
453 offB_GUEST_IP = offsetof(VexGuestPPC32State,guest_CIA);
454 szB_GUEST_IP = sizeof( ((VexGuestPPC32State*)0)->guest_CIA );
455 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC32State,host_EvC_COUNTER);
456 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC32State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000457 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000458 vassert(0 == sizeof(VexGuestPPC32State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000459 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000460 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
461 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000462 break;
463
cerionf0de28c2005-12-13 20:21:11 +0000464 case VexArchPPC64:
sewardj9e1cf152012-04-20 02:18:31 +0000465 preciseMemExnsFn = guest_ppc64_state_requires_precise_mem_exns;
466 disInstrFn = disInstr_PPC;
467 specHelper = guest_ppc64_spechelper;
468 guest_sizeB = sizeof(VexGuestPPC64State);
469 guest_word_type = Ity_I64;
470 guest_layout = &ppc64Guest_layout;
471 offB_TISTART = offsetof(VexGuestPPC64State,guest_TISTART);
472 offB_TILEN = offsetof(VexGuestPPC64State,guest_TILEN);
473 offB_GUEST_IP = offsetof(VexGuestPPC64State,guest_CIA);
474 szB_GUEST_IP = sizeof( ((VexGuestPPC64State*)0)->guest_CIA );
475 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC64State,host_EvC_COUNTER);
476 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC64State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000477 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_guest.hwcaps));
cerionf0de28c2005-12-13 20:21:11 +0000478 vassert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj3fd39672006-01-27 22:05:55 +0000479 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TISTART ) == 8);
480 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TILEN ) == 8);
481 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8);
482 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8);
cerionf0de28c2005-12-13 20:21:11 +0000483 break;
484
sewardj2019a972011-03-07 16:04:07 +0000485 case VexArchS390X:
486 preciseMemExnsFn = guest_s390x_state_requires_precise_mem_exns;
487 disInstrFn = disInstr_S390;
488 specHelper = guest_s390x_spechelper;
489 guest_sizeB = sizeof(VexGuestS390XState);
490 guest_word_type = Ity_I64;
491 guest_layout = &s390xGuest_layout;
492 offB_TISTART = offsetof(VexGuestS390XState,guest_TISTART);
493 offB_TILEN = offsetof(VexGuestS390XState,guest_TILEN);
florian8844a632012-04-13 04:04:06 +0000494 offB_GUEST_IP = offsetof(VexGuestS390XState,guest_IA);
495 szB_GUEST_IP = sizeof( ((VexGuestS390XState*)0)->guest_IA);
496 offB_HOST_EvC_COUNTER = offsetof(VexGuestS390XState,host_EvC_COUNTER);
497 offB_HOST_EvC_FAILADDR = offsetof(VexGuestS390XState,host_EvC_FAILADDR);
sewardj2019a972011-03-07 16:04:07 +0000498 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_guest.hwcaps));
499 vassert(0 == sizeof(VexGuestS390XState) % 16);
500 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TISTART ) == 8);
501 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TILEN ) == 8);
502 vassert(sizeof( ((VexGuestS390XState*)0)->guest_NRADDR ) == 8);
503 break;
504
sewardj6c299f32009-12-31 18:00:12 +0000505 case VexArchARM:
sewardjc6f970f2012-04-02 21:54:49 +0000506 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
507 disInstrFn = disInstr_ARM;
508 specHelper = guest_arm_spechelper;
509 guest_sizeB = sizeof(VexGuestARMState);
510 guest_word_type = Ity_I32;
511 guest_layout = &armGuest_layout;
512 offB_TISTART = offsetof(VexGuestARMState,guest_TISTART);
513 offB_TILEN = offsetof(VexGuestARMState,guest_TILEN);
514 offB_GUEST_IP = offsetof(VexGuestARMState,guest_R15T);
515 szB_GUEST_IP = sizeof( ((VexGuestARMState*)0)->guest_R15T );
516 offB_HOST_EvC_COUNTER = offsetof(VexGuestARMState,host_EvC_COUNTER);
517 offB_HOST_EvC_FAILADDR = offsetof(VexGuestARMState,host_EvC_FAILADDR);
sewardj6c299f32009-12-31 18:00:12 +0000518 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_guest.hwcaps));
519 vassert(0 == sizeof(VexGuestARMState) % 16);
520 vassert(sizeof( ((VexGuestARMState*)0)->guest_TISTART) == 4);
521 vassert(sizeof( ((VexGuestARMState*)0)->guest_TILEN ) == 4);
522 vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4);
523 break;
524
sewardjf13a16a2004-07-05 17:10:14 +0000525 default:
sewardj887a11a2004-07-05 17:26:47 +0000526 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000527 }
528
sewardjbc161a42011-06-07 21:28:38 +0000529 /* Set up result struct. */
530 VexTranslateResult res;
sewardjfadbbe22012-04-24 11:49:03 +0000531 res.status = VexTransOK;
532 res.n_sc_extents = 0;
533 res.offs_profInc = -1;
534 res.n_guest_instrs = 0;
sewardjbc161a42011-06-07 21:28:38 +0000535
sewardj9df271d2004-12-31 22:37:42 +0000536 /* yet more sanity checks ... */
sewardj17c7f952005-12-15 14:02:34 +0000537 if (vta->arch_guest == vta->arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000538 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000539 we are simulating one flavour of an architecture a different
540 flavour of the same architecture, which is pretty strange. */
sewardj5117ce12006-01-27 21:20:15 +0000541 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps);
sewardj9df271d2004-12-31 22:37:42 +0000542 }
sewardj2a9ad022004-11-25 02:46:58 +0000543
sewardj2d6b14a2005-11-23 04:25:07 +0000544 vexAllocSanityCheck();
545
sewardjf48ac192004-10-29 00:41:29 +0000546 if (vex_traceflags & VEX_TRACE_FE)
547 vex_printf("\n------------------------"
548 " Front end "
549 "------------------------\n\n");
550
sewardjdd40fdf2006-12-24 02:20:24 +0000551 irsb = bb_to_IR ( vta->guest_extents,
sewardjbc161a42011-06-07 21:28:38 +0000552 &res.n_sc_extents,
sewardjfadbbe22012-04-24 11:49:03 +0000553 &res.n_guest_instrs,
sewardjc716aea2006-01-17 01:48:46 +0000554 vta->callback_opaque,
sewardj9e6491a2005-07-02 19:24:10 +0000555 disInstrFn,
sewardj17c7f952005-12-15 14:02:34 +0000556 vta->guest_bytes,
557 vta->guest_bytes_addr,
558 vta->chase_into_ok,
sewardj9e6491a2005-07-02 19:24:10 +0000559 host_is_bigendian,
sewardja5f55da2006-04-30 23:37:32 +0000560 vta->arch_guest,
sewardj17c7f952005-12-15 14:02:34 +0000561 &vta->archinfo_guest,
sewardjdd40fdf2006-12-24 02:20:24 +0000562 &vta->abiinfo_both,
sewardjdb4738a2005-07-07 01:32:16 +0000563 guest_word_type,
sewardjbc161a42011-06-07 21:28:38 +0000564 vta->needs_self_check,
sewardjc716aea2006-01-17 01:48:46 +0000565 vta->preamble_function,
sewardjdb4738a2005-07-07 01:32:16 +0000566 offB_TISTART,
sewardjc6f970f2012-04-02 21:54:49 +0000567 offB_TILEN,
568 offB_GUEST_IP,
569 szB_GUEST_IP );
sewardjf13a16a2004-07-05 17:10:14 +0000570
sewardj2d6b14a2005-11-23 04:25:07 +0000571 vexAllocSanityCheck();
572
sewardjdd40fdf2006-12-24 02:20:24 +0000573 if (irsb == NULL) {
sewardjf13a16a2004-07-05 17:10:14 +0000574 /* Access failure. */
sewardj2d6b14a2005-11-23 04:25:07 +0000575 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000576 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000577 res.status = VexTransAccessFail; return res;
sewardjf13a16a2004-07-05 17:10:14 +0000578 }
sewardjaa59f942004-10-09 09:34:36 +0000579
sewardj17c7f952005-12-15 14:02:34 +0000580 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3);
581 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr);
582 for (i = 0; i < vta->guest_extents->n_used; i++) {
583 vassert(vta->guest_extents->len[i] < 10000); /* sanity */
sewardj72c72812005-01-19 11:49:45 +0000584 }
585
sewardjaa59f942004-10-09 09:34:36 +0000586 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000587 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj17c7f952005-12-15 14:02:34 +0000588 if (vta->guest_extents->n_used > 1) {
sewardj72c72812005-01-19 11:49:45 +0000589 vex_printf("can't show code due to extents > 1\n");
590 } else {
591 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000592 UChar* p = (UChar*)vta->guest_bytes;
sewardj01f8cce2009-08-31 08:50:02 +0000593 UInt sum = 0;
sewardj17c7f952005-12-15 14:02:34 +0000594 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0];
sewardj01f8cce2009-08-31 08:50:02 +0000595 vex_printf("GuestBytes %llx %u ", vta->guest_bytes_addr,
596 guest_bytes_read );
597 for (i = 0; i < guest_bytes_read; i++) {
598 UInt b = (UInt)p[i];
599 vex_printf(" %02x", b );
600 sum = (sum << 1) ^ b;
601 }
602 vex_printf(" %08x\n\n", sum);
sewardj72c72812005-01-19 11:49:45 +0000603 }
sewardjaa59f942004-10-09 09:34:36 +0000604 }
605
606 /* Sanity check the initial IR. */
sewardjdd40fdf2006-12-24 02:20:24 +0000607 sanityCheckIRSB( irsb, "initial IR",
sewardjb9230752004-12-29 19:25:06 +0000608 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000609
sewardj2d6b14a2005-11-23 04:25:07 +0000610 vexAllocSanityCheck();
611
sewardjedf4d692004-08-17 13:52:58 +0000612 /* Clean it up, hopefully a lot. */
sewardjdd40fdf2006-12-24 02:20:24 +0000613 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn,
sewardjec0d9a02010-08-22 12:54:56 +0000614 vta->guest_bytes_addr,
615 vta->arch_guest );
sewardjdd40fdf2006-12-24 02:20:24 +0000616 sanityCheckIRSB( irsb, "after initial iropt",
sewardjb9230752004-12-29 19:25:06 +0000617 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000618
sewardjf48ac192004-10-29 00:41:29 +0000619 if (vex_traceflags & VEX_TRACE_OPT1) {
620 vex_printf("\n------------------------"
621 " After pre-instr IR optimisation "
622 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000623 ppIRSB ( irsb );
sewardjedf4d692004-08-17 13:52:58 +0000624 vex_printf("\n");
625 }
626
sewardj2d6b14a2005-11-23 04:25:07 +0000627 vexAllocSanityCheck();
628
sewardjf13a16a2004-07-05 17:10:14 +0000629 /* Get the thing instrumented. */
sewardj17c7f952005-12-15 14:02:34 +0000630 if (vta->instrument1)
sewardjdd40fdf2006-12-24 02:20:24 +0000631 irsb = vta->instrument1(vta->callback_opaque,
632 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000633 vta->guest_extents,
634 guest_word_type, host_word_type);
sewardj2d6b14a2005-11-23 04:25:07 +0000635 vexAllocSanityCheck();
636
sewardj17c7f952005-12-15 14:02:34 +0000637 if (vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000638 irsb = vta->instrument2(vta->callback_opaque,
639 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000640 vta->guest_extents,
641 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000642
sewardjf48ac192004-10-29 00:41:29 +0000643 if (vex_traceflags & VEX_TRACE_INST) {
644 vex_printf("\n------------------------"
645 " After instrumentation "
646 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000647 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000648 vex_printf("\n");
649 }
650
sewardj17c7f952005-12-15 14:02:34 +0000651 if (vta->instrument1 || vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000652 sanityCheckIRSB( irsb, "after instrumentation",
sewardjb9230752004-12-29 19:25:06 +0000653 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000654
sewardj9578a8b2004-11-04 19:44:48 +0000655 /* Do a post-instrumentation cleanup pass. */
sewardj17c7f952005-12-15 14:02:34 +0000656 if (vta->instrument1 || vta->instrument2) {
sewardjdd40fdf2006-12-24 02:20:24 +0000657 do_deadcode_BB( irsb );
658 irsb = cprop_BB( irsb );
659 do_deadcode_BB( irsb );
660 sanityCheckIRSB( irsb, "after post-instrumentation cleanup",
sewardjb9230752004-12-29 19:25:06 +0000661 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000662 }
663
sewardj2d6b14a2005-11-23 04:25:07 +0000664 vexAllocSanityCheck();
665
sewardj9578a8b2004-11-04 19:44:48 +0000666 if (vex_traceflags & VEX_TRACE_OPT2) {
667 vex_printf("\n------------------------"
668 " After post-instr IR optimisation "
669 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000670 ppIRSB ( irsb );
sewardj9578a8b2004-11-04 19:44:48 +0000671 vex_printf("\n");
672 }
673
sewardjf9517d02005-11-28 13:39:37 +0000674 /* Turn it into virtual-registerised code. Build trees -- this
675 also throws away any dead bindings. */
sewardjc6f970f2012-04-02 21:54:49 +0000676 max_ga = ado_treebuild_BB( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000677
sewardjbe1b6ff2007-08-28 06:06:27 +0000678 if (vta->finaltidy) {
679 irsb = vta->finaltidy(irsb);
680 }
681
sewardj2d6b14a2005-11-23 04:25:07 +0000682 vexAllocSanityCheck();
683
sewardjf48ac192004-10-29 00:41:29 +0000684 if (vex_traceflags & VEX_TRACE_TREES) {
685 vex_printf("\n------------------------"
686 " After tree-building "
687 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000688 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000689 vex_printf("\n");
690 }
691
sewardje908c422005-02-04 21:18:16 +0000692 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000693 if (0) {
694 *(vta->host_bytes_used) = 0;
695 res.status = VexTransOK; return res;
696 }
sewardje908c422005-02-04 21:18:16 +0000697 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000698
sewardjf48ac192004-10-29 00:41:29 +0000699 if (vex_traceflags & VEX_TRACE_VCODE)
700 vex_printf("\n------------------------"
701 " Instruction selection "
702 "------------------------\n");
703
sewardjc6f970f2012-04-02 21:54:49 +0000704 /* No guest has its IP field at offset zero. If this fails it
705 means some transformation pass somewhere failed to update/copy
706 irsb->offsIP properly. */
707 vassert(irsb->offsIP >= 16);
708
709 vcode = iselSB ( irsb, vta->arch_host,
710 &vta->archinfo_host,
711 &vta->abiinfo_both,
712 offB_HOST_EvC_COUNTER,
713 offB_HOST_EvC_FAILADDR,
714 chainingAllowed,
715 vta->addProfInc,
716 max_ga );
sewardjf13a16a2004-07-05 17:10:14 +0000717
sewardj2d6b14a2005-11-23 04:25:07 +0000718 vexAllocSanityCheck();
719
sewardjf48ac192004-10-29 00:41:29 +0000720 if (vex_traceflags & VEX_TRACE_VCODE)
721 vex_printf("\n");
722
sewardjf48ac192004-10-29 00:41:29 +0000723 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000724 for (i = 0; i < vcode->arr_used; i++) {
725 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000726 ppInstr(vcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000727 vex_printf("\n");
728 }
sewardjfbcaf332004-07-08 01:46:01 +0000729 vex_printf("\n");
730 }
sewardjfbcaf332004-07-08 01:46:01 +0000731
sewardjf13a16a2004-07-05 17:10:14 +0000732 /* Register allocate. */
733 rcode = doRegisterAllocation ( vcode, available_real_regs,
cerionf0de28c2005-12-13 20:21:11 +0000734 n_available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000735 isMove, getRegUsage, mapRegs,
sewardjfb7373a2007-08-25 21:29:03 +0000736 genSpill, genReload, directReload,
737 guest_sizeB,
cerion92b64362005-12-13 12:02:26 +0000738 ppInstr, ppReg, mode64 );
sewardjf13a16a2004-07-05 17:10:14 +0000739
sewardj2d6b14a2005-11-23 04:25:07 +0000740 vexAllocSanityCheck();
741
sewardjf48ac192004-10-29 00:41:29 +0000742 if (vex_traceflags & VEX_TRACE_RCODE) {
743 vex_printf("\n------------------------"
744 " Register-allocated code "
745 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000746 for (i = 0; i < rcode->arr_used; i++) {
747 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000748 ppInstr(rcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000749 vex_printf("\n");
750 }
sewardjfbcaf332004-07-08 01:46:01 +0000751 vex_printf("\n");
752 }
sewardjfbcaf332004-07-08 01:46:01 +0000753
sewardje908c422005-02-04 21:18:16 +0000754 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000755 if (0) {
756 *(vta->host_bytes_used) = 0;
757 res.status = VexTransOK; return res;
758 }
sewardje908c422005-02-04 21:18:16 +0000759 /* end HACK */
760
sewardj81bd5502004-07-21 18:49:27 +0000761 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000762 if (vex_traceflags & VEX_TRACE_ASM) {
763 vex_printf("\n------------------------"
764 " Assembly "
765 "------------------------\n\n");
766 }
767
sewardj81bd5502004-07-21 18:49:27 +0000768 out_used = 0; /* tracks along the host_bytes array */
769 for (i = 0; i < rcode->arr_used; i++) {
sewardjc6f970f2012-04-02 21:54:49 +0000770 HInstr* hi = rcode->arr[i];
771 Bool hi_isProfInc = False;
772 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
773 ppInstr(hi, mode64);
sewardjbad34a92004-07-22 01:14:11 +0000774 vex_printf("\n");
775 }
sewardjc6f970f2012-04-02 21:54:49 +0000776 j = emit( &hi_isProfInc,
777 insn_bytes, sizeof insn_bytes, hi, mode64,
778 vta->disp_cp_chain_me_to_slowEP,
779 vta->disp_cp_chain_me_to_fastEP,
780 vta->disp_cp_xindir,
781 vta->disp_cp_xassisted );
782 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
sewardjbad34a92004-07-22 01:14:11 +0000783 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000784 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000785 vex_printf("0%x ", (UInt)insn_bytes[k]);
786 else
787 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000788 vex_printf("\n\n");
789 }
sewardjc6f970f2012-04-02 21:54:49 +0000790 if (UNLIKELY(out_used + j > vta->host_bytes_size)) {
sewardj2d6b14a2005-11-23 04:25:07 +0000791 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000792 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000793 res.status = VexTransOutputFull;
794 return res;
sewardj81bd5502004-07-21 18:49:27 +0000795 }
sewardjc6f970f2012-04-02 21:54:49 +0000796 if (UNLIKELY(hi_isProfInc)) {
797 vassert(vta->addProfInc); /* else where did it come from? */
798 vassert(res.offs_profInc == -1); /* there can be only one (tm) */
799 vassert(out_used >= 0);
800 res.offs_profInc = out_used;
801 }
802 { UChar* dst = &vta->host_bytes[out_used];
803 for (k = 0; k < j; k++) {
804 dst[k] = insn_bytes[k];
805 }
806 out_used += j;
sewardj81bd5502004-07-21 18:49:27 +0000807 }
sewardj17c7f952005-12-15 14:02:34 +0000808 vassert(out_used <= vta->host_bytes_size);
sewardj81bd5502004-07-21 18:49:27 +0000809 }
sewardj17c7f952005-12-15 14:02:34 +0000810 *(vta->host_bytes_used) = out_used;
sewardj81bd5502004-07-21 18:49:27 +0000811
sewardj2d6b14a2005-11-23 04:25:07 +0000812 vexAllocSanityCheck();
813
814 vexSetAllocModeTEMP_and_clear();
sewardjf13a16a2004-07-05 17:10:14 +0000815
sewardjf48ac192004-10-29 00:41:29 +0000816 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000817 res.status = VexTransOK;
818 return res;
sewardj35421a32004-07-05 13:12:34 +0000819}
820
821
sewardjc6f970f2012-04-02 21:54:49 +0000822/* --------- Chain/Unchain XDirects. --------- */
823
824VexInvalRange LibVEX_Chain ( VexArch arch_host,
825 void* place_to_chain,
826 void* disp_cp_chain_me_EXPECTED,
827 void* place_to_jump_to )
828{
829 VexInvalRange (*chainXDirect)(void*, void*, void*) = NULL;
830 switch (arch_host) {
831 case VexArchX86:
832 chainXDirect = chainXDirect_X86; break;
833 case VexArchAMD64:
834 chainXDirect = chainXDirect_AMD64; break;
835 case VexArchARM:
836 chainXDirect = chainXDirect_ARM; break;
florian8844a632012-04-13 04:04:06 +0000837 case VexArchS390X:
838 chainXDirect = chainXDirect_S390; break;
sewardj3dee8492012-04-20 00:13:28 +0000839 case VexArchPPC32:
840 return chainXDirect_PPC(place_to_chain,
841 disp_cp_chain_me_EXPECTED,
842 place_to_jump_to, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +0000843 case VexArchPPC64:
844 return chainXDirect_PPC(place_to_chain,
845 disp_cp_chain_me_EXPECTED,
846 place_to_jump_to, True/*mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +0000847 default:
848 vassert(0);
849 }
850 vassert(chainXDirect);
851 VexInvalRange vir
852 = chainXDirect(place_to_chain, disp_cp_chain_me_EXPECTED,
853 place_to_jump_to);
854 return vir;
855}
856
857VexInvalRange LibVEX_UnChain ( VexArch arch_host,
858 void* place_to_unchain,
859 void* place_to_jump_to_EXPECTED,
860 void* disp_cp_chain_me )
861{
862 VexInvalRange (*unchainXDirect)(void*, void*, void*) = NULL;
863 switch (arch_host) {
864 case VexArchX86:
865 unchainXDirect = unchainXDirect_X86; break;
866 case VexArchAMD64:
867 unchainXDirect = unchainXDirect_AMD64; break;
868 case VexArchARM:
869 unchainXDirect = unchainXDirect_ARM; break;
florian8844a632012-04-13 04:04:06 +0000870 case VexArchS390X:
871 unchainXDirect = unchainXDirect_S390; break;
sewardj3dee8492012-04-20 00:13:28 +0000872 case VexArchPPC32:
873 return unchainXDirect_PPC(place_to_unchain,
874 place_to_jump_to_EXPECTED,
875 disp_cp_chain_me, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +0000876 case VexArchPPC64:
877 return unchainXDirect_PPC(place_to_unchain,
878 place_to_jump_to_EXPECTED,
879 disp_cp_chain_me, True/*mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +0000880 default:
881 vassert(0);
882 }
883 vassert(unchainXDirect);
884 VexInvalRange vir
885 = unchainXDirect(place_to_unchain, place_to_jump_to_EXPECTED,
886 disp_cp_chain_me);
887 return vir;
888}
889
890Int LibVEX_evCheckSzB ( VexArch arch_host )
891{
892 static Int cached = 0; /* DO NOT MAKE NON-STATIC */
893 if (UNLIKELY(cached == 0)) {
894 switch (arch_host) {
895 case VexArchX86:
896 cached = evCheckSzB_X86(); break;
897 case VexArchAMD64:
898 cached = evCheckSzB_AMD64(); break;
899 case VexArchARM:
900 cached = evCheckSzB_ARM(); break;
florian8844a632012-04-13 04:04:06 +0000901 case VexArchS390X:
902 cached = evCheckSzB_S390(); break;
sewardj3dee8492012-04-20 00:13:28 +0000903 case VexArchPPC32:
sewardjf252de52012-04-20 10:42:24 +0000904 case VexArchPPC64:
sewardj3dee8492012-04-20 00:13:28 +0000905 cached = evCheckSzB_PPC(); break;
sewardjc6f970f2012-04-02 21:54:49 +0000906 default:
907 vassert(0);
908 }
909 }
910 return cached;
911}
912
913VexInvalRange LibVEX_PatchProfInc ( VexArch arch_host,
914 void* place_to_patch,
915 ULong* location_of_counter )
916{
917 VexInvalRange (*patchProfInc)(void*,ULong*) = NULL;
918 switch (arch_host) {
919 case VexArchX86:
920 patchProfInc = patchProfInc_X86; break;
921 case VexArchAMD64:
922 patchProfInc = patchProfInc_AMD64; break;
923 case VexArchARM:
924 patchProfInc = patchProfInc_ARM; break;
florian8844a632012-04-13 04:04:06 +0000925 case VexArchS390X:
926 patchProfInc = patchProfInc_S390; break;
sewardj3dee8492012-04-20 00:13:28 +0000927 case VexArchPPC32:
928 return patchProfInc_PPC(place_to_patch,
929 location_of_counter, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +0000930 case VexArchPPC64:
931 return patchProfInc_PPC(place_to_patch,
932 location_of_counter, True/*mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +0000933 default:
934 vassert(0);
935 }
936 vassert(patchProfInc);
937 VexInvalRange vir
938 = patchProfInc(place_to_patch, location_of_counter);
939 return vir;
940}
941
942
sewardj893aada2004-11-29 19:57:54 +0000943/* --------- Emulation warnings. --------- */
944
945HChar* LibVEX_EmWarn_string ( VexEmWarn ew )
946{
947 switch (ew) {
948 case EmWarn_NONE:
949 return "none";
950 case EmWarn_X86_x87exns:
951 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000952 case EmWarn_X86_x87precision:
953 return "Selection of non-80-bit x87 FP precision";
954 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +0000955 return "Unmasking SSE FP exceptions";
956 case EmWarn_X86_fz:
957 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
958 case EmWarn_X86_daz:
959 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +0000960 case EmWarn_X86_acFlag:
961 return "Setting %eflags.ac (setting noted but ignored)";
sewardj9dd9cf12006-01-20 14:13:55 +0000962 case EmWarn_PPCexns:
963 return "Unmasking PPC32/64 FP exceptions";
964 case EmWarn_PPC64_redir_overflow:
965 return "PPC64 function redirection stack overflow";
966 case EmWarn_PPC64_redir_underflow:
967 return "PPC64 function redirection stack underflow";
sewardj893aada2004-11-29 19:57:54 +0000968 default:
969 vpanic("LibVEX_EmWarn_string: unknown warning");
970 }
971}
sewardj35421a32004-07-05 13:12:34 +0000972
sewardj5117ce12006-01-27 21:20:15 +0000973/* ------------------ Arch/HwCaps stuff. ------------------ */
sewardjbef170b2004-12-21 01:23:00 +0000974
975const HChar* LibVEX_ppVexArch ( VexArch arch )
976{
977 switch (arch) {
978 case VexArch_INVALID: return "INVALID";
979 case VexArchX86: return "X86";
980 case VexArchAMD64: return "AMD64";
981 case VexArchARM: return "ARM";
sewardj0ec57c52005-02-01 15:24:10 +0000982 case VexArchPPC32: return "PPC32";
cerionf0de28c2005-12-13 20:21:11 +0000983 case VexArchPPC64: return "PPC64";
sewardj2019a972011-03-07 16:04:07 +0000984 case VexArchS390X: return "S390X";
sewardjbef170b2004-12-21 01:23:00 +0000985 default: return "VexArch???";
986 }
987}
988
sewardj5117ce12006-01-27 21:20:15 +0000989const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
sewardjbef170b2004-12-21 01:23:00 +0000990{
sewardj5117ce12006-01-27 21:20:15 +0000991 HChar* str = show_hwcaps(arch,hwcaps);
992 return str ? str : "INVALID";
sewardjbef170b2004-12-21 01:23:00 +0000993}
994
sewardj5117ce12006-01-27 21:20:15 +0000995
sewardj27e1dd62005-06-30 11:49:14 +0000996/* Write default settings info *vai. */
997void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
998{
sewardj5117ce12006-01-27 21:20:15 +0000999 vai->hwcaps = 0;
cerion5b2325f2005-12-23 00:55:09 +00001000 vai->ppc_cache_line_szB = 0;
sewardje971c6a2010-09-03 15:49:57 +00001001 vai->ppc_dcbz_szB = 0;
1002 vai->ppc_dcbzl_szB = 0;
1003
sewardj27e1dd62005-06-30 11:49:14 +00001004}
1005
sewardjdd40fdf2006-12-24 02:20:24 +00001006/* Write default settings info *vbi. */
1007void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
sewardjaca070a2006-10-17 00:28:22 +00001008{
sewardjdd40fdf2006-12-24 02:20:24 +00001009 vbi->guest_stack_redzone_size = 0;
sewardj2e28ac42008-12-04 00:05:12 +00001010 vbi->guest_amd64_assume_fs_is_zero = False;
1011 vbi->guest_amd64_assume_gs_is_0x60 = False;
sewardjdd40fdf2006-12-24 02:20:24 +00001012 vbi->guest_ppc_zap_RZ_at_blr = False;
1013 vbi->guest_ppc_zap_RZ_at_bl = NULL;
1014 vbi->guest_ppc_sc_continues_at_LR = False;
1015 vbi->host_ppc_calls_use_fndescrs = False;
1016 vbi->host_ppc32_regalign_int64_args = False;
sewardjaca070a2006-10-17 00:28:22 +00001017}
1018
sewardj27e1dd62005-06-30 11:49:14 +00001019
sewardj5117ce12006-01-27 21:20:15 +00001020/* Return a string showing the hwcaps in a nice way. The string will
1021 be NULL for invalid combinations of flags, so these functions also
1022 serve as a way to validate hwcaps values. */
1023
1024static HChar* show_hwcaps_x86 ( UInt hwcaps )
1025{
1026 /* Monotonic, SSE3 > SSE2 > SSE1 > baseline. */
sewardj536fbab2010-07-29 15:39:05 +00001027 switch (hwcaps) {
1028 case 0:
1029 return "x86-sse0";
1030 case VEX_HWCAPS_X86_SSE1:
1031 return "x86-sse1";
1032 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2:
1033 return "x86-sse1-sse2";
1034 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
1035 | VEX_HWCAPS_X86_LZCNT:
1036 return "x86-sse1-sse2-lzcnt";
1037 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
1038 | VEX_HWCAPS_X86_SSE3:
1039 return "x86-sse1-sse2-sse3";
1040 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
1041 | VEX_HWCAPS_X86_SSE3 | VEX_HWCAPS_X86_LZCNT:
1042 return "x86-sse1-sse2-sse3-lzcnt";
1043 default:
1044 return NULL;
1045 }
sewardj5117ce12006-01-27 21:20:15 +00001046}
1047
1048static HChar* show_hwcaps_amd64 ( UInt hwcaps )
1049{
sewardje9d8a262009-07-01 08:06:34 +00001050 /* SSE3 and CX16 are orthogonal and > baseline, although we really
1051 don't expect to come across anything which can do SSE3 but can't
sewardj536fbab2010-07-29 15:39:05 +00001052 do CX16. Still, we can handle that case. LZCNT is similarly
1053 orthogonal. */
1054 switch (hwcaps) {
1055 case 0:
1056 return "amd64-sse2";
1057 case VEX_HWCAPS_AMD64_SSE3:
1058 return "amd64-sse3";
1059 case VEX_HWCAPS_AMD64_CX16:
1060 return "amd64-sse2-cx16";
1061 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16:
1062 return "amd64-sse3-cx16";
1063 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_LZCNT:
1064 return "amd64-sse3-lzcnt";
1065 case VEX_HWCAPS_AMD64_CX16 | VEX_HWCAPS_AMD64_LZCNT:
1066 return "amd64-sse2-cx16-lzcnt";
1067 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16
1068 | VEX_HWCAPS_AMD64_LZCNT:
1069 return "amd64-sse3-cx16-lzcnt";
1070
1071 default:
1072 return NULL;
1073 }
sewardj5117ce12006-01-27 21:20:15 +00001074}
1075
1076static HChar* show_hwcaps_ppc32 ( UInt hwcaps )
1077{
1078 /* Monotonic with complications. Basically V > F > baseline,
1079 but once you have F then you can have FX or GX too. */
1080 const UInt F = VEX_HWCAPS_PPC32_F;
1081 const UInt V = VEX_HWCAPS_PPC32_V;
1082 const UInt FX = VEX_HWCAPS_PPC32_FX;
1083 const UInt GX = VEX_HWCAPS_PPC32_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001084 const UInt VX = VEX_HWCAPS_PPC32_VX;
sewardjc66d6fa2012-04-02 21:24:12 +00001085 const UInt DFP = VEX_HWCAPS_PPC32_DFP;
sewardj5117ce12006-01-27 21:20:15 +00001086 UInt c = hwcaps;
1087 if (c == 0) return "ppc32-int";
1088 if (c == F) return "ppc32-int-flt";
1089 if (c == (F|FX)) return "ppc32-int-flt-FX";
1090 if (c == (F|GX)) return "ppc32-int-flt-GX";
1091 if (c == (F|FX|GX)) return "ppc32-int-flt-FX-GX";
1092 if (c == (F|V)) return "ppc32-int-flt-vmx";
1093 if (c == (F|V|FX)) return "ppc32-int-flt-vmx-FX";
1094 if (c == (F|V|GX)) return "ppc32-int-flt-vmx-GX";
1095 if (c == (F|V|FX|GX)) return "ppc32-int-flt-vmx-FX-GX";
sewardjc66d6fa2012-04-02 21:24:12 +00001096 if (c == (F|V|FX|GX|DFP)) return "ppc32-int-flt-vmx-FX-GX-DFP";
1097 if (c == (F|V|FX|GX|VX|DFP)) return "ppc32-int-flt-vmx-FX-GX-VX-DFP";
sewardj5117ce12006-01-27 21:20:15 +00001098 return NULL;
1099}
1100
1101static HChar* show_hwcaps_ppc64 ( UInt hwcaps )
1102{
1103 /* Monotonic with complications. Basically V > baseline(==F),
1104 but once you have F then you can have FX or GX too. */
sewardj3fd39672006-01-27 22:05:55 +00001105 const UInt V = VEX_HWCAPS_PPC64_V;
1106 const UInt FX = VEX_HWCAPS_PPC64_FX;
1107 const UInt GX = VEX_HWCAPS_PPC64_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001108 const UInt VX = VEX_HWCAPS_PPC64_VX;
sewardjc66d6fa2012-04-02 21:24:12 +00001109 const UInt DFP = VEX_HWCAPS_PPC64_DFP;
sewardj5117ce12006-01-27 21:20:15 +00001110 UInt c = hwcaps;
1111 if (c == 0) return "ppc64-int-flt";
1112 if (c == FX) return "ppc64-int-flt-FX";
1113 if (c == GX) return "ppc64-int-flt-GX";
1114 if (c == (FX|GX)) return "ppc64-int-flt-FX-GX";
1115 if (c == V) return "ppc64-int-flt-vmx";
1116 if (c == (V|FX)) return "ppc64-int-flt-vmx-FX";
1117 if (c == (V|GX)) return "ppc64-int-flt-vmx-GX";
1118 if (c == (V|FX|GX)) return "ppc64-int-flt-vmx-FX-GX";
sewardjc66d6fa2012-04-02 21:24:12 +00001119 if (c == (V|FX|GX|DFP)) return "ppc64-int-flt-vmx-FX-GX-DFP";
1120 if (c == (V|FX|GX|VX|DFP)) return "ppc64-int-flt-vmx-FX-GX-VX-DFP";
sewardj5117ce12006-01-27 21:20:15 +00001121 return NULL;
1122}
1123
1124static HChar* show_hwcaps_arm ( UInt hwcaps )
1125{
sewardjec0d9a02010-08-22 12:54:56 +00001126 Bool N = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0);
1127 Bool vfp = ((hwcaps & (VEX_HWCAPS_ARM_VFP |
1128 VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3)) != 0);
1129 switch (VEX_ARM_ARCHLEVEL(hwcaps)) {
1130 case 5:
1131 if (N)
1132 return NULL;
1133 if (vfp)
1134 return "ARMv5-vfp";
1135 else
1136 return "ARMv5";
1137 return NULL;
1138 case 6:
1139 if (N)
1140 return NULL;
1141 if (vfp)
1142 return "ARMv6-vfp";
1143 else
1144 return "ARMv6";
1145 return NULL;
1146 case 7:
1147 if (vfp) {
1148 if (N)
1149 return "ARMv7-vfp-neon";
1150 else
1151 return "ARMv7-vfp";
1152 } else {
1153 if (N)
1154 return "ARMv7-neon";
1155 else
1156 return "ARMv7";
1157 }
1158 default:
1159 return NULL;
1160 }
sewardj5117ce12006-01-27 21:20:15 +00001161 return NULL;
1162}
1163
sewardj2019a972011-03-07 16:04:07 +00001164static HChar* show_hwcaps_s390x ( UInt hwcaps )
1165{
sewardjd07b8562011-04-27 11:58:22 +00001166 static const HChar prefix[] = "s390x";
1167 static const HChar facilities[][6] = {
1168 { "ldisp" },
1169 { "eimm" },
1170 { "gie" },
1171 { "dfp" },
1172 { "fgx" },
florian90ece042012-04-21 15:41:51 +00001173 { "stfle" },
1174 { "etf2" },
sewardjd07b8562011-04-27 11:58:22 +00001175 };
1176 static HChar buf[sizeof facilities + sizeof prefix + 1];
1177 static HChar *p;
1178
1179 if (buf[0] != '\0') return buf; /* already constructed */
sewardj2019a972011-03-07 16:04:07 +00001180
sewardj652b56a2011-04-13 15:38:17 +00001181 hwcaps = VEX_HWCAPS_S390X(hwcaps);
1182
sewardjd07b8562011-04-27 11:58:22 +00001183 p = buf + vex_sprintf(buf, "%s", prefix);
1184 if (hwcaps & VEX_HWCAPS_S390X_LDISP)
1185 p = p + vex_sprintf(p, "-%s", facilities[0]);
1186 if (hwcaps & VEX_HWCAPS_S390X_EIMM)
1187 p = p + vex_sprintf(p, "-%s", facilities[1]);
1188 if (hwcaps & VEX_HWCAPS_S390X_GIE)
1189 p = p + vex_sprintf(p, "-%s", facilities[2]);
1190 if (hwcaps & VEX_HWCAPS_S390X_DFP)
1191 p = p + vex_sprintf(p, "-%s", facilities[3]);
1192 if (hwcaps & VEX_HWCAPS_S390X_FGX)
1193 p = p + vex_sprintf(p, "-%s", facilities[4]);
florian90ece042012-04-21 15:41:51 +00001194 if (hwcaps & VEX_HWCAPS_S390X_STFLE)
1195 p = p + vex_sprintf(p, "-%s", facilities[5]);
1196 if (hwcaps & VEX_HWCAPS_S390X_ETF2)
1197 p = p + vex_sprintf(p, "-%s", facilities[6]);
sewardj2019a972011-03-07 16:04:07 +00001198
sewardjd07b8562011-04-27 11:58:22 +00001199 /* If there are no facilities, add "zarch" */
1200 if (hwcaps == 0)
1201 vex_sprintf(p, "-%s", "zarch");
1202
1203 return buf;
sewardj2019a972011-03-07 16:04:07 +00001204}
1205
sewardj5117ce12006-01-27 21:20:15 +00001206/* ---- */
1207static HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
1208{
1209 switch (arch) {
sewardj3fd39672006-01-27 22:05:55 +00001210 case VexArchX86: return show_hwcaps_x86(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001211 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
1212 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
1213 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
sewardj3fd39672006-01-27 22:05:55 +00001214 case VexArchARM: return show_hwcaps_arm(hwcaps);
sewardj2019a972011-03-07 16:04:07 +00001215 case VexArchS390X: return show_hwcaps_s390x(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001216 default: return NULL;
1217 }
1218}
1219
1220static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps )
1221{
1222 return show_hwcaps(arch,hwcaps) != NULL;
1223}
1224
1225
sewardj35421a32004-07-05 13:12:34 +00001226/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +00001227/*--- end main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +00001228/*---------------------------------------------------------------*/