blob: 26cdcc2f08feb10519aafdf875c7c16c983b0e1a [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;
sewardj443cd9d2004-07-18 23:06:45 +0000218 Bool (*isMove) (HInstr*, HReg*, HReg*);
219 void (*getRegUsage) (HRegUsage*, HInstr*);
220 void (*mapRegs) (HRegRemap*, HInstr*);
221 HInstr* (*genSpill) ( HReg, Int );
222 HInstr* (*genReload) ( HReg, Int );
223 void (*ppInstr) ( HInstr* );
224 void (*ppReg) ( HReg );
sewardj27e1dd62005-06-30 11:49:14 +0000225 HInstrArray* (*iselBB) ( IRBB*, VexArchInfo* );
sewardj81bd5502004-07-21 18:49:27 +0000226 Int (*emit) ( UChar*, Int, HInstr* );
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;
sewardjf13a16a2004-07-05 17:10:14 +0000242
sewardj49651f42004-10-28 22:11:04 +0000243 guest_layout = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000244 available_real_regs = NULL;
245 n_available_real_regs = 0;
246 isMove = NULL;
247 getRegUsage = NULL;
248 mapRegs = NULL;
249 genSpill = NULL;
250 genReload = NULL;
251 ppInstr = NULL;
252 ppReg = NULL;
253 iselBB = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000254 emit = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000255 specHelper = NULL;
sewardj8d2291c2004-10-25 14:50:21 +0000256 preciseMemExnsFn = NULL;
sewardj9e6491a2005-07-02 19:24:10 +0000257 disInstrFn = NULL;
sewardjcf787902004-11-03 09:08:33 +0000258 guest_word_type = Ity_INVALID;
259 host_word_type = Ity_INVALID;
sewardjdb4738a2005-07-07 01:32:16 +0000260 offB_TISTART = 0;
261 offB_TILEN = 0;
sewardj36ca5132004-07-24 13:12:23 +0000262
sewardjf48ac192004-10-29 00:41:29 +0000263 vex_traceflags = traceflags;
sewardj58800ff2004-07-28 01:51:10 +0000264
sewardj35421a32004-07-05 13:12:34 +0000265 vassert(vex_initdone);
sewardj2d6b14a2005-11-23 04:25:07 +0000266 vexSetAllocModeTEMP_and_clear();
267 vexAllocSanityCheck();
sewardj2a9ad022004-11-25 02:46:58 +0000268
sewardjf13a16a2004-07-05 17:10:14 +0000269 /* First off, check that the guest and host insn sets
270 are supported. */
sewardj2a9ad022004-11-25 02:46:58 +0000271
sewardjbef170b2004-12-21 01:23:00 +0000272 switch (arch_host) {
sewardj2a9ad022004-11-25 02:46:58 +0000273
sewardjbef170b2004-12-21 01:23:00 +0000274 case VexArchX86:
sewardjf13a16a2004-07-05 17:10:14 +0000275 getAllocableRegs_X86 ( &n_available_real_regs,
276 &available_real_regs );
277 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
278 getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_X86Instr;
279 mapRegs = (void(*)(HRegRemap*,HInstr*)) mapRegs_X86Instr;
280 genSpill = (HInstr*(*)(HReg,Int)) genSpill_X86;
281 genReload = (HInstr*(*)(HReg,Int)) genReload_X86;
sewardj2b515872004-07-05 20:50:45 +0000282 ppInstr = (void(*)(HInstr*)) ppX86Instr;
283 ppReg = (void(*)(HReg)) ppHRegX86;
sewardjf13a16a2004-07-05 17:10:14 +0000284 iselBB = iselBB_X86;
sewardj81bd5502004-07-21 18:49:27 +0000285 emit = (Int(*)(UChar*,Int,HInstr*)) emit_X86Instr;
sewardj72c72812005-01-19 11:49:45 +0000286 host_is_bigendian = False;
sewardjcf787902004-11-03 09:08:33 +0000287 host_word_type = Ity_I32;
sewardj27e1dd62005-06-30 11:49:14 +0000288 vassert(archinfo_host->subarch == VexSubArchX86_sse0
289 || archinfo_host->subarch == VexSubArchX86_sse1
290 || archinfo_host->subarch == VexSubArchX86_sse2);
sewardjf13a16a2004-07-05 17:10:14 +0000291 break;
sewardj2a9ad022004-11-25 02:46:58 +0000292
sewardjc33671d2005-02-01 20:30:00 +0000293 case VexArchAMD64:
294 getAllocableRegs_AMD64 ( &n_available_real_regs,
295 &available_real_regs );
296 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr;
297 getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_AMD64Instr;
298 mapRegs = (void(*)(HRegRemap*,HInstr*)) mapRegs_AMD64Instr;
299 genSpill = (HInstr*(*)(HReg,Int)) genSpill_AMD64;
300 genReload = (HInstr*(*)(HReg,Int)) genReload_AMD64;
301 ppInstr = (void(*)(HInstr*)) ppAMD64Instr;
302 ppReg = (void(*)(HReg)) ppHRegAMD64;
303 iselBB = iselBB_AMD64;
304 emit = (Int(*)(UChar*,Int,HInstr*)) emit_AMD64Instr;
305 host_is_bigendian = False;
306 host_word_type = Ity_I64;
sewardj27e1dd62005-06-30 11:49:14 +0000307 vassert(archinfo_host->subarch == VexSubArch_NONE);
sewardjc33671d2005-02-01 20:30:00 +0000308 break;
309
cerion487e4c92005-02-04 16:28:19 +0000310 case VexArchPPC32:
311 getAllocableRegs_PPC32 ( &n_available_real_regs,
312 &available_real_regs );
313 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPC32Instr;
314 getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_PPC32Instr;
315 mapRegs = (void(*)(HRegRemap*,HInstr*)) mapRegs_PPC32Instr;
316 genSpill = (HInstr*(*)(HReg,Int)) genSpill_PPC32;
317 genReload = (HInstr*(*)(HReg,Int)) genReload_PPC32;
318 ppInstr = (void(*)(HInstr*)) ppPPC32Instr;
319 ppReg = (void(*)(HReg)) ppHRegPPC32;
320 iselBB = iselBB_PPC32;
321 emit = (Int(*)(UChar*,Int,HInstr*)) emit_PPC32Instr;
322 host_is_bigendian = True;
323 host_word_type = Ity_I32;
sewardj059601a2005-11-13 00:53:05 +0000324 vassert(archinfo_guest->subarch == VexSubArchPPC32_I
325 || archinfo_guest->subarch == VexSubArchPPC32_FI
326 || archinfo_guest->subarch == VexSubArchPPC32_VFI);
cerion487e4c92005-02-04 16:28:19 +0000327 break;
328
sewardjf13a16a2004-07-05 17:10:14 +0000329 default:
sewardj887a11a2004-07-05 17:26:47 +0000330 vpanic("LibVEX_Translate: unsupported target insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000331 }
332
sewardj2a9ad022004-11-25 02:46:58 +0000333
sewardjbef170b2004-12-21 01:23:00 +0000334 switch (arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000335
sewardjbef170b2004-12-21 01:23:00 +0000336 case VexArchX86:
sewardj8d2291c2004-10-25 14:50:21 +0000337 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000338 disInstrFn = disInstr_X86;
sewardj2a9ad022004-11-25 02:46:58 +0000339 specHelper = guest_x86_spechelper;
sewardj81ec4182004-10-25 23:15:52 +0000340 guest_sizeB = sizeof(VexGuestX86State);
sewardjcf787902004-11-03 09:08:33 +0000341 guest_word_type = Ity_I32;
sewardj49651f42004-10-28 22:11:04 +0000342 guest_layout = &x86guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000343 offB_TISTART = offsetof(VexGuestX86State,guest_TISTART);
344 offB_TILEN = offsetof(VexGuestX86State,guest_TILEN);
sewardj27e1dd62005-06-30 11:49:14 +0000345 vassert(archinfo_guest->subarch == VexSubArchX86_sse0
346 || archinfo_guest->subarch == VexSubArchX86_sse1
347 || archinfo_guest->subarch == VexSubArchX86_sse2);
sewardje74f6f72005-08-05 02:55:36 +0000348 vassert(0 == sizeof(VexGuestX86State) % 8);
sewardjdb4738a2005-07-07 01:32:16 +0000349 vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART ) == 4);
350 vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000351 break;
sewardj2a9ad022004-11-25 02:46:58 +0000352
sewardj44d494d2005-01-20 20:26:33 +0000353 case VexArchAMD64:
354 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000355 disInstrFn = disInstr_AMD64;
sewardj44d494d2005-01-20 20:26:33 +0000356 specHelper = guest_amd64_spechelper;
357 guest_sizeB = sizeof(VexGuestAMD64State);
358 guest_word_type = Ity_I64;
359 guest_layout = &amd64guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000360 offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART);
361 offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN);
sewardj27e1dd62005-06-30 11:49:14 +0000362 vassert(archinfo_guest->subarch == VexSubArch_NONE);
sewardje74f6f72005-08-05 02:55:36 +0000363 vassert(0 == sizeof(VexGuestAMD64State) % 8);
sewardjdb4738a2005-07-07 01:32:16 +0000364 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8);
365 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000366 break;
367
sewardjbef170b2004-12-21 01:23:00 +0000368 case VexArchARM:
sewardj2a9ad022004-11-25 02:46:58 +0000369 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000370 disInstrFn = NULL; /* HACK */
sewardj2a9ad022004-11-25 02:46:58 +0000371 specHelper = guest_arm_spechelper;
372 guest_sizeB = sizeof(VexGuestARMState);
373 guest_word_type = Ity_I32;
374 guest_layout = &armGuest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000375 offB_TISTART = 0; /* hack ... arm has bitrot */
376 offB_TILEN = 0; /* hack ... arm has bitrot */
sewardj27e1dd62005-06-30 11:49:14 +0000377 vassert(archinfo_guest->subarch == VexSubArchARM_v4);
sewardj2a9ad022004-11-25 02:46:58 +0000378 break;
379
cerionaabdfbf2005-01-29 12:56:15 +0000380 case VexArchPPC32:
381 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000382 disInstrFn = disInstr_PPC32;
cerionaabdfbf2005-01-29 12:56:15 +0000383 specHelper = guest_ppc32_spechelper;
384 guest_sizeB = sizeof(VexGuestPPC32State);
385 guest_word_type = Ity_I32;
386 guest_layout = &ppc32Guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000387 offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART);
388 offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN);
sewardj059601a2005-11-13 00:53:05 +0000389 vassert(archinfo_guest->subarch == VexSubArchPPC32_I
390 || archinfo_guest->subarch == VexSubArchPPC32_FI
391 || archinfo_guest->subarch == VexSubArchPPC32_VFI);
sewardje74f6f72005-08-05 02:55:36 +0000392 vassert(0 == sizeof(VexGuestPPC32State) % 8);
sewardjdb4738a2005-07-07 01:32:16 +0000393 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4);
394 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000395 break;
396
sewardjf13a16a2004-07-05 17:10:14 +0000397 default:
sewardj887a11a2004-07-05 17:26:47 +0000398 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000399 }
400
sewardj9df271d2004-12-31 22:37:42 +0000401 /* yet more sanity checks ... */
sewardj0ec57c52005-02-01 15:24:10 +0000402 if (arch_guest == arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000403 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000404 we are simulating one flavour of an architecture a different
405 flavour of the same architecture, which is pretty strange. */
sewardj27e1dd62005-06-30 11:49:14 +0000406 vassert(archinfo_guest->subarch == archinfo_host->subarch);
sewardj9df271d2004-12-31 22:37:42 +0000407 }
sewardj2a9ad022004-11-25 02:46:58 +0000408
sewardj2d6b14a2005-11-23 04:25:07 +0000409 vexAllocSanityCheck();
410
sewardjf48ac192004-10-29 00:41:29 +0000411 if (vex_traceflags & VEX_TRACE_FE)
412 vex_printf("\n------------------------"
413 " Front end "
414 "------------------------\n\n");
415
sewardj9e6491a2005-07-02 19:24:10 +0000416 irbb = bb_to_IR ( guest_extents,
417 disInstrFn,
418 guest_bytes,
419 guest_bytes_addr,
420 chase_into_ok,
421 host_is_bigendian,
422 archinfo_guest,
sewardjdb4738a2005-07-07 01:32:16 +0000423 guest_word_type,
sewardjec3c8852005-07-07 09:56:24 +0000424 do_self_check,
sewardjdb4738a2005-07-07 01:32:16 +0000425 offB_TISTART,
426 offB_TILEN );
sewardjf13a16a2004-07-05 17:10:14 +0000427
sewardj2d6b14a2005-11-23 04:25:07 +0000428 vexAllocSanityCheck();
429
sewardjf13a16a2004-07-05 17:10:14 +0000430 if (irbb == NULL) {
431 /* Access failure. */
sewardj2d6b14a2005-11-23 04:25:07 +0000432 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000433 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000434 return VexTransAccessFail;
sewardjf13a16a2004-07-05 17:10:14 +0000435 }
sewardjaa59f942004-10-09 09:34:36 +0000436
sewardj72c72812005-01-19 11:49:45 +0000437 vassert(guest_extents->n_used >= 1 && guest_extents->n_used <= 3);
438 vassert(guest_extents->base[0] == guest_bytes_addr);
439 for (i = 0; i < guest_extents->n_used; i++) {
440 vassert(guest_extents->len[i] < 10000); /* sanity */
441 }
442
sewardjaa59f942004-10-09 09:34:36 +0000443 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000444 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj72c72812005-01-19 11:49:45 +0000445 if (guest_extents->n_used > 1) {
446 vex_printf("can't show code due to extents > 1\n");
447 } else {
448 /* HACK */
449 UChar* p = (UChar*)guest_bytes;
450 UInt guest_bytes_read = (UInt)guest_extents->len[0];
sewardjd9763622005-02-07 03:12:19 +0000451 vex_printf(". 0 %llx %u\n.", guest_bytes_addr, guest_bytes_read );
sewardj72c72812005-01-19 11:49:45 +0000452 for (i = 0; i < guest_bytes_read; i++)
sewardjaa59f942004-10-09 09:34:36 +0000453 vex_printf(" %02x", (Int)p[i] );
sewardj72c72812005-01-19 11:49:45 +0000454 vex_printf("\n\n");
455 }
sewardjaa59f942004-10-09 09:34:36 +0000456 }
457
458 /* Sanity check the initial IR. */
sewardjb9230752004-12-29 19:25:06 +0000459 sanityCheckIRBB( irbb, "initial IR",
460 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000461
sewardj2d6b14a2005-11-23 04:25:07 +0000462 vexAllocSanityCheck();
463
sewardjedf4d692004-08-17 13:52:58 +0000464 /* Clean it up, hopefully a lot. */
sewardj8d2291c2004-10-25 14:50:21 +0000465 irbb = do_iropt_BB ( irbb, specHelper, preciseMemExnsFn,
466 guest_bytes_addr );
sewardjb9230752004-12-29 19:25:06 +0000467 sanityCheckIRBB( irbb, "after initial iropt",
468 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000469
sewardjf48ac192004-10-29 00:41:29 +0000470 if (vex_traceflags & VEX_TRACE_OPT1) {
471 vex_printf("\n------------------------"
472 " After pre-instr IR optimisation "
473 "------------------------\n\n");
sewardjedf4d692004-08-17 13:52:58 +0000474 ppIRBB ( irbb );
475 vex_printf("\n");
476 }
477
sewardj2d6b14a2005-11-23 04:25:07 +0000478 vexAllocSanityCheck();
479
sewardjf13a16a2004-07-05 17:10:14 +0000480 /* Get the thing instrumented. */
sewardj49651f42004-10-28 22:11:04 +0000481 if (instrument1)
sewardj918c8f32005-03-21 00:54:33 +0000482 irbb = (*instrument1)(irbb, guest_layout,
sewardjf4611492005-10-18 12:01:48 +0000483 guest_bytes_addr_noredir, guest_extents,
484 guest_word_type, host_word_type);
sewardj2d6b14a2005-11-23 04:25:07 +0000485 vexAllocSanityCheck();
486
sewardj49651f42004-10-28 22:11:04 +0000487 if (instrument2)
sewardj918c8f32005-03-21 00:54:33 +0000488 irbb = (*instrument2)(irbb, guest_layout,
sewardjf4611492005-10-18 12:01:48 +0000489 guest_bytes_addr_noredir, guest_extents,
490 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000491
sewardjf48ac192004-10-29 00:41:29 +0000492 if (vex_traceflags & VEX_TRACE_INST) {
493 vex_printf("\n------------------------"
494 " After instrumentation "
495 "------------------------\n\n");
496 ppIRBB ( irbb );
497 vex_printf("\n");
498 }
499
sewardj49651f42004-10-28 22:11:04 +0000500 if (instrument1 || instrument2)
sewardjb9230752004-12-29 19:25:06 +0000501 sanityCheckIRBB( irbb, "after instrumentation",
502 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000503
sewardj9578a8b2004-11-04 19:44:48 +0000504 /* Do a post-instrumentation cleanup pass. */
505 if (cleanup_after_instrumentation) {
506 do_deadcode_BB( irbb );
507 irbb = cprop_BB( irbb );
508 do_deadcode_BB( irbb );
sewardjb9230752004-12-29 19:25:06 +0000509 sanityCheckIRBB( irbb, "after post-instrumentation cleanup",
510 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000511 }
512
sewardj2d6b14a2005-11-23 04:25:07 +0000513 vexAllocSanityCheck();
514
sewardj9578a8b2004-11-04 19:44:48 +0000515 if (vex_traceflags & VEX_TRACE_OPT2) {
516 vex_printf("\n------------------------"
517 " After post-instr IR optimisation "
518 "------------------------\n\n");
519 ppIRBB ( irbb );
520 vex_printf("\n");
521 }
522
sewardjf13a16a2004-07-05 17:10:14 +0000523 /* Turn it into virtual-registerised code. */
sewardj49651f42004-10-28 22:11:04 +0000524 do_deadcode_BB( irbb );
525 do_treebuild_BB( irbb );
sewardjf48ac192004-10-29 00:41:29 +0000526
sewardj2d6b14a2005-11-23 04:25:07 +0000527 vexAllocSanityCheck();
528
sewardjf48ac192004-10-29 00:41:29 +0000529 if (vex_traceflags & VEX_TRACE_TREES) {
530 vex_printf("\n------------------------"
531 " After tree-building "
532 "------------------------\n\n");
533 ppIRBB ( irbb );
534 vex_printf("\n");
535 }
536
sewardje908c422005-02-04 21:18:16 +0000537 /* HACK */
cerion54560812005-02-03 13:40:49 +0000538 if (0) { *host_bytes_used = 0; return VexTransOK; }
sewardje908c422005-02-04 21:18:16 +0000539 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000540
sewardjf48ac192004-10-29 00:41:29 +0000541 if (vex_traceflags & VEX_TRACE_VCODE)
542 vex_printf("\n------------------------"
543 " Instruction selection "
544 "------------------------\n");
545
sewardj27e1dd62005-06-30 11:49:14 +0000546 vcode = iselBB ( irbb, archinfo_host );
sewardjf13a16a2004-07-05 17:10:14 +0000547
sewardj2d6b14a2005-11-23 04:25:07 +0000548 vexAllocSanityCheck();
549
sewardjf48ac192004-10-29 00:41:29 +0000550 if (vex_traceflags & VEX_TRACE_VCODE)
551 vex_printf("\n");
552
sewardjf48ac192004-10-29 00:41:29 +0000553 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000554 for (i = 0; i < vcode->arr_used; i++) {
555 vex_printf("%3d ", i);
556 ppInstr(vcode->arr[i]);
557 vex_printf("\n");
558 }
sewardjfbcaf332004-07-08 01:46:01 +0000559 vex_printf("\n");
560 }
sewardjfbcaf332004-07-08 01:46:01 +0000561
sewardjf13a16a2004-07-05 17:10:14 +0000562 /* Register allocate. */
563 rcode = doRegisterAllocation ( vcode, available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000564 n_available_real_regs,
565 isMove, getRegUsage, mapRegs,
566 genSpill, genReload, guest_sizeB,
567 ppInstr, ppReg );
sewardjf13a16a2004-07-05 17:10:14 +0000568
sewardj2d6b14a2005-11-23 04:25:07 +0000569 vexAllocSanityCheck();
570
sewardjf48ac192004-10-29 00:41:29 +0000571 if (vex_traceflags & VEX_TRACE_RCODE) {
572 vex_printf("\n------------------------"
573 " Register-allocated code "
574 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000575 for (i = 0; i < rcode->arr_used; i++) {
576 vex_printf("%3d ", i);
577 ppInstr(rcode->arr[i]);
578 vex_printf("\n");
579 }
sewardjfbcaf332004-07-08 01:46:01 +0000580 vex_printf("\n");
581 }
sewardjfbcaf332004-07-08 01:46:01 +0000582
sewardje908c422005-02-04 21:18:16 +0000583 /* HACK */
584 if (0) { *host_bytes_used = 0; return VexTransOK; }
585 /* end HACK */
586
sewardj81bd5502004-07-21 18:49:27 +0000587 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000588 if (vex_traceflags & VEX_TRACE_ASM) {
589 vex_printf("\n------------------------"
590 " Assembly "
591 "------------------------\n\n");
592 }
593
sewardj81bd5502004-07-21 18:49:27 +0000594 out_used = 0; /* tracks along the host_bytes array */
595 for (i = 0; i < rcode->arr_used; i++) {
sewardjf48ac192004-10-29 00:41:29 +0000596 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000597 ppInstr(rcode->arr[i]);
598 vex_printf("\n");
599 }
sewardj81bd5502004-07-21 18:49:27 +0000600 j = (*emit)( insn_bytes, 32, rcode->arr[i] );
sewardjf48ac192004-10-29 00:41:29 +0000601 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000602 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000603 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000604 vex_printf("0%x ", (UInt)insn_bytes[k]);
605 else
606 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000607 vex_printf("\n\n");
608 }
sewardj81bd5502004-07-21 18:49:27 +0000609 if (out_used + j > host_bytes_size) {
sewardj2d6b14a2005-11-23 04:25:07 +0000610 vexSetAllocModeTEMP_and_clear();
sewardjf48ac192004-10-29 00:41:29 +0000611 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000612 return VexTransOutputFull;
sewardj81bd5502004-07-21 18:49:27 +0000613 }
614 for (k = 0; k < j; k++) {
615 host_bytes[out_used] = insn_bytes[k];
616 out_used++;
617 }
618 vassert(out_used <= host_bytes_size);
619 }
620 *host_bytes_used = out_used;
621
sewardj2d6b14a2005-11-23 04:25:07 +0000622 vexAllocSanityCheck();
623
624 vexSetAllocModeTEMP_and_clear();
sewardjf13a16a2004-07-05 17:10:14 +0000625
sewardjf48ac192004-10-29 00:41:29 +0000626 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000627 return VexTransOK;
sewardj35421a32004-07-05 13:12:34 +0000628}
629
630
sewardj893aada2004-11-29 19:57:54 +0000631/* --------- Emulation warnings. --------- */
632
633HChar* LibVEX_EmWarn_string ( VexEmWarn ew )
634{
635 switch (ew) {
636 case EmWarn_NONE:
637 return "none";
638 case EmWarn_X86_x87exns:
639 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000640 case EmWarn_X86_x87precision:
641 return "Selection of non-80-bit x87 FP precision";
642 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +0000643 return "Unmasking SSE FP exceptions";
644 case EmWarn_X86_fz:
645 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
646 case EmWarn_X86_daz:
647 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +0000648 case EmWarn_X86_acFlag:
649 return "Setting %eflags.ac (setting noted but ignored)";
cerion094d1392005-06-20 13:45:57 +0000650 case EmWarn_PPC32exns:
651 return "Unmasking PPC32 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000652 default:
653 vpanic("LibVEX_EmWarn_string: unknown warning");
654 }
655}
sewardj35421a32004-07-05 13:12:34 +0000656
sewardj27e1dd62005-06-30 11:49:14 +0000657/* --------- Arch/Subarch stuff. --------- */
sewardjbef170b2004-12-21 01:23:00 +0000658
659const HChar* LibVEX_ppVexArch ( VexArch arch )
660{
661 switch (arch) {
662 case VexArch_INVALID: return "INVALID";
663 case VexArchX86: return "X86";
664 case VexArchAMD64: return "AMD64";
665 case VexArchARM: return "ARM";
sewardj0ec57c52005-02-01 15:24:10 +0000666 case VexArchPPC32: return "PPC32";
sewardjbef170b2004-12-21 01:23:00 +0000667 default: return "VexArch???";
668 }
669}
670
671const HChar* LibVEX_ppVexSubArch ( VexSubArch subarch )
672{
673 switch (subarch) {
sewardj0ec57c52005-02-01 15:24:10 +0000674 case VexSubArch_INVALID: return "INVALID";
675 case VexSubArch_NONE: return "NONE";
676 case VexSubArchX86_sse0: return "x86-sse0";
677 case VexSubArchX86_sse1: return "x86-sse1";
678 case VexSubArchX86_sse2: return "x86-sse2";
679 case VexSubArchARM_v4: return "arm-v4";
sewardj059601a2005-11-13 00:53:05 +0000680 case VexSubArchPPC32_I: return "ppc32-int-only";
681 case VexSubArchPPC32_FI: return "ppc32-int-and-fp";
682 case VexSubArchPPC32_VFI: return "ppc32-int-fp-and-AV";
sewardj0ec57c52005-02-01 15:24:10 +0000683 default: return "VexSubArch???";
sewardjbef170b2004-12-21 01:23:00 +0000684 }
685}
686
sewardj27e1dd62005-06-30 11:49:14 +0000687/* Write default settings info *vai. */
688void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
689{
690 vai->subarch = VexSubArch_INVALID;
691 vai->ppc32_cache_line_szB = 0;
692}
693
694
sewardj35421a32004-07-05 13:12:34 +0000695/*---------------------------------------------------------------*/
sewardjc0ee2ed2004-07-27 10:29:41 +0000696/*--- end main/vex_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +0000697/*---------------------------------------------------------------*/