blob: 460f443d462a37c5feda545e2435e15dda600d88 [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;
sewardj3dee8492012-04-20 00:13:28 +0000317
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;
sewardj3dee8492012-04-20 00:13:28 +0000337#if 0
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;
sewardj010ac542011-05-29 09:29:18 +0000350 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
351 emit_PPCInstr;
cerionf0de28c2005-12-13 20:21:11 +0000352 host_is_bigendian = True;
353 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000354 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_host.hwcaps));
sewardj010ac542011-05-29 09:29:18 +0000355 /* return-to-dispatcher scheme */
356 vassert(vta->dispatch_unassisted == NULL);
357 vassert(vta->dispatch_assisted == NULL);
cerionf0de28c2005-12-13 20:21:11 +0000358 break;
florian8844a632012-04-13 04:04:06 +0000359#endif
sewardj2019a972011-03-07 16:04:07 +0000360 case VexArchS390X:
361 mode64 = True;
362 getAllocableRegs_S390 ( &n_available_real_regs,
363 &available_real_regs, mode64 );
364 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_S390Instr;
365 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_S390Instr;
366 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_S390Instr;
367 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_S390;
368 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_S390;
369 ppInstr = (void(*)(HInstr*, Bool)) ppS390Instr;
370 ppReg = (void(*)(HReg)) ppHRegS390;
371 iselSB = iselSB_S390;
florian8844a632012-04-13 04:04:06 +0000372 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
373 void*,void*,void*,void*)) emit_S390Instr;
sewardj2019a972011-03-07 16:04:07 +0000374 host_is_bigendian = True;
375 host_word_type = Ity_I64;
376 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_host.hwcaps));
sewardj2019a972011-03-07 16:04:07 +0000377 break;
florian8844a632012-04-13 04:04:06 +0000378
sewardj6c299f32009-12-31 18:00:12 +0000379 case VexArchARM:
sewardj2a1ed8e2009-12-31 19:26:03 +0000380 mode64 = False;
sewardj6c299f32009-12-31 18:00:12 +0000381 getAllocableRegs_ARM ( &n_available_real_regs,
382 &available_real_regs );
sewardj2a1ed8e2009-12-31 19:26:03 +0000383 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARMInstr;
384 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_ARMInstr;
385 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_ARMInstr;
386 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_ARM;
387 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_ARM;
388 ppInstr = (void(*)(HInstr*, Bool)) ppARMInstr;
389 ppReg = (void(*)(HReg)) ppHRegARM;
390 iselSB = iselSB_ARM;
sewardjc6f970f2012-04-02 21:54:49 +0000391 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
392 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000393 emit_ARMInstr;
sewardj6c299f32009-12-31 18:00:12 +0000394 host_is_bigendian = False;
395 host_word_type = Ity_I32;
396 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_host.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000397 break;
398
sewardjf13a16a2004-07-05 17:10:14 +0000399 default:
sewardj6c299f32009-12-31 18:00:12 +0000400 vpanic("LibVEX_Translate: unsupported host insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000401 }
402
sewardj2a9ad022004-11-25 02:46:58 +0000403
sewardj17c7f952005-12-15 14:02:34 +0000404 switch (vta->arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000405
sewardjbef170b2004-12-21 01:23:00 +0000406 case VexArchX86:
sewardjc6f970f2012-04-02 21:54:49 +0000407 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
408 disInstrFn = disInstr_X86;
409 specHelper = guest_x86_spechelper;
410 guest_sizeB = sizeof(VexGuestX86State);
411 guest_word_type = Ity_I32;
412 guest_layout = &x86guest_layout;
413 offB_TISTART = offsetof(VexGuestX86State,guest_TISTART);
414 offB_TILEN = offsetof(VexGuestX86State,guest_TILEN);
415 offB_GUEST_IP = offsetof(VexGuestX86State,guest_EIP);
416 szB_GUEST_IP = sizeof( ((VexGuestX86State*)0)->guest_EIP );
417 offB_HOST_EvC_COUNTER = offsetof(VexGuestX86State,host_EvC_COUNTER);
418 offB_HOST_EvC_FAILADDR = offsetof(VexGuestX86State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000419 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000420 vassert(0 == sizeof(VexGuestX86State) % 16);
sewardjce02aa72006-01-12 12:27:58 +0000421 vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART) == 4);
422 vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
423 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000424 break;
sewardj2a9ad022004-11-25 02:46:58 +0000425
sewardj44d494d2005-01-20 20:26:33 +0000426 case VexArchAMD64:
sewardjc6f970f2012-04-02 21:54:49 +0000427 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
428 disInstrFn = disInstr_AMD64;
429 specHelper = guest_amd64_spechelper;
430 guest_sizeB = sizeof(VexGuestAMD64State);
431 guest_word_type = Ity_I64;
432 guest_layout = &amd64guest_layout;
433 offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART);
434 offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN);
435 offB_GUEST_IP = offsetof(VexGuestAMD64State,guest_RIP);
436 szB_GUEST_IP = sizeof( ((VexGuestAMD64State*)0)->guest_RIP );
437 offB_HOST_EvC_COUNTER = offsetof(VexGuestAMD64State,host_EvC_COUNTER);
438 offB_HOST_EvC_FAILADDR = offsetof(VexGuestAMD64State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000439 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000440 vassert(0 == sizeof(VexGuestAMD64State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000441 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8);
sewardjce02aa72006-01-12 12:27:58 +0000442 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
443 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000444 break;
sewardj3dee8492012-04-20 00:13:28 +0000445
cerionaabdfbf2005-01-29 12:56:15 +0000446 case VexArchPPC32:
sewardj3dee8492012-04-20 00:13:28 +0000447 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
448 disInstrFn = disInstr_PPC;
449 specHelper = guest_ppc32_spechelper;
450 guest_sizeB = sizeof(VexGuestPPC32State);
451 guest_word_type = Ity_I32;
452 guest_layout = &ppc32Guest_layout;
453 offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART);
454 offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN);
455 offB_GUEST_IP = offsetof(VexGuestPPC32State,guest_CIA);
456 szB_GUEST_IP = sizeof( ((VexGuestPPC32State*)0)->guest_CIA );
457 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC32State,host_EvC_COUNTER);
458 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC32State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000459 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000460 vassert(0 == sizeof(VexGuestPPC32State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000461 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000462 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
463 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000464 break;
sewardj3dee8492012-04-20 00:13:28 +0000465#if 0
cerionf0de28c2005-12-13 20:21:11 +0000466 case VexArchPPC64:
467 preciseMemExnsFn = guest_ppc64_state_requires_precise_mem_exns;
cerion5b2325f2005-12-23 00:55:09 +0000468 disInstrFn = disInstr_PPC;
cerionf0de28c2005-12-13 20:21:11 +0000469 specHelper = guest_ppc64_spechelper;
470 guest_sizeB = sizeof(VexGuestPPC64State);
471 guest_word_type = Ity_I64;
472 guest_layout = &ppc64Guest_layout;
473 offB_TISTART = offsetof(VexGuestPPC64State,guest_TISTART);
474 offB_TILEN = offsetof(VexGuestPPC64State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000475 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_guest.hwcaps));
cerionf0de28c2005-12-13 20:21:11 +0000476 vassert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj3fd39672006-01-27 22:05:55 +0000477 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TISTART ) == 8);
478 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TILEN ) == 8);
479 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8);
480 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8);
cerionf0de28c2005-12-13 20:21:11 +0000481 break;
florian8844a632012-04-13 04:04:06 +0000482#endif
sewardj2019a972011-03-07 16:04:07 +0000483 case VexArchS390X:
484 preciseMemExnsFn = guest_s390x_state_requires_precise_mem_exns;
485 disInstrFn = disInstr_S390;
486 specHelper = guest_s390x_spechelper;
487 guest_sizeB = sizeof(VexGuestS390XState);
488 guest_word_type = Ity_I64;
489 guest_layout = &s390xGuest_layout;
490 offB_TISTART = offsetof(VexGuestS390XState,guest_TISTART);
491 offB_TILEN = offsetof(VexGuestS390XState,guest_TILEN);
florian8844a632012-04-13 04:04:06 +0000492 offB_GUEST_IP = offsetof(VexGuestS390XState,guest_IA);
493 szB_GUEST_IP = sizeof( ((VexGuestS390XState*)0)->guest_IA);
494 offB_HOST_EvC_COUNTER = offsetof(VexGuestS390XState,host_EvC_COUNTER);
495 offB_HOST_EvC_FAILADDR = offsetof(VexGuestS390XState,host_EvC_FAILADDR);
sewardj2019a972011-03-07 16:04:07 +0000496 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_guest.hwcaps));
497 vassert(0 == sizeof(VexGuestS390XState) % 16);
498 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TISTART ) == 8);
499 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TILEN ) == 8);
500 vassert(sizeof( ((VexGuestS390XState*)0)->guest_NRADDR ) == 8);
501 break;
florian8844a632012-04-13 04:04:06 +0000502
sewardj6c299f32009-12-31 18:00:12 +0000503 case VexArchARM:
sewardjc6f970f2012-04-02 21:54:49 +0000504 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
505 disInstrFn = disInstr_ARM;
506 specHelper = guest_arm_spechelper;
507 guest_sizeB = sizeof(VexGuestARMState);
508 guest_word_type = Ity_I32;
509 guest_layout = &armGuest_layout;
510 offB_TISTART = offsetof(VexGuestARMState,guest_TISTART);
511 offB_TILEN = offsetof(VexGuestARMState,guest_TILEN);
512 offB_GUEST_IP = offsetof(VexGuestARMState,guest_R15T);
513 szB_GUEST_IP = sizeof( ((VexGuestARMState*)0)->guest_R15T );
514 offB_HOST_EvC_COUNTER = offsetof(VexGuestARMState,host_EvC_COUNTER);
515 offB_HOST_EvC_FAILADDR = offsetof(VexGuestARMState,host_EvC_FAILADDR);
sewardj6c299f32009-12-31 18:00:12 +0000516 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_guest.hwcaps));
517 vassert(0 == sizeof(VexGuestARMState) % 16);
518 vassert(sizeof( ((VexGuestARMState*)0)->guest_TISTART) == 4);
519 vassert(sizeof( ((VexGuestARMState*)0)->guest_TILEN ) == 4);
520 vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4);
521 break;
522
sewardjf13a16a2004-07-05 17:10:14 +0000523 default:
sewardj887a11a2004-07-05 17:26:47 +0000524 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000525 }
526
sewardjbc161a42011-06-07 21:28:38 +0000527 /* Set up result struct. */
528 VexTranslateResult res;
529 res.status = VexTransOK;
530 res.n_sc_extents = 0;
sewardjc6f970f2012-04-02 21:54:49 +0000531 res.offs_profInc = -1;
sewardjbc161a42011-06-07 21:28:38 +0000532
sewardj9df271d2004-12-31 22:37:42 +0000533 /* yet more sanity checks ... */
sewardj17c7f952005-12-15 14:02:34 +0000534 if (vta->arch_guest == vta->arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000535 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000536 we are simulating one flavour of an architecture a different
537 flavour of the same architecture, which is pretty strange. */
sewardj5117ce12006-01-27 21:20:15 +0000538 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps);
sewardj9df271d2004-12-31 22:37:42 +0000539 }
sewardj2a9ad022004-11-25 02:46:58 +0000540
sewardj2d6b14a2005-11-23 04:25:07 +0000541 vexAllocSanityCheck();
542
sewardjf48ac192004-10-29 00:41:29 +0000543 if (vex_traceflags & VEX_TRACE_FE)
544 vex_printf("\n------------------------"
545 " Front end "
546 "------------------------\n\n");
547
sewardjdd40fdf2006-12-24 02:20:24 +0000548 irsb = bb_to_IR ( vta->guest_extents,
sewardjbc161a42011-06-07 21:28:38 +0000549 &res.n_sc_extents,
sewardjc716aea2006-01-17 01:48:46 +0000550 vta->callback_opaque,
sewardj9e6491a2005-07-02 19:24:10 +0000551 disInstrFn,
sewardj17c7f952005-12-15 14:02:34 +0000552 vta->guest_bytes,
553 vta->guest_bytes_addr,
554 vta->chase_into_ok,
sewardj9e6491a2005-07-02 19:24:10 +0000555 host_is_bigendian,
sewardja5f55da2006-04-30 23:37:32 +0000556 vta->arch_guest,
sewardj17c7f952005-12-15 14:02:34 +0000557 &vta->archinfo_guest,
sewardjdd40fdf2006-12-24 02:20:24 +0000558 &vta->abiinfo_both,
sewardjdb4738a2005-07-07 01:32:16 +0000559 guest_word_type,
sewardjbc161a42011-06-07 21:28:38 +0000560 vta->needs_self_check,
sewardjc716aea2006-01-17 01:48:46 +0000561 vta->preamble_function,
sewardjdb4738a2005-07-07 01:32:16 +0000562 offB_TISTART,
sewardjc6f970f2012-04-02 21:54:49 +0000563 offB_TILEN,
564 offB_GUEST_IP,
565 szB_GUEST_IP );
sewardjf13a16a2004-07-05 17:10:14 +0000566
sewardj2d6b14a2005-11-23 04:25:07 +0000567 vexAllocSanityCheck();
568
sewardjdd40fdf2006-12-24 02:20:24 +0000569 if (irsb == NULL) {
sewardjf13a16a2004-07-05 17:10:14 +0000570 /* Access failure. */
sewardj2d6b14a2005-11-23 04:25:07 +0000571 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000572 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000573 res.status = VexTransAccessFail; return res;
sewardjf13a16a2004-07-05 17:10:14 +0000574 }
sewardjaa59f942004-10-09 09:34:36 +0000575
sewardj17c7f952005-12-15 14:02:34 +0000576 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3);
577 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr);
578 for (i = 0; i < vta->guest_extents->n_used; i++) {
579 vassert(vta->guest_extents->len[i] < 10000); /* sanity */
sewardj72c72812005-01-19 11:49:45 +0000580 }
581
sewardjaa59f942004-10-09 09:34:36 +0000582 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000583 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj17c7f952005-12-15 14:02:34 +0000584 if (vta->guest_extents->n_used > 1) {
sewardj72c72812005-01-19 11:49:45 +0000585 vex_printf("can't show code due to extents > 1\n");
586 } else {
587 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000588 UChar* p = (UChar*)vta->guest_bytes;
sewardj01f8cce2009-08-31 08:50:02 +0000589 UInt sum = 0;
sewardj17c7f952005-12-15 14:02:34 +0000590 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0];
sewardj01f8cce2009-08-31 08:50:02 +0000591 vex_printf("GuestBytes %llx %u ", vta->guest_bytes_addr,
592 guest_bytes_read );
593 for (i = 0; i < guest_bytes_read; i++) {
594 UInt b = (UInt)p[i];
595 vex_printf(" %02x", b );
596 sum = (sum << 1) ^ b;
597 }
598 vex_printf(" %08x\n\n", sum);
sewardj72c72812005-01-19 11:49:45 +0000599 }
sewardjaa59f942004-10-09 09:34:36 +0000600 }
601
602 /* Sanity check the initial IR. */
sewardjdd40fdf2006-12-24 02:20:24 +0000603 sanityCheckIRSB( irsb, "initial IR",
sewardjb9230752004-12-29 19:25:06 +0000604 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000605
sewardj2d6b14a2005-11-23 04:25:07 +0000606 vexAllocSanityCheck();
607
sewardjedf4d692004-08-17 13:52:58 +0000608 /* Clean it up, hopefully a lot. */
sewardjdd40fdf2006-12-24 02:20:24 +0000609 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn,
sewardjec0d9a02010-08-22 12:54:56 +0000610 vta->guest_bytes_addr,
611 vta->arch_guest );
sewardjdd40fdf2006-12-24 02:20:24 +0000612 sanityCheckIRSB( irsb, "after initial iropt",
sewardjb9230752004-12-29 19:25:06 +0000613 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000614
sewardjf48ac192004-10-29 00:41:29 +0000615 if (vex_traceflags & VEX_TRACE_OPT1) {
616 vex_printf("\n------------------------"
617 " After pre-instr IR optimisation "
618 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000619 ppIRSB ( irsb );
sewardjedf4d692004-08-17 13:52:58 +0000620 vex_printf("\n");
621 }
622
sewardj2d6b14a2005-11-23 04:25:07 +0000623 vexAllocSanityCheck();
624
sewardjf13a16a2004-07-05 17:10:14 +0000625 /* Get the thing instrumented. */
sewardj17c7f952005-12-15 14:02:34 +0000626 if (vta->instrument1)
sewardjdd40fdf2006-12-24 02:20:24 +0000627 irsb = vta->instrument1(vta->callback_opaque,
628 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000629 vta->guest_extents,
630 guest_word_type, host_word_type);
sewardj2d6b14a2005-11-23 04:25:07 +0000631 vexAllocSanityCheck();
632
sewardj17c7f952005-12-15 14:02:34 +0000633 if (vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000634 irsb = vta->instrument2(vta->callback_opaque,
635 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000636 vta->guest_extents,
637 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000638
sewardjf48ac192004-10-29 00:41:29 +0000639 if (vex_traceflags & VEX_TRACE_INST) {
640 vex_printf("\n------------------------"
641 " After instrumentation "
642 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000643 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000644 vex_printf("\n");
645 }
646
sewardj17c7f952005-12-15 14:02:34 +0000647 if (vta->instrument1 || vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000648 sanityCheckIRSB( irsb, "after instrumentation",
sewardjb9230752004-12-29 19:25:06 +0000649 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000650
sewardj9578a8b2004-11-04 19:44:48 +0000651 /* Do a post-instrumentation cleanup pass. */
sewardj17c7f952005-12-15 14:02:34 +0000652 if (vta->instrument1 || vta->instrument2) {
sewardjdd40fdf2006-12-24 02:20:24 +0000653 do_deadcode_BB( irsb );
654 irsb = cprop_BB( irsb );
655 do_deadcode_BB( irsb );
656 sanityCheckIRSB( irsb, "after post-instrumentation cleanup",
sewardjb9230752004-12-29 19:25:06 +0000657 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000658 }
659
sewardj2d6b14a2005-11-23 04:25:07 +0000660 vexAllocSanityCheck();
661
sewardj9578a8b2004-11-04 19:44:48 +0000662 if (vex_traceflags & VEX_TRACE_OPT2) {
663 vex_printf("\n------------------------"
664 " After post-instr IR optimisation "
665 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000666 ppIRSB ( irsb );
sewardj9578a8b2004-11-04 19:44:48 +0000667 vex_printf("\n");
668 }
669
sewardjf9517d02005-11-28 13:39:37 +0000670 /* Turn it into virtual-registerised code. Build trees -- this
671 also throws away any dead bindings. */
sewardjc6f970f2012-04-02 21:54:49 +0000672 max_ga = ado_treebuild_BB( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000673
sewardjbe1b6ff2007-08-28 06:06:27 +0000674 if (vta->finaltidy) {
675 irsb = vta->finaltidy(irsb);
676 }
677
sewardj2d6b14a2005-11-23 04:25:07 +0000678 vexAllocSanityCheck();
679
sewardjf48ac192004-10-29 00:41:29 +0000680 if (vex_traceflags & VEX_TRACE_TREES) {
681 vex_printf("\n------------------------"
682 " After tree-building "
683 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000684 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000685 vex_printf("\n");
686 }
687
sewardje908c422005-02-04 21:18:16 +0000688 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000689 if (0) {
690 *(vta->host_bytes_used) = 0;
691 res.status = VexTransOK; return res;
692 }
sewardje908c422005-02-04 21:18:16 +0000693 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000694
sewardjf48ac192004-10-29 00:41:29 +0000695 if (vex_traceflags & VEX_TRACE_VCODE)
696 vex_printf("\n------------------------"
697 " Instruction selection "
698 "------------------------\n");
699
sewardjc6f970f2012-04-02 21:54:49 +0000700 /* No guest has its IP field at offset zero. If this fails it
701 means some transformation pass somewhere failed to update/copy
702 irsb->offsIP properly. */
703 vassert(irsb->offsIP >= 16);
704
705 vcode = iselSB ( irsb, vta->arch_host,
706 &vta->archinfo_host,
707 &vta->abiinfo_both,
708 offB_HOST_EvC_COUNTER,
709 offB_HOST_EvC_FAILADDR,
710 chainingAllowed,
711 vta->addProfInc,
712 max_ga );
sewardjf13a16a2004-07-05 17:10:14 +0000713
sewardj2d6b14a2005-11-23 04:25:07 +0000714 vexAllocSanityCheck();
715
sewardjf48ac192004-10-29 00:41:29 +0000716 if (vex_traceflags & VEX_TRACE_VCODE)
717 vex_printf("\n");
718
sewardjf48ac192004-10-29 00:41:29 +0000719 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000720 for (i = 0; i < vcode->arr_used; i++) {
721 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000722 ppInstr(vcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000723 vex_printf("\n");
724 }
sewardjfbcaf332004-07-08 01:46:01 +0000725 vex_printf("\n");
726 }
sewardjfbcaf332004-07-08 01:46:01 +0000727
sewardjf13a16a2004-07-05 17:10:14 +0000728 /* Register allocate. */
729 rcode = doRegisterAllocation ( vcode, available_real_regs,
cerionf0de28c2005-12-13 20:21:11 +0000730 n_available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000731 isMove, getRegUsage, mapRegs,
sewardjfb7373a2007-08-25 21:29:03 +0000732 genSpill, genReload, directReload,
733 guest_sizeB,
cerion92b64362005-12-13 12:02:26 +0000734 ppInstr, ppReg, mode64 );
sewardjf13a16a2004-07-05 17:10:14 +0000735
sewardj2d6b14a2005-11-23 04:25:07 +0000736 vexAllocSanityCheck();
737
sewardjf48ac192004-10-29 00:41:29 +0000738 if (vex_traceflags & VEX_TRACE_RCODE) {
739 vex_printf("\n------------------------"
740 " Register-allocated code "
741 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000742 for (i = 0; i < rcode->arr_used; i++) {
743 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000744 ppInstr(rcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000745 vex_printf("\n");
746 }
sewardjfbcaf332004-07-08 01:46:01 +0000747 vex_printf("\n");
748 }
sewardjfbcaf332004-07-08 01:46:01 +0000749
sewardje908c422005-02-04 21:18:16 +0000750 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000751 if (0) {
752 *(vta->host_bytes_used) = 0;
753 res.status = VexTransOK; return res;
754 }
sewardje908c422005-02-04 21:18:16 +0000755 /* end HACK */
756
sewardj81bd5502004-07-21 18:49:27 +0000757 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000758 if (vex_traceflags & VEX_TRACE_ASM) {
759 vex_printf("\n------------------------"
760 " Assembly "
761 "------------------------\n\n");
762 }
763
sewardj81bd5502004-07-21 18:49:27 +0000764 out_used = 0; /* tracks along the host_bytes array */
765 for (i = 0; i < rcode->arr_used; i++) {
sewardjc6f970f2012-04-02 21:54:49 +0000766 HInstr* hi = rcode->arr[i];
767 Bool hi_isProfInc = False;
768 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
769 ppInstr(hi, mode64);
sewardjbad34a92004-07-22 01:14:11 +0000770 vex_printf("\n");
771 }
sewardjc6f970f2012-04-02 21:54:49 +0000772 j = emit( &hi_isProfInc,
773 insn_bytes, sizeof insn_bytes, hi, mode64,
774 vta->disp_cp_chain_me_to_slowEP,
775 vta->disp_cp_chain_me_to_fastEP,
776 vta->disp_cp_xindir,
777 vta->disp_cp_xassisted );
778 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
sewardjbad34a92004-07-22 01:14:11 +0000779 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000780 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000781 vex_printf("0%x ", (UInt)insn_bytes[k]);
782 else
783 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000784 vex_printf("\n\n");
785 }
sewardjc6f970f2012-04-02 21:54:49 +0000786 if (UNLIKELY(out_used + j > vta->host_bytes_size)) {
sewardj2d6b14a2005-11-23 04:25:07 +0000787 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000788 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000789 res.status = VexTransOutputFull;
790 return res;
sewardj81bd5502004-07-21 18:49:27 +0000791 }
sewardjc6f970f2012-04-02 21:54:49 +0000792 if (UNLIKELY(hi_isProfInc)) {
793 vassert(vta->addProfInc); /* else where did it come from? */
794 vassert(res.offs_profInc == -1); /* there can be only one (tm) */
795 vassert(out_used >= 0);
796 res.offs_profInc = out_used;
797 }
798 { UChar* dst = &vta->host_bytes[out_used];
799 for (k = 0; k < j; k++) {
800 dst[k] = insn_bytes[k];
801 }
802 out_used += j;
sewardj81bd5502004-07-21 18:49:27 +0000803 }
sewardj17c7f952005-12-15 14:02:34 +0000804 vassert(out_used <= vta->host_bytes_size);
sewardj81bd5502004-07-21 18:49:27 +0000805 }
sewardj17c7f952005-12-15 14:02:34 +0000806 *(vta->host_bytes_used) = out_used;
sewardj81bd5502004-07-21 18:49:27 +0000807
sewardj2d6b14a2005-11-23 04:25:07 +0000808 vexAllocSanityCheck();
809
810 vexSetAllocModeTEMP_and_clear();
sewardjf13a16a2004-07-05 17:10:14 +0000811
sewardjf48ac192004-10-29 00:41:29 +0000812 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000813 res.status = VexTransOK;
814 return res;
sewardj35421a32004-07-05 13:12:34 +0000815}
816
817
sewardjc6f970f2012-04-02 21:54:49 +0000818/* --------- Chain/Unchain XDirects. --------- */
819
820VexInvalRange LibVEX_Chain ( VexArch arch_host,
821 void* place_to_chain,
822 void* disp_cp_chain_me_EXPECTED,
823 void* place_to_jump_to )
824{
825 VexInvalRange (*chainXDirect)(void*, void*, void*) = NULL;
826 switch (arch_host) {
827 case VexArchX86:
828 chainXDirect = chainXDirect_X86; break;
829 case VexArchAMD64:
830 chainXDirect = chainXDirect_AMD64; break;
831 case VexArchARM:
832 chainXDirect = chainXDirect_ARM; break;
florian8844a632012-04-13 04:04:06 +0000833 case VexArchS390X:
834 chainXDirect = chainXDirect_S390; break;
sewardj3dee8492012-04-20 00:13:28 +0000835 case VexArchPPC32:
836 return chainXDirect_PPC(place_to_chain,
837 disp_cp_chain_me_EXPECTED,
838 place_to_jump_to, False/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +0000839 default:
840 vassert(0);
841 }
842 vassert(chainXDirect);
843 VexInvalRange vir
844 = chainXDirect(place_to_chain, disp_cp_chain_me_EXPECTED,
845 place_to_jump_to);
846 return vir;
847}
848
849VexInvalRange LibVEX_UnChain ( VexArch arch_host,
850 void* place_to_unchain,
851 void* place_to_jump_to_EXPECTED,
852 void* disp_cp_chain_me )
853{
854 VexInvalRange (*unchainXDirect)(void*, void*, void*) = NULL;
855 switch (arch_host) {
856 case VexArchX86:
857 unchainXDirect = unchainXDirect_X86; break;
858 case VexArchAMD64:
859 unchainXDirect = unchainXDirect_AMD64; break;
860 case VexArchARM:
861 unchainXDirect = unchainXDirect_ARM; break;
florian8844a632012-04-13 04:04:06 +0000862 case VexArchS390X:
863 unchainXDirect = unchainXDirect_S390; break;
sewardj3dee8492012-04-20 00:13:28 +0000864 case VexArchPPC32:
865 return unchainXDirect_PPC(place_to_unchain,
866 place_to_jump_to_EXPECTED,
867 disp_cp_chain_me, False/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +0000868 default:
869 vassert(0);
870 }
871 vassert(unchainXDirect);
872 VexInvalRange vir
873 = unchainXDirect(place_to_unchain, place_to_jump_to_EXPECTED,
874 disp_cp_chain_me);
875 return vir;
876}
877
878Int LibVEX_evCheckSzB ( VexArch arch_host )
879{
880 static Int cached = 0; /* DO NOT MAKE NON-STATIC */
881 if (UNLIKELY(cached == 0)) {
882 switch (arch_host) {
883 case VexArchX86:
884 cached = evCheckSzB_X86(); break;
885 case VexArchAMD64:
886 cached = evCheckSzB_AMD64(); break;
887 case VexArchARM:
888 cached = evCheckSzB_ARM(); break;
florian8844a632012-04-13 04:04:06 +0000889 case VexArchS390X:
890 cached = evCheckSzB_S390(); break;
sewardj3dee8492012-04-20 00:13:28 +0000891 case VexArchPPC32:
892 cached = evCheckSzB_PPC(); break;
sewardjc6f970f2012-04-02 21:54:49 +0000893 default:
894 vassert(0);
895 }
896 }
897 return cached;
898}
899
900VexInvalRange LibVEX_PatchProfInc ( VexArch arch_host,
901 void* place_to_patch,
902 ULong* location_of_counter )
903{
904 VexInvalRange (*patchProfInc)(void*,ULong*) = NULL;
905 switch (arch_host) {
906 case VexArchX86:
907 patchProfInc = patchProfInc_X86; break;
908 case VexArchAMD64:
909 patchProfInc = patchProfInc_AMD64; break;
910 case VexArchARM:
911 patchProfInc = patchProfInc_ARM; break;
florian8844a632012-04-13 04:04:06 +0000912 case VexArchS390X:
913 patchProfInc = patchProfInc_S390; break;
sewardj3dee8492012-04-20 00:13:28 +0000914 case VexArchPPC32:
915 return patchProfInc_PPC(place_to_patch,
916 location_of_counter, False/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +0000917 default:
918 vassert(0);
919 }
920 vassert(patchProfInc);
921 VexInvalRange vir
922 = patchProfInc(place_to_patch, location_of_counter);
923 return vir;
924}
925
926
sewardj893aada2004-11-29 19:57:54 +0000927/* --------- Emulation warnings. --------- */
928
929HChar* LibVEX_EmWarn_string ( VexEmWarn ew )
930{
931 switch (ew) {
932 case EmWarn_NONE:
933 return "none";
934 case EmWarn_X86_x87exns:
935 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000936 case EmWarn_X86_x87precision:
937 return "Selection of non-80-bit x87 FP precision";
938 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +0000939 return "Unmasking SSE FP exceptions";
940 case EmWarn_X86_fz:
941 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
942 case EmWarn_X86_daz:
943 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +0000944 case EmWarn_X86_acFlag:
945 return "Setting %eflags.ac (setting noted but ignored)";
sewardj9dd9cf12006-01-20 14:13:55 +0000946 case EmWarn_PPCexns:
947 return "Unmasking PPC32/64 FP exceptions";
948 case EmWarn_PPC64_redir_overflow:
949 return "PPC64 function redirection stack overflow";
950 case EmWarn_PPC64_redir_underflow:
951 return "PPC64 function redirection stack underflow";
sewardj893aada2004-11-29 19:57:54 +0000952 default:
953 vpanic("LibVEX_EmWarn_string: unknown warning");
954 }
955}
sewardj35421a32004-07-05 13:12:34 +0000956
sewardj5117ce12006-01-27 21:20:15 +0000957/* ------------------ Arch/HwCaps stuff. ------------------ */
sewardjbef170b2004-12-21 01:23:00 +0000958
959const HChar* LibVEX_ppVexArch ( VexArch arch )
960{
961 switch (arch) {
962 case VexArch_INVALID: return "INVALID";
963 case VexArchX86: return "X86";
964 case VexArchAMD64: return "AMD64";
965 case VexArchARM: return "ARM";
sewardj0ec57c52005-02-01 15:24:10 +0000966 case VexArchPPC32: return "PPC32";
cerionf0de28c2005-12-13 20:21:11 +0000967 case VexArchPPC64: return "PPC64";
sewardj2019a972011-03-07 16:04:07 +0000968 case VexArchS390X: return "S390X";
sewardjbef170b2004-12-21 01:23:00 +0000969 default: return "VexArch???";
970 }
971}
972
sewardj5117ce12006-01-27 21:20:15 +0000973const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
sewardjbef170b2004-12-21 01:23:00 +0000974{
sewardj5117ce12006-01-27 21:20:15 +0000975 HChar* str = show_hwcaps(arch,hwcaps);
976 return str ? str : "INVALID";
sewardjbef170b2004-12-21 01:23:00 +0000977}
978
sewardj5117ce12006-01-27 21:20:15 +0000979
sewardj27e1dd62005-06-30 11:49:14 +0000980/* Write default settings info *vai. */
981void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
982{
sewardj5117ce12006-01-27 21:20:15 +0000983 vai->hwcaps = 0;
cerion5b2325f2005-12-23 00:55:09 +0000984 vai->ppc_cache_line_szB = 0;
sewardje971c6a2010-09-03 15:49:57 +0000985 vai->ppc_dcbz_szB = 0;
986 vai->ppc_dcbzl_szB = 0;
987
sewardj27e1dd62005-06-30 11:49:14 +0000988}
989
sewardjdd40fdf2006-12-24 02:20:24 +0000990/* Write default settings info *vbi. */
991void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
sewardjaca070a2006-10-17 00:28:22 +0000992{
sewardjdd40fdf2006-12-24 02:20:24 +0000993 vbi->guest_stack_redzone_size = 0;
sewardj2e28ac42008-12-04 00:05:12 +0000994 vbi->guest_amd64_assume_fs_is_zero = False;
995 vbi->guest_amd64_assume_gs_is_0x60 = False;
sewardjdd40fdf2006-12-24 02:20:24 +0000996 vbi->guest_ppc_zap_RZ_at_blr = False;
997 vbi->guest_ppc_zap_RZ_at_bl = NULL;
998 vbi->guest_ppc_sc_continues_at_LR = False;
999 vbi->host_ppc_calls_use_fndescrs = False;
1000 vbi->host_ppc32_regalign_int64_args = False;
sewardjaca070a2006-10-17 00:28:22 +00001001}
1002
sewardj27e1dd62005-06-30 11:49:14 +00001003
sewardj5117ce12006-01-27 21:20:15 +00001004/* Return a string showing the hwcaps in a nice way. The string will
1005 be NULL for invalid combinations of flags, so these functions also
1006 serve as a way to validate hwcaps values. */
1007
1008static HChar* show_hwcaps_x86 ( UInt hwcaps )
1009{
1010 /* Monotonic, SSE3 > SSE2 > SSE1 > baseline. */
sewardj536fbab2010-07-29 15:39:05 +00001011 switch (hwcaps) {
1012 case 0:
1013 return "x86-sse0";
1014 case VEX_HWCAPS_X86_SSE1:
1015 return "x86-sse1";
1016 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2:
1017 return "x86-sse1-sse2";
1018 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
1019 | VEX_HWCAPS_X86_LZCNT:
1020 return "x86-sse1-sse2-lzcnt";
1021 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
1022 | VEX_HWCAPS_X86_SSE3:
1023 return "x86-sse1-sse2-sse3";
1024 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
1025 | VEX_HWCAPS_X86_SSE3 | VEX_HWCAPS_X86_LZCNT:
1026 return "x86-sse1-sse2-sse3-lzcnt";
1027 default:
1028 return NULL;
1029 }
sewardj5117ce12006-01-27 21:20:15 +00001030}
1031
1032static HChar* show_hwcaps_amd64 ( UInt hwcaps )
1033{
sewardje9d8a262009-07-01 08:06:34 +00001034 /* SSE3 and CX16 are orthogonal and > baseline, although we really
1035 don't expect to come across anything which can do SSE3 but can't
sewardj536fbab2010-07-29 15:39:05 +00001036 do CX16. Still, we can handle that case. LZCNT is similarly
1037 orthogonal. */
1038 switch (hwcaps) {
1039 case 0:
1040 return "amd64-sse2";
1041 case VEX_HWCAPS_AMD64_SSE3:
1042 return "amd64-sse3";
1043 case VEX_HWCAPS_AMD64_CX16:
1044 return "amd64-sse2-cx16";
1045 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16:
1046 return "amd64-sse3-cx16";
1047 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_LZCNT:
1048 return "amd64-sse3-lzcnt";
1049 case VEX_HWCAPS_AMD64_CX16 | VEX_HWCAPS_AMD64_LZCNT:
1050 return "amd64-sse2-cx16-lzcnt";
1051 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16
1052 | VEX_HWCAPS_AMD64_LZCNT:
1053 return "amd64-sse3-cx16-lzcnt";
1054
1055 default:
1056 return NULL;
1057 }
sewardj5117ce12006-01-27 21:20:15 +00001058}
1059
1060static HChar* show_hwcaps_ppc32 ( UInt hwcaps )
1061{
1062 /* Monotonic with complications. Basically V > F > baseline,
1063 but once you have F then you can have FX or GX too. */
1064 const UInt F = VEX_HWCAPS_PPC32_F;
1065 const UInt V = VEX_HWCAPS_PPC32_V;
1066 const UInt FX = VEX_HWCAPS_PPC32_FX;
1067 const UInt GX = VEX_HWCAPS_PPC32_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001068 const UInt VX = VEX_HWCAPS_PPC32_VX;
sewardj5117ce12006-01-27 21:20:15 +00001069 UInt c = hwcaps;
1070 if (c == 0) return "ppc32-int";
1071 if (c == F) return "ppc32-int-flt";
1072 if (c == (F|FX)) return "ppc32-int-flt-FX";
1073 if (c == (F|GX)) return "ppc32-int-flt-GX";
1074 if (c == (F|FX|GX)) return "ppc32-int-flt-FX-GX";
1075 if (c == (F|V)) return "ppc32-int-flt-vmx";
1076 if (c == (F|V|FX)) return "ppc32-int-flt-vmx-FX";
1077 if (c == (F|V|GX)) return "ppc32-int-flt-vmx-GX";
1078 if (c == (F|V|FX|GX)) return "ppc32-int-flt-vmx-FX-GX";
sewardj66d5ef22011-04-15 11:55:00 +00001079 if (c == (F|V|FX|GX|VX)) return "ppc32-int-flt-vmx-FX-GX-VX";
sewardj5117ce12006-01-27 21:20:15 +00001080 return NULL;
1081}
1082
1083static HChar* show_hwcaps_ppc64 ( UInt hwcaps )
1084{
1085 /* Monotonic with complications. Basically V > baseline(==F),
1086 but once you have F then you can have FX or GX too. */
sewardj3fd39672006-01-27 22:05:55 +00001087 const UInt V = VEX_HWCAPS_PPC64_V;
1088 const UInt FX = VEX_HWCAPS_PPC64_FX;
1089 const UInt GX = VEX_HWCAPS_PPC64_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001090 const UInt VX = VEX_HWCAPS_PPC64_VX;
sewardj5117ce12006-01-27 21:20:15 +00001091 UInt c = hwcaps;
1092 if (c == 0) return "ppc64-int-flt";
1093 if (c == FX) return "ppc64-int-flt-FX";
1094 if (c == GX) return "ppc64-int-flt-GX";
1095 if (c == (FX|GX)) return "ppc64-int-flt-FX-GX";
1096 if (c == V) return "ppc64-int-flt-vmx";
1097 if (c == (V|FX)) return "ppc64-int-flt-vmx-FX";
1098 if (c == (V|GX)) return "ppc64-int-flt-vmx-GX";
1099 if (c == (V|FX|GX)) return "ppc64-int-flt-vmx-FX-GX";
sewardj66d5ef22011-04-15 11:55:00 +00001100 if (c == (V|FX|GX|VX)) return "ppc64-int-flt-vmx-FX-GX-VX";
sewardj5117ce12006-01-27 21:20:15 +00001101 return NULL;
1102}
1103
1104static HChar* show_hwcaps_arm ( UInt hwcaps )
1105{
sewardjec0d9a02010-08-22 12:54:56 +00001106 Bool N = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0);
1107 Bool vfp = ((hwcaps & (VEX_HWCAPS_ARM_VFP |
1108 VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3)) != 0);
1109 switch (VEX_ARM_ARCHLEVEL(hwcaps)) {
1110 case 5:
1111 if (N)
1112 return NULL;
1113 if (vfp)
1114 return "ARMv5-vfp";
1115 else
1116 return "ARMv5";
1117 return NULL;
1118 case 6:
1119 if (N)
1120 return NULL;
1121 if (vfp)
1122 return "ARMv6-vfp";
1123 else
1124 return "ARMv6";
1125 return NULL;
1126 case 7:
1127 if (vfp) {
1128 if (N)
1129 return "ARMv7-vfp-neon";
1130 else
1131 return "ARMv7-vfp";
1132 } else {
1133 if (N)
1134 return "ARMv7-neon";
1135 else
1136 return "ARMv7";
1137 }
1138 default:
1139 return NULL;
1140 }
sewardj5117ce12006-01-27 21:20:15 +00001141 return NULL;
1142}
1143
sewardj2019a972011-03-07 16:04:07 +00001144static HChar* show_hwcaps_s390x ( UInt hwcaps )
1145{
sewardjd07b8562011-04-27 11:58:22 +00001146 static const HChar prefix[] = "s390x";
1147 static const HChar facilities[][6] = {
1148 { "ldisp" },
1149 { "eimm" },
1150 { "gie" },
1151 { "dfp" },
1152 { "fgx" },
1153 };
1154 static HChar buf[sizeof facilities + sizeof prefix + 1];
1155 static HChar *p;
1156
1157 if (buf[0] != '\0') return buf; /* already constructed */
sewardj2019a972011-03-07 16:04:07 +00001158
sewardj652b56a2011-04-13 15:38:17 +00001159 hwcaps = VEX_HWCAPS_S390X(hwcaps);
1160
sewardjd07b8562011-04-27 11:58:22 +00001161 p = buf + vex_sprintf(buf, "%s", prefix);
1162 if (hwcaps & VEX_HWCAPS_S390X_LDISP)
1163 p = p + vex_sprintf(p, "-%s", facilities[0]);
1164 if (hwcaps & VEX_HWCAPS_S390X_EIMM)
1165 p = p + vex_sprintf(p, "-%s", facilities[1]);
1166 if (hwcaps & VEX_HWCAPS_S390X_GIE)
1167 p = p + vex_sprintf(p, "-%s", facilities[2]);
1168 if (hwcaps & VEX_HWCAPS_S390X_DFP)
1169 p = p + vex_sprintf(p, "-%s", facilities[3]);
1170 if (hwcaps & VEX_HWCAPS_S390X_FGX)
1171 p = p + vex_sprintf(p, "-%s", facilities[4]);
sewardj2019a972011-03-07 16:04:07 +00001172
sewardjd07b8562011-04-27 11:58:22 +00001173 /* If there are no facilities, add "zarch" */
1174 if (hwcaps == 0)
1175 vex_sprintf(p, "-%s", "zarch");
1176
1177 return buf;
sewardj2019a972011-03-07 16:04:07 +00001178}
1179
sewardj5117ce12006-01-27 21:20:15 +00001180/* ---- */
1181static HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
1182{
1183 switch (arch) {
sewardj3fd39672006-01-27 22:05:55 +00001184 case VexArchX86: return show_hwcaps_x86(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001185 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
1186 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
1187 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
sewardj3fd39672006-01-27 22:05:55 +00001188 case VexArchARM: return show_hwcaps_arm(hwcaps);
sewardj2019a972011-03-07 16:04:07 +00001189 case VexArchS390X: return show_hwcaps_s390x(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001190 default: return NULL;
1191 }
1192}
1193
1194static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps )
1195{
1196 return show_hwcaps(arch,hwcaps) != NULL;
1197}
1198
1199
sewardj35421a32004-07-05 13:12:34 +00001200/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +00001201/*--- end main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +00001202/*---------------------------------------------------------------*/