blob: 79685a2cd8b8c4f6a26c7702f129cdb5df75a4d1 [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
sewardj752f9062010-05-03 21:38:49 +000010 Copyright (C) 2004-2010 OpenWorks LLP
11 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);
sewardj2d6b14a2005-11-23 04:25:07 +0000231 vexSetAllocModeTEMP_and_clear();
232 vexAllocSanityCheck();
sewardj2a9ad022004-11-25 02:46:58 +0000233
sewardjf13a16a2004-07-05 17:10:14 +0000234 /* First off, check that the guest and host insn sets
235 are supported. */
sewardj2a9ad022004-11-25 02:46:58 +0000236
sewardj17c7f952005-12-15 14:02:34 +0000237 switch (vta->arch_host) {
sewardj2a9ad022004-11-25 02:46:58 +0000238
sewardjbef170b2004-12-21 01:23:00 +0000239 case VexArchX86:
sewardjfb7373a2007-08-25 21:29:03 +0000240 mode64 = False;
sewardjf13a16a2004-07-05 17:10:14 +0000241 getAllocableRegs_X86 ( &n_available_real_regs,
242 &available_real_regs );
sewardjfb7373a2007-08-25 21:29:03 +0000243 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000244 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
245 getRegUsage_X86Instr;
sewardjfb7373a2007-08-25 21:29:03 +0000246 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_X86Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000247 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
248 genSpill_X86;
249 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
250 genReload_X86;
sewardjfb7373a2007-08-25 21:29:03 +0000251 directReload = (HInstr*(*)(HInstr*,HReg,Short)) directReload_X86;
252 ppInstr = (void(*)(HInstr*, Bool)) ppX86Instr;
253 ppReg = (void(*)(HReg)) ppHRegX86;
254 iselSB = iselSB_X86;
sewardj010ac542011-05-29 09:29:18 +0000255 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
256 emit_X86Instr;
sewardj72c72812005-01-19 11:49:45 +0000257 host_is_bigendian = False;
sewardjcf787902004-11-03 09:08:33 +0000258 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000259 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_host.hwcaps));
sewardj010ac542011-05-29 09:29:18 +0000260 /* jump-to-dispatcher scheme */
261 vassert(vta->dispatch_unassisted != NULL);
262 vassert(vta->dispatch_assisted != NULL);
sewardjf13a16a2004-07-05 17:10:14 +0000263 break;
sewardj2a9ad022004-11-25 02:46:58 +0000264
sewardjc33671d2005-02-01 20:30:00 +0000265 case VexArchAMD64:
cerion92b64362005-12-13 12:02:26 +0000266 mode64 = True;
sewardjc33671d2005-02-01 20:30:00 +0000267 getAllocableRegs_AMD64 ( &n_available_real_regs,
268 &available_real_regs );
269 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000270 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
271 getRegUsage_AMD64Instr;
cerion92b64362005-12-13 12:02:26 +0000272 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000273 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
274 genSpill_AMD64;
275 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
276 genReload_AMD64;
cerion92b64362005-12-13 12:02:26 +0000277 ppInstr = (void(*)(HInstr*, Bool)) ppAMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000278 ppReg = (void(*)(HReg)) ppHRegAMD64;
sewardjdd40fdf2006-12-24 02:20:24 +0000279 iselSB = iselSB_AMD64;
sewardj010ac542011-05-29 09:29:18 +0000280 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
281 emit_AMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000282 host_is_bigendian = False;
283 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000284 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_host.hwcaps));
sewardj010ac542011-05-29 09:29:18 +0000285 /* jump-to-dispatcher scheme */
286 vassert(vta->dispatch_unassisted != NULL);
287 vassert(vta->dispatch_assisted != NULL);
sewardjc33671d2005-02-01 20:30:00 +0000288 break;
289
cerion487e4c92005-02-04 16:28:19 +0000290 case VexArchPPC32:
cerion92b64362005-12-13 12:02:26 +0000291 mode64 = False;
cerion5b2325f2005-12-23 00:55:09 +0000292 getAllocableRegs_PPC ( &n_available_real_regs,
293 &available_real_regs, mode64 );
294 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
295 getRegUsage = (void(*)(HRegUsage*,HInstr*,Bool)) getRegUsage_PPCInstr;
296 mapRegs = (void(*)(HRegRemap*,HInstr*,Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000297 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
298 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000299 ppInstr = (void(*)(HInstr*,Bool)) ppPPCInstr;
300 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000301 iselSB = iselSB_PPC;
sewardj010ac542011-05-29 09:29:18 +0000302 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
303 emit_PPCInstr;
cerion487e4c92005-02-04 16:28:19 +0000304 host_is_bigendian = True;
305 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000306 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_host.hwcaps));
sewardj010ac542011-05-29 09:29:18 +0000307 /* return-to-dispatcher scheme */
308 vassert(vta->dispatch_unassisted == NULL);
309 vassert(vta->dispatch_assisted == NULL);
cerion487e4c92005-02-04 16:28:19 +0000310 break;
311
cerionf0de28c2005-12-13 20:21:11 +0000312 case VexArchPPC64:
313 mode64 = True;
cerion5b2325f2005-12-23 00:55:09 +0000314 getAllocableRegs_PPC ( &n_available_real_regs,
315 &available_real_regs, mode64 );
316 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
317 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_PPCInstr;
318 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000319 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
320 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000321 ppInstr = (void(*)(HInstr*, Bool)) ppPPCInstr;
322 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000323 iselSB = iselSB_PPC;
sewardj010ac542011-05-29 09:29:18 +0000324 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
325 emit_PPCInstr;
cerionf0de28c2005-12-13 20:21:11 +0000326 host_is_bigendian = True;
327 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000328 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_host.hwcaps));
sewardj010ac542011-05-29 09:29:18 +0000329 /* return-to-dispatcher scheme */
330 vassert(vta->dispatch_unassisted == NULL);
331 vassert(vta->dispatch_assisted == NULL);
cerionf0de28c2005-12-13 20:21:11 +0000332 break;
333
sewardj2019a972011-03-07 16:04:07 +0000334 case VexArchS390X:
335 mode64 = True;
336 getAllocableRegs_S390 ( &n_available_real_regs,
337 &available_real_regs, mode64 );
338 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_S390Instr;
339 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_S390Instr;
340 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_S390Instr;
341 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_S390;
342 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_S390;
343 ppInstr = (void(*)(HInstr*, Bool)) ppS390Instr;
344 ppReg = (void(*)(HReg)) ppHRegS390;
345 iselSB = iselSB_S390;
sewardj010ac542011-05-29 09:29:18 +0000346 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
347 emit_S390Instr;
sewardj2019a972011-03-07 16:04:07 +0000348 host_is_bigendian = True;
349 host_word_type = Ity_I64;
350 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_host.hwcaps));
sewardj010ac542011-05-29 09:29:18 +0000351 /* return-to-dispatcher scheme */
352 vassert(vta->dispatch_unassisted == NULL);
353 vassert(vta->dispatch_assisted == NULL);
sewardj2019a972011-03-07 16:04:07 +0000354 break;
355
sewardj6c299f32009-12-31 18:00:12 +0000356 case VexArchARM:
sewardj2a1ed8e2009-12-31 19:26:03 +0000357 mode64 = False;
sewardj6c299f32009-12-31 18:00:12 +0000358 getAllocableRegs_ARM ( &n_available_real_regs,
359 &available_real_regs );
sewardj2a1ed8e2009-12-31 19:26:03 +0000360 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARMInstr;
361 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_ARMInstr;
362 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_ARMInstr;
363 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_ARM;
364 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_ARM;
365 ppInstr = (void(*)(HInstr*, Bool)) ppARMInstr;
366 ppReg = (void(*)(HReg)) ppHRegARM;
367 iselSB = iselSB_ARM;
sewardj010ac542011-05-29 09:29:18 +0000368 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
369 emit_ARMInstr;
sewardj6c299f32009-12-31 18:00:12 +0000370 host_is_bigendian = False;
371 host_word_type = Ity_I32;
372 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_host.hwcaps));
sewardj010ac542011-05-29 09:29:18 +0000373 vassert(vta->dispatch_unassisted == NULL);
374 vassert(vta->dispatch_assisted == NULL);
375 /* return-to-dispatcher scheme */
sewardj6c299f32009-12-31 18:00:12 +0000376 break;
377
sewardjf13a16a2004-07-05 17:10:14 +0000378 default:
sewardj6c299f32009-12-31 18:00:12 +0000379 vpanic("LibVEX_Translate: unsupported host insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000380 }
381
sewardj2a9ad022004-11-25 02:46:58 +0000382
sewardj17c7f952005-12-15 14:02:34 +0000383 switch (vta->arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000384
sewardjbef170b2004-12-21 01:23:00 +0000385 case VexArchX86:
sewardj8d2291c2004-10-25 14:50:21 +0000386 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000387 disInstrFn = disInstr_X86;
sewardj2a9ad022004-11-25 02:46:58 +0000388 specHelper = guest_x86_spechelper;
sewardj81ec4182004-10-25 23:15:52 +0000389 guest_sizeB = sizeof(VexGuestX86State);
sewardjcf787902004-11-03 09:08:33 +0000390 guest_word_type = Ity_I32;
sewardj49651f42004-10-28 22:11:04 +0000391 guest_layout = &x86guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000392 offB_TISTART = offsetof(VexGuestX86State,guest_TISTART);
393 offB_TILEN = offsetof(VexGuestX86State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000394 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000395 vassert(0 == sizeof(VexGuestX86State) % 16);
sewardjce02aa72006-01-12 12:27:58 +0000396 vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART) == 4);
397 vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
398 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000399 break;
sewardj2a9ad022004-11-25 02:46:58 +0000400
sewardj44d494d2005-01-20 20:26:33 +0000401 case VexArchAMD64:
402 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000403 disInstrFn = disInstr_AMD64;
sewardj44d494d2005-01-20 20:26:33 +0000404 specHelper = guest_amd64_spechelper;
405 guest_sizeB = sizeof(VexGuestAMD64State);
406 guest_word_type = Ity_I64;
407 guest_layout = &amd64guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000408 offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART);
409 offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000410 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000411 vassert(0 == sizeof(VexGuestAMD64State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000412 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8);
sewardjce02aa72006-01-12 12:27:58 +0000413 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
414 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000415 break;
416
cerionaabdfbf2005-01-29 12:56:15 +0000417 case VexArchPPC32:
418 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
cerion5b2325f2005-12-23 00:55:09 +0000419 disInstrFn = disInstr_PPC;
cerionaabdfbf2005-01-29 12:56:15 +0000420 specHelper = guest_ppc32_spechelper;
421 guest_sizeB = sizeof(VexGuestPPC32State);
422 guest_word_type = Ity_I32;
423 guest_layout = &ppc32Guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000424 offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART);
425 offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000426 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000427 vassert(0 == sizeof(VexGuestPPC32State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000428 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000429 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
430 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000431 break;
432
cerionf0de28c2005-12-13 20:21:11 +0000433 case VexArchPPC64:
434 preciseMemExnsFn = guest_ppc64_state_requires_precise_mem_exns;
cerion5b2325f2005-12-23 00:55:09 +0000435 disInstrFn = disInstr_PPC;
cerionf0de28c2005-12-13 20:21:11 +0000436 specHelper = guest_ppc64_spechelper;
437 guest_sizeB = sizeof(VexGuestPPC64State);
438 guest_word_type = Ity_I64;
439 guest_layout = &ppc64Guest_layout;
440 offB_TISTART = offsetof(VexGuestPPC64State,guest_TISTART);
441 offB_TILEN = offsetof(VexGuestPPC64State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000442 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_guest.hwcaps));
cerionf0de28c2005-12-13 20:21:11 +0000443 vassert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj3fd39672006-01-27 22:05:55 +0000444 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TISTART ) == 8);
445 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TILEN ) == 8);
446 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8);
447 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8);
cerionf0de28c2005-12-13 20:21:11 +0000448 break;
449
sewardj2019a972011-03-07 16:04:07 +0000450 case VexArchS390X:
451 preciseMemExnsFn = guest_s390x_state_requires_precise_mem_exns;
452 disInstrFn = disInstr_S390;
453 specHelper = guest_s390x_spechelper;
454 guest_sizeB = sizeof(VexGuestS390XState);
455 guest_word_type = Ity_I64;
456 guest_layout = &s390xGuest_layout;
457 offB_TISTART = offsetof(VexGuestS390XState,guest_TISTART);
458 offB_TILEN = offsetof(VexGuestS390XState,guest_TILEN);
459 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_guest.hwcaps));
460 vassert(0 == sizeof(VexGuestS390XState) % 16);
461 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TISTART ) == 8);
462 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TILEN ) == 8);
463 vassert(sizeof( ((VexGuestS390XState*)0)->guest_NRADDR ) == 8);
464 break;
465
sewardj6c299f32009-12-31 18:00:12 +0000466 case VexArchARM:
467 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
468 disInstrFn = disInstr_ARM;
469 specHelper = guest_arm_spechelper;
470 guest_sizeB = sizeof(VexGuestARMState);
471 guest_word_type = Ity_I32;
472 guest_layout = &armGuest_layout;
473 offB_TISTART = offsetof(VexGuestARMState,guest_TISTART);
474 offB_TILEN = offsetof(VexGuestARMState,guest_TILEN);
475 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_guest.hwcaps));
476 vassert(0 == sizeof(VexGuestARMState) % 16);
477 vassert(sizeof( ((VexGuestARMState*)0)->guest_TISTART) == 4);
478 vassert(sizeof( ((VexGuestARMState*)0)->guest_TILEN ) == 4);
479 vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4);
480 break;
481
sewardjf13a16a2004-07-05 17:10:14 +0000482 default:
sewardj887a11a2004-07-05 17:26:47 +0000483 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000484 }
485
sewardjbc161a42011-06-07 21:28:38 +0000486 /* Set up result struct. */
487 VexTranslateResult res;
488 res.status = VexTransOK;
489 res.n_sc_extents = 0;
490
sewardj9df271d2004-12-31 22:37:42 +0000491 /* yet more sanity checks ... */
sewardj17c7f952005-12-15 14:02:34 +0000492 if (vta->arch_guest == vta->arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000493 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000494 we are simulating one flavour of an architecture a different
495 flavour of the same architecture, which is pretty strange. */
sewardj5117ce12006-01-27 21:20:15 +0000496 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps);
sewardj9df271d2004-12-31 22:37:42 +0000497 }
sewardj2a9ad022004-11-25 02:46:58 +0000498
sewardj2d6b14a2005-11-23 04:25:07 +0000499 vexAllocSanityCheck();
500
sewardjf48ac192004-10-29 00:41:29 +0000501 if (vex_traceflags & VEX_TRACE_FE)
502 vex_printf("\n------------------------"
503 " Front end "
504 "------------------------\n\n");
505
sewardjdd40fdf2006-12-24 02:20:24 +0000506 irsb = bb_to_IR ( vta->guest_extents,
sewardjbc161a42011-06-07 21:28:38 +0000507 &res.n_sc_extents,
sewardjc716aea2006-01-17 01:48:46 +0000508 vta->callback_opaque,
sewardj9e6491a2005-07-02 19:24:10 +0000509 disInstrFn,
sewardj17c7f952005-12-15 14:02:34 +0000510 vta->guest_bytes,
511 vta->guest_bytes_addr,
512 vta->chase_into_ok,
sewardj9e6491a2005-07-02 19:24:10 +0000513 host_is_bigendian,
sewardja5f55da2006-04-30 23:37:32 +0000514 vta->arch_guest,
sewardj17c7f952005-12-15 14:02:34 +0000515 &vta->archinfo_guest,
sewardjdd40fdf2006-12-24 02:20:24 +0000516 &vta->abiinfo_both,
sewardjdb4738a2005-07-07 01:32:16 +0000517 guest_word_type,
sewardjbc161a42011-06-07 21:28:38 +0000518 vta->needs_self_check,
sewardjc716aea2006-01-17 01:48:46 +0000519 vta->preamble_function,
sewardjdb4738a2005-07-07 01:32:16 +0000520 offB_TISTART,
sewardjc716aea2006-01-17 01:48:46 +0000521 offB_TILEN );
sewardjf13a16a2004-07-05 17:10:14 +0000522
sewardj2d6b14a2005-11-23 04:25:07 +0000523 vexAllocSanityCheck();
524
sewardjdd40fdf2006-12-24 02:20:24 +0000525 if (irsb == NULL) {
sewardjf13a16a2004-07-05 17:10:14 +0000526 /* Access failure. */
sewardj2d6b14a2005-11-23 04:25:07 +0000527 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000528 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000529 res.status = VexTransAccessFail; return res;
sewardjf13a16a2004-07-05 17:10:14 +0000530 }
sewardjaa59f942004-10-09 09:34:36 +0000531
sewardj17c7f952005-12-15 14:02:34 +0000532 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3);
533 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr);
534 for (i = 0; i < vta->guest_extents->n_used; i++) {
535 vassert(vta->guest_extents->len[i] < 10000); /* sanity */
sewardj72c72812005-01-19 11:49:45 +0000536 }
537
sewardjaa59f942004-10-09 09:34:36 +0000538 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000539 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj17c7f952005-12-15 14:02:34 +0000540 if (vta->guest_extents->n_used > 1) {
sewardj72c72812005-01-19 11:49:45 +0000541 vex_printf("can't show code due to extents > 1\n");
542 } else {
543 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000544 UChar* p = (UChar*)vta->guest_bytes;
sewardj01f8cce2009-08-31 08:50:02 +0000545 UInt sum = 0;
sewardj17c7f952005-12-15 14:02:34 +0000546 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0];
sewardj01f8cce2009-08-31 08:50:02 +0000547 vex_printf("GuestBytes %llx %u ", vta->guest_bytes_addr,
548 guest_bytes_read );
549 for (i = 0; i < guest_bytes_read; i++) {
550 UInt b = (UInt)p[i];
551 vex_printf(" %02x", b );
552 sum = (sum << 1) ^ b;
553 }
554 vex_printf(" %08x\n\n", sum);
sewardj72c72812005-01-19 11:49:45 +0000555 }
sewardjaa59f942004-10-09 09:34:36 +0000556 }
557
558 /* Sanity check the initial IR. */
sewardjdd40fdf2006-12-24 02:20:24 +0000559 sanityCheckIRSB( irsb, "initial IR",
sewardjb9230752004-12-29 19:25:06 +0000560 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000561
sewardj2d6b14a2005-11-23 04:25:07 +0000562 vexAllocSanityCheck();
563
sewardjedf4d692004-08-17 13:52:58 +0000564 /* Clean it up, hopefully a lot. */
sewardjdd40fdf2006-12-24 02:20:24 +0000565 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn,
sewardjec0d9a02010-08-22 12:54:56 +0000566 vta->guest_bytes_addr,
567 vta->arch_guest );
sewardjdd40fdf2006-12-24 02:20:24 +0000568 sanityCheckIRSB( irsb, "after initial iropt",
sewardjb9230752004-12-29 19:25:06 +0000569 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000570
sewardjf48ac192004-10-29 00:41:29 +0000571 if (vex_traceflags & VEX_TRACE_OPT1) {
572 vex_printf("\n------------------------"
573 " After pre-instr IR optimisation "
574 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000575 ppIRSB ( irsb );
sewardjedf4d692004-08-17 13:52:58 +0000576 vex_printf("\n");
577 }
578
sewardj2d6b14a2005-11-23 04:25:07 +0000579 vexAllocSanityCheck();
580
sewardjf13a16a2004-07-05 17:10:14 +0000581 /* Get the thing instrumented. */
sewardj17c7f952005-12-15 14:02:34 +0000582 if (vta->instrument1)
sewardjdd40fdf2006-12-24 02:20:24 +0000583 irsb = vta->instrument1(vta->callback_opaque,
584 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000585 vta->guest_extents,
586 guest_word_type, host_word_type);
sewardj2d6b14a2005-11-23 04:25:07 +0000587 vexAllocSanityCheck();
588
sewardj17c7f952005-12-15 14:02:34 +0000589 if (vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000590 irsb = vta->instrument2(vta->callback_opaque,
591 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000592 vta->guest_extents,
593 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000594
sewardjf48ac192004-10-29 00:41:29 +0000595 if (vex_traceflags & VEX_TRACE_INST) {
596 vex_printf("\n------------------------"
597 " After instrumentation "
598 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000599 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000600 vex_printf("\n");
601 }
602
sewardj17c7f952005-12-15 14:02:34 +0000603 if (vta->instrument1 || vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000604 sanityCheckIRSB( irsb, "after instrumentation",
sewardjb9230752004-12-29 19:25:06 +0000605 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000606
sewardj9578a8b2004-11-04 19:44:48 +0000607 /* Do a post-instrumentation cleanup pass. */
sewardj17c7f952005-12-15 14:02:34 +0000608 if (vta->instrument1 || vta->instrument2) {
sewardjdd40fdf2006-12-24 02:20:24 +0000609 do_deadcode_BB( irsb );
610 irsb = cprop_BB( irsb );
611 do_deadcode_BB( irsb );
612 sanityCheckIRSB( irsb, "after post-instrumentation cleanup",
sewardjb9230752004-12-29 19:25:06 +0000613 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000614 }
615
sewardj2d6b14a2005-11-23 04:25:07 +0000616 vexAllocSanityCheck();
617
sewardj9578a8b2004-11-04 19:44:48 +0000618 if (vex_traceflags & VEX_TRACE_OPT2) {
619 vex_printf("\n------------------------"
620 " After post-instr IR optimisation "
621 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000622 ppIRSB ( irsb );
sewardj9578a8b2004-11-04 19:44:48 +0000623 vex_printf("\n");
624 }
625
sewardjf9517d02005-11-28 13:39:37 +0000626 /* Turn it into virtual-registerised code. Build trees -- this
627 also throws away any dead bindings. */
sewardjdd40fdf2006-12-24 02:20:24 +0000628 ado_treebuild_BB( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000629
sewardjbe1b6ff2007-08-28 06:06:27 +0000630 if (vta->finaltidy) {
631 irsb = vta->finaltidy(irsb);
632 }
633
sewardj2d6b14a2005-11-23 04:25:07 +0000634 vexAllocSanityCheck();
635
sewardjf48ac192004-10-29 00:41:29 +0000636 if (vex_traceflags & VEX_TRACE_TREES) {
637 vex_printf("\n------------------------"
638 " After tree-building "
639 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000640 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000641 vex_printf("\n");
642 }
643
sewardje908c422005-02-04 21:18:16 +0000644 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000645 if (0) {
646 *(vta->host_bytes_used) = 0;
647 res.status = VexTransOK; return res;
648 }
sewardje908c422005-02-04 21:18:16 +0000649 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000650
sewardjf48ac192004-10-29 00:41:29 +0000651 if (vex_traceflags & VEX_TRACE_VCODE)
652 vex_printf("\n------------------------"
653 " Instruction selection "
654 "------------------------\n");
655
sewardjdd40fdf2006-12-24 02:20:24 +0000656 vcode = iselSB ( irsb, vta->arch_host, &vta->archinfo_host,
657 &vta->abiinfo_both );
sewardjf13a16a2004-07-05 17:10:14 +0000658
sewardj2d6b14a2005-11-23 04:25:07 +0000659 vexAllocSanityCheck();
660
sewardjf48ac192004-10-29 00:41:29 +0000661 if (vex_traceflags & VEX_TRACE_VCODE)
662 vex_printf("\n");
663
sewardjf48ac192004-10-29 00:41:29 +0000664 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000665 for (i = 0; i < vcode->arr_used; i++) {
666 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000667 ppInstr(vcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000668 vex_printf("\n");
669 }
sewardjfbcaf332004-07-08 01:46:01 +0000670 vex_printf("\n");
671 }
sewardjfbcaf332004-07-08 01:46:01 +0000672
sewardjf13a16a2004-07-05 17:10:14 +0000673 /* Register allocate. */
674 rcode = doRegisterAllocation ( vcode, available_real_regs,
cerionf0de28c2005-12-13 20:21:11 +0000675 n_available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000676 isMove, getRegUsage, mapRegs,
sewardjfb7373a2007-08-25 21:29:03 +0000677 genSpill, genReload, directReload,
678 guest_sizeB,
cerion92b64362005-12-13 12:02:26 +0000679 ppInstr, ppReg, mode64 );
sewardjf13a16a2004-07-05 17:10:14 +0000680
sewardj2d6b14a2005-11-23 04:25:07 +0000681 vexAllocSanityCheck();
682
sewardjf48ac192004-10-29 00:41:29 +0000683 if (vex_traceflags & VEX_TRACE_RCODE) {
684 vex_printf("\n------------------------"
685 " Register-allocated code "
686 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000687 for (i = 0; i < rcode->arr_used; i++) {
688 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000689 ppInstr(rcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000690 vex_printf("\n");
691 }
sewardjfbcaf332004-07-08 01:46:01 +0000692 vex_printf("\n");
693 }
sewardjfbcaf332004-07-08 01:46:01 +0000694
sewardje908c422005-02-04 21:18:16 +0000695 /* HACK */
sewardjbc161a42011-06-07 21:28:38 +0000696 if (0) {
697 *(vta->host_bytes_used) = 0;
698 res.status = VexTransOK; return res;
699 }
sewardje908c422005-02-04 21:18:16 +0000700 /* end HACK */
701
sewardj81bd5502004-07-21 18:49:27 +0000702 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000703 if (vex_traceflags & VEX_TRACE_ASM) {
704 vex_printf("\n------------------------"
705 " Assembly "
706 "------------------------\n\n");
707 }
708
sewardj81bd5502004-07-21 18:49:27 +0000709 out_used = 0; /* tracks along the host_bytes array */
710 for (i = 0; i < rcode->arr_used; i++) {
sewardjf48ac192004-10-29 00:41:29 +0000711 if (vex_traceflags & VEX_TRACE_ASM) {
cerion92b64362005-12-13 12:02:26 +0000712 ppInstr(rcode->arr[i], mode64);
sewardjbad34a92004-07-22 01:14:11 +0000713 vex_printf("\n");
714 }
sewardj2019a972011-03-07 16:04:07 +0000715 j = (*emit)( insn_bytes, sizeof insn_bytes, rcode->arr[i], mode64,
sewardj010ac542011-05-29 09:29:18 +0000716 vta->dispatch_unassisted, vta->dispatch_assisted );
sewardjf48ac192004-10-29 00:41:29 +0000717 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000718 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000719 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000720 vex_printf("0%x ", (UInt)insn_bytes[k]);
721 else
722 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000723 vex_printf("\n\n");
724 }
sewardj17c7f952005-12-15 14:02:34 +0000725 if (out_used + j > vta->host_bytes_size) {
sewardj2d6b14a2005-11-23 04:25:07 +0000726 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000727 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000728 res.status = VexTransOutputFull;
729 return res;
sewardj81bd5502004-07-21 18:49:27 +0000730 }
731 for (k = 0; k < j; k++) {
sewardj17c7f952005-12-15 14:02:34 +0000732 vta->host_bytes[out_used] = insn_bytes[k];
sewardj81bd5502004-07-21 18:49:27 +0000733 out_used++;
734 }
sewardj17c7f952005-12-15 14:02:34 +0000735 vassert(out_used <= vta->host_bytes_size);
sewardj81bd5502004-07-21 18:49:27 +0000736 }
sewardj17c7f952005-12-15 14:02:34 +0000737 *(vta->host_bytes_used) = out_used;
sewardj81bd5502004-07-21 18:49:27 +0000738
sewardj2d6b14a2005-11-23 04:25:07 +0000739 vexAllocSanityCheck();
740
741 vexSetAllocModeTEMP_and_clear();
sewardjf13a16a2004-07-05 17:10:14 +0000742
sewardjf48ac192004-10-29 00:41:29 +0000743 vex_traceflags = 0;
sewardjbc161a42011-06-07 21:28:38 +0000744 res.status = VexTransOK;
745 return res;
sewardj35421a32004-07-05 13:12:34 +0000746}
747
748
sewardj893aada2004-11-29 19:57:54 +0000749/* --------- Emulation warnings. --------- */
750
751HChar* LibVEX_EmWarn_string ( VexEmWarn ew )
752{
753 switch (ew) {
754 case EmWarn_NONE:
755 return "none";
756 case EmWarn_X86_x87exns:
757 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000758 case EmWarn_X86_x87precision:
759 return "Selection of non-80-bit x87 FP precision";
760 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +0000761 return "Unmasking SSE FP exceptions";
762 case EmWarn_X86_fz:
763 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
764 case EmWarn_X86_daz:
765 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +0000766 case EmWarn_X86_acFlag:
767 return "Setting %eflags.ac (setting noted but ignored)";
sewardj9dd9cf12006-01-20 14:13:55 +0000768 case EmWarn_PPCexns:
769 return "Unmasking PPC32/64 FP exceptions";
770 case EmWarn_PPC64_redir_overflow:
771 return "PPC64 function redirection stack overflow";
772 case EmWarn_PPC64_redir_underflow:
773 return "PPC64 function redirection stack underflow";
sewardj893aada2004-11-29 19:57:54 +0000774 default:
775 vpanic("LibVEX_EmWarn_string: unknown warning");
776 }
777}
sewardj35421a32004-07-05 13:12:34 +0000778
sewardj5117ce12006-01-27 21:20:15 +0000779/* ------------------ Arch/HwCaps stuff. ------------------ */
sewardjbef170b2004-12-21 01:23:00 +0000780
781const HChar* LibVEX_ppVexArch ( VexArch arch )
782{
783 switch (arch) {
784 case VexArch_INVALID: return "INVALID";
785 case VexArchX86: return "X86";
786 case VexArchAMD64: return "AMD64";
787 case VexArchARM: return "ARM";
sewardj0ec57c52005-02-01 15:24:10 +0000788 case VexArchPPC32: return "PPC32";
cerionf0de28c2005-12-13 20:21:11 +0000789 case VexArchPPC64: return "PPC64";
sewardj2019a972011-03-07 16:04:07 +0000790 case VexArchS390X: return "S390X";
sewardjbef170b2004-12-21 01:23:00 +0000791 default: return "VexArch???";
792 }
793}
794
sewardj5117ce12006-01-27 21:20:15 +0000795const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
sewardjbef170b2004-12-21 01:23:00 +0000796{
sewardj5117ce12006-01-27 21:20:15 +0000797 HChar* str = show_hwcaps(arch,hwcaps);
798 return str ? str : "INVALID";
sewardjbef170b2004-12-21 01:23:00 +0000799}
800
sewardj5117ce12006-01-27 21:20:15 +0000801
sewardj27e1dd62005-06-30 11:49:14 +0000802/* Write default settings info *vai. */
803void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
804{
sewardj5117ce12006-01-27 21:20:15 +0000805 vai->hwcaps = 0;
cerion5b2325f2005-12-23 00:55:09 +0000806 vai->ppc_cache_line_szB = 0;
sewardje971c6a2010-09-03 15:49:57 +0000807 vai->ppc_dcbz_szB = 0;
808 vai->ppc_dcbzl_szB = 0;
809
sewardj27e1dd62005-06-30 11:49:14 +0000810}
811
sewardjdd40fdf2006-12-24 02:20:24 +0000812/* Write default settings info *vbi. */
813void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
sewardjaca070a2006-10-17 00:28:22 +0000814{
sewardjdd40fdf2006-12-24 02:20:24 +0000815 vbi->guest_stack_redzone_size = 0;
sewardj2e28ac42008-12-04 00:05:12 +0000816 vbi->guest_amd64_assume_fs_is_zero = False;
817 vbi->guest_amd64_assume_gs_is_0x60 = False;
sewardjdd40fdf2006-12-24 02:20:24 +0000818 vbi->guest_ppc_zap_RZ_at_blr = False;
819 vbi->guest_ppc_zap_RZ_at_bl = NULL;
820 vbi->guest_ppc_sc_continues_at_LR = False;
821 vbi->host_ppc_calls_use_fndescrs = False;
822 vbi->host_ppc32_regalign_int64_args = False;
sewardjaca070a2006-10-17 00:28:22 +0000823}
824
sewardj27e1dd62005-06-30 11:49:14 +0000825
sewardj5117ce12006-01-27 21:20:15 +0000826/* Return a string showing the hwcaps in a nice way. The string will
827 be NULL for invalid combinations of flags, so these functions also
828 serve as a way to validate hwcaps values. */
829
830static HChar* show_hwcaps_x86 ( UInt hwcaps )
831{
832 /* Monotonic, SSE3 > SSE2 > SSE1 > baseline. */
sewardj536fbab2010-07-29 15:39:05 +0000833 switch (hwcaps) {
834 case 0:
835 return "x86-sse0";
836 case VEX_HWCAPS_X86_SSE1:
837 return "x86-sse1";
838 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2:
839 return "x86-sse1-sse2";
840 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
841 | VEX_HWCAPS_X86_LZCNT:
842 return "x86-sse1-sse2-lzcnt";
843 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
844 | VEX_HWCAPS_X86_SSE3:
845 return "x86-sse1-sse2-sse3";
846 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
847 | VEX_HWCAPS_X86_SSE3 | VEX_HWCAPS_X86_LZCNT:
848 return "x86-sse1-sse2-sse3-lzcnt";
849 default:
850 return NULL;
851 }
sewardj5117ce12006-01-27 21:20:15 +0000852}
853
854static HChar* show_hwcaps_amd64 ( UInt hwcaps )
855{
sewardje9d8a262009-07-01 08:06:34 +0000856 /* SSE3 and CX16 are orthogonal and > baseline, although we really
857 don't expect to come across anything which can do SSE3 but can't
sewardj536fbab2010-07-29 15:39:05 +0000858 do CX16. Still, we can handle that case. LZCNT is similarly
859 orthogonal. */
860 switch (hwcaps) {
861 case 0:
862 return "amd64-sse2";
863 case VEX_HWCAPS_AMD64_SSE3:
864 return "amd64-sse3";
865 case VEX_HWCAPS_AMD64_CX16:
866 return "amd64-sse2-cx16";
867 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16:
868 return "amd64-sse3-cx16";
869 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_LZCNT:
870 return "amd64-sse3-lzcnt";
871 case VEX_HWCAPS_AMD64_CX16 | VEX_HWCAPS_AMD64_LZCNT:
872 return "amd64-sse2-cx16-lzcnt";
873 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16
874 | VEX_HWCAPS_AMD64_LZCNT:
875 return "amd64-sse3-cx16-lzcnt";
876
877 default:
878 return NULL;
879 }
sewardj5117ce12006-01-27 21:20:15 +0000880}
881
882static HChar* show_hwcaps_ppc32 ( UInt hwcaps )
883{
884 /* Monotonic with complications. Basically V > F > baseline,
885 but once you have F then you can have FX or GX too. */
886 const UInt F = VEX_HWCAPS_PPC32_F;
887 const UInt V = VEX_HWCAPS_PPC32_V;
888 const UInt FX = VEX_HWCAPS_PPC32_FX;
889 const UInt GX = VEX_HWCAPS_PPC32_GX;
sewardj66d5ef22011-04-15 11:55:00 +0000890 const UInt VX = VEX_HWCAPS_PPC32_VX;
sewardj5117ce12006-01-27 21:20:15 +0000891 UInt c = hwcaps;
892 if (c == 0) return "ppc32-int";
893 if (c == F) return "ppc32-int-flt";
894 if (c == (F|FX)) return "ppc32-int-flt-FX";
895 if (c == (F|GX)) return "ppc32-int-flt-GX";
896 if (c == (F|FX|GX)) return "ppc32-int-flt-FX-GX";
897 if (c == (F|V)) return "ppc32-int-flt-vmx";
898 if (c == (F|V|FX)) return "ppc32-int-flt-vmx-FX";
899 if (c == (F|V|GX)) return "ppc32-int-flt-vmx-GX";
900 if (c == (F|V|FX|GX)) return "ppc32-int-flt-vmx-FX-GX";
sewardj66d5ef22011-04-15 11:55:00 +0000901 if (c == (F|V|FX|GX|VX)) return "ppc32-int-flt-vmx-FX-GX-VX";
sewardj5117ce12006-01-27 21:20:15 +0000902 return NULL;
903}
904
905static HChar* show_hwcaps_ppc64 ( UInt hwcaps )
906{
907 /* Monotonic with complications. Basically V > baseline(==F),
908 but once you have F then you can have FX or GX too. */
sewardj3fd39672006-01-27 22:05:55 +0000909 const UInt V = VEX_HWCAPS_PPC64_V;
910 const UInt FX = VEX_HWCAPS_PPC64_FX;
911 const UInt GX = VEX_HWCAPS_PPC64_GX;
sewardj66d5ef22011-04-15 11:55:00 +0000912 const UInt VX = VEX_HWCAPS_PPC64_VX;
sewardj5117ce12006-01-27 21:20:15 +0000913 UInt c = hwcaps;
914 if (c == 0) return "ppc64-int-flt";
915 if (c == FX) return "ppc64-int-flt-FX";
916 if (c == GX) return "ppc64-int-flt-GX";
917 if (c == (FX|GX)) return "ppc64-int-flt-FX-GX";
918 if (c == V) return "ppc64-int-flt-vmx";
919 if (c == (V|FX)) return "ppc64-int-flt-vmx-FX";
920 if (c == (V|GX)) return "ppc64-int-flt-vmx-GX";
921 if (c == (V|FX|GX)) return "ppc64-int-flt-vmx-FX-GX";
sewardj66d5ef22011-04-15 11:55:00 +0000922 if (c == (V|FX|GX|VX)) return "ppc64-int-flt-vmx-FX-GX-VX";
sewardj5117ce12006-01-27 21:20:15 +0000923 return NULL;
924}
925
926static HChar* show_hwcaps_arm ( UInt hwcaps )
927{
sewardjec0d9a02010-08-22 12:54:56 +0000928 Bool N = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0);
929 Bool vfp = ((hwcaps & (VEX_HWCAPS_ARM_VFP |
930 VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3)) != 0);
931 switch (VEX_ARM_ARCHLEVEL(hwcaps)) {
932 case 5:
933 if (N)
934 return NULL;
935 if (vfp)
936 return "ARMv5-vfp";
937 else
938 return "ARMv5";
939 return NULL;
940 case 6:
941 if (N)
942 return NULL;
943 if (vfp)
944 return "ARMv6-vfp";
945 else
946 return "ARMv6";
947 return NULL;
948 case 7:
949 if (vfp) {
950 if (N)
951 return "ARMv7-vfp-neon";
952 else
953 return "ARMv7-vfp";
954 } else {
955 if (N)
956 return "ARMv7-neon";
957 else
958 return "ARMv7";
959 }
960 default:
961 return NULL;
962 }
sewardj5117ce12006-01-27 21:20:15 +0000963 return NULL;
964}
965
sewardj2019a972011-03-07 16:04:07 +0000966static HChar* show_hwcaps_s390x ( UInt hwcaps )
967{
sewardjd07b8562011-04-27 11:58:22 +0000968 static const HChar prefix[] = "s390x";
969 static const HChar facilities[][6] = {
970 { "ldisp" },
971 { "eimm" },
972 { "gie" },
973 { "dfp" },
974 { "fgx" },
975 };
976 static HChar buf[sizeof facilities + sizeof prefix + 1];
977 static HChar *p;
978
979 if (buf[0] != '\0') return buf; /* already constructed */
sewardj2019a972011-03-07 16:04:07 +0000980
sewardj652b56a2011-04-13 15:38:17 +0000981 hwcaps = VEX_HWCAPS_S390X(hwcaps);
982
sewardjd07b8562011-04-27 11:58:22 +0000983 p = buf + vex_sprintf(buf, "%s", prefix);
984 if (hwcaps & VEX_HWCAPS_S390X_LDISP)
985 p = p + vex_sprintf(p, "-%s", facilities[0]);
986 if (hwcaps & VEX_HWCAPS_S390X_EIMM)
987 p = p + vex_sprintf(p, "-%s", facilities[1]);
988 if (hwcaps & VEX_HWCAPS_S390X_GIE)
989 p = p + vex_sprintf(p, "-%s", facilities[2]);
990 if (hwcaps & VEX_HWCAPS_S390X_DFP)
991 p = p + vex_sprintf(p, "-%s", facilities[3]);
992 if (hwcaps & VEX_HWCAPS_S390X_FGX)
993 p = p + vex_sprintf(p, "-%s", facilities[4]);
sewardj2019a972011-03-07 16:04:07 +0000994
sewardjd07b8562011-04-27 11:58:22 +0000995 /* If there are no facilities, add "zarch" */
996 if (hwcaps == 0)
997 vex_sprintf(p, "-%s", "zarch");
998
999 return buf;
sewardj2019a972011-03-07 16:04:07 +00001000}
1001
sewardj5117ce12006-01-27 21:20:15 +00001002/* ---- */
1003static HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
1004{
1005 switch (arch) {
sewardj3fd39672006-01-27 22:05:55 +00001006 case VexArchX86: return show_hwcaps_x86(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001007 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
1008 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
1009 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
sewardj3fd39672006-01-27 22:05:55 +00001010 case VexArchARM: return show_hwcaps_arm(hwcaps);
sewardj2019a972011-03-07 16:04:07 +00001011 case VexArchS390X: return show_hwcaps_s390x(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +00001012 default: return NULL;
1013 }
1014}
1015
1016static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps )
1017{
1018 return show_hwcaps(arch,hwcaps) != NULL;
1019}
1020
1021
sewardj35421a32004-07-05 13:12:34 +00001022/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +00001023/*--- end main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +00001024/*---------------------------------------------------------------*/