blob: 7d79683076cf9c14071ea5dfae9c05383df63164 [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 ---*/
sewardj35421a32004-07-05 13:12:34 +00005/*--- Copyright (c) 2004 OpenWorks LLP. All rights reserved. ---*/
6/*--- ---*/
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
13 Copyright (C) 2004 OpenWorks, LLP.
14
15 This program is free software; you can redistribute it and/or modify
16 it under the terms of the GNU General Public License as published by
17 the Free Software Foundation; Version 2 dated June 1991 of the
18 license.
19
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or liability
23 for damages. See the GNU General Public License for more details.
24
25 Neither the names of the U.S. Department of Energy nor the
26 University of California nor the names of its contributors may be
27 used to endorse or promote products derived from this software
28 without prior written permission.
29
30 You should have received a copy of the GNU General Public License
31 along with this program; if not, write to the Free Software
32 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
33 USA.
34*/
35
sewardj887a11a2004-07-05 17:26:47 +000036#include "libvex.h"
sewardj893aada2004-11-29 19:57:54 +000037#include "libvex_emwarn.h"
sewardj81ec4182004-10-25 23:15:52 +000038#include "libvex_guest_x86.h"
sewardj44d494d2005-01-20 20:26:33 +000039#include "libvex_guest_amd64.h"
sewardj2a9ad022004-11-25 02:46:58 +000040#include "libvex_guest_arm.h"
cerionaabdfbf2005-01-29 12:56:15 +000041#include "libvex_guest_ppc32.h"
sewardjf13a16a2004-07-05 17:10:14 +000042
sewardjc0ee2ed2004-07-27 10:29:41 +000043#include "main/vex_globals.h"
44#include "main/vex_util.h"
45#include "host-generic/h_generic_regs.h"
sewardjedf4d692004-08-17 13:52:58 +000046#include "ir/iropt.h"
sewardj35421a32004-07-05 13:12:34 +000047
sewardj2a9ad022004-11-25 02:46:58 +000048#include "host-x86/hdefs.h"
sewardjc33671d2005-02-01 20:30:00 +000049#include "host-amd64/hdefs.h"
cerion487e4c92005-02-04 16:28:19 +000050#include "host-ppc32/hdefs.h"
sewardj2a9ad022004-11-25 02:46:58 +000051
52#include "guest-x86/gdefs.h"
sewardj44d494d2005-01-20 20:26:33 +000053#include "guest-amd64/gdefs.h"
sewardj2a9ad022004-11-25 02:46:58 +000054#include "guest-arm/gdefs.h"
cerionaabdfbf2005-01-29 12:56:15 +000055#include "guest-ppc32/gdefs.h"
sewardj2a9ad022004-11-25 02:46:58 +000056
sewardj35421a32004-07-05 13:12:34 +000057
58/* This file contains the top level interface to the library. */
59
60/* --------- Initialise the library. --------- */
61
62/* Exported to library client. */
63
sewardjd887b862005-01-17 18:34:34 +000064const HChar* LibVEX_Version ( void )
sewardj80f5fce2004-12-20 04:37:50 +000065{
66return
67#include "main/vex_svnversion.h"
68 ;
69}
70
71
72/* Exported to library client. */
73
sewardj08613742004-10-25 13:01:45 +000074void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon )
75{
76 vcon->iropt_verbosity = 0;
77 vcon->iropt_level = 2;
78 vcon->iropt_precise_memory_exns = False;
79 vcon->iropt_unroll_thresh = 120;
80 vcon->guest_max_insns = 50;
81 vcon->guest_chase_thresh = 10;
82}
83
84
85/* Exported to library client. */
86
sewardj887a11a2004-07-05 17:26:47 +000087void LibVEX_Init (
sewardj35421a32004-07-05 13:12:34 +000088 /* failure exit function */
sewardj2b515872004-07-05 20:50:45 +000089 __attribute__ ((noreturn))
sewardj35421a32004-07-05 13:12:34 +000090 void (*failure_exit) ( void ),
91 /* logging output function */
sewardjd9763622005-02-07 03:12:19 +000092 void (*log_bytes) ( HChar*, Int nbytes ),
sewardj35421a32004-07-05 13:12:34 +000093 /* debug paranoia level */
94 Int debuglevel,
sewardj35421a32004-07-05 13:12:34 +000095 /* Are we supporting valgrind checking? */
96 Bool valgrind_support,
sewardj08613742004-10-25 13:01:45 +000097 /* Control ... */
98 /*READONLY*/VexControl* vcon
sewardj35421a32004-07-05 13:12:34 +000099)
100{
sewardj08613742004-10-25 13:01:45 +0000101 /* First off, do enough minimal setup so that the following
102 assertions can fail in a sane fashion, if need be. */
sewardjea602bc2004-10-14 21:40:12 +0000103 vex_failure_exit = failure_exit;
104 vex_log_bytes = log_bytes;
105
106 /* Now it's safe to check parameters for sanity. */
sewardj35421a32004-07-05 13:12:34 +0000107 vassert(!vex_initdone);
108 vassert(failure_exit);
sewardj35421a32004-07-05 13:12:34 +0000109 vassert(log_bytes);
sewardj35421a32004-07-05 13:12:34 +0000110 vassert(debuglevel >= 0);
sewardj08613742004-10-25 13:01:45 +0000111
112 vassert(vcon->iropt_verbosity >= 0);
113 vassert(vcon->iropt_level >= 0);
114 vassert(vcon->iropt_level <= 2);
115 vassert(vcon->iropt_unroll_thresh >= 0);
116 vassert(vcon->iropt_unroll_thresh <= 400);
117 vassert(vcon->guest_max_insns >= 1);
118 vassert(vcon->guest_max_insns <= 100);
119 vassert(vcon->guest_chase_thresh >= 0);
120 vassert(vcon->guest_chase_thresh < vcon->guest_max_insns);
sewardj443cd9d2004-07-18 23:06:45 +0000121
sewardj81ec4182004-10-25 23:15:52 +0000122 /* All the guest state structs must have an 8-aligned size. */
sewardj32a81262005-02-05 14:32:18 +0000123 vassert(0 == sizeof(VexGuestX86State) % 8);
124 vassert(0 == sizeof(VexGuestAMD64State) % 8);
125 vassert(0 == sizeof(VexGuestPPC32State) % 8);
126 vassert(0 == sizeof(VexGuestARMState) % 8);
sewardj81ec4182004-10-25 23:15:52 +0000127
sewardjea602bc2004-10-14 21:40:12 +0000128 /* Check that Vex has been built with sizes of basic types as
129 stated in priv/libvex_basictypes.h. Failure of any of these is
130 a serious configuration error and should be corrected
131 immediately. If any of these assertions fail you can fully
132 expect Vex not to work properly, if at all. */
133
134 vassert(1 == sizeof(UChar));
135 vassert(1 == sizeof(Char));
136 vassert(2 == sizeof(UShort));
137 vassert(2 == sizeof(Short));
138 vassert(4 == sizeof(UInt));
139 vassert(4 == sizeof(Int));
140 vassert(8 == sizeof(ULong));
141 vassert(8 == sizeof(Long));
142 vassert(4 == sizeof(Float));
143 vassert(8 == sizeof(Double));
144 vassert(1 == sizeof(Bool));
145 vassert(4 == sizeof(Addr32));
146 vassert(8 == sizeof(Addr64));
sewardjc9a43662004-11-30 18:51:59 +0000147 vassert(16 == sizeof(U128));
sewardjea602bc2004-10-14 21:40:12 +0000148
149 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
150 vassert(sizeof(void*) == sizeof(int*));
151 vassert(sizeof(void*) == sizeof(HWord));
152
sewardj97e87932005-02-07 00:00:50 +0000153 vassert(VEX_HOST_WORDSIZE == sizeof(void*));
154 vassert(VEX_HOST_WORDSIZE == sizeof(HWord));
155
sewardjea602bc2004-10-14 21:40:12 +0000156 /* Really start up .. */
sewardj443cd9d2004-07-18 23:06:45 +0000157 vex_debuglevel = debuglevel;
sewardj443cd9d2004-07-18 23:06:45 +0000158 vex_valgrind_support = valgrind_support;
sewardj08613742004-10-25 13:01:45 +0000159 vex_control = *vcon;
sewardj443cd9d2004-07-18 23:06:45 +0000160 vex_initdone = True;
sewardjd887b862005-01-17 18:34:34 +0000161 vexSetAllocMode ( VexAllocModeTEMP );
sewardj35421a32004-07-05 13:12:34 +0000162}
163
164
165/* --------- Make a translation. --------- */
166
167/* Exported to library client. */
168
sewardjd887b862005-01-17 18:34:34 +0000169VexTranslateResult LibVEX_Translate (
sewardj35421a32004-07-05 13:12:34 +0000170 /* The instruction sets we are translating from and to. */
sewardjbef170b2004-12-21 01:23:00 +0000171 VexArch arch_guest,
172 VexSubArch subarch_guest,
173 VexArch arch_host,
174 VexSubArch subarch_host,
sewardj35421a32004-07-05 13:12:34 +0000175 /* IN: the block to translate, and its guest address. */
sewardjbef170b2004-12-21 01:23:00 +0000176 UChar* guest_bytes,
177 Addr64 guest_bytes_addr,
178 Bool (*chase_into_ok) ( Addr64 ),
sewardj72c72812005-01-19 11:49:45 +0000179 /* OUT: which bits of guest code actually got translated */
180 VexGuestExtents* guest_extents,
sewardj35421a32004-07-05 13:12:34 +0000181 /* IN: a place to put the resulting code, and its size */
sewardjbef170b2004-12-21 01:23:00 +0000182 UChar* host_bytes,
183 Int host_bytes_size,
sewardj35421a32004-07-05 13:12:34 +0000184 /* OUT: how much of the output area is used. */
sewardjbef170b2004-12-21 01:23:00 +0000185 Int* host_bytes_used,
sewardj49651f42004-10-28 22:11:04 +0000186 /* IN: optionally, two instrumentation functions. */
sewardjbef170b2004-12-21 01:23:00 +0000187 IRBB* (*instrument1) ( IRBB*, VexGuestLayout*, IRType hWordTy ),
188 IRBB* (*instrument2) ( IRBB*, VexGuestLayout*, IRType hWordTy ),
189 Bool cleanup_after_instrumentation,
sewardj35421a32004-07-05 13:12:34 +0000190 /* IN: optionally, an access check function for guest code. */
sewardjbef170b2004-12-21 01:23:00 +0000191 Bool (*byte_accessible) ( Addr64 ),
sewardjf48ac192004-10-29 00:41:29 +0000192 /* IN: debug: trace vex activity at various points */
sewardjbef170b2004-12-21 01:23:00 +0000193 Int traceflags
sewardj35421a32004-07-05 13:12:34 +0000194)
195{
sewardj81bd5502004-07-21 18:49:27 +0000196 /* This the bundle of functions we need to do the back-end stuff
197 (insn selection, reg-alloc, assembly) whilst being insulated
198 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +0000199 HReg* available_real_regs;
200 Int n_available_real_regs;
sewardj443cd9d2004-07-18 23:06:45 +0000201 Bool (*isMove) (HInstr*, HReg*, HReg*);
202 void (*getRegUsage) (HRegUsage*, HInstr*);
203 void (*mapRegs) (HRegRemap*, HInstr*);
204 HInstr* (*genSpill) ( HReg, Int );
205 HInstr* (*genReload) ( HReg, Int );
206 void (*ppInstr) ( HInstr* );
207 void (*ppReg) ( HReg );
sewardj9df271d2004-12-31 22:37:42 +0000208 HInstrArray* (*iselBB) ( IRBB*, VexSubArch );
sewardj72c72812005-01-19 11:49:45 +0000209 IRBB* (*bbToIR) ( UChar*, Addr64,
210 VexGuestExtents*,
sewardj5bd4d162004-11-10 13:02:48 +0000211 Bool(*)(Addr64),
sewardj72c72812005-01-19 11:49:45 +0000212 Bool(*)(Addr64),
213 Bool, VexSubArch );
sewardj81bd5502004-07-21 18:49:27 +0000214 Int (*emit) ( UChar*, Int, HInstr* );
sewardjd9763622005-02-07 03:12:19 +0000215 IRExpr* (*specHelper) ( HChar*, IRExpr** );
sewardj8d2291c2004-10-25 14:50:21 +0000216 Bool (*preciseMemExnsFn) ( Int, Int );
sewardjf13a16a2004-07-05 17:10:14 +0000217
sewardjeeac8412004-11-02 00:26:55 +0000218 VexGuestLayout* guest_layout;
219 Bool host_is_bigendian = False;
220 IRBB* irbb;
221 HInstrArray* vcode;
222 HInstrArray* rcode;
223 Int i, j, k, out_used, guest_sizeB;
224 UChar insn_bytes[32];
sewardjcf787902004-11-03 09:08:33 +0000225 IRType guest_word_type;
226 IRType host_word_type;
sewardjf13a16a2004-07-05 17:10:14 +0000227
sewardj49651f42004-10-28 22:11:04 +0000228 guest_layout = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000229 available_real_regs = NULL;
230 n_available_real_regs = 0;
231 isMove = NULL;
232 getRegUsage = NULL;
233 mapRegs = NULL;
234 genSpill = NULL;
235 genReload = NULL;
236 ppInstr = NULL;
237 ppReg = NULL;
238 iselBB = NULL;
239 bbToIR = NULL;
240 emit = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000241 specHelper = NULL;
sewardj8d2291c2004-10-25 14:50:21 +0000242 preciseMemExnsFn = NULL;
sewardjcf787902004-11-03 09:08:33 +0000243 guest_word_type = Ity_INVALID;
244 host_word_type = Ity_INVALID;
sewardj36ca5132004-07-24 13:12:23 +0000245
sewardjf48ac192004-10-29 00:41:29 +0000246 vex_traceflags = traceflags;
sewardj58800ff2004-07-28 01:51:10 +0000247
sewardj35421a32004-07-05 13:12:34 +0000248 vassert(vex_initdone);
sewardjd887b862005-01-17 18:34:34 +0000249 vexClearTEMP();
sewardjf13a16a2004-07-05 17:10:14 +0000250
sewardj2a9ad022004-11-25 02:46:58 +0000251
sewardjf13a16a2004-07-05 17:10:14 +0000252 /* First off, check that the guest and host insn sets
253 are supported. */
sewardj2a9ad022004-11-25 02:46:58 +0000254
sewardjbef170b2004-12-21 01:23:00 +0000255 switch (arch_host) {
sewardj2a9ad022004-11-25 02:46:58 +0000256
sewardjbef170b2004-12-21 01:23:00 +0000257 case VexArchX86:
sewardjf13a16a2004-07-05 17:10:14 +0000258 getAllocableRegs_X86 ( &n_available_real_regs,
259 &available_real_regs );
260 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
261 getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_X86Instr;
262 mapRegs = (void(*)(HRegRemap*,HInstr*)) mapRegs_X86Instr;
263 genSpill = (HInstr*(*)(HReg,Int)) genSpill_X86;
264 genReload = (HInstr*(*)(HReg,Int)) genReload_X86;
sewardj2b515872004-07-05 20:50:45 +0000265 ppInstr = (void(*)(HInstr*)) ppX86Instr;
266 ppReg = (void(*)(HReg)) ppHRegX86;
sewardjf13a16a2004-07-05 17:10:14 +0000267 iselBB = iselBB_X86;
sewardj81bd5502004-07-21 18:49:27 +0000268 emit = (Int(*)(UChar*,Int,HInstr*)) emit_X86Instr;
sewardj72c72812005-01-19 11:49:45 +0000269 host_is_bigendian = False;
sewardjcf787902004-11-03 09:08:33 +0000270 host_word_type = Ity_I32;
sewardj9df271d2004-12-31 22:37:42 +0000271 vassert(subarch_host == VexSubArchX86_sse0
272 || subarch_host == VexSubArchX86_sse1
273 || subarch_host == VexSubArchX86_sse2);
sewardjf13a16a2004-07-05 17:10:14 +0000274 break;
sewardj2a9ad022004-11-25 02:46:58 +0000275
sewardjc33671d2005-02-01 20:30:00 +0000276 case VexArchAMD64:
277 getAllocableRegs_AMD64 ( &n_available_real_regs,
278 &available_real_regs );
279 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr;
280 getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_AMD64Instr;
281 mapRegs = (void(*)(HRegRemap*,HInstr*)) mapRegs_AMD64Instr;
282 genSpill = (HInstr*(*)(HReg,Int)) genSpill_AMD64;
283 genReload = (HInstr*(*)(HReg,Int)) genReload_AMD64;
284 ppInstr = (void(*)(HInstr*)) ppAMD64Instr;
285 ppReg = (void(*)(HReg)) ppHRegAMD64;
286 iselBB = iselBB_AMD64;
287 emit = (Int(*)(UChar*,Int,HInstr*)) emit_AMD64Instr;
288 host_is_bigendian = False;
289 host_word_type = Ity_I64;
290 vassert(subarch_host == VexSubArch_NONE);
291 break;
292
cerion487e4c92005-02-04 16:28:19 +0000293 case VexArchPPC32:
294 getAllocableRegs_PPC32 ( &n_available_real_regs,
295 &available_real_regs );
296 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPC32Instr;
297 getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_PPC32Instr;
298 mapRegs = (void(*)(HRegRemap*,HInstr*)) mapRegs_PPC32Instr;
299 genSpill = (HInstr*(*)(HReg,Int)) genSpill_PPC32;
300 genReload = (HInstr*(*)(HReg,Int)) genReload_PPC32;
301 ppInstr = (void(*)(HInstr*)) ppPPC32Instr;
302 ppReg = (void(*)(HReg)) ppHRegPPC32;
303 iselBB = iselBB_PPC32;
304 emit = (Int(*)(UChar*,Int,HInstr*)) emit_PPC32Instr;
305 host_is_bigendian = True;
306 host_word_type = Ity_I32;
307 vassert(subarch_guest == VexSubArchPPC32_noAV
308 || subarch_guest == VexSubArchPPC32_AV);
309 break;
310
sewardjf13a16a2004-07-05 17:10:14 +0000311 default:
sewardj887a11a2004-07-05 17:26:47 +0000312 vpanic("LibVEX_Translate: unsupported target insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000313 }
314
sewardj2a9ad022004-11-25 02:46:58 +0000315
sewardjbef170b2004-12-21 01:23:00 +0000316 switch (arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000317
sewardjbef170b2004-12-21 01:23:00 +0000318 case VexArchX86:
sewardj8d2291c2004-10-25 14:50:21 +0000319 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
sewardj2a9ad022004-11-25 02:46:58 +0000320 bbToIR = bbToIR_X86;
321 specHelper = guest_x86_spechelper;
sewardj81ec4182004-10-25 23:15:52 +0000322 guest_sizeB = sizeof(VexGuestX86State);
sewardjcf787902004-11-03 09:08:33 +0000323 guest_word_type = Ity_I32;
sewardj49651f42004-10-28 22:11:04 +0000324 guest_layout = &x86guest_layout;
sewardj9df271d2004-12-31 22:37:42 +0000325 vassert(subarch_guest == VexSubArchX86_sse0
326 || subarch_guest == VexSubArchX86_sse1
327 || subarch_guest == VexSubArchX86_sse2);
sewardjf13a16a2004-07-05 17:10:14 +0000328 break;
sewardj2a9ad022004-11-25 02:46:58 +0000329
sewardj44d494d2005-01-20 20:26:33 +0000330 case VexArchAMD64:
331 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
332 bbToIR = bbToIR_AMD64;
333 specHelper = guest_amd64_spechelper;
334 guest_sizeB = sizeof(VexGuestAMD64State);
335 guest_word_type = Ity_I64;
336 guest_layout = &amd64guest_layout;
337 vassert(subarch_guest == VexSubArch_NONE);
338 break;
339
sewardjbef170b2004-12-21 01:23:00 +0000340 case VexArchARM:
sewardj2a9ad022004-11-25 02:46:58 +0000341 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
sewardjc2c87162004-11-25 13:07:02 +0000342 bbToIR = bbToIR_ARM;
sewardj2a9ad022004-11-25 02:46:58 +0000343 specHelper = guest_arm_spechelper;
344 guest_sizeB = sizeof(VexGuestARMState);
345 guest_word_type = Ity_I32;
346 guest_layout = &armGuest_layout;
sewardj44d494d2005-01-20 20:26:33 +0000347 vassert(subarch_guest == VexSubArchARM_v4);
sewardj2a9ad022004-11-25 02:46:58 +0000348 break;
349
cerionaabdfbf2005-01-29 12:56:15 +0000350 case VexArchPPC32:
351 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
352 bbToIR = bbToIR_PPC32;
353 specHelper = guest_ppc32_spechelper;
354 guest_sizeB = sizeof(VexGuestPPC32State);
355 guest_word_type = Ity_I32;
356 guest_layout = &ppc32Guest_layout;
sewardj0ec57c52005-02-01 15:24:10 +0000357 vassert(subarch_guest == VexSubArchPPC32_noAV
358 || subarch_guest == VexSubArchPPC32_AV);
cerionaabdfbf2005-01-29 12:56:15 +0000359 break;
360
sewardjf13a16a2004-07-05 17:10:14 +0000361 default:
sewardj887a11a2004-07-05 17:26:47 +0000362 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000363 }
364
sewardj9df271d2004-12-31 22:37:42 +0000365 /* yet more sanity checks ... */
sewardj0ec57c52005-02-01 15:24:10 +0000366 if (arch_guest == arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000367 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000368 we are simulating one flavour of an architecture a different
369 flavour of the same architecture, which is pretty strange. */
sewardj9df271d2004-12-31 22:37:42 +0000370 vassert(subarch_guest == subarch_host);
371 }
sewardj2a9ad022004-11-25 02:46:58 +0000372
sewardjf48ac192004-10-29 00:41:29 +0000373 if (vex_traceflags & VEX_TRACE_FE)
374 vex_printf("\n------------------------"
375 " Front end "
376 "------------------------\n\n");
377
sewardjf13a16a2004-07-05 17:10:14 +0000378 irbb = bbToIR ( guest_bytes,
sewardj72c72812005-01-19 11:49:45 +0000379 guest_bytes_addr,
380 guest_extents,
381 byte_accessible,
sewardj5bd4d162004-11-10 13:02:48 +0000382 chase_into_ok,
sewardj72c72812005-01-19 11:49:45 +0000383 host_is_bigendian,
sewardj9df271d2004-12-31 22:37:42 +0000384 subarch_guest );
sewardjf13a16a2004-07-05 17:10:14 +0000385
386 if (irbb == NULL) {
387 /* Access failure. */
sewardjd887b862005-01-17 18:34:34 +0000388 vexClearTEMP();
sewardjf48ac192004-10-29 00:41:29 +0000389 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000390 return VexTransAccessFail;
sewardjf13a16a2004-07-05 17:10:14 +0000391 }
sewardjaa59f942004-10-09 09:34:36 +0000392
sewardj72c72812005-01-19 11:49:45 +0000393 vassert(guest_extents->n_used >= 1 && guest_extents->n_used <= 3);
394 vassert(guest_extents->base[0] == guest_bytes_addr);
395 for (i = 0; i < guest_extents->n_used; i++) {
396 vassert(guest_extents->len[i] < 10000); /* sanity */
397 }
398
sewardjaa59f942004-10-09 09:34:36 +0000399 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000400 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj72c72812005-01-19 11:49:45 +0000401 if (guest_extents->n_used > 1) {
402 vex_printf("can't show code due to extents > 1\n");
403 } else {
404 /* HACK */
405 UChar* p = (UChar*)guest_bytes;
406 UInt guest_bytes_read = (UInt)guest_extents->len[0];
sewardjd9763622005-02-07 03:12:19 +0000407 vex_printf(". 0 %llx %u\n.", guest_bytes_addr, guest_bytes_read );
sewardj72c72812005-01-19 11:49:45 +0000408 for (i = 0; i < guest_bytes_read; i++)
sewardjaa59f942004-10-09 09:34:36 +0000409 vex_printf(" %02x", (Int)p[i] );
sewardj72c72812005-01-19 11:49:45 +0000410 vex_printf("\n\n");
411 }
sewardjaa59f942004-10-09 09:34:36 +0000412 }
413
414 /* Sanity check the initial IR. */
sewardjb9230752004-12-29 19:25:06 +0000415 sanityCheckIRBB( irbb, "initial IR",
416 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000417
sewardjedf4d692004-08-17 13:52:58 +0000418 /* Clean it up, hopefully a lot. */
sewardj8d2291c2004-10-25 14:50:21 +0000419 irbb = do_iropt_BB ( irbb, specHelper, preciseMemExnsFn,
420 guest_bytes_addr );
sewardjb9230752004-12-29 19:25:06 +0000421 sanityCheckIRBB( irbb, "after initial iropt",
422 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000423
sewardjf48ac192004-10-29 00:41:29 +0000424 if (vex_traceflags & VEX_TRACE_OPT1) {
425 vex_printf("\n------------------------"
426 " After pre-instr IR optimisation "
427 "------------------------\n\n");
sewardjedf4d692004-08-17 13:52:58 +0000428 ppIRBB ( irbb );
429 vex_printf("\n");
430 }
431
sewardjf13a16a2004-07-05 17:10:14 +0000432 /* Get the thing instrumented. */
sewardj49651f42004-10-28 22:11:04 +0000433 if (instrument1)
sewardjcf787902004-11-03 09:08:33 +0000434 irbb = (*instrument1)(irbb, guest_layout, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000435 if (instrument2)
sewardjcf787902004-11-03 09:08:33 +0000436 irbb = (*instrument2)(irbb, guest_layout, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000437
sewardjf48ac192004-10-29 00:41:29 +0000438 if (vex_traceflags & VEX_TRACE_INST) {
439 vex_printf("\n------------------------"
440 " After instrumentation "
441 "------------------------\n\n");
442 ppIRBB ( irbb );
443 vex_printf("\n");
444 }
445
sewardj49651f42004-10-28 22:11:04 +0000446 if (instrument1 || instrument2)
sewardjb9230752004-12-29 19:25:06 +0000447 sanityCheckIRBB( irbb, "after instrumentation",
448 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000449
sewardj9578a8b2004-11-04 19:44:48 +0000450 /* Do a post-instrumentation cleanup pass. */
451 if (cleanup_after_instrumentation) {
452 do_deadcode_BB( irbb );
453 irbb = cprop_BB( irbb );
454 do_deadcode_BB( irbb );
sewardjb9230752004-12-29 19:25:06 +0000455 sanityCheckIRBB( irbb, "after post-instrumentation cleanup",
456 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000457 }
458
459 if (vex_traceflags & VEX_TRACE_OPT2) {
460 vex_printf("\n------------------------"
461 " After post-instr IR optimisation "
462 "------------------------\n\n");
463 ppIRBB ( irbb );
464 vex_printf("\n");
465 }
466
sewardjf13a16a2004-07-05 17:10:14 +0000467 /* Turn it into virtual-registerised code. */
sewardj49651f42004-10-28 22:11:04 +0000468 do_deadcode_BB( irbb );
469 do_treebuild_BB( irbb );
sewardjf48ac192004-10-29 00:41:29 +0000470
471 if (vex_traceflags & VEX_TRACE_TREES) {
472 vex_printf("\n------------------------"
473 " After tree-building "
474 "------------------------\n\n");
475 ppIRBB ( irbb );
476 vex_printf("\n");
477 }
478
sewardje908c422005-02-04 21:18:16 +0000479 /* HACK */
cerion54560812005-02-03 13:40:49 +0000480 if (0) { *host_bytes_used = 0; return VexTransOK; }
sewardje908c422005-02-04 21:18:16 +0000481 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000482
sewardjf48ac192004-10-29 00:41:29 +0000483 if (vex_traceflags & VEX_TRACE_VCODE)
484 vex_printf("\n------------------------"
485 " Instruction selection "
486 "------------------------\n");
487
sewardj9df271d2004-12-31 22:37:42 +0000488 vcode = iselBB ( irbb, subarch_host );
sewardjf13a16a2004-07-05 17:10:14 +0000489
sewardjf48ac192004-10-29 00:41:29 +0000490 if (vex_traceflags & VEX_TRACE_VCODE)
491 vex_printf("\n");
492
sewardjf48ac192004-10-29 00:41:29 +0000493 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000494 for (i = 0; i < vcode->arr_used; i++) {
495 vex_printf("%3d ", i);
496 ppInstr(vcode->arr[i]);
497 vex_printf("\n");
498 }
sewardjfbcaf332004-07-08 01:46:01 +0000499 vex_printf("\n");
500 }
sewardjfbcaf332004-07-08 01:46:01 +0000501
sewardjf13a16a2004-07-05 17:10:14 +0000502 /* Register allocate. */
503 rcode = doRegisterAllocation ( vcode, available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000504 n_available_real_regs,
505 isMove, getRegUsage, mapRegs,
506 genSpill, genReload, guest_sizeB,
507 ppInstr, ppReg );
sewardjf13a16a2004-07-05 17:10:14 +0000508
sewardjf48ac192004-10-29 00:41:29 +0000509 if (vex_traceflags & VEX_TRACE_RCODE) {
510 vex_printf("\n------------------------"
511 " Register-allocated code "
512 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000513 for (i = 0; i < rcode->arr_used; i++) {
514 vex_printf("%3d ", i);
515 ppInstr(rcode->arr[i]);
516 vex_printf("\n");
517 }
sewardjfbcaf332004-07-08 01:46:01 +0000518 vex_printf("\n");
519 }
sewardjfbcaf332004-07-08 01:46:01 +0000520
sewardje908c422005-02-04 21:18:16 +0000521 /* HACK */
522 if (0) { *host_bytes_used = 0; return VexTransOK; }
523 /* end HACK */
524
sewardj81bd5502004-07-21 18:49:27 +0000525 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000526 if (vex_traceflags & VEX_TRACE_ASM) {
527 vex_printf("\n------------------------"
528 " Assembly "
529 "------------------------\n\n");
530 }
531
sewardj81bd5502004-07-21 18:49:27 +0000532 out_used = 0; /* tracks along the host_bytes array */
533 for (i = 0; i < rcode->arr_used; i++) {
sewardjf48ac192004-10-29 00:41:29 +0000534 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000535 ppInstr(rcode->arr[i]);
536 vex_printf("\n");
537 }
sewardj81bd5502004-07-21 18:49:27 +0000538 j = (*emit)( insn_bytes, 32, rcode->arr[i] );
sewardjf48ac192004-10-29 00:41:29 +0000539 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000540 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000541 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000542 vex_printf("0%x ", (UInt)insn_bytes[k]);
543 else
544 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000545 vex_printf("\n\n");
546 }
sewardj81bd5502004-07-21 18:49:27 +0000547 if (out_used + j > host_bytes_size) {
sewardjd887b862005-01-17 18:34:34 +0000548 vexClearTEMP();
sewardjf48ac192004-10-29 00:41:29 +0000549 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000550 return VexTransOutputFull;
sewardj81bd5502004-07-21 18:49:27 +0000551 }
552 for (k = 0; k < j; k++) {
553 host_bytes[out_used] = insn_bytes[k];
554 out_used++;
555 }
556 vassert(out_used <= host_bytes_size);
557 }
558 *host_bytes_used = out_used;
559
sewardjd887b862005-01-17 18:34:34 +0000560 vexClearTEMP();
sewardjf13a16a2004-07-05 17:10:14 +0000561
sewardjf48ac192004-10-29 00:41:29 +0000562 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000563 return VexTransOK;
sewardj35421a32004-07-05 13:12:34 +0000564}
565
566
sewardj893aada2004-11-29 19:57:54 +0000567/* --------- Emulation warnings. --------- */
568
569HChar* LibVEX_EmWarn_string ( VexEmWarn ew )
570{
571 switch (ew) {
572 case EmWarn_NONE:
573 return "none";
574 case EmWarn_X86_x87exns:
575 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000576 case EmWarn_X86_x87precision:
577 return "Selection of non-80-bit x87 FP precision";
578 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +0000579 return "Unmasking SSE FP exceptions";
580 case EmWarn_X86_fz:
581 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
582 case EmWarn_X86_daz:
583 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj893aada2004-11-29 19:57:54 +0000584 default:
585 vpanic("LibVEX_EmWarn_string: unknown warning");
586 }
587}
sewardj35421a32004-07-05 13:12:34 +0000588
sewardjbef170b2004-12-21 01:23:00 +0000589/* --------- Arch/Subarch names. --------- */
590
591const HChar* LibVEX_ppVexArch ( VexArch arch )
592{
593 switch (arch) {
594 case VexArch_INVALID: return "INVALID";
595 case VexArchX86: return "X86";
596 case VexArchAMD64: return "AMD64";
597 case VexArchARM: return "ARM";
sewardj0ec57c52005-02-01 15:24:10 +0000598 case VexArchPPC32: return "PPC32";
sewardjbef170b2004-12-21 01:23:00 +0000599 default: return "VexArch???";
600 }
601}
602
603const HChar* LibVEX_ppVexSubArch ( VexSubArch subarch )
604{
605 switch (subarch) {
sewardj0ec57c52005-02-01 15:24:10 +0000606 case VexSubArch_INVALID: return "INVALID";
607 case VexSubArch_NONE: return "NONE";
608 case VexSubArchX86_sse0: return "x86-sse0";
609 case VexSubArchX86_sse1: return "x86-sse1";
610 case VexSubArchX86_sse2: return "x86-sse2";
611 case VexSubArchARM_v4: return "arm-v4";
612 case VexSubArchPPC32_noAV: return "ppc32-noAltivec";
613 case VexSubArchPPC32_AV: return "ppc32-Altivec";
614 default: return "VexSubArch???";
sewardjbef170b2004-12-21 01:23:00 +0000615 }
616}
617
sewardj35421a32004-07-05 13:12:34 +0000618/*---------------------------------------------------------------*/
sewardjc0ee2ed2004-07-27 10:29:41 +0000619/*--- end main/vex_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +0000620/*---------------------------------------------------------------*/