blob: feaf45958956ac84957c0f0104e27f770b7bfbcb [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;
sewardj9e1cf152012-04-20 02:18:31 +0000337
cerionf0de28c2005-12-13 20:21:11 +0000338 case VexArchPPC64:
339 mode64 = True;
cerion5b2325f2005-12-23 00:55:09 +0000340 getAllocableRegs_PPC ( &n_available_real_regs,
341 &available_real_regs, mode64 );
342 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
343 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_PPCInstr;
344 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000345 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
346 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000347 ppInstr = (void(*)(HInstr*, Bool)) ppPPCInstr;
348 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000349 iselSB = iselSB_PPC;
sewardj9e1cf152012-04-20 02:18:31 +0000350 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
351 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000352 emit_PPCInstr;
cerionf0de28c2005-12-13 20:21:11 +0000353 host_is_bigendian = True;
354 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000355 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_host.hwcaps));
cerionf0de28c2005-12-13 20:21:11 +0000356 break;
sewardj9e1cf152012-04-20 02:18:31 +0000357
sewardj2019a972011-03-07 16:04:07 +0000358 case VexArchS390X:
359 mode64 = True;
360 getAllocableRegs_S390 ( &n_available_real_regs,
361 &available_real_regs, mode64 );
362 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_S390Instr;
363 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_S390Instr;
364 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_S390Instr;
365 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_S390;
366 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_S390;
367 ppInstr = (void(*)(HInstr*, Bool)) ppS390Instr;
368 ppReg = (void(*)(HReg)) ppHRegS390;
369 iselSB = iselSB_S390;
florian8844a632012-04-13 04:04:06 +0000370 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
371 void*,void*,void*,void*)) emit_S390Instr;
sewardj2019a972011-03-07 16:04:07 +0000372 host_is_bigendian = True;
373 host_word_type = Ity_I64;
374 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_host.hwcaps));
sewardj2019a972011-03-07 16:04:07 +0000375 break;
florian8844a632012-04-13 04:04:06 +0000376
sewardj6c299f32009-12-31 18:00:12 +0000377 case VexArchARM:
sewardj2a1ed8e2009-12-31 19:26:03 +0000378 mode64 = False;
sewardj6c299f32009-12-31 18:00:12 +0000379 getAllocableRegs_ARM ( &n_available_real_regs,
380 &available_real_regs );
sewardj2a1ed8e2009-12-31 19:26:03 +0000381 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARMInstr;
382 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_ARMInstr;
383 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_ARMInstr;
384 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_ARM;
385 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_ARM;
386 ppInstr = (void(*)(HInstr*, Bool)) ppARMInstr;
387 ppReg = (void(*)(HReg)) ppHRegARM;
388 iselSB = iselSB_ARM;
sewardjc6f970f2012-04-02 21:54:49 +0000389 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
390 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000391 emit_ARMInstr;
sewardj6c299f32009-12-31 18:00:12 +0000392 host_is_bigendian = False;
393 host_word_type = Ity_I32;
394 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_host.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000395 break;
396
sewardjf13a16a2004-07-05 17:10:14 +0000397 default:
sewardj6c299f32009-12-31 18:00:12 +0000398 vpanic("LibVEX_Translate: unsupported host insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000399 }
400
sewardj2a9ad022004-11-25 02:46:58 +0000401
sewardj17c7f952005-12-15 14:02:34 +0000402 switch (vta->arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000403
sewardjbef170b2004-12-21 01:23:00 +0000404 case VexArchX86:
sewardjc6f970f2012-04-02 21:54:49 +0000405 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
406 disInstrFn = disInstr_X86;
407 specHelper = guest_x86_spechelper;
408 guest_sizeB = sizeof(VexGuestX86State);
409 guest_word_type = Ity_I32;
410 guest_layout = &x86guest_layout;
411 offB_TISTART = offsetof(VexGuestX86State,guest_TISTART);
412 offB_TILEN = offsetof(VexGuestX86State,guest_TILEN);
413 offB_GUEST_IP = offsetof(VexGuestX86State,guest_EIP);
414 szB_GUEST_IP = sizeof( ((VexGuestX86State*)0)->guest_EIP );
415 offB_HOST_EvC_COUNTER = offsetof(VexGuestX86State,host_EvC_COUNTER);
416 offB_HOST_EvC_FAILADDR = offsetof(VexGuestX86State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000417 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000418 vassert(0 == sizeof(VexGuestX86State) % 16);
sewardjce02aa72006-01-12 12:27:58 +0000419 vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART) == 4);
420 vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
421 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000422 break;
sewardj2a9ad022004-11-25 02:46:58 +0000423
sewardj44d494d2005-01-20 20:26:33 +0000424 case VexArchAMD64:
sewardjc6f970f2012-04-02 21:54:49 +0000425 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
426 disInstrFn = disInstr_AMD64;
427 specHelper = guest_amd64_spechelper;
428 guest_sizeB = sizeof(VexGuestAMD64State);
429 guest_word_type = Ity_I64;
430 guest_layout = &amd64guest_layout;
431 offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART);
432 offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN);
433 offB_GUEST_IP = offsetof(VexGuestAMD64State,guest_RIP);
434 szB_GUEST_IP = sizeof( ((VexGuestAMD64State*)0)->guest_RIP );
435 offB_HOST_EvC_COUNTER = offsetof(VexGuestAMD64State,host_EvC_COUNTER);
436 offB_HOST_EvC_FAILADDR = offsetof(VexGuestAMD64State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000437 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000438 vassert(0 == sizeof(VexGuestAMD64State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000439 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8);
sewardjce02aa72006-01-12 12:27:58 +0000440 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
441 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000442 break;
sewardj3dee8492012-04-20 00:13:28 +0000443
cerionaabdfbf2005-01-29 12:56:15 +0000444 case VexArchPPC32:
sewardj3dee8492012-04-20 00:13:28 +0000445 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
446 disInstrFn = disInstr_PPC;
447 specHelper = guest_ppc32_spechelper;
448 guest_sizeB = sizeof(VexGuestPPC32State);
449 guest_word_type = Ity_I32;
450 guest_layout = &ppc32Guest_layout;
451 offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART);
452 offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN);
453 offB_GUEST_IP = offsetof(VexGuestPPC32State,guest_CIA);
454 szB_GUEST_IP = sizeof( ((VexGuestPPC32State*)0)->guest_CIA );
455 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC32State,host_EvC_COUNTER);
456 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC32State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000457 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000458 vassert(0 == sizeof(VexGuestPPC32State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000459 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000460 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
461 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000462 break;
sewardj9e1cf152012-04-20 02:18:31 +0000463
cerionf0de28c2005-12-13 20:21:11 +0000464 case VexArchPPC64:
sewardj9e1cf152012-04-20 02:18:31 +0000465 preciseMemExnsFn = guest_ppc64_state_requires_precise_mem_exns;
466 disInstrFn = disInstr_PPC;
467 specHelper = guest_ppc64_spechelper;
468 guest_sizeB = sizeof(VexGuestPPC64State);
469 guest_word_type = Ity_I64;
470 guest_layout = &ppc64Guest_layout;
471 offB_TISTART = offsetof(VexGuestPPC64State,guest_TISTART);
472 offB_TILEN = offsetof(VexGuestPPC64State,guest_TILEN);
473 offB_GUEST_IP = offsetof(VexGuestPPC64State,guest_CIA);
474 szB_GUEST_IP = sizeof( ((VexGuestPPC64State*)0)->guest_CIA );
475 offB_HOST_EvC_COUNTER = offsetof(VexGuestPPC64State,host_EvC_COUNTER);
476 offB_HOST_EvC_FAILADDR = offsetof(VexGuestPPC64State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000477 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_guest.hwcaps));
cerionf0de28c2005-12-13 20:21:11 +0000478 vassert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj3fd39672006-01-27 22:05:55 +0000479 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TISTART ) == 8);
480 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TILEN ) == 8);
481 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8);
482 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8);
cerionf0de28c2005-12-13 20:21:11 +0000483 break;
sewardj9e1cf152012-04-20 02:18:31 +0000484
sewardj2019a972011-03-07 16:04:07 +0000485 case VexArchS390X:
486 preciseMemExnsFn = guest_s390x_state_requires_precise_mem_exns;
487 disInstrFn = disInstr_S390;
488 specHelper = guest_s390x_spechelper;
489 guest_sizeB = sizeof(VexGuestS390XState);
490 guest_word_type = Ity_I64;
491 guest_layout = &s390xGuest_layout;
492 offB_TISTART = offsetof(VexGuestS390XState,guest_TISTART);
493 offB_TILEN = offsetof(VexGuestS390XState,guest_TILEN);
florian8844a632012-04-13 04:04:06 +0000494 offB_GUEST_IP = offsetof(VexGuestS390XState,guest_IA);
495 szB_GUEST_IP = sizeof( ((VexGuestS390XState*)0)->guest_IA);
496 offB_HOST_EvC_COUNTER = offsetof(VexGuestS390XState,host_EvC_COUNTER);
497 offB_HOST_EvC_FAILADDR = offsetof(VexGuestS390XState,host_EvC_FAILADDR);
sewardj2019a972011-03-07 16:04:07 +0000498 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_guest.hwcaps));
499 vassert(0 == sizeof(VexGuestS390XState) % 16);
500 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TISTART ) == 8);
501 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TILEN ) == 8);
502 vassert(sizeof( ((VexGuestS390XState*)0)->guest_NRADDR ) == 8);
503 break;
florian8844a632012-04-13 04:04:06 +0000504
sewardj6c299f32009-12-31 18:00:12 +0000505 case VexArchARM:
sewardjc6f970f2012-04-02 21:54:49 +0000506 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
507 disInstrFn = disInstr_ARM;
508 specHelper = guest_arm_spechelper;
509 guest_sizeB = sizeof(VexGuestARMState);
510 guest_word_type = Ity_I32;
511 guest_layout = &armGuest_layout;
512 offB_TISTART = offsetof(VexGuestARMState,guest_TISTART);
513 offB_TILEN = offsetof(VexGuestARMState,guest_TILEN);
514 offB_GUEST_IP = offsetof(VexGuestARMState,guest_R15T);
515 szB_GUEST_IP = sizeof( ((VexGuestARMState*)0)->guest_R15T );
516 offB_HOST_EvC_COUNTER = offsetof(VexGuestARMState,host_EvC_COUNTER);
517 offB_HOST_EvC_FAILADDR = offsetof(VexGuestARMState,host_EvC_FAILADDR);
sewardj6c299f32009-12-31 18:00:12 +0000518 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_guest.hwcaps));
519 vassert(0 == sizeof(VexGuestARMState) % 16);
520 vassert(sizeof( ((VexGuestARMState*)0)->guest_TISTART) == 4);
521 vassert(sizeof( ((VexGuestARMState*)0)->guest_TILEN ) == 4);
522 vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4);
523 break;
524
sewardjf13a16a2004-07-05 17:10:14 +0000525 default:
sewardj887a11a2004-07-05 17:26:47 +0000526 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000527 }
528
sewardjbc161a42011-06-07 21:28:38 +0000529 /* Set up result struct. */
530 VexTranslateResult res;
531 res.status = VexTransOK;
532 res.n_sc_extents = 0;
sewardjc6f970f2012-04-02 21:54:49 +0000533 res.offs_profInc = -1;
sewardjbc161a42011-06-07 21:28:38 +0000534
sewardj9df271d2004-12-31 22:37:42 +0000535 /* yet more sanity checks ... */
sewardj17c7f952005-12-15 14:02:34 +0000536 if (vta->arch_guest == vta->arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000537 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000538 we are simulating one flavour of an architecture a different
539 flavour of the same architecture, which is pretty strange. */
sewardj5117ce12006-01-27 21:20:15 +0000540 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps);
sewardj9df271d2004-12-31 22:37:42 +0000541 }
sewardj2a9ad022004-11-25 02:46:58 +0000542
sewardj2d6b14a2005-11-23 04:25:07 +0000543 vexAllocSanityCheck();
544
sewardjf48ac192004-10-29 00:41:29 +0000545 if (vex_traceflags & VEX_TRACE_FE)
546 vex_printf("\n------------------------"
547 " Front end "
548 "------------------------\n\n");
549
sewardjdd40fdf2006-12-24 02:20:24 +0000550 irsb = bb_to_IR ( vta->guest_extents,
sewardjbc161a42011-06-07 21:28:38 +0000551 &res.n_sc_extents,
sewardjc716aea2006-01-17 01:48:46 +0000552 vta->callback_opaque,
sewardj9e6491a2005-07-02 19:24:10 +0000553 disInstrFn,
sewardj17c7f952005-12-15 14:02:34 +0000554 vta->guest_bytes,
555 vta->guest_bytes_addr,
556 vta->chase_into_ok,
sewardj9e6491a2005-07-02 19:24:10 +0000557 host_is_bigendian,
sewardja5f55da2006-04-30 23:37:32 +0000558 vta->arch_guest,
sewardj17c7f952005-12-15 14:02:34 +0000559 &vta->archinfo_guest,
sewardjdd40fdf2006-12-24 02:20:24 +0000560 &vta->abiinfo_both,
sewardjdb4738a2005-07-07 01:32:16 +0000561 guest_word_type,
sewardjbc161a42011-06-07 21:28:38 +0000562 vta->needs_self_check,
sewardjc716aea2006-01-17 01:48:46 +0000563 vta->preamble_function,
sewardjdb4738a2005-07-07 01:32:16 +0000564 offB_TISTART,
sewardjc6f970f2012-04-02 21:54:49 +0000565 offB_TILEN,
566 offB_GUEST_IP,
567 szB_GUEST_IP );
sewardjf13a16a2004-07-05 17:10:14 +0000568
sewardj2d6b14a2005-11-23 04:25:07 +0000569 vexAllocSanityCheck();
570
sewardjdd40fdf2006-12-24 02:20:24 +0000571 if (irsb == NULL) {
sewardjf13a16a2004-07-05 17:10:14 +0000572 /* Access failure. */
sewardj2d6b14a2005-11-23 04:25:07 +0000573 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000574 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000575 res.status = VexTransAccessFail; return res;
sewardjf13a16a2004-07-05 17:10:14 +0000576 }
sewardjaa59f942004-10-09 09:34:36 +0000577
sewardj17c7f952005-12-15 14:02:34 +0000578 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3);
579 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr);
580 for (i = 0; i < vta->guest_extents->n_used; i++) {
581 vassert(vta->guest_extents->len[i] < 10000); /* sanity */
sewardj72c72812005-01-19 11:49:45 +0000582 }
583
sewardjaa59f942004-10-09 09:34:36 +0000584 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000585 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj17c7f952005-12-15 14:02:34 +0000586 if (vta->guest_extents->n_used > 1) {
sewardj72c72812005-01-19 11:49:45 +0000587 vex_printf("can't show code due to extents > 1\n");
588 } else {
589 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000590 UChar* p = (UChar*)vta->guest_bytes;
sewardj01f8cce2009-08-31 08:50:02 +0000591 UInt sum = 0;
sewardj17c7f952005-12-15 14:02:34 +0000592 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0];
sewardj01f8cce2009-08-31 08:50:02 +0000593 vex_printf("GuestBytes %llx %u ", vta->guest_bytes_addr,
594 guest_bytes_read );
595 for (i = 0; i < guest_bytes_read; i++) {
596 UInt b = (UInt)p[i];
597 vex_printf(" %02x", b );
598 sum = (sum << 1) ^ b;
599 }
600 vex_printf(" %08x\n\n", sum);
sewardj72c72812005-01-19 11:49:45 +0000601 }
sewardjaa59f942004-10-09 09:34:36 +0000602 }
603
604 /* Sanity check the initial IR. */
sewardjdd40fdf2006-12-24 02:20:24 +0000605 sanityCheckIRSB( irsb, "initial IR",
sewardjb9230752004-12-29 19:25:06 +0000606 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000607
sewardj2d6b14a2005-11-23 04:25:07 +0000608 vexAllocSanityCheck();
609
sewardjedf4d692004-08-17 13:52:58 +0000610 /* Clean it up, hopefully a lot. */
sewardjdd40fdf2006-12-24 02:20:24 +0000611 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn,
sewardjec0d9a02010-08-22 12:54:56 +0000612 vta->guest_bytes_addr,
613 vta->arch_guest );
sewardjdd40fdf2006-12-24 02:20:24 +0000614 sanityCheckIRSB( irsb, "after initial iropt",
sewardjb9230752004-12-29 19:25:06 +0000615 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000616
sewardjf48ac192004-10-29 00:41:29 +0000617 if (vex_traceflags & VEX_TRACE_OPT1) {
618 vex_printf("\n------------------------"
619 " After pre-instr IR optimisation "
620 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000621 ppIRSB ( irsb );
sewardjedf4d692004-08-17 13:52:58 +0000622 vex_printf("\n");
623 }
624
sewardj2d6b14a2005-11-23 04:25:07 +0000625 vexAllocSanityCheck();
626
sewardjf13a16a2004-07-05 17:10:14 +0000627 /* Get the thing instrumented. */
sewardj17c7f952005-12-15 14:02:34 +0000628 if (vta->instrument1)
sewardjdd40fdf2006-12-24 02:20:24 +0000629 irsb = vta->instrument1(vta->callback_opaque,
630 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000631 vta->guest_extents,
632 guest_word_type, host_word_type);
sewardj2d6b14a2005-11-23 04:25:07 +0000633 vexAllocSanityCheck();
634
sewardj17c7f952005-12-15 14:02:34 +0000635 if (vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000636 irsb = vta->instrument2(vta->callback_opaque,
637 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000638 vta->guest_extents,
639 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000640
sewardjf48ac192004-10-29 00:41:29 +0000641 if (vex_traceflags & VEX_TRACE_INST) {
642 vex_printf("\n------------------------"
643 " After instrumentation "
644 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000645 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000646 vex_printf("\n");
647 }
648
sewardj17c7f952005-12-15 14:02:34 +0000649 if (vta->instrument1 || vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000650 sanityCheckIRSB( irsb, "after instrumentation",
sewardjb9230752004-12-29 19:25:06 +0000651 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000652
sewardj9578a8b2004-11-04 19:44:48 +0000653 /* Do a post-instrumentation cleanup pass. */
sewardj17c7f952005-12-15 14:02:34 +0000654 if (vta->instrument1 || vta->instrument2) {
sewardjdd40fdf2006-12-24 02:20:24 +0000655 do_deadcode_BB( irsb );
656 irsb = cprop_BB( irsb );
657 do_deadcode_BB( irsb );
658 sanityCheckIRSB( irsb, "after post-instrumentation cleanup",
sewardjb9230752004-12-29 19:25:06 +0000659 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000660 }
661
sewardj2d6b14a2005-11-23 04:25:07 +0000662 vexAllocSanityCheck();
663
sewardj9578a8b2004-11-04 19:44:48 +0000664 if (vex_traceflags & VEX_TRACE_OPT2) {
665 vex_printf("\n------------------------"
666 " After post-instr IR optimisation "
667 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000668 ppIRSB ( irsb );
sewardj9578a8b2004-11-04 19:44:48 +0000669 vex_printf("\n");
670 }
671
sewardjf9517d02005-11-28 13:39:37 +0000672 /* Turn it into virtual-registerised code. Build trees -- this
673 also throws away any dead bindings. */
sewardjc6f970f2012-04-02 21:54:49 +0000674 max_ga = ado_treebuild_BB( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000675
sewardjbe1b6ff2007-08-28 06:06:27 +0000676 if (vta->finaltidy) {
677 irsb = vta->finaltidy(irsb);
678 }
679
sewardj2d6b14a2005-11-23 04:25:07 +0000680 vexAllocSanityCheck();
681
sewardjf48ac192004-10-29 00:41:29 +0000682 if (vex_traceflags & VEX_TRACE_TREES) {
683 vex_printf("\n------------------------"
684 " After tree-building "
685 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000686 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000687 vex_printf("\n");
688 }
689
sewardje908c422005-02-04 21:18:16 +0000690 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000691 if (0) {
692 *(vta->host_bytes_used) = 0;
693 res.status = VexTransOK; return res;
694 }
sewardje908c422005-02-04 21:18:16 +0000695 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000696
sewardjf48ac192004-10-29 00:41:29 +0000697 if (vex_traceflags & VEX_TRACE_VCODE)
698 vex_printf("\n------------------------"
699 " Instruction selection "
700 "------------------------\n");
701
sewardjc6f970f2012-04-02 21:54:49 +0000702 /* No guest has its IP field at offset zero. If this fails it
703 means some transformation pass somewhere failed to update/copy
704 irsb->offsIP properly. */
705 vassert(irsb->offsIP >= 16);
706
707 vcode = iselSB ( irsb, vta->arch_host,
708 &vta->archinfo_host,
709 &vta->abiinfo_both,
710 offB_HOST_EvC_COUNTER,
711 offB_HOST_EvC_FAILADDR,
712 chainingAllowed,
713 vta->addProfInc,
714 max_ga );
sewardjf13a16a2004-07-05 17:10:14 +0000715
sewardj2d6b14a2005-11-23 04:25:07 +0000716 vexAllocSanityCheck();
717
sewardjf48ac192004-10-29 00:41:29 +0000718 if (vex_traceflags & VEX_TRACE_VCODE)
719 vex_printf("\n");
720
sewardjf48ac192004-10-29 00:41:29 +0000721 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000722 for (i = 0; i < vcode->arr_used; i++) {
723 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000724 ppInstr(vcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000725 vex_printf("\n");
726 }
sewardjfbcaf332004-07-08 01:46:01 +0000727 vex_printf("\n");
728 }
sewardjfbcaf332004-07-08 01:46:01 +0000729
sewardjf13a16a2004-07-05 17:10:14 +0000730 /* Register allocate. */
731 rcode = doRegisterAllocation ( vcode, available_real_regs,
cerionf0de28c2005-12-13 20:21:11 +0000732 n_available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000733 isMove, getRegUsage, mapRegs,
sewardjfb7373a2007-08-25 21:29:03 +0000734 genSpill, genReload, directReload,
735 guest_sizeB,
cerion92b64362005-12-13 12:02:26 +0000736 ppInstr, ppReg, mode64 );
sewardjf13a16a2004-07-05 17:10:14 +0000737
sewardj2d6b14a2005-11-23 04:25:07 +0000738 vexAllocSanityCheck();
739
sewardjf48ac192004-10-29 00:41:29 +0000740 if (vex_traceflags & VEX_TRACE_RCODE) {
741 vex_printf("\n------------------------"
742 " Register-allocated code "
743 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000744 for (i = 0; i < rcode->arr_used; i++) {
745 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000746 ppInstr(rcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000747 vex_printf("\n");
748 }
sewardjfbcaf332004-07-08 01:46:01 +0000749 vex_printf("\n");
750 }
sewardjfbcaf332004-07-08 01:46:01 +0000751
sewardje908c422005-02-04 21:18:16 +0000752 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000753 if (0) {
754 *(vta->host_bytes_used) = 0;
755 res.status = VexTransOK; return res;
756 }
sewardje908c422005-02-04 21:18:16 +0000757 /* end HACK */
758
sewardj81bd5502004-07-21 18:49:27 +0000759 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000760 if (vex_traceflags & VEX_TRACE_ASM) {
761 vex_printf("\n------------------------"
762 " Assembly "
763 "------------------------\n\n");
764 }
765
sewardj81bd5502004-07-21 18:49:27 +0000766 out_used = 0; /* tracks along the host_bytes array */
767 for (i = 0; i < rcode->arr_used; i++) {
sewardjc6f970f2012-04-02 21:54:49 +0000768 HInstr* hi = rcode->arr[i];
769 Bool hi_isProfInc = False;
770 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
771 ppInstr(hi, mode64);
sewardjbad34a92004-07-22 01:14:11 +0000772 vex_printf("\n");
773 }
sewardjc6f970f2012-04-02 21:54:49 +0000774 j = emit( &hi_isProfInc,
775 insn_bytes, sizeof insn_bytes, hi, mode64,
776 vta->disp_cp_chain_me_to_slowEP,
777 vta->disp_cp_chain_me_to_fastEP,
778 vta->disp_cp_xindir,
779 vta->disp_cp_xassisted );
780 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
sewardjbad34a92004-07-22 01:14:11 +0000781 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000782 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000783 vex_printf("0%x ", (UInt)insn_bytes[k]);
784 else
785 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000786 vex_printf("\n\n");
787 }
sewardjc6f970f2012-04-02 21:54:49 +0000788 if (UNLIKELY(out_used + j > vta->host_bytes_size)) {
sewardj2d6b14a2005-11-23 04:25:07 +0000789 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000790 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000791 res.status = VexTransOutputFull;
792 return res;
sewardj81bd5502004-07-21 18:49:27 +0000793 }
sewardjc6f970f2012-04-02 21:54:49 +0000794 if (UNLIKELY(hi_isProfInc)) {
795 vassert(vta->addProfInc); /* else where did it come from? */
796 vassert(res.offs_profInc == -1); /* there can be only one (tm) */
797 vassert(out_used >= 0);
798 res.offs_profInc = out_used;
799 }
800 { UChar* dst = &vta->host_bytes[out_used];
801 for (k = 0; k < j; k++) {
802 dst[k] = insn_bytes[k];
803 }
804 out_used += j;
sewardj81bd5502004-07-21 18:49:27 +0000805 }
sewardj17c7f952005-12-15 14:02:34 +0000806 vassert(out_used <= vta->host_bytes_size);
sewardj81bd5502004-07-21 18:49:27 +0000807 }
sewardj17c7f952005-12-15 14:02:34 +0000808 *(vta->host_bytes_used) = out_used;
sewardj81bd5502004-07-21 18:49:27 +0000809
sewardj2d6b14a2005-11-23 04:25:07 +0000810 vexAllocSanityCheck();
811
812 vexSetAllocModeTEMP_and_clear();
sewardjf13a16a2004-07-05 17:10:14 +0000813
sewardjf48ac192004-10-29 00:41:29 +0000814 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000815 res.status = VexTransOK;
816 return res;
sewardj35421a32004-07-05 13:12:34 +0000817}
818
819
sewardjc6f970f2012-04-02 21:54:49 +0000820/* --------- Chain/Unchain XDirects. --------- */
821
822VexInvalRange LibVEX_Chain ( VexArch arch_host,
823 void* place_to_chain,
824 void* disp_cp_chain_me_EXPECTED,
825 void* place_to_jump_to )
826{
827 VexInvalRange (*chainXDirect)(void*, void*, void*) = NULL;
828 switch (arch_host) {
829 case VexArchX86:
830 chainXDirect = chainXDirect_X86; break;
831 case VexArchAMD64:
832 chainXDirect = chainXDirect_AMD64; break;
833 case VexArchARM:
834 chainXDirect = chainXDirect_ARM; break;
florian8844a632012-04-13 04:04:06 +0000835 case VexArchS390X:
836 chainXDirect = chainXDirect_S390; break;
sewardj3dee8492012-04-20 00:13:28 +0000837 case VexArchPPC32:
838 return chainXDirect_PPC(place_to_chain,
839 disp_cp_chain_me_EXPECTED,
840 place_to_jump_to, False/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +0000841 default:
842 vassert(0);
843 }
844 vassert(chainXDirect);
845 VexInvalRange vir
846 = chainXDirect(place_to_chain, disp_cp_chain_me_EXPECTED,
847 place_to_jump_to);
848 return vir;
849}
850
851VexInvalRange LibVEX_UnChain ( VexArch arch_host,
852 void* place_to_unchain,
853 void* place_to_jump_to_EXPECTED,
854 void* disp_cp_chain_me )
855{
856 VexInvalRange (*unchainXDirect)(void*, void*, void*) = NULL;
857 switch (arch_host) {
858 case VexArchX86:
859 unchainXDirect = unchainXDirect_X86; break;
860 case VexArchAMD64:
861 unchainXDirect = unchainXDirect_AMD64; break;
862 case VexArchARM:
863 unchainXDirect = unchainXDirect_ARM; break;
florian8844a632012-04-13 04:04:06 +0000864 case VexArchS390X:
865 unchainXDirect = unchainXDirect_S390; break;
sewardj3dee8492012-04-20 00:13:28 +0000866 case VexArchPPC32:
867 return unchainXDirect_PPC(place_to_unchain,
868 place_to_jump_to_EXPECTED,
869 disp_cp_chain_me, False/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +0000870 default:
871 vassert(0);
872 }
873 vassert(unchainXDirect);
874 VexInvalRange vir
875 = unchainXDirect(place_to_unchain, place_to_jump_to_EXPECTED,
876 disp_cp_chain_me);
877 return vir;
878}
879
880Int LibVEX_evCheckSzB ( VexArch arch_host )
881{
882 static Int cached = 0; /* DO NOT MAKE NON-STATIC */
883 if (UNLIKELY(cached == 0)) {
884 switch (arch_host) {
885 case VexArchX86:
886 cached = evCheckSzB_X86(); break;
887 case VexArchAMD64:
888 cached = evCheckSzB_AMD64(); break;
889 case VexArchARM:
890 cached = evCheckSzB_ARM(); break;
florian8844a632012-04-13 04:04:06 +0000891 case VexArchS390X:
892 cached = evCheckSzB_S390(); break;
sewardj3dee8492012-04-20 00:13:28 +0000893 case VexArchPPC32:
894 cached = evCheckSzB_PPC(); break;
sewardjc6f970f2012-04-02 21:54:49 +0000895 default:
896 vassert(0);
897 }
898 }
899 return cached;
900}
901
902VexInvalRange LibVEX_PatchProfInc ( VexArch arch_host,
903 void* place_to_patch,
904 ULong* location_of_counter )
905{
906 VexInvalRange (*patchProfInc)(void*,ULong*) = NULL;
907 switch (arch_host) {
908 case VexArchX86:
909 patchProfInc = patchProfInc_X86; break;
910 case VexArchAMD64:
911 patchProfInc = patchProfInc_AMD64; break;
912 case VexArchARM:
913 patchProfInc = patchProfInc_ARM; break;
florian8844a632012-04-13 04:04:06 +0000914 case VexArchS390X:
915 patchProfInc = patchProfInc_S390; break;
sewardj3dee8492012-04-20 00:13:28 +0000916 case VexArchPPC32:
917 return patchProfInc_PPC(place_to_patch,
918 location_of_counter, False/*!mode64*/);
sewardjc6f970f2012-04-02 21:54:49 +0000919 default:
920 vassert(0);
921 }
922 vassert(patchProfInc);
923 VexInvalRange vir
924 = patchProfInc(place_to_patch, location_of_counter);
925 return vir;
926}
927
928
sewardj893aada2004-11-29 19:57:54 +0000929/* --------- Emulation warnings. --------- */
930
931HChar* LibVEX_EmWarn_string ( VexEmWarn ew )
932{
933 switch (ew) {
934 case EmWarn_NONE:
935 return "none";
936 case EmWarn_X86_x87exns:
937 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000938 case EmWarn_X86_x87precision:
939 return "Selection of non-80-bit x87 FP precision";
940 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +0000941 return "Unmasking SSE FP exceptions";
942 case EmWarn_X86_fz:
943 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
944 case EmWarn_X86_daz:
945 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +0000946 case EmWarn_X86_acFlag:
947 return "Setting %eflags.ac (setting noted but ignored)";
sewardj9dd9cf12006-01-20 14:13:55 +0000948 case EmWarn_PPCexns:
949 return "Unmasking PPC32/64 FP exceptions";
950 case EmWarn_PPC64_redir_overflow:
951 return "PPC64 function redirection stack overflow";
952 case EmWarn_PPC64_redir_underflow:
953 return "PPC64 function redirection stack underflow";
sewardj893aada2004-11-29 19:57:54 +0000954 default:
955 vpanic("LibVEX_EmWarn_string: unknown warning");
956 }
957}
sewardj35421a32004-07-05 13:12:34 +0000958
sewardj5117ce12006-01-27 21:20:15 +0000959/* ------------------ Arch/HwCaps stuff. ------------------ */
sewardjbef170b2004-12-21 01:23:00 +0000960
961const HChar* LibVEX_ppVexArch ( VexArch arch )
962{
963 switch (arch) {
964 case VexArch_INVALID: return "INVALID";
965 case VexArchX86: return "X86";
966 case VexArchAMD64: return "AMD64";
967 case VexArchARM: return "ARM";
sewardj0ec57c52005-02-01 15:24:10 +0000968 case VexArchPPC32: return "PPC32";
cerionf0de28c2005-12-13 20:21:11 +0000969 case VexArchPPC64: return "PPC64";
sewardj2019a972011-03-07 16:04:07 +0000970 case VexArchS390X: return "S390X";
sewardjbef170b2004-12-21 01:23:00 +0000971 default: return "VexArch???";
972 }
973}
974
sewardj5117ce12006-01-27 21:20:15 +0000975const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
sewardjbef170b2004-12-21 01:23:00 +0000976{
sewardj5117ce12006-01-27 21:20:15 +0000977 HChar* str = show_hwcaps(arch,hwcaps);
978 return str ? str : "INVALID";
sewardjbef170b2004-12-21 01:23:00 +0000979}
980
sewardj5117ce12006-01-27 21:20:15 +0000981
sewardj27e1dd62005-06-30 11:49:14 +0000982/* Write default settings info *vai. */
983void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
984{
sewardj5117ce12006-01-27 21:20:15 +0000985 vai->hwcaps = 0;
cerion5b2325f2005-12-23 00:55:09 +0000986 vai->ppc_cache_line_szB = 0;
sewardje971c6a2010-09-03 15:49:57 +0000987 vai->ppc_dcbz_szB = 0;
988 vai->ppc_dcbzl_szB = 0;
989
sewardj27e1dd62005-06-30 11:49:14 +0000990}
991
sewardjdd40fdf2006-12-24 02:20:24 +0000992/* Write default settings info *vbi. */
993void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
sewardjaca070a2006-10-17 00:28:22 +0000994{
sewardjdd40fdf2006-12-24 02:20:24 +0000995 vbi->guest_stack_redzone_size = 0;
sewardj2e28ac42008-12-04 00:05:12 +0000996 vbi->guest_amd64_assume_fs_is_zero = False;
997 vbi->guest_amd64_assume_gs_is_0x60 = False;
sewardjdd40fdf2006-12-24 02:20:24 +0000998 vbi->guest_ppc_zap_RZ_at_blr = False;
999 vbi->guest_ppc_zap_RZ_at_bl = NULL;
1000 vbi->guest_ppc_sc_continues_at_LR = False;
1001 vbi->host_ppc_calls_use_fndescrs = False;
1002 vbi->host_ppc32_regalign_int64_args = False;
sewardjaca070a2006-10-17 00:28:22 +00001003}
1004
sewardj27e1dd62005-06-30 11:49:14 +00001005
sewardj5117ce12006-01-27 21:20:15 +00001006/* Return a string showing the hwcaps in a nice way. The string will
1007 be NULL for invalid combinations of flags, so these functions also
1008 serve as a way to validate hwcaps values. */
1009
1010static HChar* show_hwcaps_x86 ( UInt hwcaps )
1011{
1012 /* Monotonic, SSE3 > SSE2 > SSE1 > baseline. */
sewardj536fbab2010-07-29 15:39:05 +00001013 switch (hwcaps) {
1014 case 0:
1015 return "x86-sse0";
1016 case VEX_HWCAPS_X86_SSE1:
1017 return "x86-sse1";
1018 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2:
1019 return "x86-sse1-sse2";
1020 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
1021 | VEX_HWCAPS_X86_LZCNT:
1022 return "x86-sse1-sse2-lzcnt";
1023 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
1024 | VEX_HWCAPS_X86_SSE3:
1025 return "x86-sse1-sse2-sse3";
1026 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
1027 | VEX_HWCAPS_X86_SSE3 | VEX_HWCAPS_X86_LZCNT:
1028 return "x86-sse1-sse2-sse3-lzcnt";
1029 default:
1030 return NULL;
1031 }
sewardj5117ce12006-01-27 21:20:15 +00001032}
1033
1034static HChar* show_hwcaps_amd64 ( UInt hwcaps )
1035{
sewardje9d8a262009-07-01 08:06:34 +00001036 /* SSE3 and CX16 are orthogonal and > baseline, although we really
1037 don't expect to come across anything which can do SSE3 but can't
sewardj536fbab2010-07-29 15:39:05 +00001038 do CX16. Still, we can handle that case. LZCNT is similarly
1039 orthogonal. */
1040 switch (hwcaps) {
1041 case 0:
1042 return "amd64-sse2";
1043 case VEX_HWCAPS_AMD64_SSE3:
1044 return "amd64-sse3";
1045 case VEX_HWCAPS_AMD64_CX16:
1046 return "amd64-sse2-cx16";
1047 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16:
1048 return "amd64-sse3-cx16";
1049 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_LZCNT:
1050 return "amd64-sse3-lzcnt";
1051 case VEX_HWCAPS_AMD64_CX16 | VEX_HWCAPS_AMD64_LZCNT:
1052 return "amd64-sse2-cx16-lzcnt";
1053 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16
1054 | VEX_HWCAPS_AMD64_LZCNT:
1055 return "amd64-sse3-cx16-lzcnt";
1056
1057 default:
1058 return NULL;
1059 }
sewardj5117ce12006-01-27 21:20:15 +00001060}
1061
1062static HChar* show_hwcaps_ppc32 ( UInt hwcaps )
1063{
1064 /* Monotonic with complications. Basically V > F > baseline,
1065 but once you have F then you can have FX or GX too. */
1066 const UInt F = VEX_HWCAPS_PPC32_F;
1067 const UInt V = VEX_HWCAPS_PPC32_V;
1068 const UInt FX = VEX_HWCAPS_PPC32_FX;
1069 const UInt GX = VEX_HWCAPS_PPC32_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001070 const UInt VX = VEX_HWCAPS_PPC32_VX;
sewardj5117ce12006-01-27 21:20:15 +00001071 UInt c = hwcaps;
1072 if (c == 0) return "ppc32-int";
1073 if (c == F) return "ppc32-int-flt";
1074 if (c == (F|FX)) return "ppc32-int-flt-FX";
1075 if (c == (F|GX)) return "ppc32-int-flt-GX";
1076 if (c == (F|FX|GX)) return "ppc32-int-flt-FX-GX";
1077 if (c == (F|V)) return "ppc32-int-flt-vmx";
1078 if (c == (F|V|FX)) return "ppc32-int-flt-vmx-FX";
1079 if (c == (F|V|GX)) return "ppc32-int-flt-vmx-GX";
1080 if (c == (F|V|FX|GX)) return "ppc32-int-flt-vmx-FX-GX";
sewardj66d5ef22011-04-15 11:55:00 +00001081 if (c == (F|V|FX|GX|VX)) return "ppc32-int-flt-vmx-FX-GX-VX";
sewardj5117ce12006-01-27 21:20:15 +00001082 return NULL;
1083}
1084
1085static HChar* show_hwcaps_ppc64 ( UInt hwcaps )
1086{
1087 /* Monotonic with complications. Basically V > baseline(==F),
1088 but once you have F then you can have FX or GX too. */
sewardj3fd39672006-01-27 22:05:55 +00001089 const UInt V = VEX_HWCAPS_PPC64_V;
1090 const UInt FX = VEX_HWCAPS_PPC64_FX;
1091 const UInt GX = VEX_HWCAPS_PPC64_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001092 const UInt VX = VEX_HWCAPS_PPC64_VX;
sewardj5117ce12006-01-27 21:20:15 +00001093 UInt c = hwcaps;
1094 if (c == 0) return "ppc64-int-flt";
1095 if (c == FX) return "ppc64-int-flt-FX";
1096 if (c == GX) return "ppc64-int-flt-GX";
1097 if (c == (FX|GX)) return "ppc64-int-flt-FX-GX";
1098 if (c == V) return "ppc64-int-flt-vmx";
1099 if (c == (V|FX)) return "ppc64-int-flt-vmx-FX";
1100 if (c == (V|GX)) return "ppc64-int-flt-vmx-GX";
1101 if (c == (V|FX|GX)) return "ppc64-int-flt-vmx-FX-GX";
sewardj66d5ef22011-04-15 11:55:00 +00001102 if (c == (V|FX|GX|VX)) return "ppc64-int-flt-vmx-FX-GX-VX";
sewardj5117ce12006-01-27 21:20:15 +00001103 return NULL;
1104}
1105
1106static HChar* show_hwcaps_arm ( UInt hwcaps )
1107{
sewardjec0d9a02010-08-22 12:54:56 +00001108 Bool N = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0);
1109 Bool vfp = ((hwcaps & (VEX_HWCAPS_ARM_VFP |
1110 VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3)) != 0);
1111 switch (VEX_ARM_ARCHLEVEL(hwcaps)) {
1112 case 5:
1113 if (N)
1114 return NULL;
1115 if (vfp)
1116 return "ARMv5-vfp";
1117 else
1118 return "ARMv5";
1119 return NULL;
1120 case 6:
1121 if (N)
1122 return NULL;
1123 if (vfp)
1124 return "ARMv6-vfp";
1125 else
1126 return "ARMv6";
1127 return NULL;
1128 case 7:
1129 if (vfp) {
1130 if (N)
1131 return "ARMv7-vfp-neon";
1132 else
1133 return "ARMv7-vfp";
1134 } else {
1135 if (N)
1136 return "ARMv7-neon";
1137 else
1138 return "ARMv7";
1139 }
1140 default:
1141 return NULL;
1142 }
sewardj5117ce12006-01-27 21:20:15 +00001143 return NULL;
1144}
1145
sewardj2019a972011-03-07 16:04:07 +00001146static HChar* show_hwcaps_s390x ( UInt hwcaps )
1147{
sewardjd07b8562011-04-27 11:58:22 +00001148 static const HChar prefix[] = "s390x";
1149 static const HChar facilities[][6] = {
1150 { "ldisp" },
1151 { "eimm" },
1152 { "gie" },
1153 { "dfp" },
1154 { "fgx" },
1155 };
1156 static HChar buf[sizeof facilities + sizeof prefix + 1];
1157 static HChar *p;
1158
1159 if (buf[0] != '\0') return buf; /* already constructed */
sewardj2019a972011-03-07 16:04:07 +00001160
sewardj652b56a2011-04-13 15:38:17 +00001161 hwcaps = VEX_HWCAPS_S390X(hwcaps);
1162
sewardjd07b8562011-04-27 11:58:22 +00001163 p = buf + vex_sprintf(buf, "%s", prefix);
1164 if (hwcaps & VEX_HWCAPS_S390X_LDISP)
1165 p = p + vex_sprintf(p, "-%s", facilities[0]);
1166 if (hwcaps & VEX_HWCAPS_S390X_EIMM)
1167 p = p + vex_sprintf(p, "-%s", facilities[1]);
1168 if (hwcaps & VEX_HWCAPS_S390X_GIE)
1169 p = p + vex_sprintf(p, "-%s", facilities[2]);
1170 if (hwcaps & VEX_HWCAPS_S390X_DFP)
1171 p = p + vex_sprintf(p, "-%s", facilities[3]);
1172 if (hwcaps & VEX_HWCAPS_S390X_FGX)
1173 p = p + vex_sprintf(p, "-%s", facilities[4]);
sewardj2019a972011-03-07 16:04:07 +00001174
sewardjd07b8562011-04-27 11:58:22 +00001175 /* If there are no facilities, add "zarch" */
1176 if (hwcaps == 0)
1177 vex_sprintf(p, "-%s", "zarch");
1178
1179 return buf;
sewardj2019a972011-03-07 16:04:07 +00001180}
1181
sewardj5117ce12006-01-27 21:20:15 +00001182/* ---- */
1183static HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
1184{
1185 switch (arch) {
sewardj3fd39672006-01-27 22:05:55 +00001186 case VexArchX86: return show_hwcaps_x86(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001187 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
1188 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
1189 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
sewardj3fd39672006-01-27 22:05:55 +00001190 case VexArchARM: return show_hwcaps_arm(hwcaps);
sewardj2019a972011-03-07 16:04:07 +00001191 case VexArchS390X: return show_hwcaps_s390x(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001192 default: return NULL;
1193 }
1194}
1195
1196static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps )
1197{
1198 return show_hwcaps(arch,hwcaps) != NULL;
1199}
1200
1201
sewardj35421a32004-07-05 13:12:34 +00001202/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +00001203/*--- end main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +00001204/*---------------------------------------------------------------*/