blob: 538255f261a4276e4e7d8bc0c3149a6a4e00db04 [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;
sewardj18b4bb72005-03-29 21:32:41 +000080 vcon->guest_max_insns = 60;
sewardj08613742004-10-25 13:01:45 +000081 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. */
sewardj918c8f32005-03-21 00:54:33 +0000187 IRBB* (*instrument1) ( IRBB*, VexGuestLayout*,
188 IRType gWordTy, IRType hWordTy ),
189 IRBB* (*instrument2) ( IRBB*, VexGuestLayout*,
190 IRType gWordTy, IRType hWordTy ),
sewardjbef170b2004-12-21 01:23:00 +0000191 Bool cleanup_after_instrumentation,
sewardj35421a32004-07-05 13:12:34 +0000192 /* IN: optionally, an access check function for guest code. */
sewardjbef170b2004-12-21 01:23:00 +0000193 Bool (*byte_accessible) ( Addr64 ),
sewardjf48ac192004-10-29 00:41:29 +0000194 /* IN: debug: trace vex activity at various points */
sewardjbef170b2004-12-21 01:23:00 +0000195 Int traceflags
sewardj35421a32004-07-05 13:12:34 +0000196)
197{
sewardj81bd5502004-07-21 18:49:27 +0000198 /* This the bundle of functions we need to do the back-end stuff
199 (insn selection, reg-alloc, assembly) whilst being insulated
200 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +0000201 HReg* available_real_regs;
202 Int n_available_real_regs;
sewardj443cd9d2004-07-18 23:06:45 +0000203 Bool (*isMove) (HInstr*, HReg*, HReg*);
204 void (*getRegUsage) (HRegUsage*, HInstr*);
205 void (*mapRegs) (HRegRemap*, HInstr*);
206 HInstr* (*genSpill) ( HReg, Int );
207 HInstr* (*genReload) ( HReg, Int );
208 void (*ppInstr) ( HInstr* );
209 void (*ppReg) ( HReg );
sewardj9df271d2004-12-31 22:37:42 +0000210 HInstrArray* (*iselBB) ( IRBB*, VexSubArch );
sewardj72c72812005-01-19 11:49:45 +0000211 IRBB* (*bbToIR) ( UChar*, Addr64,
212 VexGuestExtents*,
sewardj5bd4d162004-11-10 13:02:48 +0000213 Bool(*)(Addr64),
sewardj72c72812005-01-19 11:49:45 +0000214 Bool(*)(Addr64),
215 Bool, VexSubArch );
sewardj81bd5502004-07-21 18:49:27 +0000216 Int (*emit) ( UChar*, Int, HInstr* );
sewardjd9763622005-02-07 03:12:19 +0000217 IRExpr* (*specHelper) ( HChar*, IRExpr** );
sewardj8d2291c2004-10-25 14:50:21 +0000218 Bool (*preciseMemExnsFn) ( Int, Int );
sewardjf13a16a2004-07-05 17:10:14 +0000219
sewardjeeac8412004-11-02 00:26:55 +0000220 VexGuestLayout* guest_layout;
221 Bool host_is_bigendian = False;
222 IRBB* irbb;
223 HInstrArray* vcode;
224 HInstrArray* rcode;
225 Int i, j, k, out_used, guest_sizeB;
226 UChar insn_bytes[32];
sewardjcf787902004-11-03 09:08:33 +0000227 IRType guest_word_type;
228 IRType host_word_type;
sewardjf13a16a2004-07-05 17:10:14 +0000229
sewardj49651f42004-10-28 22:11:04 +0000230 guest_layout = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000231 available_real_regs = NULL;
232 n_available_real_regs = 0;
233 isMove = NULL;
234 getRegUsage = NULL;
235 mapRegs = NULL;
236 genSpill = NULL;
237 genReload = NULL;
238 ppInstr = NULL;
239 ppReg = NULL;
240 iselBB = NULL;
241 bbToIR = NULL;
242 emit = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000243 specHelper = NULL;
sewardj8d2291c2004-10-25 14:50:21 +0000244 preciseMemExnsFn = NULL;
sewardjcf787902004-11-03 09:08:33 +0000245 guest_word_type = Ity_INVALID;
246 host_word_type = Ity_INVALID;
sewardj36ca5132004-07-24 13:12:23 +0000247
sewardjf48ac192004-10-29 00:41:29 +0000248 vex_traceflags = traceflags;
sewardj58800ff2004-07-28 01:51:10 +0000249
sewardj35421a32004-07-05 13:12:34 +0000250 vassert(vex_initdone);
sewardjd887b862005-01-17 18:34:34 +0000251 vexClearTEMP();
sewardjf13a16a2004-07-05 17:10:14 +0000252
sewardj2a9ad022004-11-25 02:46:58 +0000253
sewardjf13a16a2004-07-05 17:10:14 +0000254 /* First off, check that the guest and host insn sets
255 are supported. */
sewardj2a9ad022004-11-25 02:46:58 +0000256
sewardjbef170b2004-12-21 01:23:00 +0000257 switch (arch_host) {
sewardj2a9ad022004-11-25 02:46:58 +0000258
sewardjbef170b2004-12-21 01:23:00 +0000259 case VexArchX86:
sewardjf13a16a2004-07-05 17:10:14 +0000260 getAllocableRegs_X86 ( &n_available_real_regs,
261 &available_real_regs );
262 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
263 getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_X86Instr;
264 mapRegs = (void(*)(HRegRemap*,HInstr*)) mapRegs_X86Instr;
265 genSpill = (HInstr*(*)(HReg,Int)) genSpill_X86;
266 genReload = (HInstr*(*)(HReg,Int)) genReload_X86;
sewardj2b515872004-07-05 20:50:45 +0000267 ppInstr = (void(*)(HInstr*)) ppX86Instr;
268 ppReg = (void(*)(HReg)) ppHRegX86;
sewardjf13a16a2004-07-05 17:10:14 +0000269 iselBB = iselBB_X86;
sewardj81bd5502004-07-21 18:49:27 +0000270 emit = (Int(*)(UChar*,Int,HInstr*)) emit_X86Instr;
sewardj72c72812005-01-19 11:49:45 +0000271 host_is_bigendian = False;
sewardjcf787902004-11-03 09:08:33 +0000272 host_word_type = Ity_I32;
sewardj9df271d2004-12-31 22:37:42 +0000273 vassert(subarch_host == VexSubArchX86_sse0
274 || subarch_host == VexSubArchX86_sse1
275 || subarch_host == VexSubArchX86_sse2);
sewardjf13a16a2004-07-05 17:10:14 +0000276 break;
sewardj2a9ad022004-11-25 02:46:58 +0000277
sewardjc33671d2005-02-01 20:30:00 +0000278 case VexArchAMD64:
279 getAllocableRegs_AMD64 ( &n_available_real_regs,
280 &available_real_regs );
281 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr;
282 getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_AMD64Instr;
283 mapRegs = (void(*)(HRegRemap*,HInstr*)) mapRegs_AMD64Instr;
284 genSpill = (HInstr*(*)(HReg,Int)) genSpill_AMD64;
285 genReload = (HInstr*(*)(HReg,Int)) genReload_AMD64;
286 ppInstr = (void(*)(HInstr*)) ppAMD64Instr;
287 ppReg = (void(*)(HReg)) ppHRegAMD64;
288 iselBB = iselBB_AMD64;
289 emit = (Int(*)(UChar*,Int,HInstr*)) emit_AMD64Instr;
290 host_is_bigendian = False;
291 host_word_type = Ity_I64;
292 vassert(subarch_host == VexSubArch_NONE);
293 break;
294
cerion487e4c92005-02-04 16:28:19 +0000295 case VexArchPPC32:
296 getAllocableRegs_PPC32 ( &n_available_real_regs,
297 &available_real_regs );
298 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPC32Instr;
299 getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_PPC32Instr;
300 mapRegs = (void(*)(HRegRemap*,HInstr*)) mapRegs_PPC32Instr;
301 genSpill = (HInstr*(*)(HReg,Int)) genSpill_PPC32;
302 genReload = (HInstr*(*)(HReg,Int)) genReload_PPC32;
303 ppInstr = (void(*)(HInstr*)) ppPPC32Instr;
304 ppReg = (void(*)(HReg)) ppHRegPPC32;
305 iselBB = iselBB_PPC32;
306 emit = (Int(*)(UChar*,Int,HInstr*)) emit_PPC32Instr;
307 host_is_bigendian = True;
308 host_word_type = Ity_I32;
309 vassert(subarch_guest == VexSubArchPPC32_noAV
310 || subarch_guest == VexSubArchPPC32_AV);
311 break;
312
sewardjf13a16a2004-07-05 17:10:14 +0000313 default:
sewardj887a11a2004-07-05 17:26:47 +0000314 vpanic("LibVEX_Translate: unsupported target insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000315 }
316
sewardj2a9ad022004-11-25 02:46:58 +0000317
sewardjbef170b2004-12-21 01:23:00 +0000318 switch (arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000319
sewardjbef170b2004-12-21 01:23:00 +0000320 case VexArchX86:
sewardj8d2291c2004-10-25 14:50:21 +0000321 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
sewardj2a9ad022004-11-25 02:46:58 +0000322 bbToIR = bbToIR_X86;
323 specHelper = guest_x86_spechelper;
sewardj81ec4182004-10-25 23:15:52 +0000324 guest_sizeB = sizeof(VexGuestX86State);
sewardjcf787902004-11-03 09:08:33 +0000325 guest_word_type = Ity_I32;
sewardj49651f42004-10-28 22:11:04 +0000326 guest_layout = &x86guest_layout;
sewardj9df271d2004-12-31 22:37:42 +0000327 vassert(subarch_guest == VexSubArchX86_sse0
328 || subarch_guest == VexSubArchX86_sse1
329 || subarch_guest == VexSubArchX86_sse2);
sewardjf13a16a2004-07-05 17:10:14 +0000330 break;
sewardj2a9ad022004-11-25 02:46:58 +0000331
sewardj44d494d2005-01-20 20:26:33 +0000332 case VexArchAMD64:
333 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
334 bbToIR = bbToIR_AMD64;
335 specHelper = guest_amd64_spechelper;
336 guest_sizeB = sizeof(VexGuestAMD64State);
337 guest_word_type = Ity_I64;
338 guest_layout = &amd64guest_layout;
339 vassert(subarch_guest == VexSubArch_NONE);
340 break;
341
sewardjbef170b2004-12-21 01:23:00 +0000342 case VexArchARM:
sewardj2a9ad022004-11-25 02:46:58 +0000343 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
sewardjc2c87162004-11-25 13:07:02 +0000344 bbToIR = bbToIR_ARM;
sewardj2a9ad022004-11-25 02:46:58 +0000345 specHelper = guest_arm_spechelper;
346 guest_sizeB = sizeof(VexGuestARMState);
347 guest_word_type = Ity_I32;
348 guest_layout = &armGuest_layout;
sewardj44d494d2005-01-20 20:26:33 +0000349 vassert(subarch_guest == VexSubArchARM_v4);
sewardj2a9ad022004-11-25 02:46:58 +0000350 break;
351
cerionaabdfbf2005-01-29 12:56:15 +0000352 case VexArchPPC32:
353 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
354 bbToIR = bbToIR_PPC32;
355 specHelper = guest_ppc32_spechelper;
356 guest_sizeB = sizeof(VexGuestPPC32State);
357 guest_word_type = Ity_I32;
358 guest_layout = &ppc32Guest_layout;
sewardj0ec57c52005-02-01 15:24:10 +0000359 vassert(subarch_guest == VexSubArchPPC32_noAV
360 || subarch_guest == VexSubArchPPC32_AV);
cerionaabdfbf2005-01-29 12:56:15 +0000361 break;
362
sewardjf13a16a2004-07-05 17:10:14 +0000363 default:
sewardj887a11a2004-07-05 17:26:47 +0000364 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000365 }
366
sewardj9df271d2004-12-31 22:37:42 +0000367 /* yet more sanity checks ... */
sewardj0ec57c52005-02-01 15:24:10 +0000368 if (arch_guest == arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000369 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000370 we are simulating one flavour of an architecture a different
371 flavour of the same architecture, which is pretty strange. */
sewardj9df271d2004-12-31 22:37:42 +0000372 vassert(subarch_guest == subarch_host);
373 }
sewardj2a9ad022004-11-25 02:46:58 +0000374
sewardjf48ac192004-10-29 00:41:29 +0000375 if (vex_traceflags & VEX_TRACE_FE)
376 vex_printf("\n------------------------"
377 " Front end "
378 "------------------------\n\n");
379
sewardjf13a16a2004-07-05 17:10:14 +0000380 irbb = bbToIR ( guest_bytes,
sewardj72c72812005-01-19 11:49:45 +0000381 guest_bytes_addr,
382 guest_extents,
383 byte_accessible,
sewardj5bd4d162004-11-10 13:02:48 +0000384 chase_into_ok,
sewardj72c72812005-01-19 11:49:45 +0000385 host_is_bigendian,
sewardj9df271d2004-12-31 22:37:42 +0000386 subarch_guest );
sewardjf13a16a2004-07-05 17:10:14 +0000387
388 if (irbb == NULL) {
389 /* Access failure. */
sewardjd887b862005-01-17 18:34:34 +0000390 vexClearTEMP();
sewardjf48ac192004-10-29 00:41:29 +0000391 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000392 return VexTransAccessFail;
sewardjf13a16a2004-07-05 17:10:14 +0000393 }
sewardjaa59f942004-10-09 09:34:36 +0000394
sewardj72c72812005-01-19 11:49:45 +0000395 vassert(guest_extents->n_used >= 1 && guest_extents->n_used <= 3);
396 vassert(guest_extents->base[0] == guest_bytes_addr);
397 for (i = 0; i < guest_extents->n_used; i++) {
398 vassert(guest_extents->len[i] < 10000); /* sanity */
399 }
400
sewardjaa59f942004-10-09 09:34:36 +0000401 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000402 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj72c72812005-01-19 11:49:45 +0000403 if (guest_extents->n_used > 1) {
404 vex_printf("can't show code due to extents > 1\n");
405 } else {
406 /* HACK */
407 UChar* p = (UChar*)guest_bytes;
408 UInt guest_bytes_read = (UInt)guest_extents->len[0];
sewardjd9763622005-02-07 03:12:19 +0000409 vex_printf(". 0 %llx %u\n.", guest_bytes_addr, guest_bytes_read );
sewardj72c72812005-01-19 11:49:45 +0000410 for (i = 0; i < guest_bytes_read; i++)
sewardjaa59f942004-10-09 09:34:36 +0000411 vex_printf(" %02x", (Int)p[i] );
sewardj72c72812005-01-19 11:49:45 +0000412 vex_printf("\n\n");
413 }
sewardjaa59f942004-10-09 09:34:36 +0000414 }
415
416 /* Sanity check the initial IR. */
sewardjb9230752004-12-29 19:25:06 +0000417 sanityCheckIRBB( irbb, "initial IR",
418 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000419
sewardjedf4d692004-08-17 13:52:58 +0000420 /* Clean it up, hopefully a lot. */
sewardj8d2291c2004-10-25 14:50:21 +0000421 irbb = do_iropt_BB ( irbb, specHelper, preciseMemExnsFn,
422 guest_bytes_addr );
sewardjb9230752004-12-29 19:25:06 +0000423 sanityCheckIRBB( irbb, "after initial iropt",
424 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000425
sewardjf48ac192004-10-29 00:41:29 +0000426 if (vex_traceflags & VEX_TRACE_OPT1) {
427 vex_printf("\n------------------------"
428 " After pre-instr IR optimisation "
429 "------------------------\n\n");
sewardjedf4d692004-08-17 13:52:58 +0000430 ppIRBB ( irbb );
431 vex_printf("\n");
432 }
433
sewardjf13a16a2004-07-05 17:10:14 +0000434 /* Get the thing instrumented. */
sewardj49651f42004-10-28 22:11:04 +0000435 if (instrument1)
sewardj918c8f32005-03-21 00:54:33 +0000436 irbb = (*instrument1)(irbb, guest_layout,
437 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000438 if (instrument2)
sewardj918c8f32005-03-21 00:54:33 +0000439 irbb = (*instrument2)(irbb, guest_layout,
440 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000441
sewardjf48ac192004-10-29 00:41:29 +0000442 if (vex_traceflags & VEX_TRACE_INST) {
443 vex_printf("\n------------------------"
444 " After instrumentation "
445 "------------------------\n\n");
446 ppIRBB ( irbb );
447 vex_printf("\n");
448 }
449
sewardj49651f42004-10-28 22:11:04 +0000450 if (instrument1 || instrument2)
sewardjb9230752004-12-29 19:25:06 +0000451 sanityCheckIRBB( irbb, "after instrumentation",
452 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000453
sewardj9578a8b2004-11-04 19:44:48 +0000454 /* Do a post-instrumentation cleanup pass. */
455 if (cleanup_after_instrumentation) {
456 do_deadcode_BB( irbb );
457 irbb = cprop_BB( irbb );
458 do_deadcode_BB( irbb );
sewardjb9230752004-12-29 19:25:06 +0000459 sanityCheckIRBB( irbb, "after post-instrumentation cleanup",
460 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000461 }
462
463 if (vex_traceflags & VEX_TRACE_OPT2) {
464 vex_printf("\n------------------------"
465 " After post-instr IR optimisation "
466 "------------------------\n\n");
467 ppIRBB ( irbb );
468 vex_printf("\n");
469 }
470
sewardjf13a16a2004-07-05 17:10:14 +0000471 /* Turn it into virtual-registerised code. */
sewardj49651f42004-10-28 22:11:04 +0000472 do_deadcode_BB( irbb );
473 do_treebuild_BB( irbb );
sewardjf48ac192004-10-29 00:41:29 +0000474
475 if (vex_traceflags & VEX_TRACE_TREES) {
476 vex_printf("\n------------------------"
477 " After tree-building "
478 "------------------------\n\n");
479 ppIRBB ( irbb );
480 vex_printf("\n");
481 }
482
sewardje908c422005-02-04 21:18:16 +0000483 /* HACK */
cerion54560812005-02-03 13:40:49 +0000484 if (0) { *host_bytes_used = 0; return VexTransOK; }
sewardje908c422005-02-04 21:18:16 +0000485 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000486
sewardjf48ac192004-10-29 00:41:29 +0000487 if (vex_traceflags & VEX_TRACE_VCODE)
488 vex_printf("\n------------------------"
489 " Instruction selection "
490 "------------------------\n");
491
sewardj9df271d2004-12-31 22:37:42 +0000492 vcode = iselBB ( irbb, subarch_host );
sewardjf13a16a2004-07-05 17:10:14 +0000493
sewardjf48ac192004-10-29 00:41:29 +0000494 if (vex_traceflags & VEX_TRACE_VCODE)
495 vex_printf("\n");
496
sewardjf48ac192004-10-29 00:41:29 +0000497 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000498 for (i = 0; i < vcode->arr_used; i++) {
499 vex_printf("%3d ", i);
500 ppInstr(vcode->arr[i]);
501 vex_printf("\n");
502 }
sewardjfbcaf332004-07-08 01:46:01 +0000503 vex_printf("\n");
504 }
sewardjfbcaf332004-07-08 01:46:01 +0000505
sewardjf13a16a2004-07-05 17:10:14 +0000506 /* Register allocate. */
507 rcode = doRegisterAllocation ( vcode, available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000508 n_available_real_regs,
509 isMove, getRegUsage, mapRegs,
510 genSpill, genReload, guest_sizeB,
511 ppInstr, ppReg );
sewardjf13a16a2004-07-05 17:10:14 +0000512
sewardjf48ac192004-10-29 00:41:29 +0000513 if (vex_traceflags & VEX_TRACE_RCODE) {
514 vex_printf("\n------------------------"
515 " Register-allocated code "
516 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000517 for (i = 0; i < rcode->arr_used; i++) {
518 vex_printf("%3d ", i);
519 ppInstr(rcode->arr[i]);
520 vex_printf("\n");
521 }
sewardjfbcaf332004-07-08 01:46:01 +0000522 vex_printf("\n");
523 }
sewardjfbcaf332004-07-08 01:46:01 +0000524
sewardje908c422005-02-04 21:18:16 +0000525 /* HACK */
526 if (0) { *host_bytes_used = 0; return VexTransOK; }
527 /* end HACK */
528
sewardj81bd5502004-07-21 18:49:27 +0000529 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000530 if (vex_traceflags & VEX_TRACE_ASM) {
531 vex_printf("\n------------------------"
532 " Assembly "
533 "------------------------\n\n");
534 }
535
sewardj81bd5502004-07-21 18:49:27 +0000536 out_used = 0; /* tracks along the host_bytes array */
537 for (i = 0; i < rcode->arr_used; i++) {
sewardjf48ac192004-10-29 00:41:29 +0000538 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000539 ppInstr(rcode->arr[i]);
540 vex_printf("\n");
541 }
sewardj81bd5502004-07-21 18:49:27 +0000542 j = (*emit)( insn_bytes, 32, rcode->arr[i] );
sewardjf48ac192004-10-29 00:41:29 +0000543 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000544 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000545 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000546 vex_printf("0%x ", (UInt)insn_bytes[k]);
547 else
548 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000549 vex_printf("\n\n");
550 }
sewardj81bd5502004-07-21 18:49:27 +0000551 if (out_used + j > host_bytes_size) {
sewardjd887b862005-01-17 18:34:34 +0000552 vexClearTEMP();
sewardjf48ac192004-10-29 00:41:29 +0000553 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000554 return VexTransOutputFull;
sewardj81bd5502004-07-21 18:49:27 +0000555 }
556 for (k = 0; k < j; k++) {
557 host_bytes[out_used] = insn_bytes[k];
558 out_used++;
559 }
560 vassert(out_used <= host_bytes_size);
561 }
562 *host_bytes_used = out_used;
563
sewardjd887b862005-01-17 18:34:34 +0000564 vexClearTEMP();
sewardjf13a16a2004-07-05 17:10:14 +0000565
sewardjf48ac192004-10-29 00:41:29 +0000566 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000567 return VexTransOK;
sewardj35421a32004-07-05 13:12:34 +0000568}
569
570
sewardj893aada2004-11-29 19:57:54 +0000571/* --------- Emulation warnings. --------- */
572
573HChar* LibVEX_EmWarn_string ( VexEmWarn ew )
574{
575 switch (ew) {
576 case EmWarn_NONE:
577 return "none";
578 case EmWarn_X86_x87exns:
579 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000580 case EmWarn_X86_x87precision:
581 return "Selection of non-80-bit x87 FP precision";
582 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +0000583 return "Unmasking SSE FP exceptions";
584 case EmWarn_X86_fz:
585 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
586 case EmWarn_X86_daz:
587 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj893aada2004-11-29 19:57:54 +0000588 default:
589 vpanic("LibVEX_EmWarn_string: unknown warning");
590 }
591}
sewardj35421a32004-07-05 13:12:34 +0000592
sewardjbef170b2004-12-21 01:23:00 +0000593/* --------- Arch/Subarch names. --------- */
594
595const HChar* LibVEX_ppVexArch ( VexArch arch )
596{
597 switch (arch) {
598 case VexArch_INVALID: return "INVALID";
599 case VexArchX86: return "X86";
600 case VexArchAMD64: return "AMD64";
601 case VexArchARM: return "ARM";
sewardj0ec57c52005-02-01 15:24:10 +0000602 case VexArchPPC32: return "PPC32";
sewardjbef170b2004-12-21 01:23:00 +0000603 default: return "VexArch???";
604 }
605}
606
607const HChar* LibVEX_ppVexSubArch ( VexSubArch subarch )
608{
609 switch (subarch) {
sewardj0ec57c52005-02-01 15:24:10 +0000610 case VexSubArch_INVALID: return "INVALID";
611 case VexSubArch_NONE: return "NONE";
612 case VexSubArchX86_sse0: return "x86-sse0";
613 case VexSubArchX86_sse1: return "x86-sse1";
614 case VexSubArchX86_sse2: return "x86-sse2";
615 case VexSubArchARM_v4: return "arm-v4";
616 case VexSubArchPPC32_noAV: return "ppc32-noAltivec";
617 case VexSubArchPPC32_AV: return "ppc32-Altivec";
618 default: return "VexSubArch???";
sewardjbef170b2004-12-21 01:23:00 +0000619 }
620}
621
sewardj35421a32004-07-05 13:12:34 +0000622/*---------------------------------------------------------------*/
sewardjc0ee2ed2004-07-27 10:29:41 +0000623/*--- end main/vex_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +0000624/*---------------------------------------------------------------*/