blob: 12dcbfd60f21e2e0bee27c23f79f196a8cf7d0ed [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* );
188 Int (*emit) ( UChar*, Int, HInstr*, Bool, 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;
255 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_X86Instr;
sewardj72c72812005-01-19 11:49:45 +0000256 host_is_bigendian = False;
sewardjcf787902004-11-03 09:08:33 +0000257 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000258 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_host.hwcaps));
sewardj17c7f952005-12-15 14:02:34 +0000259 vassert(vta->dispatch != NULL); /* jump-to-dispatcher scheme */
sewardjf13a16a2004-07-05 17:10:14 +0000260 break;
sewardj2a9ad022004-11-25 02:46:58 +0000261
sewardjc33671d2005-02-01 20:30:00 +0000262 case VexArchAMD64:
cerion92b64362005-12-13 12:02:26 +0000263 mode64 = True;
sewardjc33671d2005-02-01 20:30:00 +0000264 getAllocableRegs_AMD64 ( &n_available_real_regs,
265 &available_real_regs );
266 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000267 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool))
268 getRegUsage_AMD64Instr;
cerion92b64362005-12-13 12:02:26 +0000269 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_AMD64Instr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000270 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
271 genSpill_AMD64;
272 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool))
273 genReload_AMD64;
cerion92b64362005-12-13 12:02:26 +0000274 ppInstr = (void(*)(HInstr*, Bool)) ppAMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000275 ppReg = (void(*)(HReg)) ppHRegAMD64;
sewardjdd40fdf2006-12-24 02:20:24 +0000276 iselSB = iselSB_AMD64;
sewardj0528bb52005-12-15 15:45:20 +0000277 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_AMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000278 host_is_bigendian = False;
279 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000280 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_host.hwcaps));
sewardj17c7f952005-12-15 14:02:34 +0000281 vassert(vta->dispatch != NULL); /* jump-to-dispatcher scheme */
sewardjc33671d2005-02-01 20:30:00 +0000282 break;
283
cerion487e4c92005-02-04 16:28:19 +0000284 case VexArchPPC32:
cerion92b64362005-12-13 12:02:26 +0000285 mode64 = False;
cerion5b2325f2005-12-23 00:55:09 +0000286 getAllocableRegs_PPC ( &n_available_real_regs,
287 &available_real_regs, mode64 );
288 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
289 getRegUsage = (void(*)(HRegUsage*,HInstr*,Bool)) getRegUsage_PPCInstr;
290 mapRegs = (void(*)(HRegRemap*,HInstr*,Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000291 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
292 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000293 ppInstr = (void(*)(HInstr*,Bool)) ppPPCInstr;
294 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000295 iselSB = iselSB_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000296 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_PPCInstr;
cerion487e4c92005-02-04 16:28:19 +0000297 host_is_bigendian = True;
298 host_word_type = Ity_I32;
sewardj5117ce12006-01-27 21:20:15 +0000299 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_host.hwcaps));
sewardj17c7f952005-12-15 14:02:34 +0000300 vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
cerion487e4c92005-02-04 16:28:19 +0000301 break;
302
cerionf0de28c2005-12-13 20:21:11 +0000303 case VexArchPPC64:
304 mode64 = True;
cerion5b2325f2005-12-23 00:55:09 +0000305 getAllocableRegs_PPC ( &n_available_real_regs,
306 &available_real_regs, mode64 );
307 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPCInstr;
308 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_PPCInstr;
309 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_PPCInstr;
sewardj2a1ed8e2009-12-31 19:26:03 +0000310 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_PPC;
311 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000312 ppInstr = (void(*)(HInstr*, Bool)) ppPPCInstr;
313 ppReg = (void(*)(HReg)) ppHRegPPC;
sewardjdd40fdf2006-12-24 02:20:24 +0000314 iselSB = iselSB_PPC;
cerion5b2325f2005-12-23 00:55:09 +0000315 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_PPCInstr;
cerionf0de28c2005-12-13 20:21:11 +0000316 host_is_bigendian = True;
317 host_word_type = Ity_I64;
sewardj5117ce12006-01-27 21:20:15 +0000318 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_host.hwcaps));
sewardj17c7f952005-12-15 14:02:34 +0000319 vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
cerionf0de28c2005-12-13 20:21:11 +0000320 break;
321
sewardj2019a972011-03-07 16:04:07 +0000322 case VexArchS390X:
323 mode64 = True;
324 getAllocableRegs_S390 ( &n_available_real_regs,
325 &available_real_regs, mode64 );
326 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_S390Instr;
327 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_S390Instr;
328 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_S390Instr;
329 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_S390;
330 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_S390;
331 ppInstr = (void(*)(HInstr*, Bool)) ppS390Instr;
332 ppReg = (void(*)(HReg)) ppHRegS390;
333 iselSB = iselSB_S390;
334 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_S390Instr;
335 host_is_bigendian = True;
336 host_word_type = Ity_I64;
337 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_host.hwcaps));
338 vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
339 break;
340
sewardj6c299f32009-12-31 18:00:12 +0000341 case VexArchARM:
sewardj2a1ed8e2009-12-31 19:26:03 +0000342 mode64 = False;
sewardj6c299f32009-12-31 18:00:12 +0000343 getAllocableRegs_ARM ( &n_available_real_regs,
344 &available_real_regs );
sewardj2a1ed8e2009-12-31 19:26:03 +0000345 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_ARMInstr;
346 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_ARMInstr;
347 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_ARMInstr;
348 genSpill = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genSpill_ARM;
349 genReload = (void(*)(HInstr**,HInstr**,HReg,Int,Bool)) genReload_ARM;
350 ppInstr = (void(*)(HInstr*, Bool)) ppARMInstr;
351 ppReg = (void(*)(HReg)) ppHRegARM;
352 iselSB = iselSB_ARM;
353 emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_ARMInstr;
sewardj6c299f32009-12-31 18:00:12 +0000354 host_is_bigendian = False;
355 host_word_type = Ity_I32;
356 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_host.hwcaps));
357 vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
358 break;
359
sewardjf13a16a2004-07-05 17:10:14 +0000360 default:
sewardj6c299f32009-12-31 18:00:12 +0000361 vpanic("LibVEX_Translate: unsupported host insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000362 }
363
sewardj2a9ad022004-11-25 02:46:58 +0000364
sewardj17c7f952005-12-15 14:02:34 +0000365 switch (vta->arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000366
sewardjbef170b2004-12-21 01:23:00 +0000367 case VexArchX86:
sewardj8d2291c2004-10-25 14:50:21 +0000368 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000369 disInstrFn = disInstr_X86;
sewardj2a9ad022004-11-25 02:46:58 +0000370 specHelper = guest_x86_spechelper;
sewardj81ec4182004-10-25 23:15:52 +0000371 guest_sizeB = sizeof(VexGuestX86State);
sewardjcf787902004-11-03 09:08:33 +0000372 guest_word_type = Ity_I32;
sewardj49651f42004-10-28 22:11:04 +0000373 guest_layout = &x86guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000374 offB_TISTART = offsetof(VexGuestX86State,guest_TISTART);
375 offB_TILEN = offsetof(VexGuestX86State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000376 vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000377 vassert(0 == sizeof(VexGuestX86State) % 16);
sewardjce02aa72006-01-12 12:27:58 +0000378 vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART) == 4);
379 vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
380 vassert(sizeof( ((VexGuestX86State*)0)->guest_NRADDR ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000381 break;
sewardj2a9ad022004-11-25 02:46:58 +0000382
sewardj44d494d2005-01-20 20:26:33 +0000383 case VexArchAMD64:
384 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000385 disInstrFn = disInstr_AMD64;
sewardj44d494d2005-01-20 20:26:33 +0000386 specHelper = guest_amd64_spechelper;
387 guest_sizeB = sizeof(VexGuestAMD64State);
388 guest_word_type = Ity_I64;
389 guest_layout = &amd64guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000390 offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART);
391 offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000392 vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000393 vassert(0 == sizeof(VexGuestAMD64State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000394 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8);
sewardjce02aa72006-01-12 12:27:58 +0000395 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
396 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_NRADDR ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000397 break;
398
cerionaabdfbf2005-01-29 12:56:15 +0000399 case VexArchPPC32:
400 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
cerion5b2325f2005-12-23 00:55:09 +0000401 disInstrFn = disInstr_PPC;
cerionaabdfbf2005-01-29 12:56:15 +0000402 specHelper = guest_ppc32_spechelper;
403 guest_sizeB = sizeof(VexGuestPPC32State);
404 guest_word_type = Ity_I32;
405 guest_layout = &ppc32Guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000406 offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART);
407 offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000408 vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_guest.hwcaps));
sewardj6c299f32009-12-31 18:00:12 +0000409 vassert(0 == sizeof(VexGuestPPC32State) % 16);
sewardjdb4738a2005-07-07 01:32:16 +0000410 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4);
sewardjce02aa72006-01-12 12:27:58 +0000411 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
412 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_NRADDR ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000413 break;
414
cerionf0de28c2005-12-13 20:21:11 +0000415 case VexArchPPC64:
416 preciseMemExnsFn = guest_ppc64_state_requires_precise_mem_exns;
cerion5b2325f2005-12-23 00:55:09 +0000417 disInstrFn = disInstr_PPC;
cerionf0de28c2005-12-13 20:21:11 +0000418 specHelper = guest_ppc64_spechelper;
419 guest_sizeB = sizeof(VexGuestPPC64State);
420 guest_word_type = Ity_I64;
421 guest_layout = &ppc64Guest_layout;
422 offB_TISTART = offsetof(VexGuestPPC64State,guest_TISTART);
423 offB_TILEN = offsetof(VexGuestPPC64State,guest_TILEN);
sewardj5117ce12006-01-27 21:20:15 +0000424 vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_guest.hwcaps));
cerionf0de28c2005-12-13 20:21:11 +0000425 vassert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj3fd39672006-01-27 22:05:55 +0000426 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TISTART ) == 8);
427 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_TILEN ) == 8);
428 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR ) == 8);
429 vassert(sizeof( ((VexGuestPPC64State*)0)->guest_NRADDR_GPR2) == 8);
cerionf0de28c2005-12-13 20:21:11 +0000430 break;
431
sewardj2019a972011-03-07 16:04:07 +0000432 case VexArchS390X:
433 preciseMemExnsFn = guest_s390x_state_requires_precise_mem_exns;
434 disInstrFn = disInstr_S390;
435 specHelper = guest_s390x_spechelper;
436 guest_sizeB = sizeof(VexGuestS390XState);
437 guest_word_type = Ity_I64;
438 guest_layout = &s390xGuest_layout;
439 offB_TISTART = offsetof(VexGuestS390XState,guest_TISTART);
440 offB_TILEN = offsetof(VexGuestS390XState,guest_TILEN);
441 vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_guest.hwcaps));
442 vassert(0 == sizeof(VexGuestS390XState) % 16);
443 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TISTART ) == 8);
444 vassert(sizeof( ((VexGuestS390XState*)0)->guest_TILEN ) == 8);
445 vassert(sizeof( ((VexGuestS390XState*)0)->guest_NRADDR ) == 8);
446 break;
447
sewardj6c299f32009-12-31 18:00:12 +0000448 case VexArchARM:
449 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
450 disInstrFn = disInstr_ARM;
451 specHelper = guest_arm_spechelper;
452 guest_sizeB = sizeof(VexGuestARMState);
453 guest_word_type = Ity_I32;
454 guest_layout = &armGuest_layout;
455 offB_TISTART = offsetof(VexGuestARMState,guest_TISTART);
456 offB_TILEN = offsetof(VexGuestARMState,guest_TILEN);
457 vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_guest.hwcaps));
458 vassert(0 == sizeof(VexGuestARMState) % 16);
459 vassert(sizeof( ((VexGuestARMState*)0)->guest_TISTART) == 4);
460 vassert(sizeof( ((VexGuestARMState*)0)->guest_TILEN ) == 4);
461 vassert(sizeof( ((VexGuestARMState*)0)->guest_NRADDR ) == 4);
462 break;
463
sewardjf13a16a2004-07-05 17:10:14 +0000464 default:
sewardj887a11a2004-07-05 17:26:47 +0000465 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000466 }
467
sewardj9df271d2004-12-31 22:37:42 +0000468 /* yet more sanity checks ... */
sewardj17c7f952005-12-15 14:02:34 +0000469 if (vta->arch_guest == vta->arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000470 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000471 we are simulating one flavour of an architecture a different
472 flavour of the same architecture, which is pretty strange. */
sewardj5117ce12006-01-27 21:20:15 +0000473 vassert(vta->archinfo_guest.hwcaps == vta->archinfo_host.hwcaps);
sewardj9df271d2004-12-31 22:37:42 +0000474 }
sewardj2a9ad022004-11-25 02:46:58 +0000475
sewardj2d6b14a2005-11-23 04:25:07 +0000476 vexAllocSanityCheck();
477
sewardjf48ac192004-10-29 00:41:29 +0000478 if (vex_traceflags & VEX_TRACE_FE)
479 vex_printf("\n------------------------"
480 " Front end "
481 "------------------------\n\n");
482
sewardjdd40fdf2006-12-24 02:20:24 +0000483 irsb = bb_to_IR ( vta->guest_extents,
sewardjc716aea2006-01-17 01:48:46 +0000484 vta->callback_opaque,
sewardj9e6491a2005-07-02 19:24:10 +0000485 disInstrFn,
sewardj17c7f952005-12-15 14:02:34 +0000486 vta->guest_bytes,
487 vta->guest_bytes_addr,
488 vta->chase_into_ok,
sewardj9e6491a2005-07-02 19:24:10 +0000489 host_is_bigendian,
sewardja5f55da2006-04-30 23:37:32 +0000490 vta->arch_guest,
sewardj17c7f952005-12-15 14:02:34 +0000491 &vta->archinfo_guest,
sewardjdd40fdf2006-12-24 02:20:24 +0000492 &vta->abiinfo_both,
sewardjdb4738a2005-07-07 01:32:16 +0000493 guest_word_type,
sewardj17c7f952005-12-15 14:02:34 +0000494 vta->do_self_check,
sewardjc716aea2006-01-17 01:48:46 +0000495 vta->preamble_function,
sewardjdb4738a2005-07-07 01:32:16 +0000496 offB_TISTART,
sewardjc716aea2006-01-17 01:48:46 +0000497 offB_TILEN );
sewardjf13a16a2004-07-05 17:10:14 +0000498
sewardj2d6b14a2005-11-23 04:25:07 +0000499 vexAllocSanityCheck();
500
sewardjdd40fdf2006-12-24 02:20:24 +0000501 if (irsb == NULL) {
sewardjf13a16a2004-07-05 17:10:14 +0000502 /* Access failure. */
sewardj2d6b14a2005-11-23 04:25:07 +0000503 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000504 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000505 return VexTransAccessFail;
sewardjf13a16a2004-07-05 17:10:14 +0000506 }
sewardjaa59f942004-10-09 09:34:36 +0000507
sewardj17c7f952005-12-15 14:02:34 +0000508 vassert(vta->guest_extents->n_used >= 1 && vta->guest_extents->n_used <= 3);
509 vassert(vta->guest_extents->base[0] == vta->guest_bytes_addr);
510 for (i = 0; i < vta->guest_extents->n_used; i++) {
511 vassert(vta->guest_extents->len[i] < 10000); /* sanity */
sewardj72c72812005-01-19 11:49:45 +0000512 }
513
sewardjaa59f942004-10-09 09:34:36 +0000514 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000515 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj17c7f952005-12-15 14:02:34 +0000516 if (vta->guest_extents->n_used > 1) {
sewardj72c72812005-01-19 11:49:45 +0000517 vex_printf("can't show code due to extents > 1\n");
518 } else {
519 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000520 UChar* p = (UChar*)vta->guest_bytes;
sewardj01f8cce2009-08-31 08:50:02 +0000521 UInt sum = 0;
sewardj17c7f952005-12-15 14:02:34 +0000522 UInt guest_bytes_read = (UInt)vta->guest_extents->len[0];
sewardj01f8cce2009-08-31 08:50:02 +0000523 vex_printf("GuestBytes %llx %u ", vta->guest_bytes_addr,
524 guest_bytes_read );
525 for (i = 0; i < guest_bytes_read; i++) {
526 UInt b = (UInt)p[i];
527 vex_printf(" %02x", b );
528 sum = (sum << 1) ^ b;
529 }
530 vex_printf(" %08x\n\n", sum);
sewardj72c72812005-01-19 11:49:45 +0000531 }
sewardjaa59f942004-10-09 09:34:36 +0000532 }
533
534 /* Sanity check the initial IR. */
sewardjdd40fdf2006-12-24 02:20:24 +0000535 sanityCheckIRSB( irsb, "initial IR",
sewardjb9230752004-12-29 19:25:06 +0000536 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000537
sewardj2d6b14a2005-11-23 04:25:07 +0000538 vexAllocSanityCheck();
539
sewardjedf4d692004-08-17 13:52:58 +0000540 /* Clean it up, hopefully a lot. */
sewardjdd40fdf2006-12-24 02:20:24 +0000541 irsb = do_iropt_BB ( irsb, specHelper, preciseMemExnsFn,
sewardjec0d9a02010-08-22 12:54:56 +0000542 vta->guest_bytes_addr,
543 vta->arch_guest );
sewardjdd40fdf2006-12-24 02:20:24 +0000544 sanityCheckIRSB( irsb, "after initial iropt",
sewardjb9230752004-12-29 19:25:06 +0000545 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000546
sewardjf48ac192004-10-29 00:41:29 +0000547 if (vex_traceflags & VEX_TRACE_OPT1) {
548 vex_printf("\n------------------------"
549 " After pre-instr IR optimisation "
550 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000551 ppIRSB ( irsb );
sewardjedf4d692004-08-17 13:52:58 +0000552 vex_printf("\n");
553 }
554
sewardj2d6b14a2005-11-23 04:25:07 +0000555 vexAllocSanityCheck();
556
sewardjf13a16a2004-07-05 17:10:14 +0000557 /* Get the thing instrumented. */
sewardj17c7f952005-12-15 14:02:34 +0000558 if (vta->instrument1)
sewardjdd40fdf2006-12-24 02:20:24 +0000559 irsb = vta->instrument1(vta->callback_opaque,
560 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000561 vta->guest_extents,
562 guest_word_type, host_word_type);
sewardj2d6b14a2005-11-23 04:25:07 +0000563 vexAllocSanityCheck();
564
sewardj17c7f952005-12-15 14:02:34 +0000565 if (vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000566 irsb = vta->instrument2(vta->callback_opaque,
567 irsb, guest_layout,
sewardj17c7f952005-12-15 14:02:34 +0000568 vta->guest_extents,
569 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000570
sewardjf48ac192004-10-29 00:41:29 +0000571 if (vex_traceflags & VEX_TRACE_INST) {
572 vex_printf("\n------------------------"
573 " After instrumentation "
574 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000575 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000576 vex_printf("\n");
577 }
578
sewardj17c7f952005-12-15 14:02:34 +0000579 if (vta->instrument1 || vta->instrument2)
sewardjdd40fdf2006-12-24 02:20:24 +0000580 sanityCheckIRSB( irsb, "after instrumentation",
sewardjb9230752004-12-29 19:25:06 +0000581 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000582
sewardj9578a8b2004-11-04 19:44:48 +0000583 /* Do a post-instrumentation cleanup pass. */
sewardj17c7f952005-12-15 14:02:34 +0000584 if (vta->instrument1 || vta->instrument2) {
sewardjdd40fdf2006-12-24 02:20:24 +0000585 do_deadcode_BB( irsb );
586 irsb = cprop_BB( irsb );
587 do_deadcode_BB( irsb );
588 sanityCheckIRSB( irsb, "after post-instrumentation cleanup",
sewardjb9230752004-12-29 19:25:06 +0000589 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000590 }
591
sewardj2d6b14a2005-11-23 04:25:07 +0000592 vexAllocSanityCheck();
593
sewardj9578a8b2004-11-04 19:44:48 +0000594 if (vex_traceflags & VEX_TRACE_OPT2) {
595 vex_printf("\n------------------------"
596 " After post-instr IR optimisation "
597 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000598 ppIRSB ( irsb );
sewardj9578a8b2004-11-04 19:44:48 +0000599 vex_printf("\n");
600 }
601
sewardjf9517d02005-11-28 13:39:37 +0000602 /* Turn it into virtual-registerised code. Build trees -- this
603 also throws away any dead bindings. */
sewardjdd40fdf2006-12-24 02:20:24 +0000604 ado_treebuild_BB( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000605
sewardjbe1b6ff2007-08-28 06:06:27 +0000606 if (vta->finaltidy) {
607 irsb = vta->finaltidy(irsb);
608 }
609
sewardj2d6b14a2005-11-23 04:25:07 +0000610 vexAllocSanityCheck();
611
sewardjf48ac192004-10-29 00:41:29 +0000612 if (vex_traceflags & VEX_TRACE_TREES) {
613 vex_printf("\n------------------------"
614 " After tree-building "
615 "------------------------\n\n");
sewardjdd40fdf2006-12-24 02:20:24 +0000616 ppIRSB ( irsb );
sewardjf48ac192004-10-29 00:41:29 +0000617 vex_printf("\n");
618 }
619
sewardje908c422005-02-04 21:18:16 +0000620 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000621 if (0) { *(vta->host_bytes_used) = 0; return VexTransOK; }
sewardje908c422005-02-04 21:18:16 +0000622 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000623
sewardjf48ac192004-10-29 00:41:29 +0000624 if (vex_traceflags & VEX_TRACE_VCODE)
625 vex_printf("\n------------------------"
626 " Instruction selection "
627 "------------------------\n");
628
sewardjdd40fdf2006-12-24 02:20:24 +0000629 vcode = iselSB ( irsb, vta->arch_host, &vta->archinfo_host,
630 &vta->abiinfo_both );
sewardjf13a16a2004-07-05 17:10:14 +0000631
sewardj2d6b14a2005-11-23 04:25:07 +0000632 vexAllocSanityCheck();
633
sewardjf48ac192004-10-29 00:41:29 +0000634 if (vex_traceflags & VEX_TRACE_VCODE)
635 vex_printf("\n");
636
sewardjf48ac192004-10-29 00:41:29 +0000637 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000638 for (i = 0; i < vcode->arr_used; i++) {
639 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000640 ppInstr(vcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000641 vex_printf("\n");
642 }
sewardjfbcaf332004-07-08 01:46:01 +0000643 vex_printf("\n");
644 }
sewardjfbcaf332004-07-08 01:46:01 +0000645
sewardjf13a16a2004-07-05 17:10:14 +0000646 /* Register allocate. */
647 rcode = doRegisterAllocation ( vcode, available_real_regs,
cerionf0de28c2005-12-13 20:21:11 +0000648 n_available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000649 isMove, getRegUsage, mapRegs,
sewardjfb7373a2007-08-25 21:29:03 +0000650 genSpill, genReload, directReload,
651 guest_sizeB,
cerion92b64362005-12-13 12:02:26 +0000652 ppInstr, ppReg, mode64 );
sewardjf13a16a2004-07-05 17:10:14 +0000653
sewardj2d6b14a2005-11-23 04:25:07 +0000654 vexAllocSanityCheck();
655
sewardjf48ac192004-10-29 00:41:29 +0000656 if (vex_traceflags & VEX_TRACE_RCODE) {
657 vex_printf("\n------------------------"
658 " Register-allocated code "
659 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000660 for (i = 0; i < rcode->arr_used; i++) {
661 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000662 ppInstr(rcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000663 vex_printf("\n");
664 }
sewardjfbcaf332004-07-08 01:46:01 +0000665 vex_printf("\n");
666 }
sewardjfbcaf332004-07-08 01:46:01 +0000667
sewardje908c422005-02-04 21:18:16 +0000668 /* HACK */
sewardj17c7f952005-12-15 14:02:34 +0000669 if (0) { *(vta->host_bytes_used) = 0; return VexTransOK; }
sewardje908c422005-02-04 21:18:16 +0000670 /* end HACK */
671
sewardj81bd5502004-07-21 18:49:27 +0000672 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000673 if (vex_traceflags & VEX_TRACE_ASM) {
674 vex_printf("\n------------------------"
675 " Assembly "
676 "------------------------\n\n");
677 }
678
sewardj81bd5502004-07-21 18:49:27 +0000679 out_used = 0; /* tracks along the host_bytes array */
680 for (i = 0; i < rcode->arr_used; i++) {
sewardjf48ac192004-10-29 00:41:29 +0000681 if (vex_traceflags & VEX_TRACE_ASM) {
cerion92b64362005-12-13 12:02:26 +0000682 ppInstr(rcode->arr[i], mode64);
sewardjbad34a92004-07-22 01:14:11 +0000683 vex_printf("\n");
684 }
sewardj2019a972011-03-07 16:04:07 +0000685 j = (*emit)( insn_bytes, sizeof insn_bytes, rcode->arr[i], mode64,
686 vta->dispatch );
sewardjf48ac192004-10-29 00:41:29 +0000687 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000688 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000689 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000690 vex_printf("0%x ", (UInt)insn_bytes[k]);
691 else
692 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000693 vex_printf("\n\n");
694 }
sewardj17c7f952005-12-15 14:02:34 +0000695 if (out_used + j > vta->host_bytes_size) {
sewardj2d6b14a2005-11-23 04:25:07 +0000696 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000697 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000698 return VexTransOutputFull;
sewardj81bd5502004-07-21 18:49:27 +0000699 }
700 for (k = 0; k < j; k++) {
sewardj17c7f952005-12-15 14:02:34 +0000701 vta->host_bytes[out_used] = insn_bytes[k];
sewardj81bd5502004-07-21 18:49:27 +0000702 out_used++;
703 }
sewardj17c7f952005-12-15 14:02:34 +0000704 vassert(out_used <= vta->host_bytes_size);
sewardj81bd5502004-07-21 18:49:27 +0000705 }
sewardj17c7f952005-12-15 14:02:34 +0000706 *(vta->host_bytes_used) = out_used;
sewardj81bd5502004-07-21 18:49:27 +0000707
sewardj2d6b14a2005-11-23 04:25:07 +0000708 vexAllocSanityCheck();
709
710 vexSetAllocModeTEMP_and_clear();
sewardjf13a16a2004-07-05 17:10:14 +0000711
sewardjf48ac192004-10-29 00:41:29 +0000712 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000713 return VexTransOK;
sewardj35421a32004-07-05 13:12:34 +0000714}
715
716
sewardj893aada2004-11-29 19:57:54 +0000717/* --------- Emulation warnings. --------- */
718
719HChar* LibVEX_EmWarn_string ( VexEmWarn ew )
720{
721 switch (ew) {
722 case EmWarn_NONE:
723 return "none";
724 case EmWarn_X86_x87exns:
725 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000726 case EmWarn_X86_x87precision:
727 return "Selection of non-80-bit x87 FP precision";
728 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +0000729 return "Unmasking SSE FP exceptions";
730 case EmWarn_X86_fz:
731 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
732 case EmWarn_X86_daz:
733 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +0000734 case EmWarn_X86_acFlag:
735 return "Setting %eflags.ac (setting noted but ignored)";
sewardj9dd9cf12006-01-20 14:13:55 +0000736 case EmWarn_PPCexns:
737 return "Unmasking PPC32/64 FP exceptions";
738 case EmWarn_PPC64_redir_overflow:
739 return "PPC64 function redirection stack overflow";
740 case EmWarn_PPC64_redir_underflow:
741 return "PPC64 function redirection stack underflow";
sewardj893aada2004-11-29 19:57:54 +0000742 default:
743 vpanic("LibVEX_EmWarn_string: unknown warning");
744 }
745}
sewardj35421a32004-07-05 13:12:34 +0000746
sewardj5117ce12006-01-27 21:20:15 +0000747/* ------------------ Arch/HwCaps stuff. ------------------ */
sewardjbef170b2004-12-21 01:23:00 +0000748
749const HChar* LibVEX_ppVexArch ( VexArch arch )
750{
751 switch (arch) {
752 case VexArch_INVALID: return "INVALID";
753 case VexArchX86: return "X86";
754 case VexArchAMD64: return "AMD64";
755 case VexArchARM: return "ARM";
sewardj0ec57c52005-02-01 15:24:10 +0000756 case VexArchPPC32: return "PPC32";
cerionf0de28c2005-12-13 20:21:11 +0000757 case VexArchPPC64: return "PPC64";
sewardj2019a972011-03-07 16:04:07 +0000758 case VexArchS390X: return "S390X";
sewardjbef170b2004-12-21 01:23:00 +0000759 default: return "VexArch???";
760 }
761}
762
sewardj5117ce12006-01-27 21:20:15 +0000763const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps )
sewardjbef170b2004-12-21 01:23:00 +0000764{
sewardj5117ce12006-01-27 21:20:15 +0000765 HChar* str = show_hwcaps(arch,hwcaps);
766 return str ? str : "INVALID";
sewardjbef170b2004-12-21 01:23:00 +0000767}
768
sewardj5117ce12006-01-27 21:20:15 +0000769
sewardj27e1dd62005-06-30 11:49:14 +0000770/* Write default settings info *vai. */
771void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
772{
sewardj5117ce12006-01-27 21:20:15 +0000773 vai->hwcaps = 0;
cerion5b2325f2005-12-23 00:55:09 +0000774 vai->ppc_cache_line_szB = 0;
sewardje971c6a2010-09-03 15:49:57 +0000775 vai->ppc_dcbz_szB = 0;
776 vai->ppc_dcbzl_szB = 0;
777
sewardj27e1dd62005-06-30 11:49:14 +0000778}
779
sewardjdd40fdf2006-12-24 02:20:24 +0000780/* Write default settings info *vbi. */
781void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
sewardjaca070a2006-10-17 00:28:22 +0000782{
sewardjdd40fdf2006-12-24 02:20:24 +0000783 vbi->guest_stack_redzone_size = 0;
sewardj2e28ac42008-12-04 00:05:12 +0000784 vbi->guest_amd64_assume_fs_is_zero = False;
785 vbi->guest_amd64_assume_gs_is_0x60 = False;
sewardjdd40fdf2006-12-24 02:20:24 +0000786 vbi->guest_ppc_zap_RZ_at_blr = False;
787 vbi->guest_ppc_zap_RZ_at_bl = NULL;
788 vbi->guest_ppc_sc_continues_at_LR = False;
789 vbi->host_ppc_calls_use_fndescrs = False;
790 vbi->host_ppc32_regalign_int64_args = False;
sewardjaca070a2006-10-17 00:28:22 +0000791}
792
sewardj27e1dd62005-06-30 11:49:14 +0000793
sewardj5117ce12006-01-27 21:20:15 +0000794/* Return a string showing the hwcaps in a nice way. The string will
795 be NULL for invalid combinations of flags, so these functions also
796 serve as a way to validate hwcaps values. */
797
798static HChar* show_hwcaps_x86 ( UInt hwcaps )
799{
800 /* Monotonic, SSE3 > SSE2 > SSE1 > baseline. */
sewardj536fbab2010-07-29 15:39:05 +0000801 switch (hwcaps) {
802 case 0:
803 return "x86-sse0";
804 case VEX_HWCAPS_X86_SSE1:
805 return "x86-sse1";
806 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2:
807 return "x86-sse1-sse2";
808 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
809 | VEX_HWCAPS_X86_LZCNT:
810 return "x86-sse1-sse2-lzcnt";
811 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
812 | VEX_HWCAPS_X86_SSE3:
813 return "x86-sse1-sse2-sse3";
814 case VEX_HWCAPS_X86_SSE1 | VEX_HWCAPS_X86_SSE2
815 | VEX_HWCAPS_X86_SSE3 | VEX_HWCAPS_X86_LZCNT:
816 return "x86-sse1-sse2-sse3-lzcnt";
817 default:
818 return NULL;
819 }
sewardj5117ce12006-01-27 21:20:15 +0000820}
821
822static HChar* show_hwcaps_amd64 ( UInt hwcaps )
823{
sewardje9d8a262009-07-01 08:06:34 +0000824 /* SSE3 and CX16 are orthogonal and > baseline, although we really
825 don't expect to come across anything which can do SSE3 but can't
sewardj536fbab2010-07-29 15:39:05 +0000826 do CX16. Still, we can handle that case. LZCNT is similarly
827 orthogonal. */
828 switch (hwcaps) {
829 case 0:
830 return "amd64-sse2";
831 case VEX_HWCAPS_AMD64_SSE3:
832 return "amd64-sse3";
833 case VEX_HWCAPS_AMD64_CX16:
834 return "amd64-sse2-cx16";
835 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16:
836 return "amd64-sse3-cx16";
837 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_LZCNT:
838 return "amd64-sse3-lzcnt";
839 case VEX_HWCAPS_AMD64_CX16 | VEX_HWCAPS_AMD64_LZCNT:
840 return "amd64-sse2-cx16-lzcnt";
841 case VEX_HWCAPS_AMD64_SSE3 | VEX_HWCAPS_AMD64_CX16
842 | VEX_HWCAPS_AMD64_LZCNT:
843 return "amd64-sse3-cx16-lzcnt";
844
845 default:
846 return NULL;
847 }
sewardj5117ce12006-01-27 21:20:15 +0000848}
849
850static HChar* show_hwcaps_ppc32 ( UInt hwcaps )
851{
852 /* Monotonic with complications. Basically V > F > baseline,
853 but once you have F then you can have FX or GX too. */
854 const UInt F = VEX_HWCAPS_PPC32_F;
855 const UInt V = VEX_HWCAPS_PPC32_V;
856 const UInt FX = VEX_HWCAPS_PPC32_FX;
857 const UInt GX = VEX_HWCAPS_PPC32_GX;
sewardj66d5ef22011-04-15 11:55:00 +0000858 const UInt VX = VEX_HWCAPS_PPC32_VX;
sewardj5117ce12006-01-27 21:20:15 +0000859 UInt c = hwcaps;
860 if (c == 0) return "ppc32-int";
861 if (c == F) return "ppc32-int-flt";
862 if (c == (F|FX)) return "ppc32-int-flt-FX";
863 if (c == (F|GX)) return "ppc32-int-flt-GX";
864 if (c == (F|FX|GX)) return "ppc32-int-flt-FX-GX";
865 if (c == (F|V)) return "ppc32-int-flt-vmx";
866 if (c == (F|V|FX)) return "ppc32-int-flt-vmx-FX";
867 if (c == (F|V|GX)) return "ppc32-int-flt-vmx-GX";
868 if (c == (F|V|FX|GX)) return "ppc32-int-flt-vmx-FX-GX";
sewardj66d5ef22011-04-15 11:55:00 +0000869 if (c == (F|V|FX|GX|VX)) return "ppc32-int-flt-vmx-FX-GX-VX";
sewardj5117ce12006-01-27 21:20:15 +0000870 return NULL;
871}
872
873static HChar* show_hwcaps_ppc64 ( UInt hwcaps )
874{
875 /* Monotonic with complications. Basically V > baseline(==F),
876 but once you have F then you can have FX or GX too. */
sewardj3fd39672006-01-27 22:05:55 +0000877 const UInt V = VEX_HWCAPS_PPC64_V;
878 const UInt FX = VEX_HWCAPS_PPC64_FX;
879 const UInt GX = VEX_HWCAPS_PPC64_GX;
sewardj66d5ef22011-04-15 11:55:00 +0000880 const UInt VX = VEX_HWCAPS_PPC64_VX;
sewardj5117ce12006-01-27 21:20:15 +0000881 UInt c = hwcaps;
882 if (c == 0) return "ppc64-int-flt";
883 if (c == FX) return "ppc64-int-flt-FX";
884 if (c == GX) return "ppc64-int-flt-GX";
885 if (c == (FX|GX)) return "ppc64-int-flt-FX-GX";
886 if (c == V) return "ppc64-int-flt-vmx";
887 if (c == (V|FX)) return "ppc64-int-flt-vmx-FX";
888 if (c == (V|GX)) return "ppc64-int-flt-vmx-GX";
889 if (c == (V|FX|GX)) return "ppc64-int-flt-vmx-FX-GX";
sewardj66d5ef22011-04-15 11:55:00 +0000890 if (c == (V|FX|GX|VX)) return "ppc64-int-flt-vmx-FX-GX-VX";
sewardj5117ce12006-01-27 21:20:15 +0000891 return NULL;
892}
893
894static HChar* show_hwcaps_arm ( UInt hwcaps )
895{
sewardjec0d9a02010-08-22 12:54:56 +0000896 Bool N = ((hwcaps & VEX_HWCAPS_ARM_NEON) != 0);
897 Bool vfp = ((hwcaps & (VEX_HWCAPS_ARM_VFP |
898 VEX_HWCAPS_ARM_VFP2 | VEX_HWCAPS_ARM_VFP3)) != 0);
899 switch (VEX_ARM_ARCHLEVEL(hwcaps)) {
900 case 5:
901 if (N)
902 return NULL;
903 if (vfp)
904 return "ARMv5-vfp";
905 else
906 return "ARMv5";
907 return NULL;
908 case 6:
909 if (N)
910 return NULL;
911 if (vfp)
912 return "ARMv6-vfp";
913 else
914 return "ARMv6";
915 return NULL;
916 case 7:
917 if (vfp) {
918 if (N)
919 return "ARMv7-vfp-neon";
920 else
921 return "ARMv7-vfp";
922 } else {
923 if (N)
924 return "ARMv7-neon";
925 else
926 return "ARMv7";
927 }
928 default:
929 return NULL;
930 }
sewardj5117ce12006-01-27 21:20:15 +0000931 return NULL;
932}
933
sewardj2019a972011-03-07 16:04:07 +0000934static HChar* show_hwcaps_s390x ( UInt hwcaps )
935{
936 const UInt LD = VEX_HWCAPS_S390X_LDISP;
937 const UInt EI = VEX_HWCAPS_S390X_EIMM;
938 const UInt GE = VEX_HWCAPS_S390X_GIE;
939 const UInt DF = VEX_HWCAPS_S390X_DFP;
940
sewardj652b56a2011-04-13 15:38:17 +0000941 hwcaps = VEX_HWCAPS_S390X(hwcaps);
942
sewardj2019a972011-03-07 16:04:07 +0000943 if (hwcaps == (LD)) return "s390x-ldisp";
944 if (hwcaps == (LD|EI)) return "s390x-ldisp-eimm";
945 if (hwcaps == (LD|GE)) return "s390x-ldisp-gie";
946 if (hwcaps == (LD|DF)) return "s390x-ldisp-dfp";
947 if (hwcaps == (LD|EI|GE)) return "s390x-ldisp-eimm-gie";
948 if (hwcaps == (LD|EI|DF)) return "s390x-ldisp-eimm-dfp";
949 if (hwcaps == (LD|GE|DF)) return "s390x-ldisp-gie-dfp";
950 if (hwcaps == (LD|EI|GE|DF)) return "s390x-ldisp-eimm-gie-dfp";
951
sewardj652b56a2011-04-13 15:38:17 +0000952 return "s390-zarch";
sewardj2019a972011-03-07 16:04:07 +0000953}
954
sewardj5117ce12006-01-27 21:20:15 +0000955/* ---- */
956static HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
957{
958 switch (arch) {
sewardj3fd39672006-01-27 22:05:55 +0000959 case VexArchX86: return show_hwcaps_x86(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +0000960 case VexArchAMD64: return show_hwcaps_amd64(hwcaps);
961 case VexArchPPC32: return show_hwcaps_ppc32(hwcaps);
962 case VexArchPPC64: return show_hwcaps_ppc64(hwcaps);
sewardj3fd39672006-01-27 22:05:55 +0000963 case VexArchARM: return show_hwcaps_arm(hwcaps);
sewardj2019a972011-03-07 16:04:07 +0000964 case VexArchS390X: return show_hwcaps_s390x(hwcaps);
sewardj5117ce12006-01-27 21:20:15 +0000965 default: return NULL;
966 }
967}
968
969static Bool are_valid_hwcaps ( VexArch arch, UInt hwcaps )
970{
971 return show_hwcaps(arch,hwcaps) != NULL;
972}
973
974
sewardj35421a32004-07-05 13:12:34 +0000975/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +0000976/*--- end main_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +0000977/*---------------------------------------------------------------*/