blob: 52e66b059c937db9dc4c4cdc5a5d1cc4346123ce [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
sewardj9e6491a2005-07-02 19:24:10 +000052#include "guest-generic/bb_to_IR.h"
sewardj2a9ad022004-11-25 02:46:58 +000053#include "guest-x86/gdefs.h"
sewardj44d494d2005-01-20 20:26:33 +000054#include "guest-amd64/gdefs.h"
sewardj2a9ad022004-11-25 02:46:58 +000055#include "guest-arm/gdefs.h"
cerionaabdfbf2005-01-29 12:56:15 +000056#include "guest-ppc32/gdefs.h"
sewardj2a9ad022004-11-25 02:46:58 +000057
sewardj35421a32004-07-05 13:12:34 +000058
59/* This file contains the top level interface to the library. */
60
61/* --------- Initialise the library. --------- */
62
63/* Exported to library client. */
64
sewardjd887b862005-01-17 18:34:34 +000065const HChar* LibVEX_Version ( void )
sewardj80f5fce2004-12-20 04:37:50 +000066{
67return
68#include "main/vex_svnversion.h"
69 ;
70}
71
72
73/* Exported to library client. */
74
sewardj08613742004-10-25 13:01:45 +000075void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon )
76{
77 vcon->iropt_verbosity = 0;
78 vcon->iropt_level = 2;
79 vcon->iropt_precise_memory_exns = False;
80 vcon->iropt_unroll_thresh = 120;
sewardj18b4bb72005-03-29 21:32:41 +000081 vcon->guest_max_insns = 60;
sewardj08613742004-10-25 13:01:45 +000082 vcon->guest_chase_thresh = 10;
83}
84
85
86/* Exported to library client. */
87
sewardj887a11a2004-07-05 17:26:47 +000088void LibVEX_Init (
sewardj35421a32004-07-05 13:12:34 +000089 /* failure exit function */
sewardj2b515872004-07-05 20:50:45 +000090 __attribute__ ((noreturn))
sewardj35421a32004-07-05 13:12:34 +000091 void (*failure_exit) ( void ),
92 /* logging output function */
sewardjd9763622005-02-07 03:12:19 +000093 void (*log_bytes) ( HChar*, Int nbytes ),
sewardj35421a32004-07-05 13:12:34 +000094 /* debug paranoia level */
95 Int debuglevel,
sewardj35421a32004-07-05 13:12:34 +000096 /* Are we supporting valgrind checking? */
97 Bool valgrind_support,
sewardj08613742004-10-25 13:01:45 +000098 /* Control ... */
99 /*READONLY*/VexControl* vcon
sewardj35421a32004-07-05 13:12:34 +0000100)
101{
sewardj08613742004-10-25 13:01:45 +0000102 /* First off, do enough minimal setup so that the following
103 assertions can fail in a sane fashion, if need be. */
sewardjea602bc2004-10-14 21:40:12 +0000104 vex_failure_exit = failure_exit;
105 vex_log_bytes = log_bytes;
106
107 /* Now it's safe to check parameters for sanity. */
sewardj35421a32004-07-05 13:12:34 +0000108 vassert(!vex_initdone);
109 vassert(failure_exit);
sewardj35421a32004-07-05 13:12:34 +0000110 vassert(log_bytes);
sewardj35421a32004-07-05 13:12:34 +0000111 vassert(debuglevel >= 0);
sewardj08613742004-10-25 13:01:45 +0000112
113 vassert(vcon->iropt_verbosity >= 0);
114 vassert(vcon->iropt_level >= 0);
115 vassert(vcon->iropt_level <= 2);
116 vassert(vcon->iropt_unroll_thresh >= 0);
117 vassert(vcon->iropt_unroll_thresh <= 400);
118 vassert(vcon->guest_max_insns >= 1);
119 vassert(vcon->guest_max_insns <= 100);
120 vassert(vcon->guest_chase_thresh >= 0);
121 vassert(vcon->guest_chase_thresh < vcon->guest_max_insns);
sewardj443cd9d2004-07-18 23:06:45 +0000122
sewardj81ec4182004-10-25 23:15:52 +0000123 /* All the guest state structs must have an 8-aligned size. */
sewardj32a81262005-02-05 14:32:18 +0000124 vassert(0 == sizeof(VexGuestX86State) % 8);
125 vassert(0 == sizeof(VexGuestAMD64State) % 8);
126 vassert(0 == sizeof(VexGuestPPC32State) % 8);
127 vassert(0 == sizeof(VexGuestARMState) % 8);
sewardj81ec4182004-10-25 23:15:52 +0000128
sewardjea602bc2004-10-14 21:40:12 +0000129 /* Check that Vex has been built with sizes of basic types as
130 stated in priv/libvex_basictypes.h. Failure of any of these is
131 a serious configuration error and should be corrected
132 immediately. If any of these assertions fail you can fully
133 expect Vex not to work properly, if at all. */
134
135 vassert(1 == sizeof(UChar));
136 vassert(1 == sizeof(Char));
137 vassert(2 == sizeof(UShort));
138 vassert(2 == sizeof(Short));
139 vassert(4 == sizeof(UInt));
140 vassert(4 == sizeof(Int));
141 vassert(8 == sizeof(ULong));
142 vassert(8 == sizeof(Long));
143 vassert(4 == sizeof(Float));
144 vassert(8 == sizeof(Double));
145 vassert(1 == sizeof(Bool));
146 vassert(4 == sizeof(Addr32));
147 vassert(8 == sizeof(Addr64));
sewardjc9a43662004-11-30 18:51:59 +0000148 vassert(16 == sizeof(U128));
sewardjea602bc2004-10-14 21:40:12 +0000149
150 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
151 vassert(sizeof(void*) == sizeof(int*));
152 vassert(sizeof(void*) == sizeof(HWord));
153
sewardj97e87932005-02-07 00:00:50 +0000154 vassert(VEX_HOST_WORDSIZE == sizeof(void*));
155 vassert(VEX_HOST_WORDSIZE == sizeof(HWord));
156
sewardjea602bc2004-10-14 21:40:12 +0000157 /* Really start up .. */
sewardj443cd9d2004-07-18 23:06:45 +0000158 vex_debuglevel = debuglevel;
sewardj443cd9d2004-07-18 23:06:45 +0000159 vex_valgrind_support = valgrind_support;
sewardj08613742004-10-25 13:01:45 +0000160 vex_control = *vcon;
sewardj443cd9d2004-07-18 23:06:45 +0000161 vex_initdone = True;
sewardjd887b862005-01-17 18:34:34 +0000162 vexSetAllocMode ( VexAllocModeTEMP );
sewardj35421a32004-07-05 13:12:34 +0000163}
164
165
166/* --------- Make a translation. --------- */
167
168/* Exported to library client. */
169
sewardjd887b862005-01-17 18:34:34 +0000170VexTranslateResult LibVEX_Translate (
sewardj35421a32004-07-05 13:12:34 +0000171 /* The instruction sets we are translating from and to. */
sewardj27e1dd62005-06-30 11:49:14 +0000172 VexArch arch_guest,
173 VexArchInfo* archinfo_guest,
174 VexArch arch_host,
175 VexArchInfo* archinfo_host,
sewardj35421a32004-07-05 13:12:34 +0000176 /* IN: the block to translate, and its guest address. */
sewardjbef170b2004-12-21 01:23:00 +0000177 UChar* guest_bytes,
178 Addr64 guest_bytes_addr,
179 Bool (*chase_into_ok) ( Addr64 ),
sewardj72c72812005-01-19 11:49:45 +0000180 /* OUT: which bits of guest code actually got translated */
181 VexGuestExtents* guest_extents,
sewardj35421a32004-07-05 13:12:34 +0000182 /* IN: a place to put the resulting code, and its size */
sewardjbef170b2004-12-21 01:23:00 +0000183 UChar* host_bytes,
184 Int host_bytes_size,
sewardj35421a32004-07-05 13:12:34 +0000185 /* OUT: how much of the output area is used. */
sewardjbef170b2004-12-21 01:23:00 +0000186 Int* host_bytes_used,
sewardj49651f42004-10-28 22:11:04 +0000187 /* IN: optionally, two instrumentation functions. */
sewardj918c8f32005-03-21 00:54:33 +0000188 IRBB* (*instrument1) ( IRBB*, VexGuestLayout*,
189 IRType gWordTy, IRType hWordTy ),
190 IRBB* (*instrument2) ( IRBB*, VexGuestLayout*,
191 IRType gWordTy, IRType hWordTy ),
sewardjbef170b2004-12-21 01:23:00 +0000192 Bool cleanup_after_instrumentation,
sewardj35421a32004-07-05 13:12:34 +0000193 /* IN: optionally, an access check function for guest code. */
sewardjbef170b2004-12-21 01:23:00 +0000194 Bool (*byte_accessible) ( Addr64 ),
sewardjf48ac192004-10-29 00:41:29 +0000195 /* IN: debug: trace vex activity at various points */
sewardjbef170b2004-12-21 01:23:00 +0000196 Int traceflags
sewardj35421a32004-07-05 13:12:34 +0000197)
198{
sewardj81bd5502004-07-21 18:49:27 +0000199 /* This the bundle of functions we need to do the back-end stuff
200 (insn selection, reg-alloc, assembly) whilst being insulated
201 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +0000202 HReg* available_real_regs;
203 Int n_available_real_regs;
sewardj443cd9d2004-07-18 23:06:45 +0000204 Bool (*isMove) (HInstr*, HReg*, HReg*);
205 void (*getRegUsage) (HRegUsage*, HInstr*);
206 void (*mapRegs) (HRegRemap*, HInstr*);
207 HInstr* (*genSpill) ( HReg, Int );
208 HInstr* (*genReload) ( HReg, Int );
209 void (*ppInstr) ( HInstr* );
210 void (*ppReg) ( HReg );
sewardj27e1dd62005-06-30 11:49:14 +0000211 HInstrArray* (*iselBB) ( IRBB*, VexArchInfo* );
sewardj81bd5502004-07-21 18:49:27 +0000212 Int (*emit) ( UChar*, Int, HInstr* );
sewardjd9763622005-02-07 03:12:19 +0000213 IRExpr* (*specHelper) ( HChar*, IRExpr** );
sewardj8d2291c2004-10-25 14:50:21 +0000214 Bool (*preciseMemExnsFn) ( Int, Int );
sewardjf13a16a2004-07-05 17:10:14 +0000215
sewardj9e6491a2005-07-02 19:24:10 +0000216 DisOneInstrFn disInstrFn;
217
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;
sewardj36ca5132004-07-24 13:12:23 +0000239 emit = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000240 specHelper = NULL;
sewardj8d2291c2004-10-25 14:50:21 +0000241 preciseMemExnsFn = NULL;
sewardj9e6491a2005-07-02 19:24:10 +0000242 disInstrFn = 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;
sewardj27e1dd62005-06-30 11:49:14 +0000271 vassert(archinfo_host->subarch == VexSubArchX86_sse0
272 || archinfo_host->subarch == VexSubArchX86_sse1
273 || archinfo_host->subarch == 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;
sewardj27e1dd62005-06-30 11:49:14 +0000290 vassert(archinfo_host->subarch == VexSubArch_NONE);
sewardjc33671d2005-02-01 20:30:00 +0000291 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;
sewardj27e1dd62005-06-30 11:49:14 +0000307 vassert(archinfo_guest->subarch == VexSubArchPPC32_noAV
308 || archinfo_guest->subarch == VexSubArchPPC32_AV);
cerion487e4c92005-02-04 16:28:19 +0000309 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;
sewardj9e6491a2005-07-02 19:24:10 +0000320 disInstrFn = disInstr_X86;
sewardj2a9ad022004-11-25 02:46:58 +0000321 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;
sewardj27e1dd62005-06-30 11:49:14 +0000325 vassert(archinfo_guest->subarch == VexSubArchX86_sse0
326 || archinfo_guest->subarch == VexSubArchX86_sse1
327 || archinfo_guest->subarch == 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;
sewardj9e6491a2005-07-02 19:24:10 +0000332 disInstrFn = disInstr_AMD64;
sewardj44d494d2005-01-20 20:26:33 +0000333 specHelper = guest_amd64_spechelper;
334 guest_sizeB = sizeof(VexGuestAMD64State);
335 guest_word_type = Ity_I64;
336 guest_layout = &amd64guest_layout;
sewardj27e1dd62005-06-30 11:49:14 +0000337 vassert(archinfo_guest->subarch == VexSubArch_NONE);
sewardj44d494d2005-01-20 20:26:33 +0000338 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;
sewardj9e6491a2005-07-02 19:24:10 +0000342 disInstrFn = NULL; /* HACK */
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;
sewardj27e1dd62005-06-30 11:49:14 +0000347 vassert(archinfo_guest->subarch == 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;
sewardj9e6491a2005-07-02 19:24:10 +0000352 disInstrFn = disInstr_PPC32;
cerionaabdfbf2005-01-29 12:56:15 +0000353 specHelper = guest_ppc32_spechelper;
354 guest_sizeB = sizeof(VexGuestPPC32State);
355 guest_word_type = Ity_I32;
356 guest_layout = &ppc32Guest_layout;
sewardj27e1dd62005-06-30 11:49:14 +0000357 vassert(archinfo_guest->subarch == VexSubArchPPC32_noAV
358 || archinfo_guest->subarch == 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. */
sewardj27e1dd62005-06-30 11:49:14 +0000370 vassert(archinfo_guest->subarch == archinfo_host->subarch);
sewardj9df271d2004-12-31 22:37:42 +0000371 }
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
sewardj9e6491a2005-07-02 19:24:10 +0000378 irbb = bb_to_IR ( guest_extents,
379 disInstrFn,
380 guest_bytes,
381 guest_bytes_addr,
382 chase_into_ok,
383 host_is_bigendian,
384 archinfo_guest,
385 guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000386
387 if (irbb == NULL) {
388 /* Access failure. */
sewardjd887b862005-01-17 18:34:34 +0000389 vexClearTEMP();
sewardjf48ac192004-10-29 00:41:29 +0000390 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000391 return VexTransAccessFail;
sewardjf13a16a2004-07-05 17:10:14 +0000392 }
sewardjaa59f942004-10-09 09:34:36 +0000393
sewardj72c72812005-01-19 11:49:45 +0000394 vassert(guest_extents->n_used >= 1 && guest_extents->n_used <= 3);
395 vassert(guest_extents->base[0] == guest_bytes_addr);
396 for (i = 0; i < guest_extents->n_used; i++) {
397 vassert(guest_extents->len[i] < 10000); /* sanity */
398 }
399
sewardjaa59f942004-10-09 09:34:36 +0000400 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000401 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj72c72812005-01-19 11:49:45 +0000402 if (guest_extents->n_used > 1) {
403 vex_printf("can't show code due to extents > 1\n");
404 } else {
405 /* HACK */
406 UChar* p = (UChar*)guest_bytes;
407 UInt guest_bytes_read = (UInt)guest_extents->len[0];
sewardjd9763622005-02-07 03:12:19 +0000408 vex_printf(". 0 %llx %u\n.", guest_bytes_addr, guest_bytes_read );
sewardj72c72812005-01-19 11:49:45 +0000409 for (i = 0; i < guest_bytes_read; i++)
sewardjaa59f942004-10-09 09:34:36 +0000410 vex_printf(" %02x", (Int)p[i] );
sewardj72c72812005-01-19 11:49:45 +0000411 vex_printf("\n\n");
412 }
sewardjaa59f942004-10-09 09:34:36 +0000413 }
414
415 /* Sanity check the initial IR. */
sewardjb9230752004-12-29 19:25:06 +0000416 sanityCheckIRBB( irbb, "initial IR",
417 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000418
sewardjedf4d692004-08-17 13:52:58 +0000419 /* Clean it up, hopefully a lot. */
sewardj8d2291c2004-10-25 14:50:21 +0000420 irbb = do_iropt_BB ( irbb, specHelper, preciseMemExnsFn,
421 guest_bytes_addr );
sewardjb9230752004-12-29 19:25:06 +0000422 sanityCheckIRBB( irbb, "after initial iropt",
423 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000424
sewardjf48ac192004-10-29 00:41:29 +0000425 if (vex_traceflags & VEX_TRACE_OPT1) {
426 vex_printf("\n------------------------"
427 " After pre-instr IR optimisation "
428 "------------------------\n\n");
sewardjedf4d692004-08-17 13:52:58 +0000429 ppIRBB ( irbb );
430 vex_printf("\n");
431 }
432
sewardjf13a16a2004-07-05 17:10:14 +0000433 /* Get the thing instrumented. */
sewardj49651f42004-10-28 22:11:04 +0000434 if (instrument1)
sewardj918c8f32005-03-21 00:54:33 +0000435 irbb = (*instrument1)(irbb, guest_layout,
436 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000437 if (instrument2)
sewardj918c8f32005-03-21 00:54:33 +0000438 irbb = (*instrument2)(irbb, guest_layout,
439 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000440
sewardjf48ac192004-10-29 00:41:29 +0000441 if (vex_traceflags & VEX_TRACE_INST) {
442 vex_printf("\n------------------------"
443 " After instrumentation "
444 "------------------------\n\n");
445 ppIRBB ( irbb );
446 vex_printf("\n");
447 }
448
sewardj49651f42004-10-28 22:11:04 +0000449 if (instrument1 || instrument2)
sewardjb9230752004-12-29 19:25:06 +0000450 sanityCheckIRBB( irbb, "after instrumentation",
451 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000452
sewardj9578a8b2004-11-04 19:44:48 +0000453 /* Do a post-instrumentation cleanup pass. */
454 if (cleanup_after_instrumentation) {
455 do_deadcode_BB( irbb );
456 irbb = cprop_BB( irbb );
457 do_deadcode_BB( irbb );
sewardjb9230752004-12-29 19:25:06 +0000458 sanityCheckIRBB( irbb, "after post-instrumentation cleanup",
459 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000460 }
461
462 if (vex_traceflags & VEX_TRACE_OPT2) {
463 vex_printf("\n------------------------"
464 " After post-instr IR optimisation "
465 "------------------------\n\n");
466 ppIRBB ( irbb );
467 vex_printf("\n");
468 }
469
sewardjf13a16a2004-07-05 17:10:14 +0000470 /* Turn it into virtual-registerised code. */
sewardj49651f42004-10-28 22:11:04 +0000471 do_deadcode_BB( irbb );
472 do_treebuild_BB( irbb );
sewardjf48ac192004-10-29 00:41:29 +0000473
474 if (vex_traceflags & VEX_TRACE_TREES) {
475 vex_printf("\n------------------------"
476 " After tree-building "
477 "------------------------\n\n");
478 ppIRBB ( irbb );
479 vex_printf("\n");
480 }
481
sewardje908c422005-02-04 21:18:16 +0000482 /* HACK */
cerion54560812005-02-03 13:40:49 +0000483 if (0) { *host_bytes_used = 0; return VexTransOK; }
sewardje908c422005-02-04 21:18:16 +0000484 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000485
sewardjf48ac192004-10-29 00:41:29 +0000486 if (vex_traceflags & VEX_TRACE_VCODE)
487 vex_printf("\n------------------------"
488 " Instruction selection "
489 "------------------------\n");
490
sewardj27e1dd62005-06-30 11:49:14 +0000491 vcode = iselBB ( irbb, archinfo_host );
sewardjf13a16a2004-07-05 17:10:14 +0000492
sewardjf48ac192004-10-29 00:41:29 +0000493 if (vex_traceflags & VEX_TRACE_VCODE)
494 vex_printf("\n");
495
sewardjf48ac192004-10-29 00:41:29 +0000496 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000497 for (i = 0; i < vcode->arr_used; i++) {
498 vex_printf("%3d ", i);
499 ppInstr(vcode->arr[i]);
500 vex_printf("\n");
501 }
sewardjfbcaf332004-07-08 01:46:01 +0000502 vex_printf("\n");
503 }
sewardjfbcaf332004-07-08 01:46:01 +0000504
sewardjf13a16a2004-07-05 17:10:14 +0000505 /* Register allocate. */
506 rcode = doRegisterAllocation ( vcode, available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000507 n_available_real_regs,
508 isMove, getRegUsage, mapRegs,
509 genSpill, genReload, guest_sizeB,
510 ppInstr, ppReg );
sewardjf13a16a2004-07-05 17:10:14 +0000511
sewardjf48ac192004-10-29 00:41:29 +0000512 if (vex_traceflags & VEX_TRACE_RCODE) {
513 vex_printf("\n------------------------"
514 " Register-allocated code "
515 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000516 for (i = 0; i < rcode->arr_used; i++) {
517 vex_printf("%3d ", i);
518 ppInstr(rcode->arr[i]);
519 vex_printf("\n");
520 }
sewardjfbcaf332004-07-08 01:46:01 +0000521 vex_printf("\n");
522 }
sewardjfbcaf332004-07-08 01:46:01 +0000523
sewardje908c422005-02-04 21:18:16 +0000524 /* HACK */
525 if (0) { *host_bytes_used = 0; return VexTransOK; }
526 /* end HACK */
527
sewardj81bd5502004-07-21 18:49:27 +0000528 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000529 if (vex_traceflags & VEX_TRACE_ASM) {
530 vex_printf("\n------------------------"
531 " Assembly "
532 "------------------------\n\n");
533 }
534
sewardj81bd5502004-07-21 18:49:27 +0000535 out_used = 0; /* tracks along the host_bytes array */
536 for (i = 0; i < rcode->arr_used; i++) {
sewardjf48ac192004-10-29 00:41:29 +0000537 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000538 ppInstr(rcode->arr[i]);
539 vex_printf("\n");
540 }
sewardj81bd5502004-07-21 18:49:27 +0000541 j = (*emit)( insn_bytes, 32, rcode->arr[i] );
sewardjf48ac192004-10-29 00:41:29 +0000542 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000543 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000544 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000545 vex_printf("0%x ", (UInt)insn_bytes[k]);
546 else
547 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000548 vex_printf("\n\n");
549 }
sewardj81bd5502004-07-21 18:49:27 +0000550 if (out_used + j > host_bytes_size) {
sewardjd887b862005-01-17 18:34:34 +0000551 vexClearTEMP();
sewardjf48ac192004-10-29 00:41:29 +0000552 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000553 return VexTransOutputFull;
sewardj81bd5502004-07-21 18:49:27 +0000554 }
555 for (k = 0; k < j; k++) {
556 host_bytes[out_used] = insn_bytes[k];
557 out_used++;
558 }
559 vassert(out_used <= host_bytes_size);
560 }
561 *host_bytes_used = out_used;
562
sewardjd887b862005-01-17 18:34:34 +0000563 vexClearTEMP();
sewardjf13a16a2004-07-05 17:10:14 +0000564
sewardjf48ac192004-10-29 00:41:29 +0000565 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000566 return VexTransOK;
sewardj35421a32004-07-05 13:12:34 +0000567}
568
569
sewardj893aada2004-11-29 19:57:54 +0000570/* --------- Emulation warnings. --------- */
571
572HChar* LibVEX_EmWarn_string ( VexEmWarn ew )
573{
574 switch (ew) {
575 case EmWarn_NONE:
576 return "none";
577 case EmWarn_X86_x87exns:
578 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000579 case EmWarn_X86_x87precision:
580 return "Selection of non-80-bit x87 FP precision";
581 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +0000582 return "Unmasking SSE FP exceptions";
583 case EmWarn_X86_fz:
584 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
585 case EmWarn_X86_daz:
586 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
cerion094d1392005-06-20 13:45:57 +0000587 case EmWarn_PPC32exns:
588 return "Unmasking PPC32 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000589 default:
590 vpanic("LibVEX_EmWarn_string: unknown warning");
591 }
592}
sewardj35421a32004-07-05 13:12:34 +0000593
sewardj27e1dd62005-06-30 11:49:14 +0000594/* --------- Arch/Subarch stuff. --------- */
sewardjbef170b2004-12-21 01:23:00 +0000595
596const HChar* LibVEX_ppVexArch ( VexArch arch )
597{
598 switch (arch) {
599 case VexArch_INVALID: return "INVALID";
600 case VexArchX86: return "X86";
601 case VexArchAMD64: return "AMD64";
602 case VexArchARM: return "ARM";
sewardj0ec57c52005-02-01 15:24:10 +0000603 case VexArchPPC32: return "PPC32";
sewardjbef170b2004-12-21 01:23:00 +0000604 default: return "VexArch???";
605 }
606}
607
608const HChar* LibVEX_ppVexSubArch ( VexSubArch subarch )
609{
610 switch (subarch) {
sewardj0ec57c52005-02-01 15:24:10 +0000611 case VexSubArch_INVALID: return "INVALID";
612 case VexSubArch_NONE: return "NONE";
613 case VexSubArchX86_sse0: return "x86-sse0";
614 case VexSubArchX86_sse1: return "x86-sse1";
615 case VexSubArchX86_sse2: return "x86-sse2";
616 case VexSubArchARM_v4: return "arm-v4";
617 case VexSubArchPPC32_noAV: return "ppc32-noAltivec";
618 case VexSubArchPPC32_AV: return "ppc32-Altivec";
619 default: return "VexSubArch???";
sewardjbef170b2004-12-21 01:23:00 +0000620 }
621}
622
sewardj27e1dd62005-06-30 11:49:14 +0000623/* Write default settings info *vai. */
624void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
625{
626 vai->subarch = VexSubArch_INVALID;
627 vai->ppc32_cache_line_szB = 0;
628}
629
630
sewardj35421a32004-07-05 13:12:34 +0000631/*---------------------------------------------------------------*/
sewardjc0ee2ed2004-07-27 10:29:41 +0000632/*--- end main/vex_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +0000633/*---------------------------------------------------------------*/