blob: e77c2774f901630a719148245998afbb1e413d70 [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
sewardj81ec4182004-10-25 23:15:52 +0000134 /* All the guest state structs must have an 8-aligned size. */
sewardj32a81262005-02-05 14:32:18 +0000135 vassert(0 == sizeof(VexGuestX86State) % 8);
136 vassert(0 == sizeof(VexGuestAMD64State) % 8);
137 vassert(0 == sizeof(VexGuestPPC32State) % 8);
138 vassert(0 == sizeof(VexGuestARMState) % 8);
sewardj81ec4182004-10-25 23:15:52 +0000139
sewardjea602bc2004-10-14 21:40:12 +0000140 /* Check that Vex has been built with sizes of basic types as
141 stated in priv/libvex_basictypes.h. Failure of any of these is
142 a serious configuration error and should be corrected
143 immediately. If any of these assertions fail you can fully
144 expect Vex not to work properly, if at all. */
145
146 vassert(1 == sizeof(UChar));
147 vassert(1 == sizeof(Char));
148 vassert(2 == sizeof(UShort));
149 vassert(2 == sizeof(Short));
150 vassert(4 == sizeof(UInt));
151 vassert(4 == sizeof(Int));
152 vassert(8 == sizeof(ULong));
153 vassert(8 == sizeof(Long));
154 vassert(4 == sizeof(Float));
155 vassert(8 == sizeof(Double));
156 vassert(1 == sizeof(Bool));
157 vassert(4 == sizeof(Addr32));
158 vassert(8 == sizeof(Addr64));
sewardjc9a43662004-11-30 18:51:59 +0000159 vassert(16 == sizeof(U128));
sewardjea602bc2004-10-14 21:40:12 +0000160
161 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
162 vassert(sizeof(void*) == sizeof(int*));
163 vassert(sizeof(void*) == sizeof(HWord));
164
sewardj97e87932005-02-07 00:00:50 +0000165 vassert(VEX_HOST_WORDSIZE == sizeof(void*));
166 vassert(VEX_HOST_WORDSIZE == sizeof(HWord));
167
sewardjea602bc2004-10-14 21:40:12 +0000168 /* Really start up .. */
sewardj443cd9d2004-07-18 23:06:45 +0000169 vex_debuglevel = debuglevel;
sewardj443cd9d2004-07-18 23:06:45 +0000170 vex_valgrind_support = valgrind_support;
sewardj08613742004-10-25 13:01:45 +0000171 vex_control = *vcon;
sewardj443cd9d2004-07-18 23:06:45 +0000172 vex_initdone = True;
sewardjd887b862005-01-17 18:34:34 +0000173 vexSetAllocMode ( VexAllocModeTEMP );
sewardj35421a32004-07-05 13:12:34 +0000174}
175
176
177/* --------- Make a translation. --------- */
178
179/* Exported to library client. */
180
sewardjd887b862005-01-17 18:34:34 +0000181VexTranslateResult LibVEX_Translate (
sewardj35421a32004-07-05 13:12:34 +0000182 /* The instruction sets we are translating from and to. */
sewardj27e1dd62005-06-30 11:49:14 +0000183 VexArch arch_guest,
184 VexArchInfo* archinfo_guest,
185 VexArch arch_host,
186 VexArchInfo* archinfo_host,
sewardj35421a32004-07-05 13:12:34 +0000187 /* IN: the block to translate, and its guest address. */
sewardjbef170b2004-12-21 01:23:00 +0000188 UChar* guest_bytes,
189 Addr64 guest_bytes_addr,
190 Bool (*chase_into_ok) ( Addr64 ),
sewardj72c72812005-01-19 11:49:45 +0000191 /* OUT: which bits of guest code actually got translated */
192 VexGuestExtents* guest_extents,
sewardj35421a32004-07-05 13:12:34 +0000193 /* IN: a place to put the resulting code, and its size */
sewardjbef170b2004-12-21 01:23:00 +0000194 UChar* host_bytes,
195 Int host_bytes_size,
sewardj35421a32004-07-05 13:12:34 +0000196 /* OUT: how much of the output area is used. */
sewardjbef170b2004-12-21 01:23:00 +0000197 Int* host_bytes_used,
sewardj49651f42004-10-28 22:11:04 +0000198 /* IN: optionally, two instrumentation functions. */
sewardj918c8f32005-03-21 00:54:33 +0000199 IRBB* (*instrument1) ( IRBB*, VexGuestLayout*,
200 IRType gWordTy, IRType hWordTy ),
201 IRBB* (*instrument2) ( IRBB*, VexGuestLayout*,
202 IRType gWordTy, IRType hWordTy ),
sewardjbef170b2004-12-21 01:23:00 +0000203 Bool cleanup_after_instrumentation,
sewardjec3c8852005-07-07 09:56:24 +0000204 /* IN: should this translation be self-checking? */
205 Bool do_self_check,
sewardj35421a32004-07-05 13:12:34 +0000206 /* IN: optionally, an access check function for guest code. */
sewardjbef170b2004-12-21 01:23:00 +0000207 Bool (*byte_accessible) ( Addr64 ),
sewardjf48ac192004-10-29 00:41:29 +0000208 /* IN: debug: trace vex activity at various points */
sewardjbef170b2004-12-21 01:23:00 +0000209 Int traceflags
sewardj35421a32004-07-05 13:12:34 +0000210)
211{
sewardj81bd5502004-07-21 18:49:27 +0000212 /* This the bundle of functions we need to do the back-end stuff
213 (insn selection, reg-alloc, assembly) whilst being insulated
214 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +0000215 HReg* available_real_regs;
216 Int n_available_real_regs;
sewardj443cd9d2004-07-18 23:06:45 +0000217 Bool (*isMove) (HInstr*, HReg*, HReg*);
218 void (*getRegUsage) (HRegUsage*, HInstr*);
219 void (*mapRegs) (HRegRemap*, HInstr*);
220 HInstr* (*genSpill) ( HReg, Int );
221 HInstr* (*genReload) ( HReg, Int );
222 void (*ppInstr) ( HInstr* );
223 void (*ppReg) ( HReg );
sewardj27e1dd62005-06-30 11:49:14 +0000224 HInstrArray* (*iselBB) ( IRBB*, VexArchInfo* );
sewardj81bd5502004-07-21 18:49:27 +0000225 Int (*emit) ( UChar*, Int, HInstr* );
sewardjd9763622005-02-07 03:12:19 +0000226 IRExpr* (*specHelper) ( HChar*, IRExpr** );
sewardj8d2291c2004-10-25 14:50:21 +0000227 Bool (*preciseMemExnsFn) ( Int, Int );
sewardjf13a16a2004-07-05 17:10:14 +0000228
sewardj9e6491a2005-07-02 19:24:10 +0000229 DisOneInstrFn disInstrFn;
230
sewardjeeac8412004-11-02 00:26:55 +0000231 VexGuestLayout* guest_layout;
232 Bool host_is_bigendian = False;
233 IRBB* irbb;
234 HInstrArray* vcode;
235 HInstrArray* rcode;
236 Int i, j, k, out_used, guest_sizeB;
sewardjdb4738a2005-07-07 01:32:16 +0000237 Int offB_TISTART, offB_TILEN;
sewardjeeac8412004-11-02 00:26:55 +0000238 UChar insn_bytes[32];
sewardjcf787902004-11-03 09:08:33 +0000239 IRType guest_word_type;
240 IRType host_word_type;
sewardjf13a16a2004-07-05 17:10:14 +0000241
sewardj49651f42004-10-28 22:11:04 +0000242 guest_layout = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000243 available_real_regs = NULL;
244 n_available_real_regs = 0;
245 isMove = NULL;
246 getRegUsage = NULL;
247 mapRegs = NULL;
248 genSpill = NULL;
249 genReload = NULL;
250 ppInstr = NULL;
251 ppReg = NULL;
252 iselBB = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000253 emit = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000254 specHelper = NULL;
sewardj8d2291c2004-10-25 14:50:21 +0000255 preciseMemExnsFn = NULL;
sewardj9e6491a2005-07-02 19:24:10 +0000256 disInstrFn = NULL;
sewardjcf787902004-11-03 09:08:33 +0000257 guest_word_type = Ity_INVALID;
258 host_word_type = Ity_INVALID;
sewardjdb4738a2005-07-07 01:32:16 +0000259 offB_TISTART = 0;
260 offB_TILEN = 0;
sewardj36ca5132004-07-24 13:12:23 +0000261
sewardjf48ac192004-10-29 00:41:29 +0000262 vex_traceflags = traceflags;
sewardj58800ff2004-07-28 01:51:10 +0000263
sewardj35421a32004-07-05 13:12:34 +0000264 vassert(vex_initdone);
sewardjd887b862005-01-17 18:34:34 +0000265 vexClearTEMP();
sewardjf13a16a2004-07-05 17:10:14 +0000266
sewardj2a9ad022004-11-25 02:46:58 +0000267
sewardjf13a16a2004-07-05 17:10:14 +0000268 /* First off, check that the guest and host insn sets
269 are supported. */
sewardj2a9ad022004-11-25 02:46:58 +0000270
sewardjbef170b2004-12-21 01:23:00 +0000271 switch (arch_host) {
sewardj2a9ad022004-11-25 02:46:58 +0000272
sewardjbef170b2004-12-21 01:23:00 +0000273 case VexArchX86:
sewardjf13a16a2004-07-05 17:10:14 +0000274 getAllocableRegs_X86 ( &n_available_real_regs,
275 &available_real_regs );
276 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
277 getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_X86Instr;
278 mapRegs = (void(*)(HRegRemap*,HInstr*)) mapRegs_X86Instr;
279 genSpill = (HInstr*(*)(HReg,Int)) genSpill_X86;
280 genReload = (HInstr*(*)(HReg,Int)) genReload_X86;
sewardj2b515872004-07-05 20:50:45 +0000281 ppInstr = (void(*)(HInstr*)) ppX86Instr;
282 ppReg = (void(*)(HReg)) ppHRegX86;
sewardjf13a16a2004-07-05 17:10:14 +0000283 iselBB = iselBB_X86;
sewardj81bd5502004-07-21 18:49:27 +0000284 emit = (Int(*)(UChar*,Int,HInstr*)) emit_X86Instr;
sewardj72c72812005-01-19 11:49:45 +0000285 host_is_bigendian = False;
sewardjcf787902004-11-03 09:08:33 +0000286 host_word_type = Ity_I32;
sewardj27e1dd62005-06-30 11:49:14 +0000287 vassert(archinfo_host->subarch == VexSubArchX86_sse0
288 || archinfo_host->subarch == VexSubArchX86_sse1
289 || archinfo_host->subarch == VexSubArchX86_sse2);
sewardjf13a16a2004-07-05 17:10:14 +0000290 break;
sewardj2a9ad022004-11-25 02:46:58 +0000291
sewardjc33671d2005-02-01 20:30:00 +0000292 case VexArchAMD64:
293 getAllocableRegs_AMD64 ( &n_available_real_regs,
294 &available_real_regs );
295 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr;
296 getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_AMD64Instr;
297 mapRegs = (void(*)(HRegRemap*,HInstr*)) mapRegs_AMD64Instr;
298 genSpill = (HInstr*(*)(HReg,Int)) genSpill_AMD64;
299 genReload = (HInstr*(*)(HReg,Int)) genReload_AMD64;
300 ppInstr = (void(*)(HInstr*)) ppAMD64Instr;
301 ppReg = (void(*)(HReg)) ppHRegAMD64;
302 iselBB = iselBB_AMD64;
303 emit = (Int(*)(UChar*,Int,HInstr*)) emit_AMD64Instr;
304 host_is_bigendian = False;
305 host_word_type = Ity_I64;
sewardj27e1dd62005-06-30 11:49:14 +0000306 vassert(archinfo_host->subarch == VexSubArch_NONE);
sewardjc33671d2005-02-01 20:30:00 +0000307 break;
308
cerion487e4c92005-02-04 16:28:19 +0000309 case VexArchPPC32:
310 getAllocableRegs_PPC32 ( &n_available_real_regs,
311 &available_real_regs );
312 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPC32Instr;
313 getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_PPC32Instr;
314 mapRegs = (void(*)(HRegRemap*,HInstr*)) mapRegs_PPC32Instr;
315 genSpill = (HInstr*(*)(HReg,Int)) genSpill_PPC32;
316 genReload = (HInstr*(*)(HReg,Int)) genReload_PPC32;
317 ppInstr = (void(*)(HInstr*)) ppPPC32Instr;
318 ppReg = (void(*)(HReg)) ppHRegPPC32;
319 iselBB = iselBB_PPC32;
320 emit = (Int(*)(UChar*,Int,HInstr*)) emit_PPC32Instr;
321 host_is_bigendian = True;
322 host_word_type = Ity_I32;
sewardj27e1dd62005-06-30 11:49:14 +0000323 vassert(archinfo_guest->subarch == VexSubArchPPC32_noAV
324 || archinfo_guest->subarch == VexSubArchPPC32_AV);
cerion487e4c92005-02-04 16:28:19 +0000325 break;
326
sewardjf13a16a2004-07-05 17:10:14 +0000327 default:
sewardj887a11a2004-07-05 17:26:47 +0000328 vpanic("LibVEX_Translate: unsupported target insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000329 }
330
sewardj2a9ad022004-11-25 02:46:58 +0000331
sewardjbef170b2004-12-21 01:23:00 +0000332 switch (arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000333
sewardjbef170b2004-12-21 01:23:00 +0000334 case VexArchX86:
sewardj8d2291c2004-10-25 14:50:21 +0000335 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000336 disInstrFn = disInstr_X86;
sewardj2a9ad022004-11-25 02:46:58 +0000337 specHelper = guest_x86_spechelper;
sewardj81ec4182004-10-25 23:15:52 +0000338 guest_sizeB = sizeof(VexGuestX86State);
sewardjcf787902004-11-03 09:08:33 +0000339 guest_word_type = Ity_I32;
sewardj49651f42004-10-28 22:11:04 +0000340 guest_layout = &x86guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000341 offB_TISTART = offsetof(VexGuestX86State,guest_TISTART);
342 offB_TILEN = offsetof(VexGuestX86State,guest_TILEN);
sewardj27e1dd62005-06-30 11:49:14 +0000343 vassert(archinfo_guest->subarch == VexSubArchX86_sse0
344 || archinfo_guest->subarch == VexSubArchX86_sse1
345 || archinfo_guest->subarch == VexSubArchX86_sse2);
sewardjdb4738a2005-07-07 01:32:16 +0000346 vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART ) == 4);
347 vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000348 break;
sewardj2a9ad022004-11-25 02:46:58 +0000349
sewardj44d494d2005-01-20 20:26:33 +0000350 case VexArchAMD64:
351 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000352 disInstrFn = disInstr_AMD64;
sewardj44d494d2005-01-20 20:26:33 +0000353 specHelper = guest_amd64_spechelper;
354 guest_sizeB = sizeof(VexGuestAMD64State);
355 guest_word_type = Ity_I64;
356 guest_layout = &amd64guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000357 offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART);
358 offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN);
sewardj27e1dd62005-06-30 11:49:14 +0000359 vassert(archinfo_guest->subarch == VexSubArch_NONE);
sewardjdb4738a2005-07-07 01:32:16 +0000360 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8);
361 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000362 break;
363
sewardjbef170b2004-12-21 01:23:00 +0000364 case VexArchARM:
sewardj2a9ad022004-11-25 02:46:58 +0000365 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000366 disInstrFn = NULL; /* HACK */
sewardj2a9ad022004-11-25 02:46:58 +0000367 specHelper = guest_arm_spechelper;
368 guest_sizeB = sizeof(VexGuestARMState);
369 guest_word_type = Ity_I32;
370 guest_layout = &armGuest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000371 offB_TISTART = 0; /* hack ... arm has bitrot */
372 offB_TILEN = 0; /* hack ... arm has bitrot */
sewardj27e1dd62005-06-30 11:49:14 +0000373 vassert(archinfo_guest->subarch == VexSubArchARM_v4);
sewardj2a9ad022004-11-25 02:46:58 +0000374 break;
375
cerionaabdfbf2005-01-29 12:56:15 +0000376 case VexArchPPC32:
377 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000378 disInstrFn = disInstr_PPC32;
cerionaabdfbf2005-01-29 12:56:15 +0000379 specHelper = guest_ppc32_spechelper;
380 guest_sizeB = sizeof(VexGuestPPC32State);
381 guest_word_type = Ity_I32;
382 guest_layout = &ppc32Guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000383 offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART);
384 offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN);
sewardj27e1dd62005-06-30 11:49:14 +0000385 vassert(archinfo_guest->subarch == VexSubArchPPC32_noAV
386 || archinfo_guest->subarch == VexSubArchPPC32_AV);
sewardjdb4738a2005-07-07 01:32:16 +0000387 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4);
388 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000389 break;
390
sewardjf13a16a2004-07-05 17:10:14 +0000391 default:
sewardj887a11a2004-07-05 17:26:47 +0000392 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000393 }
394
sewardj9df271d2004-12-31 22:37:42 +0000395 /* yet more sanity checks ... */
sewardj0ec57c52005-02-01 15:24:10 +0000396 if (arch_guest == arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000397 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000398 we are simulating one flavour of an architecture a different
399 flavour of the same architecture, which is pretty strange. */
sewardj27e1dd62005-06-30 11:49:14 +0000400 vassert(archinfo_guest->subarch == archinfo_host->subarch);
sewardj9df271d2004-12-31 22:37:42 +0000401 }
sewardj2a9ad022004-11-25 02:46:58 +0000402
sewardjf48ac192004-10-29 00:41:29 +0000403 if (vex_traceflags & VEX_TRACE_FE)
404 vex_printf("\n------------------------"
405 " Front end "
406 "------------------------\n\n");
407
sewardj9e6491a2005-07-02 19:24:10 +0000408 irbb = bb_to_IR ( guest_extents,
409 disInstrFn,
410 guest_bytes,
411 guest_bytes_addr,
412 chase_into_ok,
413 host_is_bigendian,
414 archinfo_guest,
sewardjdb4738a2005-07-07 01:32:16 +0000415 guest_word_type,
sewardjec3c8852005-07-07 09:56:24 +0000416 do_self_check,
sewardjdb4738a2005-07-07 01:32:16 +0000417 offB_TISTART,
418 offB_TILEN );
sewardjf13a16a2004-07-05 17:10:14 +0000419
420 if (irbb == NULL) {
421 /* Access failure. */
sewardjd887b862005-01-17 18:34:34 +0000422 vexClearTEMP();
sewardjf48ac192004-10-29 00:41:29 +0000423 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000424 return VexTransAccessFail;
sewardjf13a16a2004-07-05 17:10:14 +0000425 }
sewardjaa59f942004-10-09 09:34:36 +0000426
sewardj72c72812005-01-19 11:49:45 +0000427 vassert(guest_extents->n_used >= 1 && guest_extents->n_used <= 3);
428 vassert(guest_extents->base[0] == guest_bytes_addr);
429 for (i = 0; i < guest_extents->n_used; i++) {
430 vassert(guest_extents->len[i] < 10000); /* sanity */
431 }
432
sewardjaa59f942004-10-09 09:34:36 +0000433 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000434 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj72c72812005-01-19 11:49:45 +0000435 if (guest_extents->n_used > 1) {
436 vex_printf("can't show code due to extents > 1\n");
437 } else {
438 /* HACK */
439 UChar* p = (UChar*)guest_bytes;
440 UInt guest_bytes_read = (UInt)guest_extents->len[0];
sewardjd9763622005-02-07 03:12:19 +0000441 vex_printf(". 0 %llx %u\n.", guest_bytes_addr, guest_bytes_read );
sewardj72c72812005-01-19 11:49:45 +0000442 for (i = 0; i < guest_bytes_read; i++)
sewardjaa59f942004-10-09 09:34:36 +0000443 vex_printf(" %02x", (Int)p[i] );
sewardj72c72812005-01-19 11:49:45 +0000444 vex_printf("\n\n");
445 }
sewardjaa59f942004-10-09 09:34:36 +0000446 }
447
448 /* Sanity check the initial IR. */
sewardjb9230752004-12-29 19:25:06 +0000449 sanityCheckIRBB( irbb, "initial IR",
450 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000451
sewardjedf4d692004-08-17 13:52:58 +0000452 /* Clean it up, hopefully a lot. */
sewardj8d2291c2004-10-25 14:50:21 +0000453 irbb = do_iropt_BB ( irbb, specHelper, preciseMemExnsFn,
454 guest_bytes_addr );
sewardjb9230752004-12-29 19:25:06 +0000455 sanityCheckIRBB( irbb, "after initial iropt",
456 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000457
sewardjf48ac192004-10-29 00:41:29 +0000458 if (vex_traceflags & VEX_TRACE_OPT1) {
459 vex_printf("\n------------------------"
460 " After pre-instr IR optimisation "
461 "------------------------\n\n");
sewardjedf4d692004-08-17 13:52:58 +0000462 ppIRBB ( irbb );
463 vex_printf("\n");
464 }
465
sewardjf13a16a2004-07-05 17:10:14 +0000466 /* Get the thing instrumented. */
sewardj49651f42004-10-28 22:11:04 +0000467 if (instrument1)
sewardj918c8f32005-03-21 00:54:33 +0000468 irbb = (*instrument1)(irbb, guest_layout,
469 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000470 if (instrument2)
sewardj918c8f32005-03-21 00:54:33 +0000471 irbb = (*instrument2)(irbb, guest_layout,
472 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000473
sewardjf48ac192004-10-29 00:41:29 +0000474 if (vex_traceflags & VEX_TRACE_INST) {
475 vex_printf("\n------------------------"
476 " After instrumentation "
477 "------------------------\n\n");
478 ppIRBB ( irbb );
479 vex_printf("\n");
480 }
481
sewardj49651f42004-10-28 22:11:04 +0000482 if (instrument1 || instrument2)
sewardjb9230752004-12-29 19:25:06 +0000483 sanityCheckIRBB( irbb, "after instrumentation",
484 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000485
sewardj9578a8b2004-11-04 19:44:48 +0000486 /* Do a post-instrumentation cleanup pass. */
487 if (cleanup_after_instrumentation) {
488 do_deadcode_BB( irbb );
489 irbb = cprop_BB( irbb );
490 do_deadcode_BB( irbb );
sewardjb9230752004-12-29 19:25:06 +0000491 sanityCheckIRBB( irbb, "after post-instrumentation cleanup",
492 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000493 }
494
495 if (vex_traceflags & VEX_TRACE_OPT2) {
496 vex_printf("\n------------------------"
497 " After post-instr IR optimisation "
498 "------------------------\n\n");
499 ppIRBB ( irbb );
500 vex_printf("\n");
501 }
502
sewardjf13a16a2004-07-05 17:10:14 +0000503 /* Turn it into virtual-registerised code. */
sewardj49651f42004-10-28 22:11:04 +0000504 do_deadcode_BB( irbb );
505 do_treebuild_BB( irbb );
sewardjf48ac192004-10-29 00:41:29 +0000506
507 if (vex_traceflags & VEX_TRACE_TREES) {
508 vex_printf("\n------------------------"
509 " After tree-building "
510 "------------------------\n\n");
511 ppIRBB ( irbb );
512 vex_printf("\n");
513 }
514
sewardje908c422005-02-04 21:18:16 +0000515 /* HACK */
cerion54560812005-02-03 13:40:49 +0000516 if (0) { *host_bytes_used = 0; return VexTransOK; }
sewardje908c422005-02-04 21:18:16 +0000517 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000518
sewardjf48ac192004-10-29 00:41:29 +0000519 if (vex_traceflags & VEX_TRACE_VCODE)
520 vex_printf("\n------------------------"
521 " Instruction selection "
522 "------------------------\n");
523
sewardj27e1dd62005-06-30 11:49:14 +0000524 vcode = iselBB ( irbb, archinfo_host );
sewardjf13a16a2004-07-05 17:10:14 +0000525
sewardjf48ac192004-10-29 00:41:29 +0000526 if (vex_traceflags & VEX_TRACE_VCODE)
527 vex_printf("\n");
528
sewardjf48ac192004-10-29 00:41:29 +0000529 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000530 for (i = 0; i < vcode->arr_used; i++) {
531 vex_printf("%3d ", i);
532 ppInstr(vcode->arr[i]);
533 vex_printf("\n");
534 }
sewardjfbcaf332004-07-08 01:46:01 +0000535 vex_printf("\n");
536 }
sewardjfbcaf332004-07-08 01:46:01 +0000537
sewardjf13a16a2004-07-05 17:10:14 +0000538 /* Register allocate. */
539 rcode = doRegisterAllocation ( vcode, available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000540 n_available_real_regs,
541 isMove, getRegUsage, mapRegs,
542 genSpill, genReload, guest_sizeB,
543 ppInstr, ppReg );
sewardjf13a16a2004-07-05 17:10:14 +0000544
sewardjf48ac192004-10-29 00:41:29 +0000545 if (vex_traceflags & VEX_TRACE_RCODE) {
546 vex_printf("\n------------------------"
547 " Register-allocated code "
548 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000549 for (i = 0; i < rcode->arr_used; i++) {
550 vex_printf("%3d ", i);
551 ppInstr(rcode->arr[i]);
552 vex_printf("\n");
553 }
sewardjfbcaf332004-07-08 01:46:01 +0000554 vex_printf("\n");
555 }
sewardjfbcaf332004-07-08 01:46:01 +0000556
sewardje908c422005-02-04 21:18:16 +0000557 /* HACK */
558 if (0) { *host_bytes_used = 0; return VexTransOK; }
559 /* end HACK */
560
sewardj81bd5502004-07-21 18:49:27 +0000561 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000562 if (vex_traceflags & VEX_TRACE_ASM) {
563 vex_printf("\n------------------------"
564 " Assembly "
565 "------------------------\n\n");
566 }
567
sewardj81bd5502004-07-21 18:49:27 +0000568 out_used = 0; /* tracks along the host_bytes array */
569 for (i = 0; i < rcode->arr_used; i++) {
sewardjf48ac192004-10-29 00:41:29 +0000570 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000571 ppInstr(rcode->arr[i]);
572 vex_printf("\n");
573 }
sewardj81bd5502004-07-21 18:49:27 +0000574 j = (*emit)( insn_bytes, 32, rcode->arr[i] );
sewardjf48ac192004-10-29 00:41:29 +0000575 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000576 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000577 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000578 vex_printf("0%x ", (UInt)insn_bytes[k]);
579 else
580 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000581 vex_printf("\n\n");
582 }
sewardj81bd5502004-07-21 18:49:27 +0000583 if (out_used + j > host_bytes_size) {
sewardjd887b862005-01-17 18:34:34 +0000584 vexClearTEMP();
sewardjf48ac192004-10-29 00:41:29 +0000585 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000586 return VexTransOutputFull;
sewardj81bd5502004-07-21 18:49:27 +0000587 }
588 for (k = 0; k < j; k++) {
589 host_bytes[out_used] = insn_bytes[k];
590 out_used++;
591 }
592 vassert(out_used <= host_bytes_size);
593 }
594 *host_bytes_used = out_used;
595
sewardjd887b862005-01-17 18:34:34 +0000596 vexClearTEMP();
sewardjf13a16a2004-07-05 17:10:14 +0000597
sewardjf48ac192004-10-29 00:41:29 +0000598 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000599 return VexTransOK;
sewardj35421a32004-07-05 13:12:34 +0000600}
601
602
sewardj893aada2004-11-29 19:57:54 +0000603/* --------- Emulation warnings. --------- */
604
605HChar* LibVEX_EmWarn_string ( VexEmWarn ew )
606{
607 switch (ew) {
608 case EmWarn_NONE:
609 return "none";
610 case EmWarn_X86_x87exns:
611 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000612 case EmWarn_X86_x87precision:
613 return "Selection of non-80-bit x87 FP precision";
614 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +0000615 return "Unmasking SSE FP exceptions";
616 case EmWarn_X86_fz:
617 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
618 case EmWarn_X86_daz:
619 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
cerion094d1392005-06-20 13:45:57 +0000620 case EmWarn_PPC32exns:
621 return "Unmasking PPC32 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000622 default:
623 vpanic("LibVEX_EmWarn_string: unknown warning");
624 }
625}
sewardj35421a32004-07-05 13:12:34 +0000626
sewardj27e1dd62005-06-30 11:49:14 +0000627/* --------- Arch/Subarch stuff. --------- */
sewardjbef170b2004-12-21 01:23:00 +0000628
629const HChar* LibVEX_ppVexArch ( VexArch arch )
630{
631 switch (arch) {
632 case VexArch_INVALID: return "INVALID";
633 case VexArchX86: return "X86";
634 case VexArchAMD64: return "AMD64";
635 case VexArchARM: return "ARM";
sewardj0ec57c52005-02-01 15:24:10 +0000636 case VexArchPPC32: return "PPC32";
sewardjbef170b2004-12-21 01:23:00 +0000637 default: return "VexArch???";
638 }
639}
640
641const HChar* LibVEX_ppVexSubArch ( VexSubArch subarch )
642{
643 switch (subarch) {
sewardj0ec57c52005-02-01 15:24:10 +0000644 case VexSubArch_INVALID: return "INVALID";
645 case VexSubArch_NONE: return "NONE";
646 case VexSubArchX86_sse0: return "x86-sse0";
647 case VexSubArchX86_sse1: return "x86-sse1";
648 case VexSubArchX86_sse2: return "x86-sse2";
649 case VexSubArchARM_v4: return "arm-v4";
650 case VexSubArchPPC32_noAV: return "ppc32-noAltivec";
651 case VexSubArchPPC32_AV: return "ppc32-Altivec";
652 default: return "VexSubArch???";
sewardjbef170b2004-12-21 01:23:00 +0000653 }
654}
655
sewardj27e1dd62005-06-30 11:49:14 +0000656/* Write default settings info *vai. */
657void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
658{
659 vai->subarch = VexSubArch_INVALID;
660 vai->ppc32_cache_line_szB = 0;
661}
662
663
sewardj35421a32004-07-05 13:12:34 +0000664/*---------------------------------------------------------------*/
sewardjc0ee2ed2004-07-27 10:29:41 +0000665/*--- end main/vex_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +0000666/*---------------------------------------------------------------*/