blob: c8777fe5540672542c3b3345c82a9f57b93b34c3 [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
sewardjea602bc2004-10-14 21:40:12 +0000158 /* Really start up .. */
sewardj443cd9d2004-07-18 23:06:45 +0000159 vex_debuglevel = debuglevel;
sewardj443cd9d2004-07-18 23:06:45 +0000160 vex_valgrind_support = valgrind_support;
sewardj08613742004-10-25 13:01:45 +0000161 vex_control = *vcon;
sewardj443cd9d2004-07-18 23:06:45 +0000162 vex_initdone = True;
sewardjd887b862005-01-17 18:34:34 +0000163 vexSetAllocMode ( VexAllocModeTEMP );
sewardj35421a32004-07-05 13:12:34 +0000164}
165
166
167/* --------- Make a translation. --------- */
168
169/* Exported to library client. */
170
sewardj17c7f952005-12-15 14:02:34 +0000171VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta )
sewardj35421a32004-07-05 13:12:34 +0000172{
sewardj81bd5502004-07-21 18:49:27 +0000173 /* This the bundle of functions we need to do the back-end stuff
174 (insn selection, reg-alloc, assembly) whilst being insulated
175 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +0000176 HReg* available_real_regs;
177 Int n_available_real_regs;
sewardjfb7373a2007-08-25 21:29:03 +0000178 Bool (*isMove) ( HInstr*, HReg*, HReg* );
179 void (*getRegUsage) ( HRegUsage*, HInstr*, Bool );
180 void (*mapRegs) ( HRegRemap*, HInstr*, Bool );
sewardj6c299f32009-12-31 18:00:12 +0000181 void (*genSpill) ( HInstr**, HInstr**, HReg, Int, Bool );
182 void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool );
sewardjfb7373a2007-08-25 21:29:03 +0000183 HInstr* (*directReload) ( HInstr*, HReg, Short );
184 void (*ppInstr) ( HInstr*, Bool );
185 void (*ppReg) ( HReg );
186 HInstrArray* (*iselSB) ( IRSB*, VexArch, VexArchInfo*,
187 VexAbiInfo* );
sewardj010ac542011-05-29 09:29:18 +0000188 Int (*emit) ( UChar*, Int, HInstr*, Bool, void*, void* );
sewardjec0d9a02010-08-22 12:54:56 +0000189 IRExpr* (*specHelper) ( HChar*, IRExpr**, IRStmt**, Int );
sewardj8d2291c2004-10-25 14:50:21 +0000190 Bool (*preciseMemExnsFn) ( Int, Int );
sewardjf13a16a2004-07-05 17:10:14 +0000191
sewardj9e6491a2005-07-02 19:24:10 +0000192 DisOneInstrFn disInstrFn;
193
sewardjeeac8412004-11-02 00:26:55 +0000194 VexGuestLayout* guest_layout;
195 Bool host_is_bigendian = False;
sewardjdd40fdf2006-12-24 02:20:24 +0000196 IRSB* irsb;
sewardjeeac8412004-11-02 00:26:55 +0000197 HInstrArray* vcode;
198 HInstrArray* rcode;
199 Int i, j, k, out_used, guest_sizeB;
sewardjc716aea2006-01-17 01:48:46 +0000200 Int offB_TISTART, offB_TILEN;
sewardj2019a972011-03-07 16:04:07 +0000201 UChar insn_bytes[48];
sewardjcf787902004-11-03 09:08:33 +0000202 IRType guest_word_type;
203 IRType host_word_type;
cerion92b64362005-12-13 12:02:26 +0000204 Bool mode64;
sewardjf13a16a2004-07-05 17:10:14 +0000205
sewardj49651f42004-10-28 22:11:04 +0000206 guest_layout = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000207 available_real_regs = NULL;
208 n_available_real_regs = 0;
209 isMove = NULL;
210 getRegUsage = NULL;
211 mapRegs = NULL;
212 genSpill = NULL;
213 genReload = NULL;
sewardjfb7373a2007-08-25 21:29:03 +0000214 directReload = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000215 ppInstr = NULL;
216 ppReg = NULL;
sewardjdd40fdf2006-12-24 02:20:24 +0000217 iselSB = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000218 emit = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000219 specHelper = NULL;
sewardj8d2291c2004-10-25 14:50:21 +0000220 preciseMemExnsFn = NULL;
sewardj9e6491a2005-07-02 19:24:10 +0000221 disInstrFn = NULL;
sewardjcf787902004-11-03 09:08:33 +0000222 guest_word_type = Ity_INVALID;
223 host_word_type = Ity_INVALID;
sewardjdb4738a2005-07-07 01:32:16 +0000224 offB_TISTART = 0;
225 offB_TILEN = 0;
cerion92b64362005-12-13 12:02:26 +0000226 mode64 = False;
sewardj36ca5132004-07-24 13:12:23 +0000227
sewardj17c7f952005-12-15 14:02:34 +0000228 vex_traceflags = vta->traceflags;
sewardj58800ff2004-07-28 01:51:10 +0000229
sewardj35421a32004-07-05 13:12:34 +0000230 vassert(vex_initdone);
florian2eeeb9b2011-09-23 18:03:21 +0000231 vassert(vta->needs_self_check != NULL);
232
sewardj2d6b14a2005-11-23 04:25:07 +0000233 vexSetAllocModeTEMP_and_clear();
234 vexAllocSanityCheck();
sewardj2a9ad022004-11-25 02:46:58 +0000235
sewardjf13a16a2004-07-05 17:10:14 +0000236 /* First off, check that the guest and host insn sets
237 are supported. */
sewardj2a9ad022004-11-25 02:46:58 +0000238
sewardj17c7f952005-12-15 14:02:34 +0000239 switch (vta->arch_host) {
sewardj2a9ad022004-11-25 02:46:58 +0000240
sewardjbef170b2004-12-21 01:23:00 +0000241 case VexArchX86:
sewardjfb7373a2007-08-25 21:29:03 +0000242 mode64 = False;
sewardjf13a16a2004-07-05 17:10:14 +0000243 getAllocableRegs_X86 ( &n_available_real_regs,
244 &available_real_regs );
sewardjfb7373a2007-08-25 21:29:03 +0000245 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000246 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
247 getRegUsage_X86Instr;
sewardjfb7373a2007-08-25 21:29:03 +0000248 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000249 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
250 genSpill_X86;
251 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
252 genReload_X86;
sewardjfb7373a2007-08-25 21:29:03 +0000253 directReload = (HInstr*(*)(HInstr*,HReg,Short)) directReload_X86;
254 ppInstr = (void(*)(HInstr*, Bool)) ppX86Instr;
255 ppReg = (void(*)(HReg)) ppHRegX86;
256 iselSB = iselSB_X86;
sewardj010ac542011-05-29 09:29:18 +0000257 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
258 emit_X86Instr;
sewardj72c72812005-01-19 11:49:45 +0000259 host_is_bigendian = False;
sewardjcf787902004-11-03 09:08:33 +0000260 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000261 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_host.hwcaps));
sewardj010ac542011-05-29 09:29:18 +0000262 /* jump-to-dispatcher scheme */
263 vassert(vta->dispatch_unassisted != NULL);
264 vassert(vta->dispatch_assisted != NULL);
sewardjf13a16a2004-07-05 17:10:14 +0000265 break;
sewardj2a9ad022004-11-25 02:46:58 +0000266
sewardjc33671d2005-02-01 20:30:00 +0000267 case VexArchAMD64:
cerion92b64362005-12-13 12:02:26 +0000268 mode64 = True;
sewardjc33671d2005-02-01 20:30:00 +0000269 getAllocableRegs_AMD64 ( &n_available_real_regs,
270 &available_real_regs );
271 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000272 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
273 getRegUsage_AMD64Instr;
cerion92b64362005-12-13 12:02:26 +0000274 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000275 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
276 genSpill_AMD64;
277 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
278 genReload_AMD64;
cerion92b64362005-12-13 12:02:26 +0000279 ppInstr = (void(*)(HInstr*, Bool)) ppAMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000280 ppReg = (void(*)(HReg)) ppHRegAMD64;
sewardjdd40fdf2006-12-24 02:20:24 +0000281 iselSB = iselSB_AMD64;
sewardj010ac542011-05-29 09:29:18 +0000282 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
283 emit_AMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000284 host_is_bigendian = False;
285 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000286 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_host.hwcaps));
sewardj010ac542011-05-29 09:29:18 +0000287 /* jump-to-dispatcher scheme */
288 vassert(vta->dispatch_unassisted != NULL);
289 vassert(vta->dispatch_assisted != NULL);
sewardjc33671d2005-02-01 20:30:00 +0000290 break;
291
cerion487e4c92005-02-04 16:28:19 +0000292 case VexArchPPC32:
cerion92b64362005-12-13 12:02:26 +0000293 mode64 = False;
cerion5b2325f2005-12-23 00:55:09 +0000294 getAllocableRegs_PPC ( &n_available_real_regs,
295 &available_real_regs, mode64 );
296 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
297 getRegUsage = (void(*)(HRegUsage*,HInstr*,Bool)) getRegUsage_PPCInstr;
298 mapRegs = (void(*)(HRegRemap*,HInstr*,Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000299 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
300 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000301 ppInstr = (void(*)(HInstr*,Bool)) ppPPCInstr;
302 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000303 iselSB = iselSB_PPC;
sewardj010ac542011-05-29 09:29:18 +0000304 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
305 emit_PPCInstr;
cerion487e4c92005-02-04 16:28:19 +0000306 host_is_bigendian = True;
307 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000308 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_host.hwcaps));
sewardj010ac542011-05-29 09:29:18 +0000309 /* return-to-dispatcher scheme */
310 vassert(vta->dispatch_unassisted == NULL);
311 vassert(vta->dispatch_assisted == NULL);
cerion487e4c92005-02-04 16:28:19 +0000312 break;
313
cerionf0de28c2005-12-13 20:21:11 +0000314 case VexArchPPC64:
315 mode64 = True;
cerion5b2325f2005-12-23 00:55:09 +0000316 getAllocableRegs_PPC ( &n_available_real_regs,
317 &available_real_regs, mode64 );
318 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
319 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_PPCInstr;
320 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000321 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
322 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000323 ppInstr = (void(*)(HInstr*, Bool)) ppPPCInstr;
324 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000325 iselSB = iselSB_PPC;
sewardj010ac542011-05-29 09:29:18 +0000326 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
327 emit_PPCInstr;
cerionf0de28c2005-12-13 20:21:11 +0000328 host_is_bigendian = True;
329 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000330 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_host.hwcaps));
sewardj010ac542011-05-29 09:29:18 +0000331 /* return-to-dispatcher scheme */
332 vassert(vta->dispatch_unassisted == NULL);
333 vassert(vta->dispatch_assisted == NULL);
cerionf0de28c2005-12-13 20:21:11 +0000334 break;
335
sewardj2019a972011-03-07 16:04:07 +0000336 case VexArchS390X:
337 mode64 = True;
338 getAllocableRegs_S390 ( &n_available_real_regs,
339 &available_real_regs, mode64 );
340 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_S390Instr;
341 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_S390Instr;
342 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_S390Instr;
343 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_S390;
344 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_S390;
345 ppInstr = (void(*)(HInstr*, Bool)) ppS390Instr;
346 ppReg = (void(*)(HReg)) ppHRegS390;
347 iselSB = iselSB_S390;
sewardj010ac542011-05-29 09:29:18 +0000348 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
349 emit_S390Instr;
sewardj2019a972011-03-07 16:04:07 +0000350 host_is_bigendian = True;
351 host_word_type = Ity_I64;
352 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_host.hwcaps));
sewardj010ac542011-05-29 09:29:18 +0000353 /* return-to-dispatcher scheme */
354 vassert(vta->dispatch_unassisted == NULL);
355 vassert(vta->dispatch_assisted == NULL);
sewardj2019a972011-03-07 16:04:07 +0000356 break;
357
sewardj6c299f32009-12-31 18:00:12 +0000358 case VexArchARM:
sewardj2a1ed8e2009-12-31 19:26:03 +0000359 mode64 = False;
sewardj6c299f32009-12-31 18:00:12 +0000360 getAllocableRegs_ARM ( &n_available_real_regs,
361 &available_real_regs );
sewardj2a1ed8e2009-12-31 19:26:03 +0000362 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARMInstr;
363 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_ARMInstr;
364 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_ARMInstr;
365 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_ARM;
366 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_ARM;
367 ppInstr = (void(*)(HInstr*, Bool)) ppARMInstr;
368 ppReg = (void(*)(HReg)) ppHRegARM;
369 iselSB = iselSB_ARM;
sewardj010ac542011-05-29 09:29:18 +0000370 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
371 emit_ARMInstr;
sewardj6c299f32009-12-31 18:00:12 +0000372 host_is_bigendian = False;
373 host_word_type = Ity_I32;
374 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_host.hwcaps));
sewardj010ac542011-05-29 09:29:18 +0000375 vassert(vta->dispatch_unassisted == NULL);
376 vassert(vta->dispatch_assisted == NULL);
377 /* return-to-dispatcher scheme */
sewardj6c299f32009-12-31 18:00:12 +0000378 break;
379
sewardjf13a16a2004-07-05 17:10:14 +0000380 default:
sewardj6c299f32009-12-31 18:00:12 +0000381 vpanic("LibVEX_Translate: unsupported host insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000382 }
383
sewardj2a9ad022004-11-25 02:46:58 +0000384
sewardj17c7f952005-12-15 14:02:34 +0000385 switch (vta->arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000386
sewardjbef170b2004-12-21 01:23:00 +0000387 case VexArchX86:
sewardj8d2291c2004-10-25 14:50:21 +0000388 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000389 disInstrFn = disInstr_X86;
sewardj2a9ad022004-11-25 02:46:58 +0000390 specHelper = guest_x86_spechelper;
sewardj81ec4182004-10-25 23:15:52 +0000391 guest_sizeB = sizeof(VexGuestX86State);
sewardjcf787902004-11-03 09:08:33 +0000392 guest_word_type = Ity_I32;
sewardj49651f42004-10-28 22:11:04 +0000393 guest_layout = &x86guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000394 offB_TISTART = offsetof(VexGuestX86State,guest_TISTART);
395 offB_TILEN = offsetof(VexGuestX86State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000396 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000397 vassert(0 == sizeof(VexGuestX86State) % 16);
sewardjce02aa72006-01-12 12:27:58 +0000398 vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART) == 4);
399 vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
400 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000401 break;
sewardj2a9ad022004-11-25 02:46:58 +0000402
sewardj44d494d2005-01-20 20:26:33 +0000403 case VexArchAMD64:
404 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000405 disInstrFn = disInstr_AMD64;
sewardj44d494d2005-01-20 20:26:33 +0000406 specHelper = guest_amd64_spechelper;
407 guest_sizeB = sizeof(VexGuestAMD64State);
408 guest_word_type = Ity_I64;
409 guest_layout = &amd64guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000410 offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART);
411 offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000412 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000413 vassert(0 == sizeof(VexGuestAMD64State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000414 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8);
sewardjce02aa72006-01-12 12:27:58 +0000415 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
416 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000417 break;
418
cerionaabdfbf2005-01-29 12:56:15 +0000419 case VexArchPPC32:
420 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
cerion5b2325f2005-12-23 00:55:09 +0000421 disInstrFn = disInstr_PPC;
cerionaabdfbf2005-01-29 12:56:15 +0000422 specHelper = guest_ppc32_spechelper;
423 guest_sizeB = sizeof(VexGuestPPC32State);
424 guest_word_type = Ity_I32;
425 guest_layout = &ppc32Guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000426 offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART);
427 offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000428 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000429 vassert(0 == sizeof(VexGuestPPC32State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000430 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000431 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
432 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000433 break;
434
cerionf0de28c2005-12-13 20:21:11 +0000435 case VexArchPPC64:
436 preciseMemExnsFn = guest_ppc64_state_requires_precise_mem_exns;
cerion5b2325f2005-12-23 00:55:09 +0000437 disInstrFn = disInstr_PPC;
cerionf0de28c2005-12-13 20:21:11 +0000438 specHelper = guest_ppc64_spechelper;
439 guest_sizeB = sizeof(VexGuestPPC64State);
440 guest_word_type = Ity_I64;
441 guest_layout = &ppc64Guest_layout;
442 offB_TISTART = offsetof(VexGuestPPC64State,guest_TISTART);
443 offB_TILEN = offsetof(VexGuestPPC64State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000444 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_guest.hwcaps));
cerionf0de28c2005-12-13 20:21:11 +0000445 vassert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj3fd39672006-01-27 22:05:55 +0000446 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TISTART ) == 8);
447 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TILEN ) == 8);
448 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8);
449 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8);
cerionf0de28c2005-12-13 20:21:11 +0000450 break;
451
sewardj2019a972011-03-07 16:04:07 +0000452 case VexArchS390X:
453 preciseMemExnsFn = guest_s390x_state_requires_precise_mem_exns;
454 disInstrFn = disInstr_S390;
455 specHelper = guest_s390x_spechelper;
456 guest_sizeB = sizeof(VexGuestS390XState);
457 guest_word_type = Ity_I64;
458 guest_layout = &s390xGuest_layout;
459 offB_TISTART = offsetof(VexGuestS390XState,guest_TISTART);
460 offB_TILEN = offsetof(VexGuestS390XState,guest_TILEN);
461 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_guest.hwcaps));
462 vassert(0 == sizeof(VexGuestS390XState) % 16);
463 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TISTART ) == 8);
464 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TILEN ) == 8);
465 vassert(sizeof( ((VexGuestS390XState*)0)->guest_NRADDR ) == 8);
466 break;
467
sewardj6c299f32009-12-31 18:00:12 +0000468 case VexArchARM:
469 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
470 disInstrFn = disInstr_ARM;
471 specHelper = guest_arm_spechelper;
472 guest_sizeB = sizeof(VexGuestARMState);
473 guest_word_type = Ity_I32;
474 guest_layout = &armGuest_layout;
475 offB_TISTART = offsetof(VexGuestARMState,guest_TISTART);
476 offB_TILEN = offsetof(VexGuestARMState,guest_TILEN);
477 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_guest.hwcaps));
478 vassert(0 == sizeof(VexGuestARMState) % 16);
479 vassert(sizeof( ((VexGuestARMState*)0)->guest_TISTART) == 4);
480 vassert(sizeof( ((VexGuestARMState*)0)->guest_TILEN ) == 4);
481 vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4);
482 break;
483
sewardjf13a16a2004-07-05 17:10:14 +0000484 default:
sewardj887a11a2004-07-05 17:26:47 +0000485 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000486 }
487
sewardjbc161a42011-06-07 21:28:38 +0000488 /* Set up result struct. */
489 VexTranslateResult res;
490 res.status = VexTransOK;
491 res.n_sc_extents = 0;
492
sewardj9df271d2004-12-31 22:37:42 +0000493 /* yet more sanity checks ... */
sewardj17c7f952005-12-15 14:02:34 +0000494 if (vta->arch_guest == vta->arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000495 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000496 we are simulating one flavour of an architecture a different
497 flavour of the same architecture, which is pretty strange. */
sewardj5117ce12006-01-27 21:20:15 +0000498 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps);
sewardj9df271d2004-12-31 22:37:42 +0000499 }
sewardj2a9ad022004-11-25 02:46:58 +0000500
sewardj2d6b14a2005-11-23 04:25:07 +0000501 vexAllocSanityCheck();
502
sewardjf48ac192004-10-29 00:41:29 +0000503 if (vex_traceflags & VEX_TRACE_FE)
504 vex_printf("\n------------------------"
505 " Front end "
506 "------------------------\n\n");
507
sewardjdd40fdf2006-12-24 02:20:24 +0000508 irsb = bb_to_IR ( vta->guest_extents,
sewardjbc161a42011-06-07 21:28:38 +0000509 &res.n_sc_extents,
sewardjc716aea2006-01-17 01:48:46 +0000510 vta->callback_opaque,
sewardj9e6491a2005-07-02 19:24:10 +0000511 disInstrFn,
sewardj17c7f952005-12-15 14:02:34 +0000512 vta->guest_bytes,
513 vta->guest_bytes_addr,
514 vta->chase_into_ok,
sewardj9e6491a2005-07-02 19:24:10 +0000515 host_is_bigendian,
sewardja5f55da2006-04-30 23:37:32 +0000516 vta->arch_guest,
sewardj17c7f952005-12-15 14:02:34 +0000517 &vta->archinfo_guest,
sewardjdd40fdf2006-12-24 02:20:24 +0000518 &vta->abiinfo_both,
sewardjdb4738a2005-07-07 01:32:16 +0000519 guest_word_type,
sewardjbc161a42011-06-07 21:28:38 +0000520 vta->needs_self_check,
sewardjc716aea2006-01-17 01:48:46 +0000521 vta->preamble_function,
sewardjdb4738a2005-07-07 01:32:16 +0000522 offB_TISTART,
sewardjc716aea2006-01-17 01:48:46 +0000523 offB_TILEN );
sewardjf13a16a2004-07-05 17:10:14 +0000524
sewardj2d6b14a2005-11-23 04:25:07 +0000525 vexAllocSanityCheck();
526
sewardjdd40fdf2006-12-24 02:20:24 +0000527 if (irsb == NULL) {
sewardjf13a16a2004-07-05 17:10:14 +0000528 /* Access failure. */
sewardj2d6b14a2005-11-23 04:25:07 +0000529 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000530 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000531 res.status = VexTransAccessFail; return res;
sewardjf13a16a2004-07-05 17:10:14 +0000532 }
sewardjaa59f942004-10-09 09:34:36 +0000533
sewardj17c7f952005-12-15 14:02:34 +0000534 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3);
535 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr);
536 for (i = 0; i < vta->guest_extents->n_used; i++) {
537 vassert(vta->guest_extents->len[i] < 10000); /* sanity */
sewardj72c72812005-01-19 11:49:45 +0000538 }
539
sewardjaa59f942004-10-09 09:34:36 +0000540 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000541 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj17c7f952005-12-15 14:02:34 +0000542 if (vta->guest_extents->n_used > 1) {
sewardj72c72812005-01-19 11:49:45 +0000543 vex_printf("can't show code due to extents > 1\n");
544 } else {
545 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000546 UChar* p = (UChar*)vta->guest_bytes;
sewardj01f8cce2009-08-31 08:50:02 +0000547 UInt sum = 0;
sewardj17c7f952005-12-15 14:02:34 +0000548 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0];
sewardj01f8cce2009-08-31 08:50:02 +0000549 vex_printf("GuestBytes %llx %u ", vta->guest_bytes_addr,
550 guest_bytes_read );
551 for (i = 0; i < guest_bytes_read; i++) {
552 UInt b = (UInt)p[i];
553 vex_printf(" %02x", b );
554 sum = (sum << 1) ^ b;
555 }
556 vex_printf(" %08x\n\n", sum);
sewardj72c72812005-01-19 11:49:45 +0000557 }
sewardjaa59f942004-10-09 09:34:36 +0000558 }
559
560 /* Sanity check the initial IR. */
sewardjdd40fdf2006-12-24 02:20:24 +0000561 sanityCheckIRSB( irsb, "initial IR",
sewardjb9230752004-12-29 19:25:06 +0000562 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000563
sewardj2d6b14a2005-11-23 04:25:07 +0000564 vexAllocSanityCheck();
565
sewardjedf4d692004-08-17 13:52:58 +0000566 /* Clean it up, hopefully a lot. */
sewardjdd40fdf2006-12-24 02:20:24 +0000567 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn,
sewardjec0d9a02010-08-22 12:54:56 +0000568 vta->guest_bytes_addr,
569 vta->arch_guest );
sewardjdd40fdf2006-12-24 02:20:24 +0000570 sanityCheckIRSB( irsb, "after initial iropt",
sewardjb9230752004-12-29 19:25:06 +0000571 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000572
sewardjf48ac192004-10-29 00:41:29 +0000573 if (vex_traceflags & VEX_TRACE_OPT1) {
574 vex_printf("\n------------------------"
575 " After pre-instr IR optimisation "
576 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000577 ppIRSB ( irsb );
sewardjedf4d692004-08-17 13:52:58 +0000578 vex_printf("\n");
579 }
580
sewardj2d6b14a2005-11-23 04:25:07 +0000581 vexAllocSanityCheck();
582
sewardjf13a16a2004-07-05 17:10:14 +0000583 /* Get the thing instrumented. */
sewardj17c7f952005-12-15 14:02:34 +0000584 if (vta->instrument1)
sewardjdd40fdf2006-12-24 02:20:24 +0000585 irsb = vta->instrument1(vta->callback_opaque,
586 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000587 vta->guest_extents,
588 guest_word_type, host_word_type);
sewardj2d6b14a2005-11-23 04:25:07 +0000589 vexAllocSanityCheck();
590
sewardj17c7f952005-12-15 14:02:34 +0000591 if (vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000592 irsb = vta->instrument2(vta->callback_opaque,
593 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000594 vta->guest_extents,
595 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000596
sewardjf48ac192004-10-29 00:41:29 +0000597 if (vex_traceflags & VEX_TRACE_INST) {
598 vex_printf("\n------------------------"
599 " After instrumentation "
600 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000601 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000602 vex_printf("\n");
603 }
604
sewardj17c7f952005-12-15 14:02:34 +0000605 if (vta->instrument1 || vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000606 sanityCheckIRSB( irsb, "after instrumentation",
sewardjb9230752004-12-29 19:25:06 +0000607 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000608
sewardj9578a8b2004-11-04 19:44:48 +0000609 /* Do a post-instrumentation cleanup pass. */
sewardj17c7f952005-12-15 14:02:34 +0000610 if (vta->instrument1 || vta->instrument2) {
sewardjdd40fdf2006-12-24 02:20:24 +0000611 do_deadcode_BB( irsb );
612 irsb = cprop_BB( irsb );
613 do_deadcode_BB( irsb );
614 sanityCheckIRSB( irsb, "after post-instrumentation cleanup",
sewardjb9230752004-12-29 19:25:06 +0000615 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000616 }
617
sewardj2d6b14a2005-11-23 04:25:07 +0000618 vexAllocSanityCheck();
619
sewardj9578a8b2004-11-04 19:44:48 +0000620 if (vex_traceflags & VEX_TRACE_OPT2) {
621 vex_printf("\n------------------------"
622 " After post-instr IR optimisation "
623 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000624 ppIRSB ( irsb );
sewardj9578a8b2004-11-04 19:44:48 +0000625 vex_printf("\n");
626 }
627
sewardjf9517d02005-11-28 13:39:37 +0000628 /* Turn it into virtual-registerised code. Build trees -- this
629 also throws away any dead bindings. */
sewardjdd40fdf2006-12-24 02:20:24 +0000630 ado_treebuild_BB( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000631
sewardjbe1b6ff2007-08-28 06:06:27 +0000632 if (vta->finaltidy) {
633 irsb = vta->finaltidy(irsb);
634 }
635
sewardj2d6b14a2005-11-23 04:25:07 +0000636 vexAllocSanityCheck();
637
sewardjf48ac192004-10-29 00:41:29 +0000638 if (vex_traceflags & VEX_TRACE_TREES) {
639 vex_printf("\n------------------------"
640 " After tree-building "
641 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000642 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000643 vex_printf("\n");
644 }
645
sewardje908c422005-02-04 21:18:16 +0000646 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000647 if (0) {
648 *(vta->host_bytes_used) = 0;
649 res.status = VexTransOK; return res;
650 }
sewardje908c422005-02-04 21:18:16 +0000651 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000652
sewardjf48ac192004-10-29 00:41:29 +0000653 if (vex_traceflags & VEX_TRACE_VCODE)
654 vex_printf("\n------------------------"
655 " Instruction selection "
656 "------------------------\n");
657
sewardjdd40fdf2006-12-24 02:20:24 +0000658 vcode = iselSB ( irsb, vta->arch_host, &vta->archinfo_host,
659 &vta->abiinfo_both );
sewardjf13a16a2004-07-05 17:10:14 +0000660
sewardj2d6b14a2005-11-23 04:25:07 +0000661 vexAllocSanityCheck();
662
sewardjf48ac192004-10-29 00:41:29 +0000663 if (vex_traceflags & VEX_TRACE_VCODE)
664 vex_printf("\n");
665
sewardjf48ac192004-10-29 00:41:29 +0000666 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000667 for (i = 0; i < vcode->arr_used; i++) {
668 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000669 ppInstr(vcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000670 vex_printf("\n");
671 }
sewardjfbcaf332004-07-08 01:46:01 +0000672 vex_printf("\n");
673 }
sewardjfbcaf332004-07-08 01:46:01 +0000674
sewardjf13a16a2004-07-05 17:10:14 +0000675 /* Register allocate. */
676 rcode = doRegisterAllocation ( vcode, available_real_regs,
cerionf0de28c2005-12-13 20:21:11 +0000677 n_available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000678 isMove, getRegUsage, mapRegs,
sewardjfb7373a2007-08-25 21:29:03 +0000679 genSpill, genReload, directReload,
680 guest_sizeB,
cerion92b64362005-12-13 12:02:26 +0000681 ppInstr, ppReg, mode64 );
sewardjf13a16a2004-07-05 17:10:14 +0000682
sewardj2d6b14a2005-11-23 04:25:07 +0000683 vexAllocSanityCheck();
684
sewardjf48ac192004-10-29 00:41:29 +0000685 if (vex_traceflags & VEX_TRACE_RCODE) {
686 vex_printf("\n------------------------"
687 " Register-allocated code "
688 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000689 for (i = 0; i < rcode->arr_used; i++) {
690 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000691 ppInstr(rcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000692 vex_printf("\n");
693 }
sewardjfbcaf332004-07-08 01:46:01 +0000694 vex_printf("\n");
695 }
sewardjfbcaf332004-07-08 01:46:01 +0000696
sewardje908c422005-02-04 21:18:16 +0000697 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000698 if (0) {
699 *(vta->host_bytes_used) = 0;
700 res.status = VexTransOK; return res;
701 }
sewardje908c422005-02-04 21:18:16 +0000702 /* end HACK */
703
sewardj81bd5502004-07-21 18:49:27 +0000704 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000705 if (vex_traceflags & VEX_TRACE_ASM) {
706 vex_printf("\n------------------------"
707 " Assembly "
708 "------------------------\n\n");
709 }
710
sewardj81bd5502004-07-21 18:49:27 +0000711 out_used = 0; /* tracks along the host_bytes array */
712 for (i = 0; i < rcode->arr_used; i++) {
sewardjf48ac192004-10-29 00:41:29 +0000713 if (vex_traceflags & VEX_TRACE_ASM) {
cerion92b64362005-12-13 12:02:26 +0000714 ppInstr(rcode->arr[i], mode64);
sewardjbad34a92004-07-22 01:14:11 +0000715 vex_printf("\n");
716 }
sewardj2019a972011-03-07 16:04:07 +0000717 j = (*emit)( insn_bytes, sizeof insn_bytes, rcode->arr[i], mode64,
sewardj010ac542011-05-29 09:29:18 +0000718 vta->dispatch_unassisted, vta->dispatch_assisted );
sewardjf48ac192004-10-29 00:41:29 +0000719 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000720 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000721 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000722 vex_printf("0%x ", (UInt)insn_bytes[k]);
723 else
724 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000725 vex_printf("\n\n");
726 }
sewardj17c7f952005-12-15 14:02:34 +0000727 if (out_used + j > vta->host_bytes_size) {
sewardj2d6b14a2005-11-23 04:25:07 +0000728 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000729 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000730 res.status = VexTransOutputFull;
731 return res;
sewardj81bd5502004-07-21 18:49:27 +0000732 }
733 for (k = 0; k < j; k++) {
sewardj17c7f952005-12-15 14:02:34 +0000734 vta->host_bytes[out_used] = insn_bytes[k];
sewardj81bd5502004-07-21 18:49:27 +0000735 out_used++;
736 }
sewardj17c7f952005-12-15 14:02:34 +0000737 vassert(out_used <= vta->host_bytes_size);
sewardj81bd5502004-07-21 18:49:27 +0000738 }
sewardj17c7f952005-12-15 14:02:34 +0000739 *(vta->host_bytes_used) = out_used;
sewardj81bd5502004-07-21 18:49:27 +0000740
sewardj2d6b14a2005-11-23 04:25:07 +0000741 vexAllocSanityCheck();
742
743 vexSetAllocModeTEMP_and_clear();
sewardjf13a16a2004-07-05 17:10:14 +0000744
sewardjf48ac192004-10-29 00:41:29 +0000745 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000746 res.status = VexTransOK;
747 return res;
sewardj35421a32004-07-05 13:12:34 +0000748}
749
750
sewardj893aada2004-11-29 19:57:54 +0000751/* --------- Emulation warnings. --------- */
752
753HChar* LibVEX_EmWarn_string ( VexEmWarn ew )
754{
755 switch (ew) {
756 case EmWarn_NONE:
757 return "none";
758 case EmWarn_X86_x87exns:
759 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000760 case EmWarn_X86_x87precision:
761 return "Selection of non-80-bit x87 FP precision";
762 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +0000763 return "Unmasking SSE FP exceptions";
764 case EmWarn_X86_fz:
765 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
766 case EmWarn_X86_daz:
767 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +0000768 case EmWarn_X86_acFlag:
769 return "Setting %eflags.ac (setting noted but ignored)";
sewardj9dd9cf12006-01-20 14:13:55 +0000770 case EmWarn_PPCexns:
771 return "Unmasking PPC32/64 FP exceptions";
772 case EmWarn_PPC64_redir_overflow:
773 return "PPC64 function redirection stack overflow";
774 case EmWarn_PPC64_redir_underflow:
775 return "PPC64 function redirection stack underflow";
sewardj893aada2004-11-29 19:57:54 +0000776 default:
777 vpanic("LibVEX_EmWarn_string: unknown warning");
778 }
779}
sewardj35421a32004-07-05 13:12:34 +0000780
sewardj5117ce12006-01-27 21:20:15 +0000781/* ------------------ Arch/HwCaps stuff. ------------------ */
sewardjbef170b2004-12-21 01:23:00 +0000782
783const HChar* LibVEX_ppVexArch ( VexArch arch )
784{
785 switch (arch) {
786 case VexArch_INVALID: return "INVALID";
787 case VexArchX86: return "X86";
788 case VexArchAMD64: return "AMD64";
789 case VexArchARM: return "ARM";
sewardj0ec57c52005-02-01 15:24:10 +0000790 case VexArchPPC32: return "PPC32";
cerionf0de28c2005-12-13 20:21:11 +0000791 case VexArchPPC64: return "PPC64";
sewardj2019a972011-03-07 16:04:07 +0000792 case VexArchS390X: return "S390X";
sewardjbef170b2004-12-21 01:23:00 +0000793 default: return "VexArch???";
794 }
795}
796
sewardj5117ce12006-01-27 21:20:15 +0000797const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
sewardjbef170b2004-12-21 01:23:00 +0000798{
sewardj5117ce12006-01-27 21:20:15 +0000799 HChar* str = show_hwcaps(arch,hwcaps);
800 return str ? str : "INVALID";
sewardjbef170b2004-12-21 01:23:00 +0000801}
802
sewardj5117ce12006-01-27 21:20:15 +0000803
sewardj27e1dd62005-06-30 11:49:14 +0000804/* Write default settings info *vai. */
805void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
806{
sewardj5117ce12006-01-27 21:20:15 +0000807 vai->hwcaps = 0;
cerion5b2325f2005-12-23 00:55:09 +0000808 vai->ppc_cache_line_szB = 0;
sewardje971c6a2010-09-03 15:49:57 +0000809 vai->ppc_dcbz_szB = 0;
810 vai->ppc_dcbzl_szB = 0;
811
sewardj27e1dd62005-06-30 11:49:14 +0000812}
813
sewardjdd40fdf2006-12-24 02:20:24 +0000814/* Write default settings info *vbi. */
815void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
sewardjaca070a2006-10-17 00:28:22 +0000816{
sewardjdd40fdf2006-12-24 02:20:24 +0000817 vbi->guest_stack_redzone_size = 0;
sewardj2e28ac42008-12-04 00:05:12 +0000818 vbi->guest_amd64_assume_fs_is_zero = False;
819 vbi->guest_amd64_assume_gs_is_0x60 = False;
sewardjdd40fdf2006-12-24 02:20:24 +0000820 vbi->guest_ppc_zap_RZ_at_blr = False;
821 vbi->guest_ppc_zap_RZ_at_bl = NULL;
822 vbi->guest_ppc_sc_continues_at_LR = False;
823 vbi->host_ppc_calls_use_fndescrs = False;
824 vbi->host_ppc32_regalign_int64_args = False;
sewardjaca070a2006-10-17 00:28:22 +0000825}
826
sewardj27e1dd62005-06-30 11:49:14 +0000827
sewardj5117ce12006-01-27 21:20:15 +0000828/* Return a string showing the hwcaps in a nice way. The string will
829 be NULL for invalid combinations of flags, so these functions also
830 serve as a way to validate hwcaps values. */
831
832static HChar* show_hwcaps_x86 ( UInt hwcaps )
833{
834 /* Monotonic, SSE3 > SSE2 > SSE1 > baseline. */
sewardj536fbab2010-07-29 15:39:05 +0000835 switch (hwcaps) {
836 case 0:
837 return "x86-sse0";
838 case VEX_HWCAPS_X86_SSE1:
839 return "x86-sse1";
840 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2:
841 return "x86-sse1-sse2";
842 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
843 | VEX_HWCAPS_X86_LZCNT:
844 return "x86-sse1-sse2-lzcnt";
845 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
846 | VEX_HWCAPS_X86_SSE3:
847 return "x86-sse1-sse2-sse3";
848 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
849 | VEX_HWCAPS_X86_SSE3 | VEX_HWCAPS_X86_LZCNT:
850 return "x86-sse1-sse2-sse3-lzcnt";
851 default:
852 return NULL;
853 }
sewardj5117ce12006-01-27 21:20:15 +0000854}
855
856static HChar* show_hwcaps_amd64 ( UInt hwcaps )
857{
sewardje9d8a262009-07-01 08:06:34 +0000858 /* SSE3 and CX16 are orthogonal and > baseline, although we really
859 don't expect to come across anything which can do SSE3 but can't
sewardj536fbab2010-07-29 15:39:05 +0000860 do CX16. Still, we can handle that case. LZCNT is similarly
861 orthogonal. */
862 switch (hwcaps) {
863 case 0:
864 return "amd64-sse2";
865 case VEX_HWCAPS_AMD64_SSE3:
866 return "amd64-sse3";
867 case VEX_HWCAPS_AMD64_CX16:
868 return "amd64-sse2-cx16";
869 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16:
870 return "amd64-sse3-cx16";
871 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_LZCNT:
872 return "amd64-sse3-lzcnt";
873 case VEX_HWCAPS_AMD64_CX16 | VEX_HWCAPS_AMD64_LZCNT:
874 return "amd64-sse2-cx16-lzcnt";
875 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16
876 | VEX_HWCAPS_AMD64_LZCNT:
877 return "amd64-sse3-cx16-lzcnt";
878
879 default:
880 return NULL;
881 }
sewardj5117ce12006-01-27 21:20:15 +0000882}
883
884static HChar* show_hwcaps_ppc32 ( UInt hwcaps )
885{
886 /* Monotonic with complications. Basically V > F > baseline,
887 but once you have F then you can have FX or GX too. */
888 const UInt F = VEX_HWCAPS_PPC32_F;
889 const UInt V = VEX_HWCAPS_PPC32_V;
890 const UInt FX = VEX_HWCAPS_PPC32_FX;
891 const UInt GX = VEX_HWCAPS_PPC32_GX;
sewardj66d5ef22011-04-15 11:55:00 +0000892 const UInt VX = VEX_HWCAPS_PPC32_VX;
sewardjc66d6fa2012-04-02 21:24:12 +0000893 const UInt DFP = VEX_HWCAPS_PPC32_DFP;
sewardj5117ce12006-01-27 21:20:15 +0000894 UInt c = hwcaps;
895 if (c == 0) return "ppc32-int";
896 if (c == F) return "ppc32-int-flt";
897 if (c == (F|FX)) return "ppc32-int-flt-FX";
898 if (c == (F|GX)) return "ppc32-int-flt-GX";
899 if (c == (F|FX|GX)) return "ppc32-int-flt-FX-GX";
900 if (c == (F|V)) return "ppc32-int-flt-vmx";
901 if (c == (F|V|FX)) return "ppc32-int-flt-vmx-FX";
902 if (c == (F|V|GX)) return "ppc32-int-flt-vmx-GX";
903 if (c == (F|V|FX|GX)) return "ppc32-int-flt-vmx-FX-GX";
sewardjc66d6fa2012-04-02 21:24:12 +0000904 if (c == (F|V|FX|GX|DFP)) return "ppc32-int-flt-vmx-FX-GX-DFP";
905 if (c == (F|V|FX|GX|VX|DFP)) return "ppc32-int-flt-vmx-FX-GX-VX-DFP";
sewardj5117ce12006-01-27 21:20:15 +0000906 return NULL;
907}
908
909static HChar* show_hwcaps_ppc64 ( UInt hwcaps )
910{
911 /* Monotonic with complications. Basically V > baseline(==F),
912 but once you have F then you can have FX or GX too. */
sewardj3fd39672006-01-27 22:05:55 +0000913 const UInt V = VEX_HWCAPS_PPC64_V;
914 const UInt FX = VEX_HWCAPS_PPC64_FX;
915 const UInt GX = VEX_HWCAPS_PPC64_GX;
sewardj66d5ef22011-04-15 11:55:00 +0000916 const UInt VX = VEX_HWCAPS_PPC64_VX;
sewardjc66d6fa2012-04-02 21:24:12 +0000917 const UInt DFP = VEX_HWCAPS_PPC64_DFP;
sewardj5117ce12006-01-27 21:20:15 +0000918 UInt c = hwcaps;
919 if (c == 0) return "ppc64-int-flt";
920 if (c == FX) return "ppc64-int-flt-FX";
921 if (c == GX) return "ppc64-int-flt-GX";
922 if (c == (FX|GX)) return "ppc64-int-flt-FX-GX";
923 if (c == V) return "ppc64-int-flt-vmx";
924 if (c == (V|FX)) return "ppc64-int-flt-vmx-FX";
925 if (c == (V|GX)) return "ppc64-int-flt-vmx-GX";
926 if (c == (V|FX|GX)) return "ppc64-int-flt-vmx-FX-GX";
sewardjc66d6fa2012-04-02 21:24:12 +0000927 if (c == (V|FX|GX|DFP)) return "ppc64-int-flt-vmx-FX-GX-DFP";
928 if (c == (V|FX|GX|VX|DFP)) return "ppc64-int-flt-vmx-FX-GX-VX-DFP";
sewardj5117ce12006-01-27 21:20:15 +0000929 return NULL;
930}
931
932static HChar* show_hwcaps_arm ( UInt hwcaps )
933{
sewardjec0d9a02010-08-22 12:54:56 +0000934 Bool N = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0);
935 Bool vfp = ((hwcaps & (VEX_HWCAPS_ARM_VFP |
936 VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3)) != 0);
937 switch (VEX_ARM_ARCHLEVEL(hwcaps)) {
938 case 5:
939 if (N)
940 return NULL;
941 if (vfp)
942 return "ARMv5-vfp";
943 else
944 return "ARMv5";
945 return NULL;
946 case 6:
947 if (N)
948 return NULL;
949 if (vfp)
950 return "ARMv6-vfp";
951 else
952 return "ARMv6";
953 return NULL;
954 case 7:
955 if (vfp) {
956 if (N)
957 return "ARMv7-vfp-neon";
958 else
959 return "ARMv7-vfp";
960 } else {
961 if (N)
962 return "ARMv7-neon";
963 else
964 return "ARMv7";
965 }
966 default:
967 return NULL;
968 }
sewardj5117ce12006-01-27 21:20:15 +0000969 return NULL;
970}
971
sewardj2019a972011-03-07 16:04:07 +0000972static HChar* show_hwcaps_s390x ( UInt hwcaps )
973{
sewardjd07b8562011-04-27 11:58:22 +0000974 static const HChar prefix[] = "s390x";
975 static const HChar facilities[][6] = {
976 { "ldisp" },
977 { "eimm" },
978 { "gie" },
979 { "dfp" },
980 { "fgx" },
981 };
982 static HChar buf[sizeof facilities + sizeof prefix + 1];
983 static HChar *p;
984
985 if (buf[0] != '\0') return buf; /* already constructed */
sewardj2019a972011-03-07 16:04:07 +0000986
sewardj652b56a2011-04-13 15:38:17 +0000987 hwcaps = VEX_HWCAPS_S390X(hwcaps);
988
sewardjd07b8562011-04-27 11:58:22 +0000989 p = buf + vex_sprintf(buf, "%s", prefix);
990 if (hwcaps & VEX_HWCAPS_S390X_LDISP)
991 p = p + vex_sprintf(p, "-%s", facilities[0]);
992 if (hwcaps & VEX_HWCAPS_S390X_EIMM)
993 p = p + vex_sprintf(p, "-%s", facilities[1]);
994 if (hwcaps & VEX_HWCAPS_S390X_GIE)
995 p = p + vex_sprintf(p, "-%s", facilities[2]);
996 if (hwcaps & VEX_HWCAPS_S390X_DFP)
997 p = p + vex_sprintf(p, "-%s", facilities[3]);
998 if (hwcaps & VEX_HWCAPS_S390X_FGX)
999 p = p + vex_sprintf(p, "-%s", facilities[4]);
sewardj2019a972011-03-07 16:04:07 +00001000
sewardjd07b8562011-04-27 11:58:22 +00001001 /* If there are no facilities, add "zarch" */
1002 if (hwcaps == 0)
1003 vex_sprintf(p, "-%s", "zarch");
1004
1005 return buf;
sewardj2019a972011-03-07 16:04:07 +00001006}
1007
sewardj5117ce12006-01-27 21:20:15 +00001008/* ---- */
1009static HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
1010{
1011 switch (arch) {
sewardj3fd39672006-01-27 22:05:55 +00001012 case VexArchX86: return show_hwcaps_x86(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001013 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
1014 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
1015 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
sewardj3fd39672006-01-27 22:05:55 +00001016 case VexArchARM: return show_hwcaps_arm(hwcaps);
sewardj2019a972011-03-07 16:04:07 +00001017 case VexArchS390X: return show_hwcaps_s390x(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001018 default: return NULL;
1019 }
1020}
1021
1022static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps )
1023{
1024 return show_hwcaps(arch,hwcaps) != NULL;
1025}
1026
1027
sewardj35421a32004-07-05 13:12:34 +00001028/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +00001029/*--- end main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +00001030/*---------------------------------------------------------------*/