blob: 37bd709d03a66e33e97f8961144a268c1a63ae28 [file] [log] [blame]
sewardj35421a32004-07-05 13:12:34 +00001
2/*---------------------------------------------------------------*/
3/*--- ---*/
sewardjc0ee2ed2004-07-27 10:29:41 +00004/*--- This file (main/vex_main.c) is ---*/
sewardjdbcfae72005-08-02 11:14:04 +00005/*--- Copyright (C) OpenWorks LLP. All rights reserved. ---*/
sewardj35421a32004-07-05 13:12:34 +00006/*--- ---*/
7/*---------------------------------------------------------------*/
8
sewardjf8ed9d82004-11-12 17:40:23 +00009/*
10 This file is part of LibVEX, a library for dynamic binary
11 instrumentation and translation.
12
sewardj7bd6ffe2005-08-03 16:07:36 +000013 Copyright (C) 2004-2005 OpenWorks LLP. All rights reserved.
sewardjf8ed9d82004-11-12 17:40:23 +000014
sewardj7bd6ffe2005-08-03 16:07:36 +000015 This library is made available under a dual licensing scheme.
sewardjf8ed9d82004-11-12 17:40:23 +000016
sewardj7bd6ffe2005-08-03 16:07:36 +000017 If you link LibVEX against other code all of which is itself
18 licensed under the GNU General Public License, version 2 dated June
19 1991 ("GPL v2"), then you may use LibVEX under the terms of the GPL
20 v2, as appearing in the file LICENSE.GPL. If the file LICENSE.GPL
21 is missing, you can obtain a copy of the GPL v2 from the Free
22 Software Foundation Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 02110-1301, USA.
24
25 For any other uses of LibVEX, you must first obtain a commercial
26 license from OpenWorks LLP. Please contact info@open-works.co.uk
27 for information about commercial licensing.
28
29 This software is provided by OpenWorks LLP "as is" and any express
30 or implied warranties, including, but not limited to, the implied
31 warranties of merchantability and fitness for a particular purpose
32 are disclaimed. In no event shall OpenWorks LLP be liable for any
33 direct, indirect, incidental, special, exemplary, or consequential
34 damages (including, but not limited to, procurement of substitute
35 goods or services; loss of use, data, or profits; or business
36 interruption) however caused and on any theory of liability,
37 whether in contract, strict liability, or tort (including
38 negligence or otherwise) arising in any way out of the use of this
39 software, even if advised of the possibility of such damage.
sewardjf8ed9d82004-11-12 17:40:23 +000040
41 Neither the names of the U.S. Department of Energy nor the
42 University of California nor the names of its contributors may be
43 used to endorse or promote products derived from this software
44 without prior written permission.
sewardjf8ed9d82004-11-12 17:40:23 +000045*/
46
sewardj887a11a2004-07-05 17:26:47 +000047#include "libvex.h"
sewardj893aada2004-11-29 19:57:54 +000048#include "libvex_emwarn.h"
sewardj81ec4182004-10-25 23:15:52 +000049#include "libvex_guest_x86.h"
sewardj44d494d2005-01-20 20:26:33 +000050#include "libvex_guest_amd64.h"
sewardj2a9ad022004-11-25 02:46:58 +000051#include "libvex_guest_arm.h"
cerionaabdfbf2005-01-29 12:56:15 +000052#include "libvex_guest_ppc32.h"
sewardjf13a16a2004-07-05 17:10:14 +000053
sewardjc0ee2ed2004-07-27 10:29:41 +000054#include "main/vex_globals.h"
55#include "main/vex_util.h"
56#include "host-generic/h_generic_regs.h"
sewardjedf4d692004-08-17 13:52:58 +000057#include "ir/iropt.h"
sewardj35421a32004-07-05 13:12:34 +000058
sewardj2a9ad022004-11-25 02:46:58 +000059#include "host-x86/hdefs.h"
sewardjc33671d2005-02-01 20:30:00 +000060#include "host-amd64/hdefs.h"
cerion487e4c92005-02-04 16:28:19 +000061#include "host-ppc32/hdefs.h"
sewardj2a9ad022004-11-25 02:46:58 +000062
sewardj9e6491a2005-07-02 19:24:10 +000063#include "guest-generic/bb_to_IR.h"
sewardj2a9ad022004-11-25 02:46:58 +000064#include "guest-x86/gdefs.h"
sewardj44d494d2005-01-20 20:26:33 +000065#include "guest-amd64/gdefs.h"
sewardj2a9ad022004-11-25 02:46:58 +000066#include "guest-arm/gdefs.h"
cerionaabdfbf2005-01-29 12:56:15 +000067#include "guest-ppc32/gdefs.h"
sewardj2a9ad022004-11-25 02:46:58 +000068
sewardj35421a32004-07-05 13:12:34 +000069
70/* This file contains the top level interface to the library. */
71
72/* --------- Initialise the library. --------- */
73
74/* Exported to library client. */
75
sewardjd887b862005-01-17 18:34:34 +000076const HChar* LibVEX_Version ( void )
sewardj80f5fce2004-12-20 04:37:50 +000077{
78return
79#include "main/vex_svnversion.h"
80 ;
81}
82
83
84/* Exported to library client. */
85
sewardj08613742004-10-25 13:01:45 +000086void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon )
87{
88 vcon->iropt_verbosity = 0;
89 vcon->iropt_level = 2;
90 vcon->iropt_precise_memory_exns = False;
91 vcon->iropt_unroll_thresh = 120;
sewardj18b4bb72005-03-29 21:32:41 +000092 vcon->guest_max_insns = 60;
sewardj08613742004-10-25 13:01:45 +000093 vcon->guest_chase_thresh = 10;
94}
95
96
97/* Exported to library client. */
98
sewardj887a11a2004-07-05 17:26:47 +000099void LibVEX_Init (
sewardj35421a32004-07-05 13:12:34 +0000100 /* failure exit function */
sewardj2b515872004-07-05 20:50:45 +0000101 __attribute__ ((noreturn))
sewardj35421a32004-07-05 13:12:34 +0000102 void (*failure_exit) ( void ),
103 /* logging output function */
sewardjd9763622005-02-07 03:12:19 +0000104 void (*log_bytes) ( HChar*, Int nbytes ),
sewardj35421a32004-07-05 13:12:34 +0000105 /* debug paranoia level */
106 Int debuglevel,
sewardj35421a32004-07-05 13:12:34 +0000107 /* Are we supporting valgrind checking? */
108 Bool valgrind_support,
sewardj08613742004-10-25 13:01:45 +0000109 /* Control ... */
110 /*READONLY*/VexControl* vcon
sewardj35421a32004-07-05 13:12:34 +0000111)
112{
sewardj08613742004-10-25 13:01:45 +0000113 /* First off, do enough minimal setup so that the following
114 assertions can fail in a sane fashion, if need be. */
sewardjea602bc2004-10-14 21:40:12 +0000115 vex_failure_exit = failure_exit;
116 vex_log_bytes = log_bytes;
117
118 /* Now it's safe to check parameters for sanity. */
sewardj35421a32004-07-05 13:12:34 +0000119 vassert(!vex_initdone);
120 vassert(failure_exit);
sewardj35421a32004-07-05 13:12:34 +0000121 vassert(log_bytes);
sewardj35421a32004-07-05 13:12:34 +0000122 vassert(debuglevel >= 0);
sewardj08613742004-10-25 13:01:45 +0000123
124 vassert(vcon->iropt_verbosity >= 0);
125 vassert(vcon->iropt_level >= 0);
126 vassert(vcon->iropt_level <= 2);
127 vassert(vcon->iropt_unroll_thresh >= 0);
128 vassert(vcon->iropt_unroll_thresh <= 400);
129 vassert(vcon->guest_max_insns >= 1);
130 vassert(vcon->guest_max_insns <= 100);
131 vassert(vcon->guest_chase_thresh >= 0);
132 vassert(vcon->guest_chase_thresh < vcon->guest_max_insns);
sewardj443cd9d2004-07-18 23:06:45 +0000133
sewardjea602bc2004-10-14 21:40:12 +0000134 /* Check that Vex has been built with sizes of basic types as
135 stated in priv/libvex_basictypes.h. Failure of any of these is
136 a serious configuration error and should be corrected
137 immediately. If any of these assertions fail you can fully
138 expect Vex not to work properly, if at all. */
139
140 vassert(1 == sizeof(UChar));
141 vassert(1 == sizeof(Char));
142 vassert(2 == sizeof(UShort));
143 vassert(2 == sizeof(Short));
144 vassert(4 == sizeof(UInt));
145 vassert(4 == sizeof(Int));
146 vassert(8 == sizeof(ULong));
147 vassert(8 == sizeof(Long));
148 vassert(4 == sizeof(Float));
149 vassert(8 == sizeof(Double));
150 vassert(1 == sizeof(Bool));
151 vassert(4 == sizeof(Addr32));
152 vassert(8 == sizeof(Addr64));
sewardjc9a43662004-11-30 18:51:59 +0000153 vassert(16 == sizeof(U128));
sewardjea602bc2004-10-14 21:40:12 +0000154
155 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
156 vassert(sizeof(void*) == sizeof(int*));
157 vassert(sizeof(void*) == sizeof(HWord));
158
sewardj97e87932005-02-07 00:00:50 +0000159 vassert(VEX_HOST_WORDSIZE == sizeof(void*));
160 vassert(VEX_HOST_WORDSIZE == sizeof(HWord));
161
sewardjea602bc2004-10-14 21:40:12 +0000162 /* Really start up .. */
sewardj443cd9d2004-07-18 23:06:45 +0000163 vex_debuglevel = debuglevel;
sewardj443cd9d2004-07-18 23:06:45 +0000164 vex_valgrind_support = valgrind_support;
sewardj08613742004-10-25 13:01:45 +0000165 vex_control = *vcon;
sewardj443cd9d2004-07-18 23:06:45 +0000166 vex_initdone = True;
sewardjd887b862005-01-17 18:34:34 +0000167 vexSetAllocMode ( VexAllocModeTEMP );
sewardj35421a32004-07-05 13:12:34 +0000168}
169
170
171/* --------- Make a translation. --------- */
172
173/* Exported to library client. */
174
sewardjd887b862005-01-17 18:34:34 +0000175VexTranslateResult LibVEX_Translate (
sewardj35421a32004-07-05 13:12:34 +0000176 /* The instruction sets we are translating from and to. */
sewardj27e1dd62005-06-30 11:49:14 +0000177 VexArch arch_guest,
178 VexArchInfo* archinfo_guest,
179 VexArch arch_host,
180 VexArchInfo* archinfo_host,
sewardj35421a32004-07-05 13:12:34 +0000181 /* IN: the block to translate, and its guest address. */
sewardjf4611492005-10-18 12:01:48 +0000182 /* where are the actual bytes in the host's address space? */
sewardjbef170b2004-12-21 01:23:00 +0000183 UChar* guest_bytes,
sewardjf4611492005-10-18 12:01:48 +0000184 /* where do the bytes came from in the guest's aspace? */
sewardjbef170b2004-12-21 01:23:00 +0000185 Addr64 guest_bytes_addr,
sewardjf4611492005-10-18 12:01:48 +0000186 /* what guest entry point address do they correspond to? */
187 Addr64 guest_bytes_addr_noredir,
188 /* Is it OK to chase into this guest address? */
sewardjbef170b2004-12-21 01:23:00 +0000189 Bool (*chase_into_ok) ( Addr64 ),
sewardj72c72812005-01-19 11:49:45 +0000190 /* OUT: which bits of guest code actually got translated */
191 VexGuestExtents* guest_extents,
sewardj35421a32004-07-05 13:12:34 +0000192 /* IN: a place to put the resulting code, and its size */
sewardjbef170b2004-12-21 01:23:00 +0000193 UChar* host_bytes,
194 Int host_bytes_size,
sewardj35421a32004-07-05 13:12:34 +0000195 /* OUT: how much of the output area is used. */
sewardjbef170b2004-12-21 01:23:00 +0000196 Int* host_bytes_used,
sewardj49651f42004-10-28 22:11:04 +0000197 /* IN: optionally, two instrumentation functions. */
sewardj918c8f32005-03-21 00:54:33 +0000198 IRBB* (*instrument1) ( IRBB*, VexGuestLayout*,
sewardjf4611492005-10-18 12:01:48 +0000199 Addr64, VexGuestExtents*,
sewardj918c8f32005-03-21 00:54:33 +0000200 IRType gWordTy, IRType hWordTy ),
201 IRBB* (*instrument2) ( IRBB*, VexGuestLayout*,
sewardjf4611492005-10-18 12:01:48 +0000202 Addr64, VexGuestExtents*,
sewardj918c8f32005-03-21 00:54:33 +0000203 IRType gWordTy, IRType hWordTy ),
sewardjbef170b2004-12-21 01:23:00 +0000204 Bool cleanup_after_instrumentation,
sewardjec3c8852005-07-07 09:56:24 +0000205 /* IN: should this translation be self-checking? */
206 Bool do_self_check,
sewardj35421a32004-07-05 13:12:34 +0000207 /* IN: optionally, an access check function for guest code. */
sewardjbef170b2004-12-21 01:23:00 +0000208 Bool (*byte_accessible) ( Addr64 ),
sewardjf48ac192004-10-29 00:41:29 +0000209 /* IN: debug: trace vex activity at various points */
sewardjbef170b2004-12-21 01:23:00 +0000210 Int traceflags
sewardj35421a32004-07-05 13:12:34 +0000211)
212{
sewardj81bd5502004-07-21 18:49:27 +0000213 /* This the bundle of functions we need to do the back-end stuff
214 (insn selection, reg-alloc, assembly) whilst being insulated
215 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +0000216 HReg* available_real_regs;
217 Int n_available_real_regs;
cerion92b64362005-12-13 12:02:26 +0000218 Bool (*isMove) ( HInstr*, HReg*, HReg* );
219 void (*getRegUsage) ( HRegUsage*, HInstr*, Bool );
220 void (*mapRegs) ( HRegRemap*, HInstr*, Bool );
221 HInstr* (*genSpill) ( HReg, Int, Bool );
222 HInstr* (*genReload) ( HReg, Int, Bool );
223 void (*ppInstr) ( HInstr*, Bool );
sewardj443cd9d2004-07-18 23:06:45 +0000224 void (*ppReg) ( HReg );
sewardj27e1dd62005-06-30 11:49:14 +0000225 HInstrArray* (*iselBB) ( IRBB*, VexArchInfo* );
cerion92b64362005-12-13 12:02:26 +0000226 Int (*emit) ( UChar*, Int, HInstr*, Bool );
sewardjd9763622005-02-07 03:12:19 +0000227 IRExpr* (*specHelper) ( HChar*, IRExpr** );
sewardj8d2291c2004-10-25 14:50:21 +0000228 Bool (*preciseMemExnsFn) ( Int, Int );
sewardjf13a16a2004-07-05 17:10:14 +0000229
sewardj9e6491a2005-07-02 19:24:10 +0000230 DisOneInstrFn disInstrFn;
231
sewardjeeac8412004-11-02 00:26:55 +0000232 VexGuestLayout* guest_layout;
233 Bool host_is_bigendian = False;
234 IRBB* irbb;
235 HInstrArray* vcode;
236 HInstrArray* rcode;
237 Int i, j, k, out_used, guest_sizeB;
sewardjdb4738a2005-07-07 01:32:16 +0000238 Int offB_TISTART, offB_TILEN;
sewardjeeac8412004-11-02 00:26:55 +0000239 UChar insn_bytes[32];
sewardjcf787902004-11-03 09:08:33 +0000240 IRType guest_word_type;
241 IRType host_word_type;
cerion92b64362005-12-13 12:02:26 +0000242 Bool mode64;
sewardjf13a16a2004-07-05 17:10:14 +0000243
sewardj49651f42004-10-28 22:11:04 +0000244 guest_layout = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000245 available_real_regs = NULL;
246 n_available_real_regs = 0;
247 isMove = NULL;
248 getRegUsage = NULL;
249 mapRegs = NULL;
250 genSpill = NULL;
251 genReload = NULL;
252 ppInstr = NULL;
253 ppReg = NULL;
254 iselBB = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000255 emit = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000256 specHelper = NULL;
sewardj8d2291c2004-10-25 14:50:21 +0000257 preciseMemExnsFn = NULL;
sewardj9e6491a2005-07-02 19:24:10 +0000258 disInstrFn = NULL;
sewardjcf787902004-11-03 09:08:33 +0000259 guest_word_type = Ity_INVALID;
260 host_word_type = Ity_INVALID;
sewardjdb4738a2005-07-07 01:32:16 +0000261 offB_TISTART = 0;
262 offB_TILEN = 0;
cerion92b64362005-12-13 12:02:26 +0000263 mode64 = False;
sewardj36ca5132004-07-24 13:12:23 +0000264
sewardjf48ac192004-10-29 00:41:29 +0000265 vex_traceflags = traceflags;
sewardj58800ff2004-07-28 01:51:10 +0000266
sewardj35421a32004-07-05 13:12:34 +0000267 vassert(vex_initdone);
sewardj2d6b14a2005-11-23 04:25:07 +0000268 vexSetAllocModeTEMP_and_clear();
269 vexAllocSanityCheck();
sewardj2a9ad022004-11-25 02:46:58 +0000270
sewardjf13a16a2004-07-05 17:10:14 +0000271 /* First off, check that the guest and host insn sets
272 are supported. */
sewardj2a9ad022004-11-25 02:46:58 +0000273
sewardjbef170b2004-12-21 01:23:00 +0000274 switch (arch_host) {
sewardj2a9ad022004-11-25 02:46:58 +0000275
sewardjbef170b2004-12-21 01:23:00 +0000276 case VexArchX86:
cerion92b64362005-12-13 12:02:26 +0000277 mode64 = False;
sewardjf13a16a2004-07-05 17:10:14 +0000278 getAllocableRegs_X86 ( &n_available_real_regs,
279 &available_real_regs );
280 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
cerion92b64362005-12-13 12:02:26 +0000281 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_X86Instr;
282 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_X86Instr;
283 genSpill = (HInstr*(*)(HReg,Int, Bool)) genSpill_X86;
284 genReload = (HInstr*(*)(HReg,Int, Bool)) genReload_X86;
285 ppInstr = (void(*)(HInstr*, Bool)) ppX86Instr;
sewardj2b515872004-07-05 20:50:45 +0000286 ppReg = (void(*)(HReg)) ppHRegX86;
sewardjf13a16a2004-07-05 17:10:14 +0000287 iselBB = iselBB_X86;
cerion92b64362005-12-13 12:02:26 +0000288 emit = (Int(*)(UChar*,Int,HInstr*, Bool)) emit_X86Instr;
sewardj72c72812005-01-19 11:49:45 +0000289 host_is_bigendian = False;
sewardjcf787902004-11-03 09:08:33 +0000290 host_word_type = Ity_I32;
sewardj27e1dd62005-06-30 11:49:14 +0000291 vassert(archinfo_host->subarch == VexSubArchX86_sse0
292 || archinfo_host->subarch == VexSubArchX86_sse1
293 || archinfo_host->subarch == VexSubArchX86_sse2);
sewardjf13a16a2004-07-05 17:10:14 +0000294 break;
sewardj2a9ad022004-11-25 02:46:58 +0000295
sewardjc33671d2005-02-01 20:30:00 +0000296 case VexArchAMD64:
cerion92b64362005-12-13 12:02:26 +0000297 mode64 = True;
sewardjc33671d2005-02-01 20:30:00 +0000298 getAllocableRegs_AMD64 ( &n_available_real_regs,
299 &available_real_regs );
300 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr;
cerion92b64362005-12-13 12:02:26 +0000301 getRegUsage = (void(*)(HRegUsage*,HInstr*, Bool)) getRegUsage_AMD64Instr;
302 mapRegs = (void(*)(HRegRemap*,HInstr*, Bool)) mapRegs_AMD64Instr;
303 genSpill = (HInstr*(*)(HReg,Int, Bool)) genSpill_AMD64;
304 genReload = (HInstr*(*)(HReg,Int, Bool)) genReload_AMD64;
305 ppInstr = (void(*)(HInstr*, Bool)) ppAMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000306 ppReg = (void(*)(HReg)) ppHRegAMD64;
307 iselBB = iselBB_AMD64;
cerion92b64362005-12-13 12:02:26 +0000308 emit = (Int(*)(UChar*,Int,HInstr*, Bool)) emit_AMD64Instr;
sewardjc33671d2005-02-01 20:30:00 +0000309 host_is_bigendian = False;
310 host_word_type = Ity_I64;
sewardj27e1dd62005-06-30 11:49:14 +0000311 vassert(archinfo_host->subarch == VexSubArch_NONE);
sewardjc33671d2005-02-01 20:30:00 +0000312 break;
313
cerion487e4c92005-02-04 16:28:19 +0000314 case VexArchPPC32:
cerion92b64362005-12-13 12:02:26 +0000315 mode64 = False;
cerion487e4c92005-02-04 16:28:19 +0000316 getAllocableRegs_PPC32 ( &n_available_real_regs,
cerion92b64362005-12-13 12:02:26 +0000317 &available_real_regs, mode64 );
cerion487e4c92005-02-04 16:28:19 +0000318 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPC32Instr;
cerion92b64362005-12-13 12:02:26 +0000319 getRegUsage = (void(*)(HRegUsage*,HInstr*,Bool)) getRegUsage_PPC32Instr;
320 mapRegs = (void(*)(HRegRemap*,HInstr*,Bool)) mapRegs_PPC32Instr;
321 genSpill = (HInstr*(*)(HReg,Int,Bool)) genSpill_PPC32;
322 genReload = (HInstr*(*)(HReg,Int,Bool)) genReload_PPC32;
323 ppInstr = (void(*)(HInstr*,Bool)) ppPPC32Instr;
cerion487e4c92005-02-04 16:28:19 +0000324 ppReg = (void(*)(HReg)) ppHRegPPC32;
325 iselBB = iselBB_PPC32;
cerion92b64362005-12-13 12:02:26 +0000326 emit = (Int(*)(UChar*,Int,HInstr*,Bool)) emit_PPC32Instr;
cerion487e4c92005-02-04 16:28:19 +0000327 host_is_bigendian = True;
328 host_word_type = Ity_I32;
sewardj059601a2005-11-13 00:53:05 +0000329 vassert(archinfo_guest->subarch == VexSubArchPPC32_I
330 || archinfo_guest->subarch == VexSubArchPPC32_FI
331 || archinfo_guest->subarch == VexSubArchPPC32_VFI);
cerion487e4c92005-02-04 16:28:19 +0000332 break;
333
sewardjf13a16a2004-07-05 17:10:14 +0000334 default:
sewardj887a11a2004-07-05 17:26:47 +0000335 vpanic("LibVEX_Translate: unsupported target insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000336 }
337
sewardj2a9ad022004-11-25 02:46:58 +0000338
sewardjbef170b2004-12-21 01:23:00 +0000339 switch (arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000340
sewardjbef170b2004-12-21 01:23:00 +0000341 case VexArchX86:
sewardj8d2291c2004-10-25 14:50:21 +0000342 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000343 disInstrFn = disInstr_X86;
sewardj2a9ad022004-11-25 02:46:58 +0000344 specHelper = guest_x86_spechelper;
sewardj81ec4182004-10-25 23:15:52 +0000345 guest_sizeB = sizeof(VexGuestX86State);
sewardjcf787902004-11-03 09:08:33 +0000346 guest_word_type = Ity_I32;
sewardj49651f42004-10-28 22:11:04 +0000347 guest_layout = &x86guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000348 offB_TISTART = offsetof(VexGuestX86State,guest_TISTART);
349 offB_TILEN = offsetof(VexGuestX86State,guest_TILEN);
sewardj27e1dd62005-06-30 11:49:14 +0000350 vassert(archinfo_guest->subarch == VexSubArchX86_sse0
351 || archinfo_guest->subarch == VexSubArchX86_sse1
352 || archinfo_guest->subarch == VexSubArchX86_sse2);
sewardje74f6f72005-08-05 02:55:36 +0000353 vassert(0 == sizeof(VexGuestX86State) % 8);
sewardjdb4738a2005-07-07 01:32:16 +0000354 vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART ) == 4);
355 vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000356 break;
sewardj2a9ad022004-11-25 02:46:58 +0000357
sewardj44d494d2005-01-20 20:26:33 +0000358 case VexArchAMD64:
359 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000360 disInstrFn = disInstr_AMD64;
sewardj44d494d2005-01-20 20:26:33 +0000361 specHelper = guest_amd64_spechelper;
362 guest_sizeB = sizeof(VexGuestAMD64State);
363 guest_word_type = Ity_I64;
364 guest_layout = &amd64guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000365 offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART);
366 offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN);
sewardj27e1dd62005-06-30 11:49:14 +0000367 vassert(archinfo_guest->subarch == VexSubArch_NONE);
sewardje74f6f72005-08-05 02:55:36 +0000368 vassert(0 == sizeof(VexGuestAMD64State) % 8);
sewardjdb4738a2005-07-07 01:32:16 +0000369 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8);
370 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000371 break;
372
sewardjbef170b2004-12-21 01:23:00 +0000373 case VexArchARM:
sewardj2a9ad022004-11-25 02:46:58 +0000374 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000375 disInstrFn = NULL; /* HACK */
sewardj2a9ad022004-11-25 02:46:58 +0000376 specHelper = guest_arm_spechelper;
377 guest_sizeB = sizeof(VexGuestARMState);
378 guest_word_type = Ity_I32;
379 guest_layout = &armGuest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000380 offB_TISTART = 0; /* hack ... arm has bitrot */
381 offB_TILEN = 0; /* hack ... arm has bitrot */
sewardj27e1dd62005-06-30 11:49:14 +0000382 vassert(archinfo_guest->subarch == VexSubArchARM_v4);
sewardj2a9ad022004-11-25 02:46:58 +0000383 break;
384
cerionaabdfbf2005-01-29 12:56:15 +0000385 case VexArchPPC32:
386 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000387 disInstrFn = disInstr_PPC32;
cerionaabdfbf2005-01-29 12:56:15 +0000388 specHelper = guest_ppc32_spechelper;
389 guest_sizeB = sizeof(VexGuestPPC32State);
390 guest_word_type = Ity_I32;
391 guest_layout = &ppc32Guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000392 offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART);
393 offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN);
sewardj059601a2005-11-13 00:53:05 +0000394 vassert(archinfo_guest->subarch == VexSubArchPPC32_I
395 || archinfo_guest->subarch == VexSubArchPPC32_FI
396 || archinfo_guest->subarch == VexSubArchPPC32_VFI);
sewardje74f6f72005-08-05 02:55:36 +0000397 vassert(0 == sizeof(VexGuestPPC32State) % 8);
sewardjdb4738a2005-07-07 01:32:16 +0000398 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4);
399 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000400 break;
401
sewardjf13a16a2004-07-05 17:10:14 +0000402 default:
sewardj887a11a2004-07-05 17:26:47 +0000403 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000404 }
405
sewardj9df271d2004-12-31 22:37:42 +0000406 /* yet more sanity checks ... */
sewardj0ec57c52005-02-01 15:24:10 +0000407 if (arch_guest == arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000408 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000409 we are simulating one flavour of an architecture a different
410 flavour of the same architecture, which is pretty strange. */
sewardj27e1dd62005-06-30 11:49:14 +0000411 vassert(archinfo_guest->subarch == archinfo_host->subarch);
sewardj9df271d2004-12-31 22:37:42 +0000412 }
sewardj2a9ad022004-11-25 02:46:58 +0000413
sewardj2d6b14a2005-11-23 04:25:07 +0000414 vexAllocSanityCheck();
415
sewardjf48ac192004-10-29 00:41:29 +0000416 if (vex_traceflags & VEX_TRACE_FE)
417 vex_printf("\n------------------------"
418 " Front end "
419 "------------------------\n\n");
420
sewardj9e6491a2005-07-02 19:24:10 +0000421 irbb = bb_to_IR ( guest_extents,
422 disInstrFn,
423 guest_bytes,
424 guest_bytes_addr,
425 chase_into_ok,
426 host_is_bigendian,
427 archinfo_guest,
sewardjdb4738a2005-07-07 01:32:16 +0000428 guest_word_type,
sewardjec3c8852005-07-07 09:56:24 +0000429 do_self_check,
sewardjdb4738a2005-07-07 01:32:16 +0000430 offB_TISTART,
431 offB_TILEN );
sewardjf13a16a2004-07-05 17:10:14 +0000432
sewardj2d6b14a2005-11-23 04:25:07 +0000433 vexAllocSanityCheck();
434
sewardjf13a16a2004-07-05 17:10:14 +0000435 if (irbb == NULL) {
436 /* Access failure. */
sewardj2d6b14a2005-11-23 04:25:07 +0000437 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000438 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000439 return VexTransAccessFail;
sewardjf13a16a2004-07-05 17:10:14 +0000440 }
sewardjaa59f942004-10-09 09:34:36 +0000441
sewardj72c72812005-01-19 11:49:45 +0000442 vassert(guest_extents->n_used >= 1 && guest_extents->n_used <= 3);
443 vassert(guest_extents->base[0] == guest_bytes_addr);
444 for (i = 0; i < guest_extents->n_used; i++) {
445 vassert(guest_extents->len[i] < 10000); /* sanity */
446 }
447
sewardjaa59f942004-10-09 09:34:36 +0000448 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000449 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj72c72812005-01-19 11:49:45 +0000450 if (guest_extents->n_used > 1) {
451 vex_printf("can't show code due to extents > 1\n");
452 } else {
453 /* HACK */
454 UChar* p = (UChar*)guest_bytes;
455 UInt guest_bytes_read = (UInt)guest_extents->len[0];
sewardjd9763622005-02-07 03:12:19 +0000456 vex_printf(". 0 %llx %u\n.", guest_bytes_addr, guest_bytes_read );
sewardj72c72812005-01-19 11:49:45 +0000457 for (i = 0; i < guest_bytes_read; i++)
sewardjaa59f942004-10-09 09:34:36 +0000458 vex_printf(" %02x", (Int)p[i] );
sewardj72c72812005-01-19 11:49:45 +0000459 vex_printf("\n\n");
460 }
sewardjaa59f942004-10-09 09:34:36 +0000461 }
462
463 /* Sanity check the initial IR. */
sewardjb9230752004-12-29 19:25:06 +0000464 sanityCheckIRBB( irbb, "initial IR",
465 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000466
sewardj2d6b14a2005-11-23 04:25:07 +0000467 vexAllocSanityCheck();
468
sewardjedf4d692004-08-17 13:52:58 +0000469 /* Clean it up, hopefully a lot. */
sewardj8d2291c2004-10-25 14:50:21 +0000470 irbb = do_iropt_BB ( irbb, specHelper, preciseMemExnsFn,
471 guest_bytes_addr );
sewardjb9230752004-12-29 19:25:06 +0000472 sanityCheckIRBB( irbb, "after initial iropt",
473 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000474
sewardjf48ac192004-10-29 00:41:29 +0000475 if (vex_traceflags & VEX_TRACE_OPT1) {
476 vex_printf("\n------------------------"
477 " After pre-instr IR optimisation "
478 "------------------------\n\n");
sewardjedf4d692004-08-17 13:52:58 +0000479 ppIRBB ( irbb );
480 vex_printf("\n");
481 }
482
sewardj2d6b14a2005-11-23 04:25:07 +0000483 vexAllocSanityCheck();
484
sewardjf13a16a2004-07-05 17:10:14 +0000485 /* Get the thing instrumented. */
sewardj49651f42004-10-28 22:11:04 +0000486 if (instrument1)
sewardj918c8f32005-03-21 00:54:33 +0000487 irbb = (*instrument1)(irbb, guest_layout,
sewardjf4611492005-10-18 12:01:48 +0000488 guest_bytes_addr_noredir, guest_extents,
489 guest_word_type, host_word_type);
sewardj2d6b14a2005-11-23 04:25:07 +0000490 vexAllocSanityCheck();
491
sewardj49651f42004-10-28 22:11:04 +0000492 if (instrument2)
sewardj918c8f32005-03-21 00:54:33 +0000493 irbb = (*instrument2)(irbb, guest_layout,
sewardjf4611492005-10-18 12:01:48 +0000494 guest_bytes_addr_noredir, guest_extents,
495 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000496
sewardjf48ac192004-10-29 00:41:29 +0000497 if (vex_traceflags & VEX_TRACE_INST) {
498 vex_printf("\n------------------------"
499 " After instrumentation "
500 "------------------------\n\n");
501 ppIRBB ( irbb );
502 vex_printf("\n");
503 }
504
sewardj49651f42004-10-28 22:11:04 +0000505 if (instrument1 || instrument2)
sewardjb9230752004-12-29 19:25:06 +0000506 sanityCheckIRBB( irbb, "after instrumentation",
507 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000508
sewardj9578a8b2004-11-04 19:44:48 +0000509 /* Do a post-instrumentation cleanup pass. */
510 if (cleanup_after_instrumentation) {
511 do_deadcode_BB( irbb );
512 irbb = cprop_BB( irbb );
513 do_deadcode_BB( irbb );
sewardjb9230752004-12-29 19:25:06 +0000514 sanityCheckIRBB( irbb, "after post-instrumentation cleanup",
515 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000516 }
517
sewardj2d6b14a2005-11-23 04:25:07 +0000518 vexAllocSanityCheck();
519
sewardj9578a8b2004-11-04 19:44:48 +0000520 if (vex_traceflags & VEX_TRACE_OPT2) {
521 vex_printf("\n------------------------"
522 " After post-instr IR optimisation "
523 "------------------------\n\n");
524 ppIRBB ( irbb );
525 vex_printf("\n");
526 }
527
sewardjf9517d02005-11-28 13:39:37 +0000528 /* Turn it into virtual-registerised code. Build trees -- this
529 also throws away any dead bindings. */
530 ado_treebuild_BB( irbb );
sewardjf48ac192004-10-29 00:41:29 +0000531
sewardj2d6b14a2005-11-23 04:25:07 +0000532 vexAllocSanityCheck();
533
sewardjf48ac192004-10-29 00:41:29 +0000534 if (vex_traceflags & VEX_TRACE_TREES) {
535 vex_printf("\n------------------------"
536 " After tree-building "
537 "------------------------\n\n");
538 ppIRBB ( irbb );
539 vex_printf("\n");
540 }
541
sewardje908c422005-02-04 21:18:16 +0000542 /* HACK */
cerion54560812005-02-03 13:40:49 +0000543 if (0) { *host_bytes_used = 0; return VexTransOK; }
sewardje908c422005-02-04 21:18:16 +0000544 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000545
sewardjf48ac192004-10-29 00:41:29 +0000546 if (vex_traceflags & VEX_TRACE_VCODE)
547 vex_printf("\n------------------------"
548 " Instruction selection "
549 "------------------------\n");
550
sewardj27e1dd62005-06-30 11:49:14 +0000551 vcode = iselBB ( irbb, archinfo_host );
sewardjf13a16a2004-07-05 17:10:14 +0000552
sewardj2d6b14a2005-11-23 04:25:07 +0000553 vexAllocSanityCheck();
554
sewardjf48ac192004-10-29 00:41:29 +0000555 if (vex_traceflags & VEX_TRACE_VCODE)
556 vex_printf("\n");
557
sewardjf48ac192004-10-29 00:41:29 +0000558 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000559 for (i = 0; i < vcode->arr_used; i++) {
560 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000561 ppInstr(vcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000562 vex_printf("\n");
563 }
sewardjfbcaf332004-07-08 01:46:01 +0000564 vex_printf("\n");
565 }
sewardjfbcaf332004-07-08 01:46:01 +0000566
sewardjf13a16a2004-07-05 17:10:14 +0000567 /* Register allocate. */
568 rcode = doRegisterAllocation ( vcode, available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000569 n_available_real_regs,
570 isMove, getRegUsage, mapRegs,
571 genSpill, genReload, guest_sizeB,
cerion92b64362005-12-13 12:02:26 +0000572 ppInstr, ppReg, mode64 );
sewardjf13a16a2004-07-05 17:10:14 +0000573
sewardj2d6b14a2005-11-23 04:25:07 +0000574 vexAllocSanityCheck();
575
sewardjf48ac192004-10-29 00:41:29 +0000576 if (vex_traceflags & VEX_TRACE_RCODE) {
577 vex_printf("\n------------------------"
578 " Register-allocated code "
579 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000580 for (i = 0; i < rcode->arr_used; i++) {
581 vex_printf("%3d ", i);
cerion92b64362005-12-13 12:02:26 +0000582 ppInstr(rcode->arr[i], mode64);
sewardj1f40a0a2004-07-21 12:28:07 +0000583 vex_printf("\n");
584 }
sewardjfbcaf332004-07-08 01:46:01 +0000585 vex_printf("\n");
586 }
sewardjfbcaf332004-07-08 01:46:01 +0000587
sewardje908c422005-02-04 21:18:16 +0000588 /* HACK */
589 if (0) { *host_bytes_used = 0; return VexTransOK; }
590 /* end HACK */
591
sewardj81bd5502004-07-21 18:49:27 +0000592 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000593 if (vex_traceflags & VEX_TRACE_ASM) {
594 vex_printf("\n------------------------"
595 " Assembly "
596 "------------------------\n\n");
597 }
598
sewardj81bd5502004-07-21 18:49:27 +0000599 out_used = 0; /* tracks along the host_bytes array */
600 for (i = 0; i < rcode->arr_used; i++) {
sewardjf48ac192004-10-29 00:41:29 +0000601 if (vex_traceflags & VEX_TRACE_ASM) {
cerion92b64362005-12-13 12:02:26 +0000602 ppInstr(rcode->arr[i], mode64);
sewardjbad34a92004-07-22 01:14:11 +0000603 vex_printf("\n");
604 }
cerion92b64362005-12-13 12:02:26 +0000605 j = (*emit)( insn_bytes, 32, rcode->arr[i], mode64 );
sewardjf48ac192004-10-29 00:41:29 +0000606 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000607 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000608 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000609 vex_printf("0%x ", (UInt)insn_bytes[k]);
610 else
611 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000612 vex_printf("\n\n");
613 }
sewardj81bd5502004-07-21 18:49:27 +0000614 if (out_used + j > host_bytes_size) {
sewardj2d6b14a2005-11-23 04:25:07 +0000615 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000616 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000617 return VexTransOutputFull;
sewardj81bd5502004-07-21 18:49:27 +0000618 }
619 for (k = 0; k < j; k++) {
620 host_bytes[out_used] = insn_bytes[k];
621 out_used++;
622 }
623 vassert(out_used <= host_bytes_size);
624 }
625 *host_bytes_used = out_used;
626
sewardj2d6b14a2005-11-23 04:25:07 +0000627 vexAllocSanityCheck();
628
629 vexSetAllocModeTEMP_and_clear();
sewardjf13a16a2004-07-05 17:10:14 +0000630
sewardjf48ac192004-10-29 00:41:29 +0000631 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000632 return VexTransOK;
sewardj35421a32004-07-05 13:12:34 +0000633}
634
635
sewardj893aada2004-11-29 19:57:54 +0000636/* --------- Emulation warnings. --------- */
637
638HChar* LibVEX_EmWarn_string ( VexEmWarn ew )
639{
640 switch (ew) {
641 case EmWarn_NONE:
642 return "none";
643 case EmWarn_X86_x87exns:
644 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000645 case EmWarn_X86_x87precision:
646 return "Selection of non-80-bit x87 FP precision";
647 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +0000648 return "Unmasking SSE FP exceptions";
649 case EmWarn_X86_fz:
650 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
651 case EmWarn_X86_daz:
652 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +0000653 case EmWarn_X86_acFlag:
654 return "Setting %eflags.ac (setting noted but ignored)";
cerion094d1392005-06-20 13:45:57 +0000655 case EmWarn_PPC32exns:
656 return "Unmasking PPC32 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000657 default:
658 vpanic("LibVEX_EmWarn_string: unknown warning");
659 }
660}
sewardj35421a32004-07-05 13:12:34 +0000661
sewardj27e1dd62005-06-30 11:49:14 +0000662/* --------- Arch/Subarch stuff. --------- */
sewardjbef170b2004-12-21 01:23:00 +0000663
664const HChar* LibVEX_ppVexArch ( VexArch arch )
665{
666 switch (arch) {
667 case VexArch_INVALID: return "INVALID";
668 case VexArchX86: return "X86";
669 case VexArchAMD64: return "AMD64";
670 case VexArchARM: return "ARM";
sewardj0ec57c52005-02-01 15:24:10 +0000671 case VexArchPPC32: return "PPC32";
sewardjbef170b2004-12-21 01:23:00 +0000672 default: return "VexArch???";
673 }
674}
675
676const HChar* LibVEX_ppVexSubArch ( VexSubArch subarch )
677{
678 switch (subarch) {
sewardj0ec57c52005-02-01 15:24:10 +0000679 case VexSubArch_INVALID: return "INVALID";
680 case VexSubArch_NONE: return "NONE";
681 case VexSubArchX86_sse0: return "x86-sse0";
682 case VexSubArchX86_sse1: return "x86-sse1";
683 case VexSubArchX86_sse2: return "x86-sse2";
684 case VexSubArchARM_v4: return "arm-v4";
sewardj059601a2005-11-13 00:53:05 +0000685 case VexSubArchPPC32_I: return "ppc32-int-only";
686 case VexSubArchPPC32_FI: return "ppc32-int-and-fp";
687 case VexSubArchPPC32_VFI: return "ppc32-int-fp-and-AV";
sewardj0ec57c52005-02-01 15:24:10 +0000688 default: return "VexSubArch???";
sewardjbef170b2004-12-21 01:23:00 +0000689 }
690}
691
sewardj27e1dd62005-06-30 11:49:14 +0000692/* Write default settings info *vai. */
693void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
694{
695 vai->subarch = VexSubArch_INVALID;
696 vai->ppc32_cache_line_szB = 0;
697}
698
699
sewardj35421a32004-07-05 13:12:34 +0000700/*---------------------------------------------------------------*/
sewardjc0ee2ed2004-07-27 10:29:41 +0000701/*--- end main/vex_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +0000702/*---------------------------------------------------------------*/