blob: b0f03dea69a502e16829326c2dd0b5d478c850f0 [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;
sewardjc6f970f2012-04-02 21:54:49 +0000317#if 0
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;
sewardj010ac542011-05-29 09:29:18 +0000330 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
331 emit_PPCInstr;
cerion487e4c92005-02-04 16:28:19 +0000332 host_is_bigendian = True;
333 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000334 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_host.hwcaps));
sewardj010ac542011-05-29 09:29:18 +0000335 /* return-to-dispatcher scheme */
336 vassert(vta->dispatch_unassisted == NULL);
337 vassert(vta->dispatch_assisted == NULL);
cerion487e4c92005-02-04 16:28:19 +0000338 break;
339
cerionf0de28c2005-12-13 20:21:11 +0000340 case VexArchPPC64:
341 mode64 = True;
cerion5b2325f2005-12-23 00:55:09 +0000342 getAllocableRegs_PPC ( &n_available_real_regs,
343 &available_real_regs, mode64 );
344 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
345 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_PPCInstr;
346 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000347 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
348 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000349 ppInstr = (void(*)(HInstr*, Bool)) ppPPCInstr;
350 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000351 iselSB = iselSB_PPC;
sewardj010ac542011-05-29 09:29:18 +0000352 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
353 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));
sewardj010ac542011-05-29 09:29:18 +0000357 /* return-to-dispatcher scheme */
358 vassert(vta->dispatch_unassisted == NULL);
359 vassert(vta->dispatch_assisted == NULL);
cerionf0de28c2005-12-13 20:21:11 +0000360 break;
florian8844a632012-04-13 04:04:06 +0000361#endif
sewardj2019a972011-03-07 16:04:07 +0000362 case VexArchS390X:
363 mode64 = True;
364 getAllocableRegs_S390 ( &n_available_real_regs,
365 &available_real_regs, mode64 );
366 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_S390Instr;
367 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_S390Instr;
368 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_S390Instr;
369 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_S390;
370 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_S390;
371 ppInstr = (void(*)(HInstr*, Bool)) ppS390Instr;
372 ppReg = (void(*)(HReg)) ppHRegS390;
373 iselSB = iselSB_S390;
florian8844a632012-04-13 04:04:06 +0000374 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
375 void*,void*,void*,void*)) emit_S390Instr;
sewardj2019a972011-03-07 16:04:07 +0000376 host_is_bigendian = True;
377 host_word_type = Ity_I64;
378 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_host.hwcaps));
sewardj2019a972011-03-07 16:04:07 +0000379 break;
florian8844a632012-04-13 04:04:06 +0000380
sewardj6c299f32009-12-31 18:00:12 +0000381 case VexArchARM:
sewardj2a1ed8e2009-12-31 19:26:03 +0000382 mode64 = False;
sewardj6c299f32009-12-31 18:00:12 +0000383 getAllocableRegs_ARM ( &n_available_real_regs,
384 &available_real_regs );
sewardj2a1ed8e2009-12-31 19:26:03 +0000385 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARMInstr;
386 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_ARMInstr;
387 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_ARMInstr;
388 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_ARM;
389 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_ARM;
390 ppInstr = (void(*)(HInstr*, Bool)) ppARMInstr;
391 ppReg = (void(*)(HReg)) ppHRegARM;
392 iselSB = iselSB_ARM;
sewardjc6f970f2012-04-02 21:54:49 +0000393 emit = (Int(*)(Bool*,UChar*,Int,HInstr*,Bool,
394 void*,void*,void*,void*))
sewardj010ac542011-05-29 09:29:18 +0000395 emit_ARMInstr;
sewardj6c299f32009-12-31 18:00:12 +0000396 host_is_bigendian = False;
397 host_word_type = Ity_I32;
398 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_host.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000399 break;
400
sewardjf13a16a2004-07-05 17:10:14 +0000401 default:
sewardj6c299f32009-12-31 18:00:12 +0000402 vpanic("LibVEX_Translate: unsupported host insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000403 }
404
sewardj2a9ad022004-11-25 02:46:58 +0000405
sewardj17c7f952005-12-15 14:02:34 +0000406 switch (vta->arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000407
sewardjbef170b2004-12-21 01:23:00 +0000408 case VexArchX86:
sewardjc6f970f2012-04-02 21:54:49 +0000409 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
410 disInstrFn = disInstr_X86;
411 specHelper = guest_x86_spechelper;
412 guest_sizeB = sizeof(VexGuestX86State);
413 guest_word_type = Ity_I32;
414 guest_layout = &x86guest_layout;
415 offB_TISTART = offsetof(VexGuestX86State,guest_TISTART);
416 offB_TILEN = offsetof(VexGuestX86State,guest_TILEN);
417 offB_GUEST_IP = offsetof(VexGuestX86State,guest_EIP);
418 szB_GUEST_IP = sizeof( ((VexGuestX86State*)0)->guest_EIP );
419 offB_HOST_EvC_COUNTER = offsetof(VexGuestX86State,host_EvC_COUNTER);
420 offB_HOST_EvC_FAILADDR = offsetof(VexGuestX86State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000421 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000422 vassert(0 == sizeof(VexGuestX86State) % 16);
sewardjce02aa72006-01-12 12:27:58 +0000423 vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART) == 4);
424 vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
425 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000426 break;
sewardj2a9ad022004-11-25 02:46:58 +0000427
sewardj44d494d2005-01-20 20:26:33 +0000428 case VexArchAMD64:
sewardjc6f970f2012-04-02 21:54:49 +0000429 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
430 disInstrFn = disInstr_AMD64;
431 specHelper = guest_amd64_spechelper;
432 guest_sizeB = sizeof(VexGuestAMD64State);
433 guest_word_type = Ity_I64;
434 guest_layout = &amd64guest_layout;
435 offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART);
436 offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN);
437 offB_GUEST_IP = offsetof(VexGuestAMD64State,guest_RIP);
438 szB_GUEST_IP = sizeof( ((VexGuestAMD64State*)0)->guest_RIP );
439 offB_HOST_EvC_COUNTER = offsetof(VexGuestAMD64State,host_EvC_COUNTER);
440 offB_HOST_EvC_FAILADDR = offsetof(VexGuestAMD64State,host_EvC_FAILADDR);
sewardj5117ce12006-01-27 21:20:15 +0000441 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000442 vassert(0 == sizeof(VexGuestAMD64State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000443 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8);
sewardjce02aa72006-01-12 12:27:58 +0000444 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
445 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000446 break;
sewardjc6f970f2012-04-02 21:54:49 +0000447#if 0
cerionaabdfbf2005-01-29 12:56:15 +0000448 case VexArchPPC32:
449 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
cerion5b2325f2005-12-23 00:55:09 +0000450 disInstrFn = disInstr_PPC;
cerionaabdfbf2005-01-29 12:56:15 +0000451 specHelper = guest_ppc32_spechelper;
452 guest_sizeB = sizeof(VexGuestPPC32State);
453 guest_word_type = Ity_I32;
454 guest_layout = &ppc32Guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000455 offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART);
456 offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000457 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000458 vassert(0 == sizeof(VexGuestPPC32State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000459 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000460 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
461 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000462 break;
463
cerionf0de28c2005-12-13 20:21:11 +0000464 case VexArchPPC64:
465 preciseMemExnsFn = guest_ppc64_state_requires_precise_mem_exns;
cerion5b2325f2005-12-23 00:55:09 +0000466 disInstrFn = disInstr_PPC;
cerionf0de28c2005-12-13 20:21:11 +0000467 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);
sewardj5117ce12006-01-27 21:20:15 +0000473 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_guest.hwcaps));
cerionf0de28c2005-12-13 20:21:11 +0000474 vassert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj3fd39672006-01-27 22:05:55 +0000475 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TISTART ) == 8);
476 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TILEN ) == 8);
477 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8);
478 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8);
cerionf0de28c2005-12-13 20:21:11 +0000479 break;
florian8844a632012-04-13 04:04:06 +0000480#endif
sewardj2019a972011-03-07 16:04:07 +0000481 case VexArchS390X:
482 preciseMemExnsFn = guest_s390x_state_requires_precise_mem_exns;
483 disInstrFn = disInstr_S390;
484 specHelper = guest_s390x_spechelper;
485 guest_sizeB = sizeof(VexGuestS390XState);
486 guest_word_type = Ity_I64;
487 guest_layout = &s390xGuest_layout;
488 offB_TISTART = offsetof(VexGuestS390XState,guest_TISTART);
489 offB_TILEN = offsetof(VexGuestS390XState,guest_TILEN);
florian8844a632012-04-13 04:04:06 +0000490 offB_GUEST_IP = offsetof(VexGuestS390XState,guest_IA);
491 szB_GUEST_IP = sizeof( ((VexGuestS390XState*)0)->guest_IA);
492 offB_HOST_EvC_COUNTER = offsetof(VexGuestS390XState,host_EvC_COUNTER);
493 offB_HOST_EvC_FAILADDR = offsetof(VexGuestS390XState,host_EvC_FAILADDR);
sewardj2019a972011-03-07 16:04:07 +0000494 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_guest.hwcaps));
495 vassert(0 == sizeof(VexGuestS390XState) % 16);
496 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TISTART ) == 8);
497 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TILEN ) == 8);
498 vassert(sizeof( ((VexGuestS390XState*)0)->guest_NRADDR ) == 8);
499 break;
florian8844a632012-04-13 04:04:06 +0000500
sewardj6c299f32009-12-31 18:00:12 +0000501 case VexArchARM:
sewardjc6f970f2012-04-02 21:54:49 +0000502 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
503 disInstrFn = disInstr_ARM;
504 specHelper = guest_arm_spechelper;
505 guest_sizeB = sizeof(VexGuestARMState);
506 guest_word_type = Ity_I32;
507 guest_layout = &armGuest_layout;
508 offB_TISTART = offsetof(VexGuestARMState,guest_TISTART);
509 offB_TILEN = offsetof(VexGuestARMState,guest_TILEN);
510 offB_GUEST_IP = offsetof(VexGuestARMState,guest_R15T);
511 szB_GUEST_IP = sizeof( ((VexGuestARMState*)0)->guest_R15T );
512 offB_HOST_EvC_COUNTER = offsetof(VexGuestARMState,host_EvC_COUNTER);
513 offB_HOST_EvC_FAILADDR = offsetof(VexGuestARMState,host_EvC_FAILADDR);
sewardj6c299f32009-12-31 18:00:12 +0000514 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_guest.hwcaps));
515 vassert(0 == sizeof(VexGuestARMState) % 16);
516 vassert(sizeof( ((VexGuestARMState*)0)->guest_TISTART) == 4);
517 vassert(sizeof( ((VexGuestARMState*)0)->guest_TILEN ) == 4);
518 vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4);
519 break;
520
sewardjf13a16a2004-07-05 17:10:14 +0000521 default:
sewardj887a11a2004-07-05 17:26:47 +0000522 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000523 }
524
sewardjbc161a42011-06-07 21:28:38 +0000525 /* Set up result struct. */
526 VexTranslateResult res;
527 res.status = VexTransOK;
528 res.n_sc_extents = 0;
sewardjc6f970f2012-04-02 21:54:49 +0000529 res.offs_profInc = -1;
sewardjbc161a42011-06-07 21:28:38 +0000530
sewardj9df271d2004-12-31 22:37:42 +0000531 /* yet more sanity checks ... */
sewardj17c7f952005-12-15 14:02:34 +0000532 if (vta->arch_guest == vta->arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000533 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000534 we are simulating one flavour of an architecture a different
535 flavour of the same architecture, which is pretty strange. */
sewardj5117ce12006-01-27 21:20:15 +0000536 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps);
sewardj9df271d2004-12-31 22:37:42 +0000537 }
sewardj2a9ad022004-11-25 02:46:58 +0000538
sewardj2d6b14a2005-11-23 04:25:07 +0000539 vexAllocSanityCheck();
540
sewardjf48ac192004-10-29 00:41:29 +0000541 if (vex_traceflags & VEX_TRACE_FE)
542 vex_printf("\n------------------------"
543 " Front end "
544 "------------------------\n\n");
545
sewardjdd40fdf2006-12-24 02:20:24 +0000546 irsb = bb_to_IR ( vta->guest_extents,
sewardjbc161a42011-06-07 21:28:38 +0000547 &res.n_sc_extents,
sewardjc716aea2006-01-17 01:48:46 +0000548 vta->callback_opaque,
sewardj9e6491a2005-07-02 19:24:10 +0000549 disInstrFn,
sewardj17c7f952005-12-15 14:02:34 +0000550 vta->guest_bytes,
551 vta->guest_bytes_addr,
552 vta->chase_into_ok,
sewardj9e6491a2005-07-02 19:24:10 +0000553 host_is_bigendian,
sewardja5f55da2006-04-30 23:37:32 +0000554 vta->arch_guest,
sewardj17c7f952005-12-15 14:02:34 +0000555 &vta->archinfo_guest,
sewardjdd40fdf2006-12-24 02:20:24 +0000556 &vta->abiinfo_both,
sewardjdb4738a2005-07-07 01:32:16 +0000557 guest_word_type,
sewardjbc161a42011-06-07 21:28:38 +0000558 vta->needs_self_check,
sewardjc716aea2006-01-17 01:48:46 +0000559 vta->preamble_function,
sewardjdb4738a2005-07-07 01:32:16 +0000560 offB_TISTART,
sewardjc6f970f2012-04-02 21:54:49 +0000561 offB_TILEN,
562 offB_GUEST_IP,
563 szB_GUEST_IP );
sewardjf13a16a2004-07-05 17:10:14 +0000564
sewardj2d6b14a2005-11-23 04:25:07 +0000565 vexAllocSanityCheck();
566
sewardjdd40fdf2006-12-24 02:20:24 +0000567 if (irsb == NULL) {
sewardjf13a16a2004-07-05 17:10:14 +0000568 /* Access failure. */
sewardj2d6b14a2005-11-23 04:25:07 +0000569 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000570 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000571 res.status = VexTransAccessFail; return res;
sewardjf13a16a2004-07-05 17:10:14 +0000572 }
sewardjaa59f942004-10-09 09:34:36 +0000573
sewardj17c7f952005-12-15 14:02:34 +0000574 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3);
575 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr);
576 for (i = 0; i < vta->guest_extents->n_used; i++) {
577 vassert(vta->guest_extents->len[i] < 10000); /* sanity */
sewardj72c72812005-01-19 11:49:45 +0000578 }
579
sewardjaa59f942004-10-09 09:34:36 +0000580 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000581 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj17c7f952005-12-15 14:02:34 +0000582 if (vta->guest_extents->n_used > 1) {
sewardj72c72812005-01-19 11:49:45 +0000583 vex_printf("can't show code due to extents > 1\n");
584 } else {
585 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000586 UChar* p = (UChar*)vta->guest_bytes;
sewardj01f8cce2009-08-31 08:50:02 +0000587 UInt sum = 0;
sewardj17c7f952005-12-15 14:02:34 +0000588 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0];
sewardj01f8cce2009-08-31 08:50:02 +0000589 vex_printf("GuestBytes %llx %u ", vta->guest_bytes_addr,
590 guest_bytes_read );
591 for (i = 0; i < guest_bytes_read; i++) {
592 UInt b = (UInt)p[i];
593 vex_printf(" %02x", b );
594 sum = (sum << 1) ^ b;
595 }
596 vex_printf(" %08x\n\n", sum);
sewardj72c72812005-01-19 11:49:45 +0000597 }
sewardjaa59f942004-10-09 09:34:36 +0000598 }
599
600 /* Sanity check the initial IR. */
sewardjdd40fdf2006-12-24 02:20:24 +0000601 sanityCheckIRSB( irsb, "initial IR",
sewardjb9230752004-12-29 19:25:06 +0000602 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000603
sewardj2d6b14a2005-11-23 04:25:07 +0000604 vexAllocSanityCheck();
605
sewardjedf4d692004-08-17 13:52:58 +0000606 /* Clean it up, hopefully a lot. */
sewardjdd40fdf2006-12-24 02:20:24 +0000607 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn,
sewardjec0d9a02010-08-22 12:54:56 +0000608 vta->guest_bytes_addr,
609 vta->arch_guest );
sewardjdd40fdf2006-12-24 02:20:24 +0000610 sanityCheckIRSB( irsb, "after initial iropt",
sewardjb9230752004-12-29 19:25:06 +0000611 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000612
sewardjf48ac192004-10-29 00:41:29 +0000613 if (vex_traceflags & VEX_TRACE_OPT1) {
614 vex_printf("\n------------------------"
615 " After pre-instr IR optimisation "
616 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000617 ppIRSB ( irsb );
sewardjedf4d692004-08-17 13:52:58 +0000618 vex_printf("\n");
619 }
620
sewardj2d6b14a2005-11-23 04:25:07 +0000621 vexAllocSanityCheck();
622
sewardjf13a16a2004-07-05 17:10:14 +0000623 /* Get the thing instrumented. */
sewardj17c7f952005-12-15 14:02:34 +0000624 if (vta->instrument1)
sewardjdd40fdf2006-12-24 02:20:24 +0000625 irsb = vta->instrument1(vta->callback_opaque,
626 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000627 vta->guest_extents,
628 guest_word_type, host_word_type);
sewardj2d6b14a2005-11-23 04:25:07 +0000629 vexAllocSanityCheck();
630
sewardj17c7f952005-12-15 14:02:34 +0000631 if (vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000632 irsb = vta->instrument2(vta->callback_opaque,
633 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000634 vta->guest_extents,
635 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000636
sewardjf48ac192004-10-29 00:41:29 +0000637 if (vex_traceflags & VEX_TRACE_INST) {
638 vex_printf("\n------------------------"
639 " After instrumentation "
640 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000641 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000642 vex_printf("\n");
643 }
644
sewardj17c7f952005-12-15 14:02:34 +0000645 if (vta->instrument1 || vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000646 sanityCheckIRSB( irsb, "after instrumentation",
sewardjb9230752004-12-29 19:25:06 +0000647 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000648
sewardj9578a8b2004-11-04 19:44:48 +0000649 /* Do a post-instrumentation cleanup pass. */
sewardj17c7f952005-12-15 14:02:34 +0000650 if (vta->instrument1 || vta->instrument2) {
sewardjdd40fdf2006-12-24 02:20:24 +0000651 do_deadcode_BB( irsb );
652 irsb = cprop_BB( irsb );
653 do_deadcode_BB( irsb );
654 sanityCheckIRSB( irsb, "after post-instrumentation cleanup",
sewardjb9230752004-12-29 19:25:06 +0000655 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000656 }
657
sewardj2d6b14a2005-11-23 04:25:07 +0000658 vexAllocSanityCheck();
659
sewardj9578a8b2004-11-04 19:44:48 +0000660 if (vex_traceflags & VEX_TRACE_OPT2) {
661 vex_printf("\n------------------------"
662 " After post-instr IR optimisation "
663 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000664 ppIRSB ( irsb );
sewardj9578a8b2004-11-04 19:44:48 +0000665 vex_printf("\n");
666 }
667
sewardjf9517d02005-11-28 13:39:37 +0000668 /* Turn it into virtual-registerised code. Build trees -- this
669 also throws away any dead bindings. */
sewardjc6f970f2012-04-02 21:54:49 +0000670 max_ga = ado_treebuild_BB( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000671
sewardjbe1b6ff2007-08-28 06:06:27 +0000672 if (vta->finaltidy) {
673 irsb = vta->finaltidy(irsb);
674 }
675
sewardj2d6b14a2005-11-23 04:25:07 +0000676 vexAllocSanityCheck();
677
sewardjf48ac192004-10-29 00:41:29 +0000678 if (vex_traceflags & VEX_TRACE_TREES) {
679 vex_printf("\n------------------------"
680 " After tree-building "
681 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000682 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000683 vex_printf("\n");
684 }
685
sewardje908c422005-02-04 21:18:16 +0000686 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000687 if (0) {
688 *(vta->host_bytes_used) = 0;
689 res.status = VexTransOK; return res;
690 }
sewardje908c422005-02-04 21:18:16 +0000691 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000692
sewardjf48ac192004-10-29 00:41:29 +0000693 if (vex_traceflags & VEX_TRACE_VCODE)
694 vex_printf("\n------------------------"
695 " Instruction selection "
696 "------------------------\n");
697
sewardjc6f970f2012-04-02 21:54:49 +0000698 /* No guest has its IP field at offset zero. If this fails it
699 means some transformation pass somewhere failed to update/copy
700 irsb->offsIP properly. */
701 vassert(irsb->offsIP >= 16);
702
703 vcode = iselSB ( irsb, vta->arch_host,
704 &vta->archinfo_host,
705 &vta->abiinfo_both,
706 offB_HOST_EvC_COUNTER,
707 offB_HOST_EvC_FAILADDR,
708 chainingAllowed,
709 vta->addProfInc,
710 max_ga );
sewardjf13a16a2004-07-05 17:10:14 +0000711
sewardj2d6b14a2005-11-23 04:25:07 +0000712 vexAllocSanityCheck();
713
sewardjf48ac192004-10-29 00:41:29 +0000714 if (vex_traceflags & VEX_TRACE_VCODE)
715 vex_printf("\n");
716
sewardjf48ac192004-10-29 00:41:29 +0000717 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000718 for (i = 0; i < vcode->arr_used; i++) {
719 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000720 ppInstr(vcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000721 vex_printf("\n");
722 }
sewardjfbcaf332004-07-08 01:46:01 +0000723 vex_printf("\n");
724 }
sewardjfbcaf332004-07-08 01:46:01 +0000725
sewardjf13a16a2004-07-05 17:10:14 +0000726 /* Register allocate. */
727 rcode = doRegisterAllocation ( vcode, available_real_regs,
cerionf0de28c2005-12-13 20:21:11 +0000728 n_available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000729 isMove, getRegUsage, mapRegs,
sewardjfb7373a2007-08-25 21:29:03 +0000730 genSpill, genReload, directReload,
731 guest_sizeB,
cerion92b64362005-12-13 12:02:26 +0000732 ppInstr, ppReg, mode64 );
sewardjf13a16a2004-07-05 17:10:14 +0000733
sewardj2d6b14a2005-11-23 04:25:07 +0000734 vexAllocSanityCheck();
735
sewardjf48ac192004-10-29 00:41:29 +0000736 if (vex_traceflags & VEX_TRACE_RCODE) {
737 vex_printf("\n------------------------"
738 " Register-allocated code "
739 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000740 for (i = 0; i < rcode->arr_used; i++) {
741 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000742 ppInstr(rcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000743 vex_printf("\n");
744 }
sewardjfbcaf332004-07-08 01:46:01 +0000745 vex_printf("\n");
746 }
sewardjfbcaf332004-07-08 01:46:01 +0000747
sewardje908c422005-02-04 21:18:16 +0000748 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000749 if (0) {
750 *(vta->host_bytes_used) = 0;
751 res.status = VexTransOK; return res;
752 }
sewardje908c422005-02-04 21:18:16 +0000753 /* end HACK */
754
sewardj81bd5502004-07-21 18:49:27 +0000755 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000756 if (vex_traceflags & VEX_TRACE_ASM) {
757 vex_printf("\n------------------------"
758 " Assembly "
759 "------------------------\n\n");
760 }
761
sewardj81bd5502004-07-21 18:49:27 +0000762 out_used = 0; /* tracks along the host_bytes array */
763 for (i = 0; i < rcode->arr_used; i++) {
sewardjc6f970f2012-04-02 21:54:49 +0000764 HInstr* hi = rcode->arr[i];
765 Bool hi_isProfInc = False;
766 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
767 ppInstr(hi, mode64);
sewardjbad34a92004-07-22 01:14:11 +0000768 vex_printf("\n");
769 }
sewardjc6f970f2012-04-02 21:54:49 +0000770 j = emit( &hi_isProfInc,
771 insn_bytes, sizeof insn_bytes, hi, mode64,
772 vta->disp_cp_chain_me_to_slowEP,
773 vta->disp_cp_chain_me_to_fastEP,
774 vta->disp_cp_xindir,
775 vta->disp_cp_xassisted );
776 if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) {
sewardjbad34a92004-07-22 01:14:11 +0000777 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000778 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000779 vex_printf("0%x ", (UInt)insn_bytes[k]);
780 else
781 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000782 vex_printf("\n\n");
783 }
sewardjc6f970f2012-04-02 21:54:49 +0000784 if (UNLIKELY(out_used + j > vta->host_bytes_size)) {
sewardj2d6b14a2005-11-23 04:25:07 +0000785 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000786 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000787 res.status = VexTransOutputFull;
788 return res;
sewardj81bd5502004-07-21 18:49:27 +0000789 }
sewardjc6f970f2012-04-02 21:54:49 +0000790 if (UNLIKELY(hi_isProfInc)) {
791 vassert(vta->addProfInc); /* else where did it come from? */
792 vassert(res.offs_profInc == -1); /* there can be only one (tm) */
793 vassert(out_used >= 0);
794 res.offs_profInc = out_used;
795 }
796 { UChar* dst = &vta->host_bytes[out_used];
797 for (k = 0; k < j; k++) {
798 dst[k] = insn_bytes[k];
799 }
800 out_used += j;
sewardj81bd5502004-07-21 18:49:27 +0000801 }
sewardj17c7f952005-12-15 14:02:34 +0000802 vassert(out_used <= vta->host_bytes_size);
sewardj81bd5502004-07-21 18:49:27 +0000803 }
sewardj17c7f952005-12-15 14:02:34 +0000804 *(vta->host_bytes_used) = out_used;
sewardj81bd5502004-07-21 18:49:27 +0000805
sewardj2d6b14a2005-11-23 04:25:07 +0000806 vexAllocSanityCheck();
807
808 vexSetAllocModeTEMP_and_clear();
sewardjf13a16a2004-07-05 17:10:14 +0000809
sewardjf48ac192004-10-29 00:41:29 +0000810 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000811 res.status = VexTransOK;
812 return res;
sewardj35421a32004-07-05 13:12:34 +0000813}
814
815
sewardjc6f970f2012-04-02 21:54:49 +0000816/* --------- Chain/Unchain XDirects. --------- */
817
818VexInvalRange LibVEX_Chain ( VexArch arch_host,
819 void* place_to_chain,
820 void* disp_cp_chain_me_EXPECTED,
821 void* place_to_jump_to )
822{
823 VexInvalRange (*chainXDirect)(void*, void*, void*) = NULL;
824 switch (arch_host) {
825 case VexArchX86:
826 chainXDirect = chainXDirect_X86; break;
827 case VexArchAMD64:
828 chainXDirect = chainXDirect_AMD64; break;
829 case VexArchARM:
830 chainXDirect = chainXDirect_ARM; break;
florian8844a632012-04-13 04:04:06 +0000831 case VexArchS390X:
832 chainXDirect = chainXDirect_S390; break;
sewardjc6f970f2012-04-02 21:54:49 +0000833 default:
834 vassert(0);
835 }
836 vassert(chainXDirect);
837 VexInvalRange vir
838 = chainXDirect(place_to_chain, disp_cp_chain_me_EXPECTED,
839 place_to_jump_to);
840 return vir;
841}
842
843VexInvalRange LibVEX_UnChain ( VexArch arch_host,
844 void* place_to_unchain,
845 void* place_to_jump_to_EXPECTED,
846 void* disp_cp_chain_me )
847{
848 VexInvalRange (*unchainXDirect)(void*, void*, void*) = NULL;
849 switch (arch_host) {
850 case VexArchX86:
851 unchainXDirect = unchainXDirect_X86; break;
852 case VexArchAMD64:
853 unchainXDirect = unchainXDirect_AMD64; break;
854 case VexArchARM:
855 unchainXDirect = unchainXDirect_ARM; break;
florian8844a632012-04-13 04:04:06 +0000856 case VexArchS390X:
857 unchainXDirect = unchainXDirect_S390; break;
sewardjc6f970f2012-04-02 21:54:49 +0000858 default:
859 vassert(0);
860 }
861 vassert(unchainXDirect);
862 VexInvalRange vir
863 = unchainXDirect(place_to_unchain, place_to_jump_to_EXPECTED,
864 disp_cp_chain_me);
865 return vir;
866}
867
868Int LibVEX_evCheckSzB ( VexArch arch_host )
869{
870 static Int cached = 0; /* DO NOT MAKE NON-STATIC */
871 if (UNLIKELY(cached == 0)) {
872 switch (arch_host) {
873 case VexArchX86:
874 cached = evCheckSzB_X86(); break;
875 case VexArchAMD64:
876 cached = evCheckSzB_AMD64(); break;
877 case VexArchARM:
878 cached = evCheckSzB_ARM(); break;
florian8844a632012-04-13 04:04:06 +0000879 case VexArchS390X:
880 cached = evCheckSzB_S390(); break;
sewardjc6f970f2012-04-02 21:54:49 +0000881 default:
882 vassert(0);
883 }
884 }
885 return cached;
886}
887
888VexInvalRange LibVEX_PatchProfInc ( VexArch arch_host,
889 void* place_to_patch,
890 ULong* location_of_counter )
891{
892 VexInvalRange (*patchProfInc)(void*,ULong*) = NULL;
893 switch (arch_host) {
894 case VexArchX86:
895 patchProfInc = patchProfInc_X86; break;
896 case VexArchAMD64:
897 patchProfInc = patchProfInc_AMD64; break;
898 case VexArchARM:
899 patchProfInc = patchProfInc_ARM; break;
florian8844a632012-04-13 04:04:06 +0000900 case VexArchS390X:
901 patchProfInc = patchProfInc_S390; break;
sewardjc6f970f2012-04-02 21:54:49 +0000902 default:
903 vassert(0);
904 }
905 vassert(patchProfInc);
906 VexInvalRange vir
907 = patchProfInc(place_to_patch, location_of_counter);
908 return vir;
909}
910
911
sewardj893aada2004-11-29 19:57:54 +0000912/* --------- Emulation warnings. --------- */
913
914HChar* LibVEX_EmWarn_string ( VexEmWarn ew )
915{
916 switch (ew) {
917 case EmWarn_NONE:
918 return "none";
919 case EmWarn_X86_x87exns:
920 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000921 case EmWarn_X86_x87precision:
922 return "Selection of non-80-bit x87 FP precision";
923 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +0000924 return "Unmasking SSE FP exceptions";
925 case EmWarn_X86_fz:
926 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
927 case EmWarn_X86_daz:
928 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +0000929 case EmWarn_X86_acFlag:
930 return "Setting %eflags.ac (setting noted but ignored)";
sewardj9dd9cf12006-01-20 14:13:55 +0000931 case EmWarn_PPCexns:
932 return "Unmasking PPC32/64 FP exceptions";
933 case EmWarn_PPC64_redir_overflow:
934 return "PPC64 function redirection stack overflow";
935 case EmWarn_PPC64_redir_underflow:
936 return "PPC64 function redirection stack underflow";
sewardj893aada2004-11-29 19:57:54 +0000937 default:
938 vpanic("LibVEX_EmWarn_string: unknown warning");
939 }
940}
sewardj35421a32004-07-05 13:12:34 +0000941
sewardj5117ce12006-01-27 21:20:15 +0000942/* ------------------ Arch/HwCaps stuff. ------------------ */
sewardjbef170b2004-12-21 01:23:00 +0000943
944const HChar* LibVEX_ppVexArch ( VexArch arch )
945{
946 switch (arch) {
947 case VexArch_INVALID: return "INVALID";
948 case VexArchX86: return "X86";
949 case VexArchAMD64: return "AMD64";
950 case VexArchARM: return "ARM";
sewardj0ec57c52005-02-01 15:24:10 +0000951 case VexArchPPC32: return "PPC32";
cerionf0de28c2005-12-13 20:21:11 +0000952 case VexArchPPC64: return "PPC64";
sewardj2019a972011-03-07 16:04:07 +0000953 case VexArchS390X: return "S390X";
sewardjbef170b2004-12-21 01:23:00 +0000954 default: return "VexArch???";
955 }
956}
957
sewardj5117ce12006-01-27 21:20:15 +0000958const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
sewardjbef170b2004-12-21 01:23:00 +0000959{
sewardj5117ce12006-01-27 21:20:15 +0000960 HChar* str = show_hwcaps(arch,hwcaps);
961 return str ? str : "INVALID";
sewardjbef170b2004-12-21 01:23:00 +0000962}
963
sewardj5117ce12006-01-27 21:20:15 +0000964
sewardj27e1dd62005-06-30 11:49:14 +0000965/* Write default settings info *vai. */
966void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
967{
sewardj5117ce12006-01-27 21:20:15 +0000968 vai->hwcaps = 0;
cerion5b2325f2005-12-23 00:55:09 +0000969 vai->ppc_cache_line_szB = 0;
sewardje971c6a2010-09-03 15:49:57 +0000970 vai->ppc_dcbz_szB = 0;
971 vai->ppc_dcbzl_szB = 0;
972
sewardj27e1dd62005-06-30 11:49:14 +0000973}
974
sewardjdd40fdf2006-12-24 02:20:24 +0000975/* Write default settings info *vbi. */
976void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
sewardjaca070a2006-10-17 00:28:22 +0000977{
sewardjdd40fdf2006-12-24 02:20:24 +0000978 vbi->guest_stack_redzone_size = 0;
sewardj2e28ac42008-12-04 00:05:12 +0000979 vbi->guest_amd64_assume_fs_is_zero = False;
980 vbi->guest_amd64_assume_gs_is_0x60 = False;
sewardjdd40fdf2006-12-24 02:20:24 +0000981 vbi->guest_ppc_zap_RZ_at_blr = False;
982 vbi->guest_ppc_zap_RZ_at_bl = NULL;
983 vbi->guest_ppc_sc_continues_at_LR = False;
984 vbi->host_ppc_calls_use_fndescrs = False;
985 vbi->host_ppc32_regalign_int64_args = False;
sewardjaca070a2006-10-17 00:28:22 +0000986}
987
sewardj27e1dd62005-06-30 11:49:14 +0000988
sewardj5117ce12006-01-27 21:20:15 +0000989/* Return a string showing the hwcaps in a nice way. The string will
990 be NULL for invalid combinations of flags, so these functions also
991 serve as a way to validate hwcaps values. */
992
993static HChar* show_hwcaps_x86 ( UInt hwcaps )
994{
995 /* Monotonic, SSE3 > SSE2 > SSE1 > baseline. */
sewardj536fbab2010-07-29 15:39:05 +0000996 switch (hwcaps) {
997 case 0:
998 return "x86-sse0";
999 case VEX_HWCAPS_X86_SSE1:
1000 return "x86-sse1";
1001 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2:
1002 return "x86-sse1-sse2";
1003 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
1004 | VEX_HWCAPS_X86_LZCNT:
1005 return "x86-sse1-sse2-lzcnt";
1006 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
1007 | VEX_HWCAPS_X86_SSE3:
1008 return "x86-sse1-sse2-sse3";
1009 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
1010 | VEX_HWCAPS_X86_SSE3 | VEX_HWCAPS_X86_LZCNT:
1011 return "x86-sse1-sse2-sse3-lzcnt";
1012 default:
1013 return NULL;
1014 }
sewardj5117ce12006-01-27 21:20:15 +00001015}
1016
1017static HChar* show_hwcaps_amd64 ( UInt hwcaps )
1018{
sewardje9d8a262009-07-01 08:06:34 +00001019 /* SSE3 and CX16 are orthogonal and > baseline, although we really
1020 don't expect to come across anything which can do SSE3 but can't
sewardj536fbab2010-07-29 15:39:05 +00001021 do CX16. Still, we can handle that case. LZCNT is similarly
1022 orthogonal. */
1023 switch (hwcaps) {
1024 case 0:
1025 return "amd64-sse2";
1026 case VEX_HWCAPS_AMD64_SSE3:
1027 return "amd64-sse3";
1028 case VEX_HWCAPS_AMD64_CX16:
1029 return "amd64-sse2-cx16";
1030 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16:
1031 return "amd64-sse3-cx16";
1032 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_LZCNT:
1033 return "amd64-sse3-lzcnt";
1034 case VEX_HWCAPS_AMD64_CX16 | VEX_HWCAPS_AMD64_LZCNT:
1035 return "amd64-sse2-cx16-lzcnt";
1036 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16
1037 | VEX_HWCAPS_AMD64_LZCNT:
1038 return "amd64-sse3-cx16-lzcnt";
1039
1040 default:
1041 return NULL;
1042 }
sewardj5117ce12006-01-27 21:20:15 +00001043}
1044
1045static HChar* show_hwcaps_ppc32 ( UInt hwcaps )
1046{
1047 /* Monotonic with complications. Basically V > F > baseline,
1048 but once you have F then you can have FX or GX too. */
1049 const UInt F = VEX_HWCAPS_PPC32_F;
1050 const UInt V = VEX_HWCAPS_PPC32_V;
1051 const UInt FX = VEX_HWCAPS_PPC32_FX;
1052 const UInt GX = VEX_HWCAPS_PPC32_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001053 const UInt VX = VEX_HWCAPS_PPC32_VX;
sewardj5117ce12006-01-27 21:20:15 +00001054 UInt c = hwcaps;
1055 if (c == 0) return "ppc32-int";
1056 if (c == F) return "ppc32-int-flt";
1057 if (c == (F|FX)) return "ppc32-int-flt-FX";
1058 if (c == (F|GX)) return "ppc32-int-flt-GX";
1059 if (c == (F|FX|GX)) return "ppc32-int-flt-FX-GX";
1060 if (c == (F|V)) return "ppc32-int-flt-vmx";
1061 if (c == (F|V|FX)) return "ppc32-int-flt-vmx-FX";
1062 if (c == (F|V|GX)) return "ppc32-int-flt-vmx-GX";
1063 if (c == (F|V|FX|GX)) return "ppc32-int-flt-vmx-FX-GX";
sewardj66d5ef22011-04-15 11:55:00 +00001064 if (c == (F|V|FX|GX|VX)) return "ppc32-int-flt-vmx-FX-GX-VX";
sewardj5117ce12006-01-27 21:20:15 +00001065 return NULL;
1066}
1067
1068static HChar* show_hwcaps_ppc64 ( UInt hwcaps )
1069{
1070 /* Monotonic with complications. Basically V > baseline(==F),
1071 but once you have F then you can have FX or GX too. */
sewardj3fd39672006-01-27 22:05:55 +00001072 const UInt V = VEX_HWCAPS_PPC64_V;
1073 const UInt FX = VEX_HWCAPS_PPC64_FX;
1074 const UInt GX = VEX_HWCAPS_PPC64_GX;
sewardj66d5ef22011-04-15 11:55:00 +00001075 const UInt VX = VEX_HWCAPS_PPC64_VX;
sewardj5117ce12006-01-27 21:20:15 +00001076 UInt c = hwcaps;
1077 if (c == 0) return "ppc64-int-flt";
1078 if (c == FX) return "ppc64-int-flt-FX";
1079 if (c == GX) return "ppc64-int-flt-GX";
1080 if (c == (FX|GX)) return "ppc64-int-flt-FX-GX";
1081 if (c == V) return "ppc64-int-flt-vmx";
1082 if (c == (V|FX)) return "ppc64-int-flt-vmx-FX";
1083 if (c == (V|GX)) return "ppc64-int-flt-vmx-GX";
1084 if (c == (V|FX|GX)) return "ppc64-int-flt-vmx-FX-GX";
sewardj66d5ef22011-04-15 11:55:00 +00001085 if (c == (V|FX|GX|VX)) return "ppc64-int-flt-vmx-FX-GX-VX";
sewardj5117ce12006-01-27 21:20:15 +00001086 return NULL;
1087}
1088
1089static HChar* show_hwcaps_arm ( UInt hwcaps )
1090{
sewardjec0d9a02010-08-22 12:54:56 +00001091 Bool N = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0);
1092 Bool vfp = ((hwcaps & (VEX_HWCAPS_ARM_VFP |
1093 VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3)) != 0);
1094 switch (VEX_ARM_ARCHLEVEL(hwcaps)) {
1095 case 5:
1096 if (N)
1097 return NULL;
1098 if (vfp)
1099 return "ARMv5-vfp";
1100 else
1101 return "ARMv5";
1102 return NULL;
1103 case 6:
1104 if (N)
1105 return NULL;
1106 if (vfp)
1107 return "ARMv6-vfp";
1108 else
1109 return "ARMv6";
1110 return NULL;
1111 case 7:
1112 if (vfp) {
1113 if (N)
1114 return "ARMv7-vfp-neon";
1115 else
1116 return "ARMv7-vfp";
1117 } else {
1118 if (N)
1119 return "ARMv7-neon";
1120 else
1121 return "ARMv7";
1122 }
1123 default:
1124 return NULL;
1125 }
sewardj5117ce12006-01-27 21:20:15 +00001126 return NULL;
1127}
1128
sewardj2019a972011-03-07 16:04:07 +00001129static HChar* show_hwcaps_s390x ( UInt hwcaps )
1130{
sewardjd07b8562011-04-27 11:58:22 +00001131 static const HChar prefix[] = "s390x";
1132 static const HChar facilities[][6] = {
1133 { "ldisp" },
1134 { "eimm" },
1135 { "gie" },
1136 { "dfp" },
1137 { "fgx" },
1138 };
1139 static HChar buf[sizeof facilities + sizeof prefix + 1];
1140 static HChar *p;
1141
1142 if (buf[0] != '\0') return buf; /* already constructed */
sewardj2019a972011-03-07 16:04:07 +00001143
sewardj652b56a2011-04-13 15:38:17 +00001144 hwcaps = VEX_HWCAPS_S390X(hwcaps);
1145
sewardjd07b8562011-04-27 11:58:22 +00001146 p = buf + vex_sprintf(buf, "%s", prefix);
1147 if (hwcaps & VEX_HWCAPS_S390X_LDISP)
1148 p = p + vex_sprintf(p, "-%s", facilities[0]);
1149 if (hwcaps & VEX_HWCAPS_S390X_EIMM)
1150 p = p + vex_sprintf(p, "-%s", facilities[1]);
1151 if (hwcaps & VEX_HWCAPS_S390X_GIE)
1152 p = p + vex_sprintf(p, "-%s", facilities[2]);
1153 if (hwcaps & VEX_HWCAPS_S390X_DFP)
1154 p = p + vex_sprintf(p, "-%s", facilities[3]);
1155 if (hwcaps & VEX_HWCAPS_S390X_FGX)
1156 p = p + vex_sprintf(p, "-%s", facilities[4]);
sewardj2019a972011-03-07 16:04:07 +00001157
sewardjd07b8562011-04-27 11:58:22 +00001158 /* If there are no facilities, add "zarch" */
1159 if (hwcaps == 0)
1160 vex_sprintf(p, "-%s", "zarch");
1161
1162 return buf;
sewardj2019a972011-03-07 16:04:07 +00001163}
1164
sewardj5117ce12006-01-27 21:20:15 +00001165/* ---- */
1166static HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
1167{
1168 switch (arch) {
sewardj3fd39672006-01-27 22:05:55 +00001169 case VexArchX86: return show_hwcaps_x86(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001170 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
1171 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
1172 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
sewardj3fd39672006-01-27 22:05:55 +00001173 case VexArchARM: return show_hwcaps_arm(hwcaps);
sewardj2019a972011-03-07 16:04:07 +00001174 case VexArchS390X: return show_hwcaps_s390x(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001175 default: return NULL;
1176 }
1177}
1178
1179static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps )
1180{
1181 return show_hwcaps(arch,hwcaps) != NULL;
1182}
1183
1184
sewardj35421a32004-07-05 13:12:34 +00001185/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +00001186/*--- end main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +00001187/*---------------------------------------------------------------*/