blob: 01567a0e75a490f14f21d01df23b4e3f8070f757 [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"
sewardj2a9ad022004-11-25 02:46:58 +000050
51#include "guest-x86/gdefs.h"
sewardj44d494d2005-01-20 20:26:33 +000052#include "guest-amd64/gdefs.h"
sewardj2a9ad022004-11-25 02:46:58 +000053#include "guest-arm/gdefs.h"
cerionaabdfbf2005-01-29 12:56:15 +000054#include "guest-ppc32/gdefs.h"
sewardj2a9ad022004-11-25 02:46:58 +000055
sewardj35421a32004-07-05 13:12:34 +000056
57/* This file contains the top level interface to the library. */
58
59/* --------- Initialise the library. --------- */
60
61/* Exported to library client. */
62
sewardjd887b862005-01-17 18:34:34 +000063const HChar* LibVEX_Version ( void )
sewardj80f5fce2004-12-20 04:37:50 +000064{
65return
66#include "main/vex_svnversion.h"
67 ;
68}
69
70
71/* Exported to library client. */
72
sewardj08613742004-10-25 13:01:45 +000073void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon )
74{
75 vcon->iropt_verbosity = 0;
76 vcon->iropt_level = 2;
77 vcon->iropt_precise_memory_exns = False;
78 vcon->iropt_unroll_thresh = 120;
79 vcon->guest_max_insns = 50;
80 vcon->guest_chase_thresh = 10;
81}
82
83
84/* Exported to library client. */
85
sewardj887a11a2004-07-05 17:26:47 +000086void LibVEX_Init (
sewardj35421a32004-07-05 13:12:34 +000087 /* failure exit function */
sewardj2b515872004-07-05 20:50:45 +000088 __attribute__ ((noreturn))
sewardj35421a32004-07-05 13:12:34 +000089 void (*failure_exit) ( void ),
90 /* logging output function */
91 void (*log_bytes) ( Char*, Int nbytes ),
92 /* debug paranoia level */
93 Int debuglevel,
sewardj35421a32004-07-05 13:12:34 +000094 /* Are we supporting valgrind checking? */
95 Bool valgrind_support,
sewardj08613742004-10-25 13:01:45 +000096 /* Control ... */
97 /*READONLY*/VexControl* vcon
sewardj35421a32004-07-05 13:12:34 +000098)
99{
sewardj08613742004-10-25 13:01:45 +0000100 /* First off, do enough minimal setup so that the following
101 assertions can fail in a sane fashion, if need be. */
sewardjea602bc2004-10-14 21:40:12 +0000102 vex_failure_exit = failure_exit;
103 vex_log_bytes = log_bytes;
104
105 /* Now it's safe to check parameters for sanity. */
sewardj35421a32004-07-05 13:12:34 +0000106 vassert(!vex_initdone);
107 vassert(failure_exit);
sewardj35421a32004-07-05 13:12:34 +0000108 vassert(log_bytes);
sewardj35421a32004-07-05 13:12:34 +0000109 vassert(debuglevel >= 0);
sewardj08613742004-10-25 13:01:45 +0000110
111 vassert(vcon->iropt_verbosity >= 0);
112 vassert(vcon->iropt_level >= 0);
113 vassert(vcon->iropt_level <= 2);
114 vassert(vcon->iropt_unroll_thresh >= 0);
115 vassert(vcon->iropt_unroll_thresh <= 400);
116 vassert(vcon->guest_max_insns >= 1);
117 vassert(vcon->guest_max_insns <= 100);
118 vassert(vcon->guest_chase_thresh >= 0);
119 vassert(vcon->guest_chase_thresh < vcon->guest_max_insns);
sewardj443cd9d2004-07-18 23:06:45 +0000120
sewardj81ec4182004-10-25 23:15:52 +0000121 /* All the guest state structs must have an 8-aligned size. */
122 vassert(0 == sizeof(VexGuestX86State) % 8);
123
sewardjea602bc2004-10-14 21:40:12 +0000124 /* Check that Vex has been built with sizes of basic types as
125 stated in priv/libvex_basictypes.h. Failure of any of these is
126 a serious configuration error and should be corrected
127 immediately. If any of these assertions fail you can fully
128 expect Vex not to work properly, if at all. */
129
130 vassert(1 == sizeof(UChar));
131 vassert(1 == sizeof(Char));
132 vassert(2 == sizeof(UShort));
133 vassert(2 == sizeof(Short));
134 vassert(4 == sizeof(UInt));
135 vassert(4 == sizeof(Int));
136 vassert(8 == sizeof(ULong));
137 vassert(8 == sizeof(Long));
138 vassert(4 == sizeof(Float));
139 vassert(8 == sizeof(Double));
140 vassert(1 == sizeof(Bool));
141 vassert(4 == sizeof(Addr32));
142 vassert(8 == sizeof(Addr64));
sewardjc9a43662004-11-30 18:51:59 +0000143 vassert(16 == sizeof(U128));
sewardjea602bc2004-10-14 21:40:12 +0000144
145 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
146 vassert(sizeof(void*) == sizeof(int*));
147 vassert(sizeof(void*) == sizeof(HWord));
148
149 /* Really start up .. */
sewardj443cd9d2004-07-18 23:06:45 +0000150 vex_debuglevel = debuglevel;
sewardj443cd9d2004-07-18 23:06:45 +0000151 vex_valgrind_support = valgrind_support;
sewardj08613742004-10-25 13:01:45 +0000152 vex_control = *vcon;
sewardj443cd9d2004-07-18 23:06:45 +0000153 vex_initdone = True;
sewardjd887b862005-01-17 18:34:34 +0000154 vexSetAllocMode ( VexAllocModeTEMP );
sewardj35421a32004-07-05 13:12:34 +0000155}
156
157
158/* --------- Make a translation. --------- */
159
160/* Exported to library client. */
161
sewardjd887b862005-01-17 18:34:34 +0000162VexTranslateResult LibVEX_Translate (
sewardj35421a32004-07-05 13:12:34 +0000163 /* The instruction sets we are translating from and to. */
sewardjbef170b2004-12-21 01:23:00 +0000164 VexArch arch_guest,
165 VexSubArch subarch_guest,
166 VexArch arch_host,
167 VexSubArch subarch_host,
sewardj35421a32004-07-05 13:12:34 +0000168 /* IN: the block to translate, and its guest address. */
sewardjbef170b2004-12-21 01:23:00 +0000169 UChar* guest_bytes,
170 Addr64 guest_bytes_addr,
171 Bool (*chase_into_ok) ( Addr64 ),
sewardj72c72812005-01-19 11:49:45 +0000172 /* OUT: which bits of guest code actually got translated */
173 VexGuestExtents* guest_extents,
sewardj35421a32004-07-05 13:12:34 +0000174 /* IN: a place to put the resulting code, and its size */
sewardjbef170b2004-12-21 01:23:00 +0000175 UChar* host_bytes,
176 Int host_bytes_size,
sewardj35421a32004-07-05 13:12:34 +0000177 /* OUT: how much of the output area is used. */
sewardjbef170b2004-12-21 01:23:00 +0000178 Int* host_bytes_used,
sewardj49651f42004-10-28 22:11:04 +0000179 /* IN: optionally, two instrumentation functions. */
sewardjbef170b2004-12-21 01:23:00 +0000180 IRBB* (*instrument1) ( IRBB*, VexGuestLayout*, IRType hWordTy ),
181 IRBB* (*instrument2) ( IRBB*, VexGuestLayout*, IRType hWordTy ),
182 Bool cleanup_after_instrumentation,
sewardj35421a32004-07-05 13:12:34 +0000183 /* IN: optionally, an access check function for guest code. */
sewardjbef170b2004-12-21 01:23:00 +0000184 Bool (*byte_accessible) ( Addr64 ),
sewardjf48ac192004-10-29 00:41:29 +0000185 /* IN: debug: trace vex activity at various points */
sewardjbef170b2004-12-21 01:23:00 +0000186 Int traceflags
sewardj35421a32004-07-05 13:12:34 +0000187)
188{
sewardj81bd5502004-07-21 18:49:27 +0000189 /* This the bundle of functions we need to do the back-end stuff
190 (insn selection, reg-alloc, assembly) whilst being insulated
191 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +0000192 HReg* available_real_regs;
193 Int n_available_real_regs;
sewardj443cd9d2004-07-18 23:06:45 +0000194 Bool (*isMove) (HInstr*, HReg*, HReg*);
195 void (*getRegUsage) (HRegUsage*, HInstr*);
196 void (*mapRegs) (HRegRemap*, HInstr*);
197 HInstr* (*genSpill) ( HReg, Int );
198 HInstr* (*genReload) ( HReg, Int );
199 void (*ppInstr) ( HInstr* );
200 void (*ppReg) ( HReg );
sewardj9df271d2004-12-31 22:37:42 +0000201 HInstrArray* (*iselBB) ( IRBB*, VexSubArch );
sewardj72c72812005-01-19 11:49:45 +0000202 IRBB* (*bbToIR) ( UChar*, Addr64,
203 VexGuestExtents*,
sewardj5bd4d162004-11-10 13:02:48 +0000204 Bool(*)(Addr64),
sewardj72c72812005-01-19 11:49:45 +0000205 Bool(*)(Addr64),
206 Bool, VexSubArch );
sewardj81bd5502004-07-21 18:49:27 +0000207 Int (*emit) ( UChar*, Int, HInstr* );
sewardj84ff0652004-08-23 16:16:08 +0000208 IRExpr* (*specHelper) ( Char*, IRExpr** );
sewardj8d2291c2004-10-25 14:50:21 +0000209 Bool (*preciseMemExnsFn) ( Int, Int );
sewardjf13a16a2004-07-05 17:10:14 +0000210
sewardjeeac8412004-11-02 00:26:55 +0000211 VexGuestLayout* guest_layout;
212 Bool host_is_bigendian = False;
213 IRBB* irbb;
214 HInstrArray* vcode;
215 HInstrArray* rcode;
216 Int i, j, k, out_used, guest_sizeB;
217 UChar insn_bytes[32];
sewardjcf787902004-11-03 09:08:33 +0000218 IRType guest_word_type;
219 IRType host_word_type;
sewardjf13a16a2004-07-05 17:10:14 +0000220
sewardj49651f42004-10-28 22:11:04 +0000221 guest_layout = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000222 available_real_regs = NULL;
223 n_available_real_regs = 0;
224 isMove = NULL;
225 getRegUsage = NULL;
226 mapRegs = NULL;
227 genSpill = NULL;
228 genReload = NULL;
229 ppInstr = NULL;
230 ppReg = NULL;
231 iselBB = NULL;
232 bbToIR = NULL;
233 emit = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000234 specHelper = NULL;
sewardj8d2291c2004-10-25 14:50:21 +0000235 preciseMemExnsFn = NULL;
sewardjcf787902004-11-03 09:08:33 +0000236 guest_word_type = Ity_INVALID;
237 host_word_type = Ity_INVALID;
sewardj36ca5132004-07-24 13:12:23 +0000238
sewardjf48ac192004-10-29 00:41:29 +0000239 vex_traceflags = traceflags;
sewardj58800ff2004-07-28 01:51:10 +0000240
sewardj35421a32004-07-05 13:12:34 +0000241 vassert(vex_initdone);
sewardjd887b862005-01-17 18:34:34 +0000242 vexClearTEMP();
sewardjf13a16a2004-07-05 17:10:14 +0000243
sewardj2a9ad022004-11-25 02:46:58 +0000244
sewardjf13a16a2004-07-05 17:10:14 +0000245 /* First off, check that the guest and host insn sets
246 are supported. */
sewardj2a9ad022004-11-25 02:46:58 +0000247
sewardjbef170b2004-12-21 01:23:00 +0000248 switch (arch_host) {
sewardj2a9ad022004-11-25 02:46:58 +0000249
sewardjbef170b2004-12-21 01:23:00 +0000250 case VexArchX86:
sewardjf13a16a2004-07-05 17:10:14 +0000251 getAllocableRegs_X86 ( &n_available_real_regs,
252 &available_real_regs );
253 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
254 getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_X86Instr;
255 mapRegs = (void(*)(HRegRemap*,HInstr*)) mapRegs_X86Instr;
256 genSpill = (HInstr*(*)(HReg,Int)) genSpill_X86;
257 genReload = (HInstr*(*)(HReg,Int)) genReload_X86;
sewardj2b515872004-07-05 20:50:45 +0000258 ppInstr = (void(*)(HInstr*)) ppX86Instr;
259 ppReg = (void(*)(HReg)) ppHRegX86;
sewardjf13a16a2004-07-05 17:10:14 +0000260 iselBB = iselBB_X86;
sewardj81bd5502004-07-21 18:49:27 +0000261 emit = (Int(*)(UChar*,Int,HInstr*)) emit_X86Instr;
sewardj72c72812005-01-19 11:49:45 +0000262 host_is_bigendian = False;
sewardjcf787902004-11-03 09:08:33 +0000263 host_word_type = Ity_I32;
sewardj9df271d2004-12-31 22:37:42 +0000264 vassert(subarch_host == VexSubArchX86_sse0
265 || subarch_host == VexSubArchX86_sse1
266 || subarch_host == VexSubArchX86_sse2);
sewardjf13a16a2004-07-05 17:10:14 +0000267 break;
sewardj2a9ad022004-11-25 02:46:58 +0000268
sewardjc33671d2005-02-01 20:30:00 +0000269 case VexArchAMD64:
270 getAllocableRegs_AMD64 ( &n_available_real_regs,
271 &available_real_regs );
272 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr;
273 getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_AMD64Instr;
274 mapRegs = (void(*)(HRegRemap*,HInstr*)) mapRegs_AMD64Instr;
275 genSpill = (HInstr*(*)(HReg,Int)) genSpill_AMD64;
276 genReload = (HInstr*(*)(HReg,Int)) genReload_AMD64;
277 ppInstr = (void(*)(HInstr*)) ppAMD64Instr;
278 ppReg = (void(*)(HReg)) ppHRegAMD64;
279 iselBB = iselBB_AMD64;
280 emit = (Int(*)(UChar*,Int,HInstr*)) emit_AMD64Instr;
281 host_is_bigendian = False;
282 host_word_type = Ity_I64;
283 vassert(subarch_host == VexSubArch_NONE);
284 break;
285
sewardjf13a16a2004-07-05 17:10:14 +0000286 default:
sewardj887a11a2004-07-05 17:26:47 +0000287 vpanic("LibVEX_Translate: unsupported target insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000288 }
289
sewardj2a9ad022004-11-25 02:46:58 +0000290
sewardjbef170b2004-12-21 01:23:00 +0000291 switch (arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000292
sewardjbef170b2004-12-21 01:23:00 +0000293 case VexArchX86:
sewardj8d2291c2004-10-25 14:50:21 +0000294 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
sewardj2a9ad022004-11-25 02:46:58 +0000295 bbToIR = bbToIR_X86;
296 specHelper = guest_x86_spechelper;
sewardj81ec4182004-10-25 23:15:52 +0000297 guest_sizeB = sizeof(VexGuestX86State);
sewardjcf787902004-11-03 09:08:33 +0000298 guest_word_type = Ity_I32;
sewardj49651f42004-10-28 22:11:04 +0000299 guest_layout = &x86guest_layout;
sewardj9df271d2004-12-31 22:37:42 +0000300 vassert(subarch_guest == VexSubArchX86_sse0
301 || subarch_guest == VexSubArchX86_sse1
302 || subarch_guest == VexSubArchX86_sse2);
sewardjf13a16a2004-07-05 17:10:14 +0000303 break;
sewardj2a9ad022004-11-25 02:46:58 +0000304
sewardj44d494d2005-01-20 20:26:33 +0000305 case VexArchAMD64:
306 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
307 bbToIR = bbToIR_AMD64;
308 specHelper = guest_amd64_spechelper;
309 guest_sizeB = sizeof(VexGuestAMD64State);
310 guest_word_type = Ity_I64;
311 guest_layout = &amd64guest_layout;
312 vassert(subarch_guest == VexSubArch_NONE);
313 break;
314
sewardjbef170b2004-12-21 01:23:00 +0000315 case VexArchARM:
sewardj2a9ad022004-11-25 02:46:58 +0000316 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
sewardjc2c87162004-11-25 13:07:02 +0000317 bbToIR = bbToIR_ARM;
sewardj2a9ad022004-11-25 02:46:58 +0000318 specHelper = guest_arm_spechelper;
319 guest_sizeB = sizeof(VexGuestARMState);
320 guest_word_type = Ity_I32;
321 guest_layout = &armGuest_layout;
sewardj44d494d2005-01-20 20:26:33 +0000322 vassert(subarch_guest == VexSubArchARM_v4);
sewardj2a9ad022004-11-25 02:46:58 +0000323 break;
324
cerionaabdfbf2005-01-29 12:56:15 +0000325 case VexArchPPC32:
326 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
327 bbToIR = bbToIR_PPC32;
328 specHelper = guest_ppc32_spechelper;
329 guest_sizeB = sizeof(VexGuestPPC32State);
330 guest_word_type = Ity_I32;
331 guest_layout = &ppc32Guest_layout;
sewardj0ec57c52005-02-01 15:24:10 +0000332 vassert(subarch_guest == VexSubArchPPC32_noAV
333 || subarch_guest == VexSubArchPPC32_AV);
cerionaabdfbf2005-01-29 12:56:15 +0000334 break;
335
sewardjf13a16a2004-07-05 17:10:14 +0000336 default:
sewardj887a11a2004-07-05 17:26:47 +0000337 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000338 }
339
sewardj9df271d2004-12-31 22:37:42 +0000340 /* yet more sanity checks ... */
sewardj0ec57c52005-02-01 15:24:10 +0000341 if (arch_guest == arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000342 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000343 we are simulating one flavour of an architecture a different
344 flavour of the same architecture, which is pretty strange. */
sewardj9df271d2004-12-31 22:37:42 +0000345 vassert(subarch_guest == subarch_host);
346 }
sewardj2a9ad022004-11-25 02:46:58 +0000347
sewardjf48ac192004-10-29 00:41:29 +0000348 if (vex_traceflags & VEX_TRACE_FE)
349 vex_printf("\n------------------------"
350 " Front end "
351 "------------------------\n\n");
352
sewardjf13a16a2004-07-05 17:10:14 +0000353 irbb = bbToIR ( guest_bytes,
sewardj72c72812005-01-19 11:49:45 +0000354 guest_bytes_addr,
355 guest_extents,
356 byte_accessible,
sewardj5bd4d162004-11-10 13:02:48 +0000357 chase_into_ok,
sewardj72c72812005-01-19 11:49:45 +0000358 host_is_bigendian,
sewardj9df271d2004-12-31 22:37:42 +0000359 subarch_guest );
sewardjf13a16a2004-07-05 17:10:14 +0000360
361 if (irbb == NULL) {
362 /* Access failure. */
sewardjd887b862005-01-17 18:34:34 +0000363 vexClearTEMP();
sewardjf48ac192004-10-29 00:41:29 +0000364 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000365 return VexTransAccessFail;
sewardjf13a16a2004-07-05 17:10:14 +0000366 }
sewardjaa59f942004-10-09 09:34:36 +0000367
sewardj72c72812005-01-19 11:49:45 +0000368 vassert(guest_extents->n_used >= 1 && guest_extents->n_used <= 3);
369 vassert(guest_extents->base[0] == guest_bytes_addr);
370 for (i = 0; i < guest_extents->n_used; i++) {
371 vassert(guest_extents->len[i] < 10000); /* sanity */
372 }
373
sewardjaa59f942004-10-09 09:34:36 +0000374 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000375 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj72c72812005-01-19 11:49:45 +0000376 if (guest_extents->n_used > 1) {
377 vex_printf("can't show code due to extents > 1\n");
378 } else {
379 /* HACK */
380 UChar* p = (UChar*)guest_bytes;
381 UInt guest_bytes_read = (UInt)guest_extents->len[0];
382 vex_printf(". 0 %llx %d\n.", guest_bytes_addr, guest_bytes_read );
383 for (i = 0; i < guest_bytes_read; i++)
sewardjaa59f942004-10-09 09:34:36 +0000384 vex_printf(" %02x", (Int)p[i] );
sewardj72c72812005-01-19 11:49:45 +0000385 vex_printf("\n\n");
386 }
sewardjaa59f942004-10-09 09:34:36 +0000387 }
388
389 /* Sanity check the initial IR. */
sewardjb9230752004-12-29 19:25:06 +0000390 sanityCheckIRBB( irbb, "initial IR",
391 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000392
sewardjedf4d692004-08-17 13:52:58 +0000393 /* Clean it up, hopefully a lot. */
sewardj8d2291c2004-10-25 14:50:21 +0000394 irbb = do_iropt_BB ( irbb, specHelper, preciseMemExnsFn,
395 guest_bytes_addr );
sewardjb9230752004-12-29 19:25:06 +0000396 sanityCheckIRBB( irbb, "after initial iropt",
397 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000398
sewardjf48ac192004-10-29 00:41:29 +0000399 if (vex_traceflags & VEX_TRACE_OPT1) {
400 vex_printf("\n------------------------"
401 " After pre-instr IR optimisation "
402 "------------------------\n\n");
sewardjedf4d692004-08-17 13:52:58 +0000403 ppIRBB ( irbb );
404 vex_printf("\n");
405 }
406
sewardjf13a16a2004-07-05 17:10:14 +0000407 /* Get the thing instrumented. */
sewardj49651f42004-10-28 22:11:04 +0000408 if (instrument1)
sewardjcf787902004-11-03 09:08:33 +0000409 irbb = (*instrument1)(irbb, guest_layout, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000410 if (instrument2)
sewardjcf787902004-11-03 09:08:33 +0000411 irbb = (*instrument2)(irbb, guest_layout, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000412
sewardjf48ac192004-10-29 00:41:29 +0000413 if (vex_traceflags & VEX_TRACE_INST) {
414 vex_printf("\n------------------------"
415 " After instrumentation "
416 "------------------------\n\n");
417 ppIRBB ( irbb );
418 vex_printf("\n");
419 }
420
sewardj49651f42004-10-28 22:11:04 +0000421 if (instrument1 || instrument2)
sewardjb9230752004-12-29 19:25:06 +0000422 sanityCheckIRBB( irbb, "after instrumentation",
423 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000424
sewardj9578a8b2004-11-04 19:44:48 +0000425 /* Do a post-instrumentation cleanup pass. */
426 if (cleanup_after_instrumentation) {
427 do_deadcode_BB( irbb );
428 irbb = cprop_BB( irbb );
429 do_deadcode_BB( irbb );
sewardjb9230752004-12-29 19:25:06 +0000430 sanityCheckIRBB( irbb, "after post-instrumentation cleanup",
431 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000432 }
433
434 if (vex_traceflags & VEX_TRACE_OPT2) {
435 vex_printf("\n------------------------"
436 " After post-instr IR optimisation "
437 "------------------------\n\n");
438 ppIRBB ( irbb );
439 vex_printf("\n");
440 }
441
sewardjf13a16a2004-07-05 17:10:14 +0000442 /* Turn it into virtual-registerised code. */
sewardj49651f42004-10-28 22:11:04 +0000443 do_deadcode_BB( irbb );
444 do_treebuild_BB( irbb );
sewardjf48ac192004-10-29 00:41:29 +0000445
446 if (vex_traceflags & VEX_TRACE_TREES) {
447 vex_printf("\n------------------------"
448 " After tree-building "
449 "------------------------\n\n");
450 ppIRBB ( irbb );
451 vex_printf("\n");
452 }
453
sewardjc33671d2005-02-01 20:30:00 +0000454 if (0) { *host_bytes_used = 0; return VexTransOK; }
455
sewardjf48ac192004-10-29 00:41:29 +0000456 if (vex_traceflags & VEX_TRACE_VCODE)
457 vex_printf("\n------------------------"
458 " Instruction selection "
459 "------------------------\n");
460
sewardj9df271d2004-12-31 22:37:42 +0000461 vcode = iselBB ( irbb, subarch_host );
sewardjf13a16a2004-07-05 17:10:14 +0000462
sewardjf48ac192004-10-29 00:41:29 +0000463 if (vex_traceflags & VEX_TRACE_VCODE)
464 vex_printf("\n");
465
sewardjf48ac192004-10-29 00:41:29 +0000466 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000467 for (i = 0; i < vcode->arr_used; i++) {
468 vex_printf("%3d ", i);
469 ppInstr(vcode->arr[i]);
470 vex_printf("\n");
471 }
sewardjfbcaf332004-07-08 01:46:01 +0000472 vex_printf("\n");
473 }
sewardjfbcaf332004-07-08 01:46:01 +0000474
sewardjf13a16a2004-07-05 17:10:14 +0000475 /* Register allocate. */
476 rcode = doRegisterAllocation ( vcode, available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000477 n_available_real_regs,
478 isMove, getRegUsage, mapRegs,
479 genSpill, genReload, guest_sizeB,
480 ppInstr, ppReg );
sewardjf13a16a2004-07-05 17:10:14 +0000481
sewardjf48ac192004-10-29 00:41:29 +0000482 if (vex_traceflags & VEX_TRACE_RCODE) {
483 vex_printf("\n------------------------"
484 " Register-allocated code "
485 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000486 for (i = 0; i < rcode->arr_used; i++) {
487 vex_printf("%3d ", i);
488 ppInstr(rcode->arr[i]);
489 vex_printf("\n");
490 }
sewardjfbcaf332004-07-08 01:46:01 +0000491 vex_printf("\n");
492 }
sewardjfbcaf332004-07-08 01:46:01 +0000493
sewardj81bd5502004-07-21 18:49:27 +0000494 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000495 if (vex_traceflags & VEX_TRACE_ASM) {
496 vex_printf("\n------------------------"
497 " Assembly "
498 "------------------------\n\n");
499 }
500
sewardj81bd5502004-07-21 18:49:27 +0000501 out_used = 0; /* tracks along the host_bytes array */
502 for (i = 0; i < rcode->arr_used; i++) {
sewardjf48ac192004-10-29 00:41:29 +0000503 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000504 ppInstr(rcode->arr[i]);
505 vex_printf("\n");
506 }
sewardj81bd5502004-07-21 18:49:27 +0000507 j = (*emit)( insn_bytes, 32, rcode->arr[i] );
sewardjf48ac192004-10-29 00:41:29 +0000508 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000509 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000510 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000511 vex_printf("0%x ", (UInt)insn_bytes[k]);
512 else
513 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000514 vex_printf("\n\n");
515 }
sewardj81bd5502004-07-21 18:49:27 +0000516 if (out_used + j > host_bytes_size) {
sewardjd887b862005-01-17 18:34:34 +0000517 vexClearTEMP();
sewardjf48ac192004-10-29 00:41:29 +0000518 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000519 return VexTransOutputFull;
sewardj81bd5502004-07-21 18:49:27 +0000520 }
521 for (k = 0; k < j; k++) {
522 host_bytes[out_used] = insn_bytes[k];
523 out_used++;
524 }
525 vassert(out_used <= host_bytes_size);
526 }
527 *host_bytes_used = out_used;
528
sewardjd887b862005-01-17 18:34:34 +0000529 vexClearTEMP();
sewardjf13a16a2004-07-05 17:10:14 +0000530
sewardjf48ac192004-10-29 00:41:29 +0000531 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000532 return VexTransOK;
sewardj35421a32004-07-05 13:12:34 +0000533}
534
535
sewardj893aada2004-11-29 19:57:54 +0000536/* --------- Emulation warnings. --------- */
537
538HChar* LibVEX_EmWarn_string ( VexEmWarn ew )
539{
540 switch (ew) {
541 case EmWarn_NONE:
542 return "none";
543 case EmWarn_X86_x87exns:
544 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000545 case EmWarn_X86_x87precision:
546 return "Selection of non-80-bit x87 FP precision";
547 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +0000548 return "Unmasking SSE FP exceptions";
549 case EmWarn_X86_fz:
550 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
551 case EmWarn_X86_daz:
552 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
sewardj893aada2004-11-29 19:57:54 +0000553 default:
554 vpanic("LibVEX_EmWarn_string: unknown warning");
555 }
556}
sewardj35421a32004-07-05 13:12:34 +0000557
sewardjbef170b2004-12-21 01:23:00 +0000558/* --------- Arch/Subarch names. --------- */
559
560const HChar* LibVEX_ppVexArch ( VexArch arch )
561{
562 switch (arch) {
563 case VexArch_INVALID: return "INVALID";
564 case VexArchX86: return "X86";
565 case VexArchAMD64: return "AMD64";
566 case VexArchARM: return "ARM";
sewardj0ec57c52005-02-01 15:24:10 +0000567 case VexArchPPC32: return "PPC32";
sewardjbef170b2004-12-21 01:23:00 +0000568 default: return "VexArch???";
569 }
570}
571
572const HChar* LibVEX_ppVexSubArch ( VexSubArch subarch )
573{
574 switch (subarch) {
sewardj0ec57c52005-02-01 15:24:10 +0000575 case VexSubArch_INVALID: return "INVALID";
576 case VexSubArch_NONE: return "NONE";
577 case VexSubArchX86_sse0: return "x86-sse0";
578 case VexSubArchX86_sse1: return "x86-sse1";
579 case VexSubArchX86_sse2: return "x86-sse2";
580 case VexSubArchARM_v4: return "arm-v4";
581 case VexSubArchPPC32_noAV: return "ppc32-noAltivec";
582 case VexSubArchPPC32_AV: return "ppc32-Altivec";
583 default: return "VexSubArch???";
sewardjbef170b2004-12-21 01:23:00 +0000584 }
585}
586
sewardj35421a32004-07-05 13:12:34 +0000587/*---------------------------------------------------------------*/
sewardjc0ee2ed2004-07-27 10:29:41 +0000588/*--- end main/vex_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +0000589/*---------------------------------------------------------------*/