blob: 7c97e76227525a76957da48e22d57b66483edd78 [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);
sewardjd887b862005-01-17 18:34:34 +0000266 vexClearTEMP();
sewardjf13a16a2004-07-05 17:10:14 +0000267
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;
sewardj27e1dd62005-06-30 11:49:14 +0000324 vassert(archinfo_guest->subarch == VexSubArchPPC32_noAV
325 || archinfo_guest->subarch == VexSubArchPPC32_AV);
cerion487e4c92005-02-04 16:28:19 +0000326 break;
327
sewardjf13a16a2004-07-05 17:10:14 +0000328 default:
sewardj887a11a2004-07-05 17:26:47 +0000329 vpanic("LibVEX_Translate: unsupported target insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000330 }
331
sewardj2a9ad022004-11-25 02:46:58 +0000332
sewardjbef170b2004-12-21 01:23:00 +0000333 switch (arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000334
sewardjbef170b2004-12-21 01:23:00 +0000335 case VexArchX86:
sewardj8d2291c2004-10-25 14:50:21 +0000336 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000337 disInstrFn = disInstr_X86;
sewardj2a9ad022004-11-25 02:46:58 +0000338 specHelper = guest_x86_spechelper;
sewardj81ec4182004-10-25 23:15:52 +0000339 guest_sizeB = sizeof(VexGuestX86State);
sewardjcf787902004-11-03 09:08:33 +0000340 guest_word_type = Ity_I32;
sewardj49651f42004-10-28 22:11:04 +0000341 guest_layout = &x86guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000342 offB_TISTART = offsetof(VexGuestX86State,guest_TISTART);
343 offB_TILEN = offsetof(VexGuestX86State,guest_TILEN);
sewardj27e1dd62005-06-30 11:49:14 +0000344 vassert(archinfo_guest->subarch == VexSubArchX86_sse0
345 || archinfo_guest->subarch == VexSubArchX86_sse1
346 || archinfo_guest->subarch == VexSubArchX86_sse2);
sewardje74f6f72005-08-05 02:55:36 +0000347 vassert(0 == sizeof(VexGuestX86State) % 8);
sewardjdb4738a2005-07-07 01:32:16 +0000348 vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART ) == 4);
349 vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000350 break;
sewardj2a9ad022004-11-25 02:46:58 +0000351
sewardj44d494d2005-01-20 20:26:33 +0000352 case VexArchAMD64:
353 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000354 disInstrFn = disInstr_AMD64;
sewardj44d494d2005-01-20 20:26:33 +0000355 specHelper = guest_amd64_spechelper;
356 guest_sizeB = sizeof(VexGuestAMD64State);
357 guest_word_type = Ity_I64;
358 guest_layout = &amd64guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000359 offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART);
360 offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN);
sewardj27e1dd62005-06-30 11:49:14 +0000361 vassert(archinfo_guest->subarch == VexSubArch_NONE);
sewardje74f6f72005-08-05 02:55:36 +0000362 vassert(0 == sizeof(VexGuestAMD64State) % 8);
sewardjdb4738a2005-07-07 01:32:16 +0000363 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8);
364 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000365 break;
366
sewardjbef170b2004-12-21 01:23:00 +0000367 case VexArchARM:
sewardj2a9ad022004-11-25 02:46:58 +0000368 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000369 disInstrFn = NULL; /* HACK */
sewardj2a9ad022004-11-25 02:46:58 +0000370 specHelper = guest_arm_spechelper;
371 guest_sizeB = sizeof(VexGuestARMState);
372 guest_word_type = Ity_I32;
373 guest_layout = &armGuest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000374 offB_TISTART = 0; /* hack ... arm has bitrot */
375 offB_TILEN = 0; /* hack ... arm has bitrot */
sewardj27e1dd62005-06-30 11:49:14 +0000376 vassert(archinfo_guest->subarch == VexSubArchARM_v4);
sewardj2a9ad022004-11-25 02:46:58 +0000377 break;
378
cerionaabdfbf2005-01-29 12:56:15 +0000379 case VexArchPPC32:
380 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000381 disInstrFn = disInstr_PPC32;
cerionaabdfbf2005-01-29 12:56:15 +0000382 specHelper = guest_ppc32_spechelper;
383 guest_sizeB = sizeof(VexGuestPPC32State);
384 guest_word_type = Ity_I32;
385 guest_layout = &ppc32Guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000386 offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART);
387 offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN);
sewardj27e1dd62005-06-30 11:49:14 +0000388 vassert(archinfo_guest->subarch == VexSubArchPPC32_noAV
389 || archinfo_guest->subarch == VexSubArchPPC32_AV);
sewardje74f6f72005-08-05 02:55:36 +0000390 vassert(0 == sizeof(VexGuestPPC32State) % 8);
sewardjdb4738a2005-07-07 01:32:16 +0000391 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4);
392 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000393 break;
394
sewardjf13a16a2004-07-05 17:10:14 +0000395 default:
sewardj887a11a2004-07-05 17:26:47 +0000396 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000397 }
398
sewardj9df271d2004-12-31 22:37:42 +0000399 /* yet more sanity checks ... */
sewardj0ec57c52005-02-01 15:24:10 +0000400 if (arch_guest == arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000401 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000402 we are simulating one flavour of an architecture a different
403 flavour of the same architecture, which is pretty strange. */
sewardj27e1dd62005-06-30 11:49:14 +0000404 vassert(archinfo_guest->subarch == archinfo_host->subarch);
sewardj9df271d2004-12-31 22:37:42 +0000405 }
sewardj2a9ad022004-11-25 02:46:58 +0000406
sewardjf48ac192004-10-29 00:41:29 +0000407 if (vex_traceflags & VEX_TRACE_FE)
408 vex_printf("\n------------------------"
409 " Front end "
410 "------------------------\n\n");
411
sewardj9e6491a2005-07-02 19:24:10 +0000412 irbb = bb_to_IR ( guest_extents,
413 disInstrFn,
414 guest_bytes,
415 guest_bytes_addr,
416 chase_into_ok,
417 host_is_bigendian,
418 archinfo_guest,
sewardjdb4738a2005-07-07 01:32:16 +0000419 guest_word_type,
sewardjec3c8852005-07-07 09:56:24 +0000420 do_self_check,
sewardjdb4738a2005-07-07 01:32:16 +0000421 offB_TISTART,
422 offB_TILEN );
sewardjf13a16a2004-07-05 17:10:14 +0000423
424 if (irbb == NULL) {
425 /* Access failure. */
sewardjd887b862005-01-17 18:34:34 +0000426 vexClearTEMP();
sewardjf48ac192004-10-29 00:41:29 +0000427 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000428 return VexTransAccessFail;
sewardjf13a16a2004-07-05 17:10:14 +0000429 }
sewardjaa59f942004-10-09 09:34:36 +0000430
sewardj72c72812005-01-19 11:49:45 +0000431 vassert(guest_extents->n_used >= 1 && guest_extents->n_used <= 3);
432 vassert(guest_extents->base[0] == guest_bytes_addr);
433 for (i = 0; i < guest_extents->n_used; i++) {
434 vassert(guest_extents->len[i] < 10000); /* sanity */
435 }
436
sewardjaa59f942004-10-09 09:34:36 +0000437 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000438 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj72c72812005-01-19 11:49:45 +0000439 if (guest_extents->n_used > 1) {
440 vex_printf("can't show code due to extents > 1\n");
441 } else {
442 /* HACK */
443 UChar* p = (UChar*)guest_bytes;
444 UInt guest_bytes_read = (UInt)guest_extents->len[0];
sewardjd9763622005-02-07 03:12:19 +0000445 vex_printf(". 0 %llx %u\n.", guest_bytes_addr, guest_bytes_read );
sewardj72c72812005-01-19 11:49:45 +0000446 for (i = 0; i < guest_bytes_read; i++)
sewardjaa59f942004-10-09 09:34:36 +0000447 vex_printf(" %02x", (Int)p[i] );
sewardj72c72812005-01-19 11:49:45 +0000448 vex_printf("\n\n");
449 }
sewardjaa59f942004-10-09 09:34:36 +0000450 }
451
452 /* Sanity check the initial IR. */
sewardjb9230752004-12-29 19:25:06 +0000453 sanityCheckIRBB( irbb, "initial IR",
454 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000455
sewardjedf4d692004-08-17 13:52:58 +0000456 /* Clean it up, hopefully a lot. */
sewardj8d2291c2004-10-25 14:50:21 +0000457 irbb = do_iropt_BB ( irbb, specHelper, preciseMemExnsFn,
458 guest_bytes_addr );
sewardjb9230752004-12-29 19:25:06 +0000459 sanityCheckIRBB( irbb, "after initial iropt",
460 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000461
sewardjf48ac192004-10-29 00:41:29 +0000462 if (vex_traceflags & VEX_TRACE_OPT1) {
463 vex_printf("\n------------------------"
464 " After pre-instr IR optimisation "
465 "------------------------\n\n");
sewardjedf4d692004-08-17 13:52:58 +0000466 ppIRBB ( irbb );
467 vex_printf("\n");
468 }
469
sewardjf13a16a2004-07-05 17:10:14 +0000470 /* Get the thing instrumented. */
sewardj49651f42004-10-28 22:11:04 +0000471 if (instrument1)
sewardj918c8f32005-03-21 00:54:33 +0000472 irbb = (*instrument1)(irbb, guest_layout,
sewardjf4611492005-10-18 12:01:48 +0000473 guest_bytes_addr_noredir, guest_extents,
474 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000475 if (instrument2)
sewardj918c8f32005-03-21 00:54:33 +0000476 irbb = (*instrument2)(irbb, guest_layout,
sewardjf4611492005-10-18 12:01:48 +0000477 guest_bytes_addr_noredir, guest_extents,
478 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000479
sewardjf48ac192004-10-29 00:41:29 +0000480 if (vex_traceflags & VEX_TRACE_INST) {
481 vex_printf("\n------------------------"
482 " After instrumentation "
483 "------------------------\n\n");
484 ppIRBB ( irbb );
485 vex_printf("\n");
486 }
487
sewardj49651f42004-10-28 22:11:04 +0000488 if (instrument1 || instrument2)
sewardjb9230752004-12-29 19:25:06 +0000489 sanityCheckIRBB( irbb, "after instrumentation",
490 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000491
sewardj9578a8b2004-11-04 19:44:48 +0000492 /* Do a post-instrumentation cleanup pass. */
493 if (cleanup_after_instrumentation) {
494 do_deadcode_BB( irbb );
495 irbb = cprop_BB( irbb );
496 do_deadcode_BB( irbb );
sewardjb9230752004-12-29 19:25:06 +0000497 sanityCheckIRBB( irbb, "after post-instrumentation cleanup",
498 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000499 }
500
501 if (vex_traceflags & VEX_TRACE_OPT2) {
502 vex_printf("\n------------------------"
503 " After post-instr IR optimisation "
504 "------------------------\n\n");
505 ppIRBB ( irbb );
506 vex_printf("\n");
507 }
508
sewardjf13a16a2004-07-05 17:10:14 +0000509 /* Turn it into virtual-registerised code. */
sewardj49651f42004-10-28 22:11:04 +0000510 do_deadcode_BB( irbb );
511 do_treebuild_BB( irbb );
sewardjf48ac192004-10-29 00:41:29 +0000512
513 if (vex_traceflags & VEX_TRACE_TREES) {
514 vex_printf("\n------------------------"
515 " After tree-building "
516 "------------------------\n\n");
517 ppIRBB ( irbb );
518 vex_printf("\n");
519 }
520
sewardje908c422005-02-04 21:18:16 +0000521 /* HACK */
cerion54560812005-02-03 13:40:49 +0000522 if (0) { *host_bytes_used = 0; return VexTransOK; }
sewardje908c422005-02-04 21:18:16 +0000523 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000524
sewardjf48ac192004-10-29 00:41:29 +0000525 if (vex_traceflags & VEX_TRACE_VCODE)
526 vex_printf("\n------------------------"
527 " Instruction selection "
528 "------------------------\n");
529
sewardj27e1dd62005-06-30 11:49:14 +0000530 vcode = iselBB ( irbb, archinfo_host );
sewardjf13a16a2004-07-05 17:10:14 +0000531
sewardjf48ac192004-10-29 00:41:29 +0000532 if (vex_traceflags & VEX_TRACE_VCODE)
533 vex_printf("\n");
534
sewardjf48ac192004-10-29 00:41:29 +0000535 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000536 for (i = 0; i < vcode->arr_used; i++) {
537 vex_printf("%3d ", i);
538 ppInstr(vcode->arr[i]);
539 vex_printf("\n");
540 }
sewardjfbcaf332004-07-08 01:46:01 +0000541 vex_printf("\n");
542 }
sewardjfbcaf332004-07-08 01:46:01 +0000543
sewardjf13a16a2004-07-05 17:10:14 +0000544 /* Register allocate. */
545 rcode = doRegisterAllocation ( vcode, available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000546 n_available_real_regs,
547 isMove, getRegUsage, mapRegs,
548 genSpill, genReload, guest_sizeB,
549 ppInstr, ppReg );
sewardjf13a16a2004-07-05 17:10:14 +0000550
sewardjf48ac192004-10-29 00:41:29 +0000551 if (vex_traceflags & VEX_TRACE_RCODE) {
552 vex_printf("\n------------------------"
553 " Register-allocated code "
554 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000555 for (i = 0; i < rcode->arr_used; i++) {
556 vex_printf("%3d ", i);
557 ppInstr(rcode->arr[i]);
558 vex_printf("\n");
559 }
sewardjfbcaf332004-07-08 01:46:01 +0000560 vex_printf("\n");
561 }
sewardjfbcaf332004-07-08 01:46:01 +0000562
sewardje908c422005-02-04 21:18:16 +0000563 /* HACK */
564 if (0) { *host_bytes_used = 0; return VexTransOK; }
565 /* end HACK */
566
sewardj81bd5502004-07-21 18:49:27 +0000567 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000568 if (vex_traceflags & VEX_TRACE_ASM) {
569 vex_printf("\n------------------------"
570 " Assembly "
571 "------------------------\n\n");
572 }
573
sewardj81bd5502004-07-21 18:49:27 +0000574 out_used = 0; /* tracks along the host_bytes array */
575 for (i = 0; i < rcode->arr_used; i++) {
sewardjf48ac192004-10-29 00:41:29 +0000576 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000577 ppInstr(rcode->arr[i]);
578 vex_printf("\n");
579 }
sewardj81bd5502004-07-21 18:49:27 +0000580 j = (*emit)( insn_bytes, 32, rcode->arr[i] );
sewardjf48ac192004-10-29 00:41:29 +0000581 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000582 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000583 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000584 vex_printf("0%x ", (UInt)insn_bytes[k]);
585 else
586 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000587 vex_printf("\n\n");
588 }
sewardj81bd5502004-07-21 18:49:27 +0000589 if (out_used + j > host_bytes_size) {
sewardjd887b862005-01-17 18:34:34 +0000590 vexClearTEMP();
sewardjf48ac192004-10-29 00:41:29 +0000591 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000592 return VexTransOutputFull;
sewardj81bd5502004-07-21 18:49:27 +0000593 }
594 for (k = 0; k < j; k++) {
595 host_bytes[out_used] = insn_bytes[k];
596 out_used++;
597 }
598 vassert(out_used <= host_bytes_size);
599 }
600 *host_bytes_used = out_used;
601
sewardjd887b862005-01-17 18:34:34 +0000602 vexClearTEMP();
sewardjf13a16a2004-07-05 17:10:14 +0000603
sewardjf48ac192004-10-29 00:41:29 +0000604 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000605 return VexTransOK;
sewardj35421a32004-07-05 13:12:34 +0000606}
607
608
sewardj893aada2004-11-29 19:57:54 +0000609/* --------- Emulation warnings. --------- */
610
611HChar* LibVEX_EmWarn_string ( VexEmWarn ew )
612{
613 switch (ew) {
614 case EmWarn_NONE:
615 return "none";
616 case EmWarn_X86_x87exns:
617 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000618 case EmWarn_X86_x87precision:
619 return "Selection of non-80-bit x87 FP precision";
620 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +0000621 return "Unmasking SSE FP exceptions";
622 case EmWarn_X86_fz:
623 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
624 case EmWarn_X86_daz:
625 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj6d269842005-08-06 11:45:02 +0000626 case EmWarn_X86_acFlag:
627 return "Setting %eflags.ac (setting noted but ignored)";
cerion094d1392005-06-20 13:45:57 +0000628 case EmWarn_PPC32exns:
629 return "Unmasking PPC32 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000630 default:
631 vpanic("LibVEX_EmWarn_string: unknown warning");
632 }
633}
sewardj35421a32004-07-05 13:12:34 +0000634
sewardj27e1dd62005-06-30 11:49:14 +0000635/* --------- Arch/Subarch stuff. --------- */
sewardjbef170b2004-12-21 01:23:00 +0000636
637const HChar* LibVEX_ppVexArch ( VexArch arch )
638{
639 switch (arch) {
640 case VexArch_INVALID: return "INVALID";
641 case VexArchX86: return "X86";
642 case VexArchAMD64: return "AMD64";
643 case VexArchARM: return "ARM";
sewardj0ec57c52005-02-01 15:24:10 +0000644 case VexArchPPC32: return "PPC32";
sewardjbef170b2004-12-21 01:23:00 +0000645 default: return "VexArch???";
646 }
647}
648
649const HChar* LibVEX_ppVexSubArch ( VexSubArch subarch )
650{
651 switch (subarch) {
sewardj0ec57c52005-02-01 15:24:10 +0000652 case VexSubArch_INVALID: return "INVALID";
653 case VexSubArch_NONE: return "NONE";
654 case VexSubArchX86_sse0: return "x86-sse0";
655 case VexSubArchX86_sse1: return "x86-sse1";
656 case VexSubArchX86_sse2: return "x86-sse2";
657 case VexSubArchARM_v4: return "arm-v4";
658 case VexSubArchPPC32_noAV: return "ppc32-noAltivec";
659 case VexSubArchPPC32_AV: return "ppc32-Altivec";
660 default: return "VexSubArch???";
sewardjbef170b2004-12-21 01:23:00 +0000661 }
662}
663
sewardj27e1dd62005-06-30 11:49:14 +0000664/* Write default settings info *vai. */
665void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
666{
667 vai->subarch = VexSubArch_INVALID;
668 vai->ppc32_cache_line_szB = 0;
669}
670
671
sewardj35421a32004-07-05 13:12:34 +0000672/*---------------------------------------------------------------*/
sewardjc0ee2ed2004-07-27 10:29:41 +0000673/*--- end main/vex_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +0000674/*---------------------------------------------------------------*/