blob: b3ab987b03d183553d037102a78773884c19a4d4 [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));
sewardjc9069f22012-06-01 16:09:50 +0000150 vassert(32 == sizeof(U256));
sewardjea602bc2004-10-14 21:40:12 +0000151
152 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
153 vassert(sizeof(void*) == sizeof(int*));
154 vassert(sizeof(void*) == sizeof(HWord));
155
sewardj97e87932005-02-07 00:00:50 +0000156 vassert(VEX_HOST_WORDSIZE == sizeof(void*));
157 vassert(VEX_HOST_WORDSIZE == sizeof(HWord));
158
sewardjc6f970f2012-04-02 21:54:49 +0000159 /* These take a lot of space, so make sure we don't have
160 any unnoticed size regressions. */
161 if (VEX_HOST_WORDSIZE == 4) {
162 vassert(sizeof(IRExpr) == 24);
163 vassert(sizeof(IRStmt) == 20 /* x86 */
164 || sizeof(IRStmt) == 24 /* arm */);
165 } else {
166 vassert(sizeof(IRExpr) == 48);
floriand6f38b32012-05-31 15:46:18 +0000167 vassert(sizeof(IRStmt) == 32);
sewardjc6f970f2012-04-02 21:54:49 +0000168 }
169
sewardjea602bc2004-10-14 21:40:12 +0000170 /* Really start up .. */
sewardj443cd9d2004-07-18 23:06:45 +0000171 vex_debuglevel = debuglevel;
sewardj443cd9d2004-07-18 23:06:45 +0000172 vex_valgrind_support = valgrind_support;
sewardj08613742004-10-25 13:01:45 +0000173 vex_control = *vcon;
sewardj443cd9d2004-07-18 23:06:45 +0000174 vex_initdone = True;
sewardjd887b862005-01-17 18:34:34 +0000175 vexSetAllocMode ( VexAllocModeTEMP );
sewardj35421a32004-07-05 13:12:34 +0000176}
177
178
179/* --------- Make a translation. --------- */
180
181/* Exported to library client. */
182
sewardj17c7f952005-12-15 14:02:34 +0000183VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
sewardj35421a32004-07-05 13:12:34 +0000184{
sewardj81bd5502004-07-21 18:49:27 +0000185 /* This the bundle of functions we need to do the back-end stuff
186 (insn selection, reg-alloc, assembly) whilst being insulated
187 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +0000188 HReg* available_real_regs;
189 Int n_available_real_regs;
sewardjfb7373a2007-08-25 21:29:03 +0000190 Bool (*isMove) ( HInstr*, HReg*, HReg* );
191 void (*getRegUsage) ( HRegUsage*, HInstr*, Bool );
192 void (*mapRegs) ( HRegRemap*, HInstr*, Bool );
sewardj6c299f32009-12-31 18:00:12 +0000193 void (*genSpill) ( HInstr**, HInstr**, HReg, Int, Bool );
194 void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool );
sewardjfb7373a2007-08-25 21:29:03 +0000195 HInstr* (*directReload) ( HInstr*, HReg, Short );
196 void (*ppInstr) ( HInstr*, Bool );
197 void (*ppReg) ( HReg );
sewardjc6f970f2012-04-02 21:54:49 +0000198 HInstrArray* (*iselSB) ( IRSB*, VexArch, VexArchInfo*, VexAbiInfo*,
199 Int, Int, Bool, Bool, Addr64 );
200 Int (*emit) ( /*MB_MOD*/Bool*,
201 UChar*, Int, HInstr*, Bool,
202 void*, void*, void*, void* );
sewardjec0d9a02010-08-22 12:54:56 +0000203 IRExpr* (*specHelper) ( HChar*, IRExpr**, IRStmt**, Int );
sewardj8d2291c2004-10-25 14:50:21 +0000204 Bool (*preciseMemExnsFn) ( Int, Int );
sewardjf13a16a2004-07-05 17:10:14 +0000205
sewardj9e6491a2005-07-02 19:24:10 +0000206 DisOneInstrFn disInstrFn;
207
sewardjeeac8412004-11-02 00:26:55 +0000208 VexGuestLayout* guest_layout;
209 Bool host_is_bigendian = False;
sewardjdd40fdf2006-12-24 02:20:24 +0000210 IRSB* irsb;
sewardjeeac8412004-11-02 00:26:55 +0000211 HInstrArray* vcode;
212 HInstrArray* rcode;
213 Int i, j, k, out_used, guest_sizeB;
sewardjc6f970f2012-04-02 21:54:49 +0000214 Int offB_TISTART, offB_TILEN, offB_GUEST_IP, szB_GUEST_IP;
215 Int offB_HOST_EvC_COUNTER, offB_HOST_EvC_FAILADDR;
216 UChar insn_bytes[64];
sewardjcf787902004-11-03 09:08:33 +0000217 IRType guest_word_type;
218 IRType host_word_type;
sewardjc6f970f2012-04-02 21:54:49 +0000219 Bool mode64, chainingAllowed;
220 Addr64 max_ga;
sewardjf13a16a2004-07-05 17:10:14 +0000221
sewardj49651f42004-10-28 22:11:04 +0000222 guest_layout = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000223 available_real_regs = NULL;
224 n_available_real_regs = 0;
225 isMove = NULL;
226 getRegUsage = NULL;
227 mapRegs = NULL;
228 genSpill = NULL;
229 genReload = NULL;
sewardjfb7373a2007-08-25 21:29:03 +0000230 directReload = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000231 ppInstr = NULL;
232 ppReg = NULL;
sewardjdd40fdf2006-12-24 02:20:24 +0000233 iselSB = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000234 emit = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000235 specHelper = NULL;
sewardj8d2291c2004-10-25 14:50:21 +0000236 preciseMemExnsFn = NULL;
sewardj9e6491a2005-07-02 19:24:10 +0000237 disInstrFn = NULL;
sewardjcf787902004-11-03 09:08:33 +0000238 guest_word_type = Ity_INVALID;
239 host_word_type = Ity_INVALID;
sewardjdb4738a2005-07-07 01:32:16 +0000240 offB_TISTART = 0;
241 offB_TILEN = 0;
sewardjc6f970f2012-04-02 21:54:49 +0000242 offB_GUEST_IP = 0;
243 szB_GUEST_IP = 0;
244 offB_HOST_EvC_COUNTER = 0;
245 offB_HOST_EvC_FAILADDR = 0;
cerion92b64362005-12-13 12:02:26 +0000246 mode64 = False;
sewardjc6f970f2012-04-02 21:54:49 +0000247 chainingAllowed = False;
sewardj36ca5132004-07-24 13:12:23 +0000248
sewardj17c7f952005-12-15 14:02:34 +0000249 vex_traceflags = vta->traceflags;
sewardj58800ff2004-07-28 01:51:10 +0000250
sewardj35421a32004-07-05 13:12:34 +0000251 vassert(vex_initdone);
sewardjc6f970f2012-04-02 21:54:49 +0000252 vassert(vta->needs_self_check != NULL);
253 vassert(vta->disp_cp_xassisted != NULL);
254 /* Both the chainers and the indir are either NULL or non-NULL. */
255 if (vta->disp_cp_chain_me_to_slowEP != NULL) {
256 vassert(vta->disp_cp_chain_me_to_fastEP != NULL);
257 vassert(vta->disp_cp_xindir != NULL);
258 chainingAllowed = True;
259 } else {
260 vassert(vta->disp_cp_chain_me_to_fastEP == NULL);
261 vassert(vta->disp_cp_xindir == NULL);
262 }
florian2eeeb9b2011-09-23 18:03:21 +0000263
sewardj2d6b14a2005-11-23 04:25:07 +0000264 vexSetAllocModeTEMP_and_clear();
265 vexAllocSanityCheck();
sewardj2a9ad022004-11-25 02:46:58 +0000266
sewardjf13a16a2004-07-05 17:10:14 +0000267 /* First off, check that the guest and host insn sets
268 are supported. */
sewardj2a9ad022004-11-25 02:46:58 +0000269
sewardj17c7f952005-12-15 14:02:34 +0000270 switch (vta->arch_host) {
sewardj2a9ad022004-11-25 02:46:58 +0000271
sewardjbef170b2004-12-21 01:23:00 +0000272 case VexArchX86:
sewardjfb7373a2007-08-25 21:29:03 +0000273 mode64 = False;
sewardjf13a16a2004-07-05 17:10:14 +0000274 getAllocableRegs_X86 ( &n_available_real_regs,
275 &available_real_regs );
sewardjfb7373a2007-08-25 21:29:03 +0000276 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000277 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
278 getRegUsage_X86Instr;
sewardjfb7373a2007-08-25 21:29:03 +0000279 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000280 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
281 genSpill_X86;
282 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
283 genReload_X86;
sewardjfb7373a2007-08-25 21:29:03 +0000284 directReload = (HInstr*(*)(HInstr*,HReg,Short)) directReload_X86;
285 ppInstr = (void(*)(HInstr*, Bool)) ppX86Instr;
286 ppReg = (void(*)(HReg)) ppHRegX86;
287 iselSB = iselSB_X86;
sewardjc6f970f2012-04-02 21:54:49 +0000288 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
289 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000290 emit_X86Instr;
sewardj72c72812005-01-19 11:49:45 +0000291 host_is_bigendian = False;
sewardjcf787902004-11-03 09:08:33 +0000292 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000293 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_host.hwcaps));
sewardjf13a16a2004-07-05 17:10:14 +0000294 break;
sewardj2a9ad022004-11-25 02:46:58 +0000295
sewardjc33671d2005-02-01 20:30:00 +0000296 case VexArchAMD64:
cerion92b64362005-12-13 12:02:26 +0000297 mode64 = True;
sewardjc33671d2005-02-01 20:30:00 +0000298 getAllocableRegs_AMD64 ( &n_available_real_regs,
299 &available_real_regs );
300 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000301 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
302 getRegUsage_AMD64Instr;
cerion92b64362005-12-13 12:02:26 +0000303 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000304 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
305 genSpill_AMD64;
306 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
307 genReload_AMD64;
cerion92b64362005-12-13 12:02:26 +0000308 ppInstr = (void(*)(HInstr*, Bool)) ppAMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000309 ppReg = (void(*)(HReg)) ppHRegAMD64;
sewardjdd40fdf2006-12-24 02:20:24 +0000310 iselSB = iselSB_AMD64;
sewardjc6f970f2012-04-02 21:54:49 +0000311 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
312 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000313 emit_AMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000314 host_is_bigendian = False;
315 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000316 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_host.hwcaps));
sewardjc33671d2005-02-01 20:30:00 +0000317 break;
318
cerion487e4c92005-02-04 16:28:19 +0000319 case VexArchPPC32:
cerion92b64362005-12-13 12:02:26 +0000320 mode64 = False;
cerion5b2325f2005-12-23 00:55:09 +0000321 getAllocableRegs_PPC ( &n_available_real_regs,
322 &available_real_regs, mode64 );
323 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
324 getRegUsage = (void(*)(HRegUsage*,HInstr*,Bool)) getRegUsage_PPCInstr;
325 mapRegs = (void(*)(HRegRemap*,HInstr*,Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000326 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
327 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000328 ppInstr = (void(*)(HInstr*,Bool)) ppPPCInstr;
329 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000330 iselSB = iselSB_PPC;
sewardj3dee8492012-04-20 00:13:28 +0000331 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
332 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000333 emit_PPCInstr;
cerion487e4c92005-02-04 16:28:19 +0000334 host_is_bigendian = True;
335 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000336 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_host.hwcaps));
cerion487e4c92005-02-04 16:28:19 +0000337 break;
338
cerionf0de28c2005-12-13 20:21:11 +0000339 case VexArchPPC64:
340 mode64 = True;
cerion5b2325f2005-12-23 00:55:09 +0000341 getAllocableRegs_PPC ( &n_available_real_regs,
342 &available_real_regs, mode64 );
343 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
344 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_PPCInstr;
345 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000346 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
347 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000348 ppInstr = (void(*)(HInstr*, Bool)) ppPPCInstr;
349 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000350 iselSB = iselSB_PPC;
sewardj9e1cf152012-04-20 02:18:31 +0000351 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
352 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000353 emit_PPCInstr;
cerionf0de28c2005-12-13 20:21:11 +0000354 host_is_bigendian = True;
355 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000356 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_host.hwcaps));
cerionf0de28c2005-12-13 20:21:11 +0000357 break;
358
sewardj2019a972011-03-07 16:04:07 +0000359 case VexArchS390X:
360 mode64 = True;
361 getAllocableRegs_S390 ( &n_available_real_regs,
362 &available_real_regs, mode64 );
363 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_S390Instr;
364 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_S390Instr;
365 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_S390Instr;
366 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_S390;
367 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_S390;
368 ppInstr = (void(*)(HInstr*, Bool)) ppS390Instr;
369 ppReg = (void(*)(HReg)) ppHRegS390;
370 iselSB = iselSB_S390;
florian8844a632012-04-13 04:04:06 +0000371 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
372 void*,void*,void*,void*)) emit_S390Instr;
sewardj2019a972011-03-07 16:04:07 +0000373 host_is_bigendian = True;
374 host_word_type = Ity_I64;
375 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_host.hwcaps));
sewardj2019a972011-03-07 16:04:07 +0000376 break;
377
sewardj6c299f32009-12-31 18:00:12 +0000378 case VexArchARM:
sewardj2a1ed8e2009-12-31 19:26:03 +0000379 mode64 = False;
sewardj6c299f32009-12-31 18:00:12 +0000380 getAllocableRegs_ARM ( &n_available_real_regs,
381 &available_real_regs );
sewardj2a1ed8e2009-12-31 19:26:03 +0000382 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARMInstr;
383 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_ARMInstr;
384 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_ARMInstr;
385 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_ARM;
386 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_ARM;
387 ppInstr = (void(*)(HInstr*, Bool)) ppARMInstr;
388 ppReg = (void(*)(HReg)) ppHRegARM;
389 iselSB = iselSB_ARM;
sewardjc6f970f2012-04-02 21:54:49 +0000390 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
391 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000392 emit_ARMInstr;
sewardj6c299f32009-12-31 18:00:12 +0000393 host_is_bigendian = False;
394 host_word_type = Ity_I32;
395 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_host.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000396 break;
397
sewardjf13a16a2004-07-05 17:10:14 +0000398 default:
sewardj6c299f32009-12-31 18:00:12 +0000399 vpanic("LibVEX_Translate: unsupported host insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000400 }
401
sewardj2a9ad022004-11-25 02:46:58 +0000402
sewardj17c7f952005-12-15 14:02:34 +0000403 switch (vta->arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000404
sewardjbef170b2004-12-21 01:23:00 +0000405 case VexArchX86:
sewardjc6f970f2012-04-02 21:54:49 +0000406 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
407 disInstrFn = disInstr_X86;
408 specHelper = guest_x86_spechelper;
409 guest_sizeB = sizeof(VexGuestX86State);
410 guest_word_type = Ity_I32;
411 guest_layout = &x86guest_layout;
412 offB_TISTART = offsetof(VexGuestX86State,guest_TISTART);
413 offB_TILEN = offsetof(VexGuestX86State,guest_TILEN);
414 offB_GUEST_IP = offsetof(VexGuestX86State,guest_EIP);
415 szB_GUEST_IP = sizeof( ((VexGuestX86State*)0)->guest_EIP );
416 offB_HOST_EvC_COUNTER = offsetof(VexGuestX86State,host_EvC_COUNTER);
417 offB_HOST_EvC_FAILADDR = offsetof(VexGuestX86State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000418 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000419 vassert(0 == sizeof(VexGuestX86State) % 16);
sewardjce02aa72006-01-12 12:27:58 +0000420 vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART) == 4);
421 vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
422 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000423 break;
sewardj2a9ad022004-11-25 02:46:58 +0000424
sewardj44d494d2005-01-20 20:26:33 +0000425 case VexArchAMD64:
sewardjc6f970f2012-04-02 21:54:49 +0000426 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
427 disInstrFn = disInstr_AMD64;
428 specHelper = guest_amd64_spechelper;
429 guest_sizeB = sizeof(VexGuestAMD64State);
430 guest_word_type = Ity_I64;
431 guest_layout = &amd64guest_layout;
432 offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART);
433 offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN);
434 offB_GUEST_IP = offsetof(VexGuestAMD64State,guest_RIP);
435 szB_GUEST_IP = sizeof( ((VexGuestAMD64State*)0)->guest_RIP );
436 offB_HOST_EvC_COUNTER = offsetof(VexGuestAMD64State,host_EvC_COUNTER);
437 offB_HOST_EvC_FAILADDR = offsetof(VexGuestAMD64State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000438 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000439 vassert(0 == sizeof(VexGuestAMD64State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000440 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8);
sewardjce02aa72006-01-12 12:27:58 +0000441 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
442 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000443 break;
444
cerionaabdfbf2005-01-29 12:56:15 +0000445 case VexArchPPC32:
sewardj3dee8492012-04-20 00:13:28 +0000446 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
447 disInstrFn = disInstr_PPC;
448 specHelper = guest_ppc32_spechelper;
449 guest_sizeB = sizeof(VexGuestPPC32State);
450 guest_word_type = Ity_I32;
451 guest_layout = &ppc32Guest_layout;
452 offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART);
453 offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN);
454 offB_GUEST_IP = offsetof(VexGuestPPC32State,guest_CIA);
455 szB_GUEST_IP = sizeof( ((VexGuestPPC32State*)0)->guest_CIA );
456 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC32State,host_EvC_COUNTER);
457 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC32State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000458 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000459 vassert(0 == sizeof(VexGuestPPC32State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000460 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000461 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
462 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000463 break;
464
cerionf0de28c2005-12-13 20:21:11 +0000465 case VexArchPPC64:
sewardj9e1cf152012-04-20 02:18:31 +0000466 preciseMemExnsFn = guest_ppc64_state_requires_precise_mem_exns;
467 disInstrFn = disInstr_PPC;
468 specHelper = guest_ppc64_spechelper;
469 guest_sizeB = sizeof(VexGuestPPC64State);
470 guest_word_type = Ity_I64;
471 guest_layout = &ppc64Guest_layout;
472 offB_TISTART = offsetof(VexGuestPPC64State,guest_TISTART);
473 offB_TILEN = offsetof(VexGuestPPC64State,guest_TILEN);
474 offB_GUEST_IP = offsetof(VexGuestPPC64State,guest_CIA);
475 szB_GUEST_IP = sizeof( ((VexGuestPPC64State*)0)->guest_CIA );
476 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC64State,host_EvC_COUNTER);
477 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC64State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000478 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_guest.hwcaps));
cerionf0de28c2005-12-13 20:21:11 +0000479 vassert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj3fd39672006-01-27 22:05:55 +0000480 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TISTART ) == 8);
481 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TILEN ) == 8);
482 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8);
483 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8);
cerionf0de28c2005-12-13 20:21:11 +0000484 break;
485
sewardj2019a972011-03-07 16:04:07 +0000486 case VexArchS390X:
487 preciseMemExnsFn = guest_s390x_state_requires_precise_mem_exns;
488 disInstrFn = disInstr_S390;
489 specHelper = guest_s390x_spechelper;
490 guest_sizeB = sizeof(VexGuestS390XState);
491 guest_word_type = Ity_I64;
492 guest_layout = &s390xGuest_layout;
493 offB_TISTART = offsetof(VexGuestS390XState,guest_TISTART);
494 offB_TILEN = offsetof(VexGuestS390XState,guest_TILEN);
florian8844a632012-04-13 04:04:06 +0000495 offB_GUEST_IP = offsetof(VexGuestS390XState,guest_IA);
496 szB_GUEST_IP = sizeof( ((VexGuestS390XState*)0)->guest_IA);
497 offB_HOST_EvC_COUNTER = offsetof(VexGuestS390XState,host_EvC_COUNTER);
498 offB_HOST_EvC_FAILADDR = offsetof(VexGuestS390XState,host_EvC_FAILADDR);
sewardj2019a972011-03-07 16:04:07 +0000499 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_guest.hwcaps));
500 vassert(0 == sizeof(VexGuestS390XState) % 16);
501 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TISTART ) == 8);
502 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TILEN ) == 8);
503 vassert(sizeof( ((VexGuestS390XState*)0)->guest_NRADDR ) == 8);
504 break;
505
sewardj6c299f32009-12-31 18:00:12 +0000506 case VexArchARM:
sewardjc6f970f2012-04-02 21:54:49 +0000507 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
508 disInstrFn = disInstr_ARM;
509 specHelper = guest_arm_spechelper;
510 guest_sizeB = sizeof(VexGuestARMState);
511 guest_word_type = Ity_I32;
512 guest_layout = &armGuest_layout;
513 offB_TISTART = offsetof(VexGuestARMState,guest_TISTART);
514 offB_TILEN = offsetof(VexGuestARMState,guest_TILEN);
515 offB_GUEST_IP = offsetof(VexGuestARMState,guest_R15T);
516 szB_GUEST_IP = sizeof( ((VexGuestARMState*)0)->guest_R15T );
517 offB_HOST_EvC_COUNTER = offsetof(VexGuestARMState,host_EvC_COUNTER);
518 offB_HOST_EvC_FAILADDR = offsetof(VexGuestARMState,host_EvC_FAILADDR);
sewardj6c299f32009-12-31 18:00:12 +0000519 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_guest.hwcaps));
520 vassert(0 == sizeof(VexGuestARMState) % 16);
521 vassert(sizeof( ((VexGuestARMState*)0)->guest_TISTART) == 4);
522 vassert(sizeof( ((VexGuestARMState*)0)->guest_TILEN ) == 4);
523 vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4);
524 break;
525
sewardjf13a16a2004-07-05 17:10:14 +0000526 default:
sewardj887a11a2004-07-05 17:26:47 +0000527 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000528 }
529
sewardjbc161a42011-06-07 21:28:38 +0000530 /* Set up result struct. */
531 VexTranslateResult res;
sewardjfadbbe22012-04-24 11:49:03 +0000532 res.status = VexTransOK;
533 res.n_sc_extents = 0;
534 res.offs_profInc = -1;
535 res.n_guest_instrs = 0;
sewardjbc161a42011-06-07 21:28:38 +0000536
sewardj9df271d2004-12-31 22:37:42 +0000537 /* yet more sanity checks ... */
sewardj17c7f952005-12-15 14:02:34 +0000538 if (vta->arch_guest == vta->arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000539 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000540 we are simulating one flavour of an architecture a different
541 flavour of the same architecture, which is pretty strange. */
sewardj5117ce12006-01-27 21:20:15 +0000542 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps);
sewardj9df271d2004-12-31 22:37:42 +0000543 }
sewardj2a9ad022004-11-25 02:46:58 +0000544
sewardj2d6b14a2005-11-23 04:25:07 +0000545 vexAllocSanityCheck();
546
sewardjf48ac192004-10-29 00:41:29 +0000547 if (vex_traceflags & VEX_TRACE_FE)
548 vex_printf("\n------------------------"
549 " Front end "
550 "------------------------\n\n");
551
sewardjdd40fdf2006-12-24 02:20:24 +0000552 irsb = bb_to_IR ( vta->guest_extents,
sewardjbc161a42011-06-07 21:28:38 +0000553 &res.n_sc_extents,
sewardjfadbbe22012-04-24 11:49:03 +0000554 &res.n_guest_instrs,
sewardjc716aea2006-01-17 01:48:46 +0000555 vta->callback_opaque,
sewardj9e6491a2005-07-02 19:24:10 +0000556 disInstrFn,
sewardj17c7f952005-12-15 14:02:34 +0000557 vta->guest_bytes,
558 vta->guest_bytes_addr,
559 vta->chase_into_ok,
sewardj9e6491a2005-07-02 19:24:10 +0000560 host_is_bigendian,
sewardja5f55da2006-04-30 23:37:32 +0000561 vta->arch_guest,
sewardj17c7f952005-12-15 14:02:34 +0000562 &vta->archinfo_guest,
sewardjdd40fdf2006-12-24 02:20:24 +0000563 &vta->abiinfo_both,
sewardjdb4738a2005-07-07 01:32:16 +0000564 guest_word_type,
sewardjbc161a42011-06-07 21:28:38 +0000565 vta->needs_self_check,
sewardjc716aea2006-01-17 01:48:46 +0000566 vta->preamble_function,
sewardjdb4738a2005-07-07 01:32:16 +0000567 offB_TISTART,
sewardjc6f970f2012-04-02 21:54:49 +0000568 offB_TILEN,
569 offB_GUEST_IP,
570 szB_GUEST_IP );
sewardjf13a16a2004-07-05 17:10:14 +0000571
sewardj2d6b14a2005-11-23 04:25:07 +0000572 vexAllocSanityCheck();
573
sewardjdd40fdf2006-12-24 02:20:24 +0000574 if (irsb == NULL) {
sewardjf13a16a2004-07-05 17:10:14 +0000575 /* Access failure. */
sewardj2d6b14a2005-11-23 04:25:07 +0000576 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000577 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000578 res.status = VexTransAccessFail; return res;
sewardjf13a16a2004-07-05 17:10:14 +0000579 }
sewardjaa59f942004-10-09 09:34:36 +0000580
sewardj17c7f952005-12-15 14:02:34 +0000581 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3);
582 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr);
583 for (i = 0; i < vta->guest_extents->n_used; i++) {
584 vassert(vta->guest_extents->len[i] < 10000); /* sanity */
sewardj72c72812005-01-19 11:49:45 +0000585 }
586
sewardjaa59f942004-10-09 09:34:36 +0000587 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000588 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj17c7f952005-12-15 14:02:34 +0000589 if (vta->guest_extents->n_used > 1) {
sewardj72c72812005-01-19 11:49:45 +0000590 vex_printf("can't show code due to extents > 1\n");
591 } else {
592 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000593 UChar* p = (UChar*)vta->guest_bytes;
sewardj01f8cce2009-08-31 08:50:02 +0000594 UInt sum = 0;
sewardj17c7f952005-12-15 14:02:34 +0000595 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0];
sewardj01f8cce2009-08-31 08:50:02 +0000596 vex_printf("GuestBytes %llx %u ", vta->guest_bytes_addr,
597 guest_bytes_read );
598 for (i = 0; i < guest_bytes_read; i++) {
599 UInt b = (UInt)p[i];
600 vex_printf(" %02x", b );
601 sum = (sum << 1) ^ b;
602 }
603 vex_printf(" %08x\n\n", sum);
sewardj72c72812005-01-19 11:49:45 +0000604 }
sewardjaa59f942004-10-09 09:34:36 +0000605 }
606
607 /* Sanity check the initial IR. */
sewardjdd40fdf2006-12-24 02:20:24 +0000608 sanityCheckIRSB( irsb, "initial IR",
sewardjb9230752004-12-29 19:25:06 +0000609 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000610
sewardj2d6b14a2005-11-23 04:25:07 +0000611 vexAllocSanityCheck();
612
sewardjedf4d692004-08-17 13:52:58 +0000613 /* Clean it up, hopefully a lot. */
sewardjdd40fdf2006-12-24 02:20:24 +0000614 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn,
sewardjec0d9a02010-08-22 12:54:56 +0000615 vta->guest_bytes_addr,
616 vta->arch_guest );
sewardjdd40fdf2006-12-24 02:20:24 +0000617 sanityCheckIRSB( irsb, "after initial iropt",
sewardjb9230752004-12-29 19:25:06 +0000618 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000619
sewardjf48ac192004-10-29 00:41:29 +0000620 if (vex_traceflags & VEX_TRACE_OPT1) {
621 vex_printf("\n------------------------"
622 " After pre-instr IR optimisation "
623 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000624 ppIRSB ( irsb );
sewardjedf4d692004-08-17 13:52:58 +0000625 vex_printf("\n");
626 }
627
sewardj2d6b14a2005-11-23 04:25:07 +0000628 vexAllocSanityCheck();
629
sewardjf13a16a2004-07-05 17:10:14 +0000630 /* Get the thing instrumented. */
sewardj17c7f952005-12-15 14:02:34 +0000631 if (vta->instrument1)
sewardjdd40fdf2006-12-24 02:20:24 +0000632 irsb = vta->instrument1(vta->callback_opaque,
633 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000634 vta->guest_extents,
635 guest_word_type, host_word_type);
sewardj2d6b14a2005-11-23 04:25:07 +0000636 vexAllocSanityCheck();
637
sewardj17c7f952005-12-15 14:02:34 +0000638 if (vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000639 irsb = vta->instrument2(vta->callback_opaque,
640 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000641 vta->guest_extents,
642 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000643
sewardjf48ac192004-10-29 00:41:29 +0000644 if (vex_traceflags & VEX_TRACE_INST) {
645 vex_printf("\n------------------------"
646 " After instrumentation "
647 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000648 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000649 vex_printf("\n");
650 }
651
sewardj17c7f952005-12-15 14:02:34 +0000652 if (vta->instrument1 || vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000653 sanityCheckIRSB( irsb, "after instrumentation",
sewardjb9230752004-12-29 19:25:06 +0000654 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000655
sewardj9578a8b2004-11-04 19:44:48 +0000656 /* Do a post-instrumentation cleanup pass. */
sewardj17c7f952005-12-15 14:02:34 +0000657 if (vta->instrument1 || vta->instrument2) {
sewardjdd40fdf2006-12-24 02:20:24 +0000658 do_deadcode_BB( irsb );
659 irsb = cprop_BB( irsb );
660 do_deadcode_BB( irsb );
661 sanityCheckIRSB( irsb, "after post-instrumentation cleanup",
sewardjb9230752004-12-29 19:25:06 +0000662 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000663 }
664
sewardj2d6b14a2005-11-23 04:25:07 +0000665 vexAllocSanityCheck();
666
sewardj9578a8b2004-11-04 19:44:48 +0000667 if (vex_traceflags & VEX_TRACE_OPT2) {
668 vex_printf("\n------------------------"
669 " After post-instr IR optimisation "
670 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000671 ppIRSB ( irsb );
sewardj9578a8b2004-11-04 19:44:48 +0000672 vex_printf("\n");
673 }
674
sewardjf9517d02005-11-28 13:39:37 +0000675 /* Turn it into virtual-registerised code. Build trees -- this
676 also throws away any dead bindings. */
sewardjc6f970f2012-04-02 21:54:49 +0000677 max_ga = ado_treebuild_BB( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000678
sewardjbe1b6ff2007-08-28 06:06:27 +0000679 if (vta->finaltidy) {
680 irsb = vta->finaltidy(irsb);
681 }
682
sewardj2d6b14a2005-11-23 04:25:07 +0000683 vexAllocSanityCheck();
684
sewardjf48ac192004-10-29 00:41:29 +0000685 if (vex_traceflags & VEX_TRACE_TREES) {
686 vex_printf("\n------------------------"
687 " After tree-building "
688 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000689 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000690 vex_printf("\n");
691 }
692
sewardje908c422005-02-04 21:18:16 +0000693 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000694 if (0) {
695 *(vta->host_bytes_used) = 0;
696 res.status = VexTransOK; return res;
697 }
sewardje908c422005-02-04 21:18:16 +0000698 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000699
sewardjf48ac192004-10-29 00:41:29 +0000700 if (vex_traceflags & VEX_TRACE_VCODE)
701 vex_printf("\n------------------------"
702 " Instruction selection "
703 "------------------------\n");
704
sewardjc6f970f2012-04-02 21:54:49 +0000705 /* No guest has its IP field at offset zero. If this fails it
706 means some transformation pass somewhere failed to update/copy
707 irsb->offsIP properly. */
708 vassert(irsb->offsIP >= 16);
709
710 vcode = iselSB ( irsb, vta->arch_host,
711 &vta->archinfo_host,
712 &vta->abiinfo_both,
713 offB_HOST_EvC_COUNTER,
714 offB_HOST_EvC_FAILADDR,
715 chainingAllowed,
716 vta->addProfInc,
717 max_ga );
sewardjf13a16a2004-07-05 17:10:14 +0000718
sewardj2d6b14a2005-11-23 04:25:07 +0000719 vexAllocSanityCheck();
720
sewardjf48ac192004-10-29 00:41:29 +0000721 if (vex_traceflags & VEX_TRACE_VCODE)
722 vex_printf("\n");
723
sewardjf48ac192004-10-29 00:41:29 +0000724 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000725 for (i = 0; i < vcode->arr_used; i++) {
726 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000727 ppInstr(vcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000728 vex_printf("\n");
729 }
sewardjfbcaf332004-07-08 01:46:01 +0000730 vex_printf("\n");
731 }
sewardjfbcaf332004-07-08 01:46:01 +0000732
sewardjf13a16a2004-07-05 17:10:14 +0000733 /* Register allocate. */
734 rcode = doRegisterAllocation ( vcode, available_real_regs,
cerionf0de28c2005-12-13 20:21:11 +0000735 n_available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000736 isMove, getRegUsage, mapRegs,
sewardjfb7373a2007-08-25 21:29:03 +0000737 genSpill, genReload, directReload,
738 guest_sizeB,
cerion92b64362005-12-13 12:02:26 +0000739 ppInstr, ppReg, mode64 );
sewardjf13a16a2004-07-05 17:10:14 +0000740
sewardj2d6b14a2005-11-23 04:25:07 +0000741 vexAllocSanityCheck();
742
sewardjf48ac192004-10-29 00:41:29 +0000743 if (vex_traceflags & VEX_TRACE_RCODE) {
744 vex_printf("\n------------------------"
745 " Register-allocated code "
746 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000747 for (i = 0; i < rcode->arr_used; i++) {
748 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000749 ppInstr(rcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000750 vex_printf("\n");
751 }
sewardjfbcaf332004-07-08 01:46:01 +0000752 vex_printf("\n");
753 }
sewardjfbcaf332004-07-08 01:46:01 +0000754
sewardje908c422005-02-04 21:18:16 +0000755 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000756 if (0) {
757 *(vta->host_bytes_used) = 0;
758 res.status = VexTransOK; return res;
759 }
sewardje908c422005-02-04 21:18:16 +0000760 /* end HACK */
761
sewardj81bd5502004-07-21 18:49:27 +0000762 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000763 if (vex_traceflags & VEX_TRACE_ASM) {
764 vex_printf("\n------------------------"
765 " Assembly "
766 "------------------------\n\n");
767 }
768
sewardj81bd5502004-07-21 18:49:27 +0000769 out_used = 0; /* tracks along the host_bytes array */
770 for (i = 0; i < rcode->arr_used; i++) {
sewardjc6f970f2012-04-02 21:54:49 +0000771 HInstr* hi = rcode->arr[i];
772 Bool hi_isProfInc = False;
773 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
774 ppInstr(hi, mode64);
sewardjbad34a92004-07-22 01:14:11 +0000775 vex_printf("\n");
776 }
sewardjc6f970f2012-04-02 21:54:49 +0000777 j = emit( &hi_isProfInc,
778 insn_bytes, sizeof insn_bytes, hi, mode64,
779 vta->disp_cp_chain_me_to_slowEP,
780 vta->disp_cp_chain_me_to_fastEP,
781 vta->disp_cp_xindir,
782 vta->disp_cp_xassisted );
783 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
sewardjbad34a92004-07-22 01:14:11 +0000784 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000785 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000786 vex_printf("0%x ", (UInt)insn_bytes[k]);
787 else
788 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000789 vex_printf("\n\n");
790 }
sewardjc6f970f2012-04-02 21:54:49 +0000791 if (UNLIKELY(out_used + j > vta->host_bytes_size)) {
sewardj2d6b14a2005-11-23 04:25:07 +0000792 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000793 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000794 res.status = VexTransOutputFull;
795 return res;
sewardj81bd5502004-07-21 18:49:27 +0000796 }
sewardjc6f970f2012-04-02 21:54:49 +0000797 if (UNLIKELY(hi_isProfInc)) {
798 vassert(vta->addProfInc); /* else where did it come from? */
799 vassert(res.offs_profInc == -1); /* there can be only one (tm) */
800 vassert(out_used >= 0);
801 res.offs_profInc = out_used;
802 }
803 { UChar* dst = &vta->host_bytes[out_used];
804 for (k = 0; k < j; k++) {
805 dst[k] = insn_bytes[k];
806 }
807 out_used += j;
sewardj81bd5502004-07-21 18:49:27 +0000808 }
sewardj17c7f952005-12-15 14:02:34 +0000809 vassert(out_used <= vta->host_bytes_size);
sewardj81bd5502004-07-21 18:49:27 +0000810 }
sewardj17c7f952005-12-15 14:02:34 +0000811 *(vta->host_bytes_used) = out_used;
sewardj81bd5502004-07-21 18:49:27 +0000812
sewardj2d6b14a2005-11-23 04:25:07 +0000813 vexAllocSanityCheck();
814
815 vexSetAllocModeTEMP_and_clear();
sewardjf13a16a2004-07-05 17:10:14 +0000816
sewardjf48ac192004-10-29 00:41:29 +0000817 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000818 res.status = VexTransOK;
819 return res;
sewardj35421a32004-07-05 13:12:34 +0000820}
821
822
sewardjc6f970f2012-04-02 21:54:49 +0000823/* --------- Chain/Unchain XDirects. --------- */
824
825VexInvalRange LibVEX_Chain ( VexArch arch_host,
826 void* place_to_chain,
827 void* disp_cp_chain_me_EXPECTED,
828 void* place_to_jump_to )
829{
830 VexInvalRange (*chainXDirect)(void*, void*, void*) = NULL;
831 switch (arch_host) {
832 case VexArchX86:
833 chainXDirect = chainXDirect_X86; break;
834 case VexArchAMD64:
835 chainXDirect = chainXDirect_AMD64; break;
836 case VexArchARM:
837 chainXDirect = chainXDirect_ARM; break;
florian8844a632012-04-13 04:04:06 +0000838 case VexArchS390X:
839 chainXDirect = chainXDirect_S390; break;
sewardj3dee8492012-04-20 00:13:28 +0000840 case VexArchPPC32:
841 return chainXDirect_PPC(place_to_chain,
842 disp_cp_chain_me_EXPECTED,
843 place_to_jump_to, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +0000844 case VexArchPPC64:
845 return chainXDirect_PPC(place_to_chain,
846 disp_cp_chain_me_EXPECTED,
847 place_to_jump_to, True/*mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +0000848 default:
849 vassert(0);
850 }
851 vassert(chainXDirect);
852 VexInvalRange vir
853 = chainXDirect(place_to_chain, disp_cp_chain_me_EXPECTED,
854 place_to_jump_to);
855 return vir;
856}
857
858VexInvalRange LibVEX_UnChain ( VexArch arch_host,
859 void* place_to_unchain,
860 void* place_to_jump_to_EXPECTED,
861 void* disp_cp_chain_me )
862{
863 VexInvalRange (*unchainXDirect)(void*, void*, void*) = NULL;
864 switch (arch_host) {
865 case VexArchX86:
866 unchainXDirect = unchainXDirect_X86; break;
867 case VexArchAMD64:
868 unchainXDirect = unchainXDirect_AMD64; break;
869 case VexArchARM:
870 unchainXDirect = unchainXDirect_ARM; break;
florian8844a632012-04-13 04:04:06 +0000871 case VexArchS390X:
872 unchainXDirect = unchainXDirect_S390; break;
sewardj3dee8492012-04-20 00:13:28 +0000873 case VexArchPPC32:
874 return unchainXDirect_PPC(place_to_unchain,
875 place_to_jump_to_EXPECTED,
876 disp_cp_chain_me, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +0000877 case VexArchPPC64:
878 return unchainXDirect_PPC(place_to_unchain,
879 place_to_jump_to_EXPECTED,
880 disp_cp_chain_me, True/*mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +0000881 default:
882 vassert(0);
883 }
884 vassert(unchainXDirect);
885 VexInvalRange vir
886 = unchainXDirect(place_to_unchain, place_to_jump_to_EXPECTED,
887 disp_cp_chain_me);
888 return vir;
889}
890
891Int LibVEX_evCheckSzB ( VexArch arch_host )
892{
893 static Int cached = 0; /* DO NOT MAKE NON-STATIC */
894 if (UNLIKELY(cached == 0)) {
895 switch (arch_host) {
896 case VexArchX86:
897 cached = evCheckSzB_X86(); break;
898 case VexArchAMD64:
899 cached = evCheckSzB_AMD64(); break;
900 case VexArchARM:
901 cached = evCheckSzB_ARM(); break;
florian8844a632012-04-13 04:04:06 +0000902 case VexArchS390X:
903 cached = evCheckSzB_S390(); break;
sewardj3dee8492012-04-20 00:13:28 +0000904 case VexArchPPC32:
sewardjf252de52012-04-20 10:42:24 +0000905 case VexArchPPC64:
sewardj3dee8492012-04-20 00:13:28 +0000906 cached = evCheckSzB_PPC(); break;
sewardjc6f970f2012-04-02 21:54:49 +0000907 default:
908 vassert(0);
909 }
910 }
911 return cached;
912}
913
914VexInvalRange LibVEX_PatchProfInc ( VexArch arch_host,
915 void* place_to_patch,
916 ULong* location_of_counter )
917{
918 VexInvalRange (*patchProfInc)(void*,ULong*) = NULL;
919 switch (arch_host) {
920 case VexArchX86:
921 patchProfInc = patchProfInc_X86; break;
922 case VexArchAMD64:
923 patchProfInc = patchProfInc_AMD64; break;
924 case VexArchARM:
925 patchProfInc = patchProfInc_ARM; break;
florian8844a632012-04-13 04:04:06 +0000926 case VexArchS390X:
927 patchProfInc = patchProfInc_S390; break;
sewardj3dee8492012-04-20 00:13:28 +0000928 case VexArchPPC32:
929 return patchProfInc_PPC(place_to_patch,
930 location_of_counter, False/*!mode64*/);
sewardjf252de52012-04-20 10:42:24 +0000931 case VexArchPPC64:
932 return patchProfInc_PPC(place_to_patch,
933 location_of_counter, True/*mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +0000934 default:
935 vassert(0);
936 }
937 vassert(patchProfInc);
938 VexInvalRange vir
939 = patchProfInc(place_to_patch, location_of_counter);
940 return vir;
941}
942
943
sewardj893aada2004-11-29 19:57:54 +0000944/* --------- Emulation warnings. --------- */
945
946HChar* LibVEX_EmWarn_string ( VexEmWarn ew )
947{
948 switch (ew) {
949 case EmWarn_NONE:
950 return "none";
951 case EmWarn_X86_x87exns:
952 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000953 case EmWarn_X86_x87precision:
954 return "Selection of non-80-bit x87 FP precision";
955 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +0000956 return "Unmasking SSE FP exceptions";
957 case EmWarn_X86_fz:
958 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
959 case EmWarn_X86_daz:
960 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +0000961 case EmWarn_X86_acFlag:
962 return "Setting %eflags.ac (setting noted but ignored)";
sewardj9dd9cf12006-01-20 14:13:55 +0000963 case EmWarn_PPCexns:
964 return "Unmasking PPC32/64 FP exceptions";
965 case EmWarn_PPC64_redir_overflow:
966 return "PPC64 function redirection stack overflow";
967 case EmWarn_PPC64_redir_underflow:
968 return "PPC64 function redirection stack underflow";
sewardj893aada2004-11-29 19:57:54 +0000969 default:
970 vpanic("LibVEX_EmWarn_string: unknown warning");
971 }
972}
sewardj35421a32004-07-05 13:12:34 +0000973
sewardj5117ce12006-01-27 21:20:15 +0000974/* ------------------ Arch/HwCaps stuff. ------------------ */
sewardjbef170b2004-12-21 01:23:00 +0000975
976const HChar* LibVEX_ppVexArch ( VexArch arch )
977{
978 switch (arch) {
979 case VexArch_INVALID: return "INVALID";
980 case VexArchX86: return "X86";
981 case VexArchAMD64: return "AMD64";
982 case VexArchARM: return "ARM";
sewardj0ec57c52005-02-01 15:24:10 +0000983 case VexArchPPC32: return "PPC32";
cerionf0de28c2005-12-13 20:21:11 +0000984 case VexArchPPC64: return "PPC64";
sewardj2019a972011-03-07 16:04:07 +0000985 case VexArchS390X: return "S390X";
sewardjbef170b2004-12-21 01:23:00 +0000986 default: return "VexArch???";
987 }
988}
989
sewardj5117ce12006-01-27 21:20:15 +0000990const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
sewardjbef170b2004-12-21 01:23:00 +0000991{
sewardj5117ce12006-01-27 21:20:15 +0000992 HChar* str = show_hwcaps(arch,hwcaps);
993 return str ? str : "INVALID";
sewardjbef170b2004-12-21 01:23:00 +0000994}
995
sewardj5117ce12006-01-27 21:20:15 +0000996
sewardj27e1dd62005-06-30 11:49:14 +0000997/* Write default settings info *vai. */
998void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
999{
sewardj5117ce12006-01-27 21:20:15 +00001000 vai->hwcaps = 0;
cerion5b2325f2005-12-23 00:55:09 +00001001 vai->ppc_cache_line_szB = 0;
sewardje971c6a2010-09-03 15:49:57 +00001002 vai->ppc_dcbz_szB = 0;
1003 vai->ppc_dcbzl_szB = 0;
1004
sewardj27e1dd62005-06-30 11:49:14 +00001005}
1006
sewardjdd40fdf2006-12-24 02:20:24 +00001007/* Write default settings info *vbi. */
1008void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
sewardjaca070a2006-10-17 00:28:22 +00001009{
sewardjdd40fdf2006-12-24 02:20:24 +00001010 vbi->guest_stack_redzone_size = 0;
sewardj2e28ac42008-12-04 00:05:12 +00001011 vbi->guest_amd64_assume_fs_is_zero = False;
1012 vbi->guest_amd64_assume_gs_is_0x60 = False;
sewardjdd40fdf2006-12-24 02:20:24 +00001013 vbi->guest_ppc_zap_RZ_at_blr = False;
1014 vbi->guest_ppc_zap_RZ_at_bl = NULL;
1015 vbi->guest_ppc_sc_continues_at_LR = False;
1016 vbi->host_ppc_calls_use_fndescrs = False;
1017 vbi->host_ppc32_regalign_int64_args = False;
sewardjaca070a2006-10-17 00:28:22 +00001018}
1019
sewardj27e1dd62005-06-30 11:49:14 +00001020
sewardj5117ce12006-01-27 21:20:15 +00001021/* Return a string showing the hwcaps in a nice way. The string will
1022 be NULL for invalid combinations of flags, so these functions also
1023 serve as a way to validate hwcaps values. */
1024
1025static HChar* show_hwcaps_x86 ( UInt hwcaps )
1026{
1027 /* Monotonic, SSE3 > SSE2 > SSE1 > baseline. */
sewardj536fbab2010-07-29 15:39:05 +00001028 switch (hwcaps) {
1029 case 0:
1030 return "x86-sse0";
1031 case VEX_HWCAPS_X86_SSE1:
1032 return "x86-sse1";
1033 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2:
1034 return "x86-sse1-sse2";
1035 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
1036 | VEX_HWCAPS_X86_LZCNT:
1037 return "x86-sse1-sse2-lzcnt";
1038 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
1039 | VEX_HWCAPS_X86_SSE3:
1040 return "x86-sse1-sse2-sse3";
1041 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
1042 | VEX_HWCAPS_X86_SSE3 | VEX_HWCAPS_X86_LZCNT:
1043 return "x86-sse1-sse2-sse3-lzcnt";
1044 default:
1045 return NULL;
1046 }
sewardj5117ce12006-01-27 21:20:15 +00001047}
1048
1049static HChar* show_hwcaps_amd64 ( UInt hwcaps )
1050{
sewardje9d8a262009-07-01 08:06:34 +00001051 /* SSE3 and CX16 are orthogonal and > baseline, although we really
1052 don't expect to come across anything which can do SSE3 but can't
sewardj536fbab2010-07-29 15:39:05 +00001053 do CX16. Still, we can handle that case. LZCNT is similarly
sewardjf350a422012-04-26 14:16:52 +00001054 orthogonal. AVX is technically orthogonal, but just add the
1055 cases we actually come across. (This scheme for printing is
1056 very stupid. We should add strings independently based on
1057 feature bits, but then it would be hard to return a string that
1058 didn't need deallocating by the caller.) */
sewardjc4530ae2012-05-21 10:18:49 +00001059 /* FIXME: show_hwcaps_s390x is a much better way to do this. */
sewardj536fbab2010-07-29 15:39:05 +00001060 switch (hwcaps) {
1061 case 0:
1062 return "amd64-sse2";
1063 case VEX_HWCAPS_AMD64_SSE3:
1064 return "amd64-sse3";
1065 case VEX_HWCAPS_AMD64_CX16:
1066 return "amd64-sse2-cx16";
1067 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16:
1068 return "amd64-sse3-cx16";
1069 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_LZCNT:
1070 return "amd64-sse3-lzcnt";
1071 case VEX_HWCAPS_AMD64_CX16 | VEX_HWCAPS_AMD64_LZCNT:
1072 return "amd64-sse2-cx16-lzcnt";
1073 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16
1074 | VEX_HWCAPS_AMD64_LZCNT:
1075 return "amd64-sse3-cx16-lzcnt";
sewardjf350a422012-04-26 14:16:52 +00001076 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16
1077 | VEX_HWCAPS_AMD64_AVX:
1078 return "amd64-sse3-cx16-avx";
sewardjb5e17b92012-05-21 16:16:13 +00001079 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16
1080 | VEX_HWCAPS_AMD64_LZCNT | VEX_HWCAPS_AMD64_AVX:
1081 return "amd64-sse3-cx16-lzcnt-avx";
sewardj536fbab2010-07-29 15:39:05 +00001082 default:
1083 return NULL;
1084 }
sewardj5117ce12006-01-27 21:20:15 +00001085}
1086
1087static HChar* show_hwcaps_ppc32 ( UInt hwcaps )
1088{
1089 /* Monotonic with complications. Basically V > F > baseline,
1090 but once you have F then you can have FX or GX too. */
1091 const UInt F = VEX_HWCAPS_PPC32_F;
1092 const UInt V = VEX_HWCAPS_PPC32_V;
1093 const UInt FX = VEX_HWCAPS_PPC32_FX;
1094 const UInt GX = VEX_HWCAPS_PPC32_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001095 const UInt VX = VEX_HWCAPS_PPC32_VX;
sewardjc66d6fa2012-04-02 21:24:12 +00001096 const UInt DFP = VEX_HWCAPS_PPC32_DFP;
sewardj5117ce12006-01-27 21:20:15 +00001097 UInt c = hwcaps;
1098 if (c == 0) return "ppc32-int";
1099 if (c == F) return "ppc32-int-flt";
1100 if (c == (F|FX)) return "ppc32-int-flt-FX";
1101 if (c == (F|GX)) return "ppc32-int-flt-GX";
1102 if (c == (F|FX|GX)) return "ppc32-int-flt-FX-GX";
1103 if (c == (F|V)) return "ppc32-int-flt-vmx";
1104 if (c == (F|V|FX)) return "ppc32-int-flt-vmx-FX";
1105 if (c == (F|V|GX)) return "ppc32-int-flt-vmx-GX";
1106 if (c == (F|V|FX|GX)) return "ppc32-int-flt-vmx-FX-GX";
sewardjc66d6fa2012-04-02 21:24:12 +00001107 if (c == (F|V|FX|GX|DFP)) return "ppc32-int-flt-vmx-FX-GX-DFP";
1108 if (c == (F|V|FX|GX|VX|DFP)) return "ppc32-int-flt-vmx-FX-GX-VX-DFP";
sewardj5117ce12006-01-27 21:20:15 +00001109 return NULL;
1110}
1111
1112static HChar* show_hwcaps_ppc64 ( UInt hwcaps )
1113{
1114 /* Monotonic with complications. Basically V > baseline(==F),
1115 but once you have F then you can have FX or GX too. */
sewardj3fd39672006-01-27 22:05:55 +00001116 const UInt V = VEX_HWCAPS_PPC64_V;
1117 const UInt FX = VEX_HWCAPS_PPC64_FX;
1118 const UInt GX = VEX_HWCAPS_PPC64_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001119 const UInt VX = VEX_HWCAPS_PPC64_VX;
sewardjc66d6fa2012-04-02 21:24:12 +00001120 const UInt DFP = VEX_HWCAPS_PPC64_DFP;
sewardj5117ce12006-01-27 21:20:15 +00001121 UInt c = hwcaps;
1122 if (c == 0) return "ppc64-int-flt";
1123 if (c == FX) return "ppc64-int-flt-FX";
1124 if (c == GX) return "ppc64-int-flt-GX";
1125 if (c == (FX|GX)) return "ppc64-int-flt-FX-GX";
1126 if (c == V) return "ppc64-int-flt-vmx";
1127 if (c == (V|FX)) return "ppc64-int-flt-vmx-FX";
1128 if (c == (V|GX)) return "ppc64-int-flt-vmx-GX";
1129 if (c == (V|FX|GX)) return "ppc64-int-flt-vmx-FX-GX";
sewardjc66d6fa2012-04-02 21:24:12 +00001130 if (c == (V|FX|GX|DFP)) return "ppc64-int-flt-vmx-FX-GX-DFP";
1131 if (c == (V|FX|GX|VX|DFP)) return "ppc64-int-flt-vmx-FX-GX-VX-DFP";
sewardj5117ce12006-01-27 21:20:15 +00001132 return NULL;
1133}
1134
1135static HChar* show_hwcaps_arm ( UInt hwcaps )
1136{
sewardjec0d9a02010-08-22 12:54:56 +00001137 Bool N = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0);
1138 Bool vfp = ((hwcaps & (VEX_HWCAPS_ARM_VFP |
1139 VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3)) != 0);
1140 switch (VEX_ARM_ARCHLEVEL(hwcaps)) {
1141 case 5:
1142 if (N)
1143 return NULL;
1144 if (vfp)
1145 return "ARMv5-vfp";
1146 else
1147 return "ARMv5";
1148 return NULL;
1149 case 6:
1150 if (N)
1151 return NULL;
1152 if (vfp)
1153 return "ARMv6-vfp";
1154 else
1155 return "ARMv6";
1156 return NULL;
1157 case 7:
1158 if (vfp) {
1159 if (N)
1160 return "ARMv7-vfp-neon";
1161 else
1162 return "ARMv7-vfp";
1163 } else {
1164 if (N)
1165 return "ARMv7-neon";
1166 else
1167 return "ARMv7";
1168 }
1169 default:
1170 return NULL;
1171 }
sewardj5117ce12006-01-27 21:20:15 +00001172 return NULL;
1173}
1174
sewardj2019a972011-03-07 16:04:07 +00001175static HChar* show_hwcaps_s390x ( UInt hwcaps )
1176{
sewardjd07b8562011-04-27 11:58:22 +00001177 static const HChar prefix[] = "s390x";
1178 static const HChar facilities[][6] = {
1179 { "ldisp" },
1180 { "eimm" },
1181 { "gie" },
1182 { "dfp" },
1183 { "fgx" },
florian90ece042012-04-21 15:41:51 +00001184 { "stfle" },
1185 { "etf2" },
florian79bee4b2012-05-03 01:30:48 +00001186 { "etf3" },
sewardjd07b8562011-04-27 11:58:22 +00001187 };
1188 static HChar buf[sizeof facilities + sizeof prefix + 1];
1189 static HChar *p;
1190
1191 if (buf[0] != '\0') return buf; /* already constructed */
sewardj2019a972011-03-07 16:04:07 +00001192
sewardj652b56a2011-04-13 15:38:17 +00001193 hwcaps = VEX_HWCAPS_S390X(hwcaps);
1194
sewardjd07b8562011-04-27 11:58:22 +00001195 p = buf + vex_sprintf(buf, "%s", prefix);
1196 if (hwcaps & VEX_HWCAPS_S390X_LDISP)
1197 p = p + vex_sprintf(p, "-%s", facilities[0]);
1198 if (hwcaps & VEX_HWCAPS_S390X_EIMM)
1199 p = p + vex_sprintf(p, "-%s", facilities[1]);
1200 if (hwcaps & VEX_HWCAPS_S390X_GIE)
1201 p = p + vex_sprintf(p, "-%s", facilities[2]);
1202 if (hwcaps & VEX_HWCAPS_S390X_DFP)
1203 p = p + vex_sprintf(p, "-%s", facilities[3]);
1204 if (hwcaps & VEX_HWCAPS_S390X_FGX)
1205 p = p + vex_sprintf(p, "-%s", facilities[4]);
florian90ece042012-04-21 15:41:51 +00001206 if (hwcaps & VEX_HWCAPS_S390X_STFLE)
1207 p = p + vex_sprintf(p, "-%s", facilities[5]);
1208 if (hwcaps & VEX_HWCAPS_S390X_ETF2)
1209 p = p + vex_sprintf(p, "-%s", facilities[6]);
florian79bee4b2012-05-03 01:30:48 +00001210 if (hwcaps & VEX_HWCAPS_S390X_ETF3)
1211 p = p + vex_sprintf(p, "-%s", facilities[7]);
sewardj2019a972011-03-07 16:04:07 +00001212
sewardjd07b8562011-04-27 11:58:22 +00001213 /* If there are no facilities, add "zarch" */
1214 if (hwcaps == 0)
1215 vex_sprintf(p, "-%s", "zarch");
1216
1217 return buf;
sewardj2019a972011-03-07 16:04:07 +00001218}
1219
sewardj5117ce12006-01-27 21:20:15 +00001220/* ---- */
1221static HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
1222{
1223 switch (arch) {
sewardj3fd39672006-01-27 22:05:55 +00001224 case VexArchX86: return show_hwcaps_x86(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001225 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
1226 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
1227 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
sewardj3fd39672006-01-27 22:05:55 +00001228 case VexArchARM: return show_hwcaps_arm(hwcaps);
sewardj2019a972011-03-07 16:04:07 +00001229 case VexArchS390X: return show_hwcaps_s390x(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001230 default: return NULL;
1231 }
1232}
1233
1234static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps )
1235{
1236 return show_hwcaps(arch,hwcaps) != NULL;
1237}
1238
1239
sewardj35421a32004-07-05 13:12:34 +00001240/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +00001241/*--- end main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +00001242/*---------------------------------------------------------------*/