blob: 3145608f7dbccd17c8397a792c3a7c115bc327a8 [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;
sewardjdb4738a2005-07-07 01:32:16 +0000224 Int offB_TISTART, offB_TILEN;
sewardjeeac8412004-11-02 00:26:55 +0000225 UChar insn_bytes[32];
sewardjcf787902004-11-03 09:08:33 +0000226 IRType guest_word_type;
227 IRType host_word_type;
sewardjf13a16a2004-07-05 17:10:14 +0000228
sewardj49651f42004-10-28 22:11:04 +0000229 guest_layout = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000230 available_real_regs = NULL;
231 n_available_real_regs = 0;
232 isMove = NULL;
233 getRegUsage = NULL;
234 mapRegs = NULL;
235 genSpill = NULL;
236 genReload = NULL;
237 ppInstr = NULL;
238 ppReg = NULL;
239 iselBB = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000240 emit = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000241 specHelper = NULL;
sewardj8d2291c2004-10-25 14:50:21 +0000242 preciseMemExnsFn = NULL;
sewardj9e6491a2005-07-02 19:24:10 +0000243 disInstrFn = NULL;
sewardjcf787902004-11-03 09:08:33 +0000244 guest_word_type = Ity_INVALID;
245 host_word_type = Ity_INVALID;
sewardjdb4738a2005-07-07 01:32:16 +0000246 offB_TISTART = 0;
247 offB_TILEN = 0;
sewardj36ca5132004-07-24 13:12:23 +0000248
sewardjf48ac192004-10-29 00:41:29 +0000249 vex_traceflags = traceflags;
sewardj58800ff2004-07-28 01:51:10 +0000250
sewardj35421a32004-07-05 13:12:34 +0000251 vassert(vex_initdone);
sewardjd887b862005-01-17 18:34:34 +0000252 vexClearTEMP();
sewardjf13a16a2004-07-05 17:10:14 +0000253
sewardj2a9ad022004-11-25 02:46:58 +0000254
sewardjf13a16a2004-07-05 17:10:14 +0000255 /* First off, check that the guest and host insn sets
256 are supported. */
sewardj2a9ad022004-11-25 02:46:58 +0000257
sewardjbef170b2004-12-21 01:23:00 +0000258 switch (arch_host) {
sewardj2a9ad022004-11-25 02:46:58 +0000259
sewardjbef170b2004-12-21 01:23:00 +0000260 case VexArchX86:
sewardjf13a16a2004-07-05 17:10:14 +0000261 getAllocableRegs_X86 ( &n_available_real_regs,
262 &available_real_regs );
263 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
264 getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_X86Instr;
265 mapRegs = (void(*)(HRegRemap*,HInstr*)) mapRegs_X86Instr;
266 genSpill = (HInstr*(*)(HReg,Int)) genSpill_X86;
267 genReload = (HInstr*(*)(HReg,Int)) genReload_X86;
sewardj2b515872004-07-05 20:50:45 +0000268 ppInstr = (void(*)(HInstr*)) ppX86Instr;
269 ppReg = (void(*)(HReg)) ppHRegX86;
sewardjf13a16a2004-07-05 17:10:14 +0000270 iselBB = iselBB_X86;
sewardj81bd5502004-07-21 18:49:27 +0000271 emit = (Int(*)(UChar*,Int,HInstr*)) emit_X86Instr;
sewardj72c72812005-01-19 11:49:45 +0000272 host_is_bigendian = False;
sewardjcf787902004-11-03 09:08:33 +0000273 host_word_type = Ity_I32;
sewardj27e1dd62005-06-30 11:49:14 +0000274 vassert(archinfo_host->subarch == VexSubArchX86_sse0
275 || archinfo_host->subarch == VexSubArchX86_sse1
276 || archinfo_host->subarch == VexSubArchX86_sse2);
sewardjf13a16a2004-07-05 17:10:14 +0000277 break;
sewardj2a9ad022004-11-25 02:46:58 +0000278
sewardjc33671d2005-02-01 20:30:00 +0000279 case VexArchAMD64:
280 getAllocableRegs_AMD64 ( &n_available_real_regs,
281 &available_real_regs );
282 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_AMD64Instr;
283 getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_AMD64Instr;
284 mapRegs = (void(*)(HRegRemap*,HInstr*)) mapRegs_AMD64Instr;
285 genSpill = (HInstr*(*)(HReg,Int)) genSpill_AMD64;
286 genReload = (HInstr*(*)(HReg,Int)) genReload_AMD64;
287 ppInstr = (void(*)(HInstr*)) ppAMD64Instr;
288 ppReg = (void(*)(HReg)) ppHRegAMD64;
289 iselBB = iselBB_AMD64;
290 emit = (Int(*)(UChar*,Int,HInstr*)) emit_AMD64Instr;
291 host_is_bigendian = False;
292 host_word_type = Ity_I64;
sewardj27e1dd62005-06-30 11:49:14 +0000293 vassert(archinfo_host->subarch == VexSubArch_NONE);
sewardjc33671d2005-02-01 20:30:00 +0000294 break;
295
cerion487e4c92005-02-04 16:28:19 +0000296 case VexArchPPC32:
297 getAllocableRegs_PPC32 ( &n_available_real_regs,
298 &available_real_regs );
299 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_PPC32Instr;
300 getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_PPC32Instr;
301 mapRegs = (void(*)(HRegRemap*,HInstr*)) mapRegs_PPC32Instr;
302 genSpill = (HInstr*(*)(HReg,Int)) genSpill_PPC32;
303 genReload = (HInstr*(*)(HReg,Int)) genReload_PPC32;
304 ppInstr = (void(*)(HInstr*)) ppPPC32Instr;
305 ppReg = (void(*)(HReg)) ppHRegPPC32;
306 iselBB = iselBB_PPC32;
307 emit = (Int(*)(UChar*,Int,HInstr*)) emit_PPC32Instr;
308 host_is_bigendian = True;
309 host_word_type = Ity_I32;
sewardj27e1dd62005-06-30 11:49:14 +0000310 vassert(archinfo_guest->subarch == VexSubArchPPC32_noAV
311 || archinfo_guest->subarch == VexSubArchPPC32_AV);
cerion487e4c92005-02-04 16:28:19 +0000312 break;
313
sewardjf13a16a2004-07-05 17:10:14 +0000314 default:
sewardj887a11a2004-07-05 17:26:47 +0000315 vpanic("LibVEX_Translate: unsupported target insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000316 }
317
sewardj2a9ad022004-11-25 02:46:58 +0000318
sewardjbef170b2004-12-21 01:23:00 +0000319 switch (arch_guest) {
sewardj2a9ad022004-11-25 02:46:58 +0000320
sewardjbef170b2004-12-21 01:23:00 +0000321 case VexArchX86:
sewardj8d2291c2004-10-25 14:50:21 +0000322 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000323 disInstrFn = disInstr_X86;
sewardj2a9ad022004-11-25 02:46:58 +0000324 specHelper = guest_x86_spechelper;
sewardj81ec4182004-10-25 23:15:52 +0000325 guest_sizeB = sizeof(VexGuestX86State);
sewardjcf787902004-11-03 09:08:33 +0000326 guest_word_type = Ity_I32;
sewardj49651f42004-10-28 22:11:04 +0000327 guest_layout = &x86guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000328 offB_TISTART = offsetof(VexGuestX86State,guest_TISTART);
329 offB_TILEN = offsetof(VexGuestX86State,guest_TILEN);
sewardj27e1dd62005-06-30 11:49:14 +0000330 vassert(archinfo_guest->subarch == VexSubArchX86_sse0
331 || archinfo_guest->subarch == VexSubArchX86_sse1
332 || archinfo_guest->subarch == VexSubArchX86_sse2);
sewardjdb4738a2005-07-07 01:32:16 +0000333 vassert(sizeof( ((VexGuestX86State*)0)->guest_TISTART ) == 4);
334 vassert(sizeof( ((VexGuestX86State*)0)->guest_TILEN ) == 4);
sewardjf13a16a2004-07-05 17:10:14 +0000335 break;
sewardj2a9ad022004-11-25 02:46:58 +0000336
sewardj44d494d2005-01-20 20:26:33 +0000337 case VexArchAMD64:
338 preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000339 disInstrFn = disInstr_AMD64;
sewardj44d494d2005-01-20 20:26:33 +0000340 specHelper = guest_amd64_spechelper;
341 guest_sizeB = sizeof(VexGuestAMD64State);
342 guest_word_type = Ity_I64;
343 guest_layout = &amd64guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000344 offB_TISTART = offsetof(VexGuestAMD64State,guest_TISTART);
345 offB_TILEN = offsetof(VexGuestAMD64State,guest_TILEN);
sewardj27e1dd62005-06-30 11:49:14 +0000346 vassert(archinfo_guest->subarch == VexSubArch_NONE);
sewardjdb4738a2005-07-07 01:32:16 +0000347 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TISTART ) == 8);
348 vassert(sizeof( ((VexGuestAMD64State*)0)->guest_TILEN ) == 8);
sewardj44d494d2005-01-20 20:26:33 +0000349 break;
350
sewardjbef170b2004-12-21 01:23:00 +0000351 case VexArchARM:
sewardj2a9ad022004-11-25 02:46:58 +0000352 preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000353 disInstrFn = NULL; /* HACK */
sewardj2a9ad022004-11-25 02:46:58 +0000354 specHelper = guest_arm_spechelper;
355 guest_sizeB = sizeof(VexGuestARMState);
356 guest_word_type = Ity_I32;
357 guest_layout = &armGuest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000358 offB_TISTART = 0; /* hack ... arm has bitrot */
359 offB_TILEN = 0; /* hack ... arm has bitrot */
sewardj27e1dd62005-06-30 11:49:14 +0000360 vassert(archinfo_guest->subarch == VexSubArchARM_v4);
sewardj2a9ad022004-11-25 02:46:58 +0000361 break;
362
cerionaabdfbf2005-01-29 12:56:15 +0000363 case VexArchPPC32:
364 preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
sewardj9e6491a2005-07-02 19:24:10 +0000365 disInstrFn = disInstr_PPC32;
cerionaabdfbf2005-01-29 12:56:15 +0000366 specHelper = guest_ppc32_spechelper;
367 guest_sizeB = sizeof(VexGuestPPC32State);
368 guest_word_type = Ity_I32;
369 guest_layout = &ppc32Guest_layout;
sewardjdb4738a2005-07-07 01:32:16 +0000370 offB_TISTART = offsetof(VexGuestPPC32State,guest_TISTART);
371 offB_TILEN = offsetof(VexGuestPPC32State,guest_TILEN);
sewardj27e1dd62005-06-30 11:49:14 +0000372 vassert(archinfo_guest->subarch == VexSubArchPPC32_noAV
373 || archinfo_guest->subarch == VexSubArchPPC32_AV);
sewardjdb4738a2005-07-07 01:32:16 +0000374 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TISTART ) == 4);
375 vassert(sizeof( ((VexGuestPPC32State*)0)->guest_TILEN ) == 4);
cerionaabdfbf2005-01-29 12:56:15 +0000376 break;
377
sewardjf13a16a2004-07-05 17:10:14 +0000378 default:
sewardj887a11a2004-07-05 17:26:47 +0000379 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000380 }
381
sewardj9df271d2004-12-31 22:37:42 +0000382 /* yet more sanity checks ... */
sewardj0ec57c52005-02-01 15:24:10 +0000383 if (arch_guest == arch_host) {
sewardj9df271d2004-12-31 22:37:42 +0000384 /* doesn't necessarily have to be true, but if it isn't it means
sewardj0ec57c52005-02-01 15:24:10 +0000385 we are simulating one flavour of an architecture a different
386 flavour of the same architecture, which is pretty strange. */
sewardj27e1dd62005-06-30 11:49:14 +0000387 vassert(archinfo_guest->subarch == archinfo_host->subarch);
sewardj9df271d2004-12-31 22:37:42 +0000388 }
sewardj2a9ad022004-11-25 02:46:58 +0000389
sewardjf48ac192004-10-29 00:41:29 +0000390 if (vex_traceflags & VEX_TRACE_FE)
391 vex_printf("\n------------------------"
392 " Front end "
393 "------------------------\n\n");
394
sewardj9e6491a2005-07-02 19:24:10 +0000395 irbb = bb_to_IR ( guest_extents,
396 disInstrFn,
397 guest_bytes,
398 guest_bytes_addr,
399 chase_into_ok,
400 host_is_bigendian,
401 archinfo_guest,
sewardjdb4738a2005-07-07 01:32:16 +0000402 guest_word_type,
403 False/*selfcheck*/,
404 offB_TISTART,
405 offB_TILEN );
sewardjf13a16a2004-07-05 17:10:14 +0000406
407 if (irbb == NULL) {
408 /* Access failure. */
sewardjd887b862005-01-17 18:34:34 +0000409 vexClearTEMP();
sewardjf48ac192004-10-29 00:41:29 +0000410 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000411 return VexTransAccessFail;
sewardjf13a16a2004-07-05 17:10:14 +0000412 }
sewardjaa59f942004-10-09 09:34:36 +0000413
sewardj72c72812005-01-19 11:49:45 +0000414 vassert(guest_extents->n_used >= 1 && guest_extents->n_used <= 3);
415 vassert(guest_extents->base[0] == guest_bytes_addr);
416 for (i = 0; i < guest_extents->n_used; i++) {
417 vassert(guest_extents->len[i] < 10000); /* sanity */
418 }
419
sewardjaa59f942004-10-09 09:34:36 +0000420 /* If debugging, show the raw guest bytes for this bb. */
sewardj109ffdb2004-12-10 21:45:38 +0000421 if (0 || (vex_traceflags & VEX_TRACE_FE)) {
sewardj72c72812005-01-19 11:49:45 +0000422 if (guest_extents->n_used > 1) {
423 vex_printf("can't show code due to extents > 1\n");
424 } else {
425 /* HACK */
426 UChar* p = (UChar*)guest_bytes;
427 UInt guest_bytes_read = (UInt)guest_extents->len[0];
sewardjd9763622005-02-07 03:12:19 +0000428 vex_printf(". 0 %llx %u\n.", guest_bytes_addr, guest_bytes_read );
sewardj72c72812005-01-19 11:49:45 +0000429 for (i = 0; i < guest_bytes_read; i++)
sewardjaa59f942004-10-09 09:34:36 +0000430 vex_printf(" %02x", (Int)p[i] );
sewardj72c72812005-01-19 11:49:45 +0000431 vex_printf("\n\n");
432 }
sewardjaa59f942004-10-09 09:34:36 +0000433 }
434
435 /* Sanity check the initial IR. */
sewardjb9230752004-12-29 19:25:06 +0000436 sanityCheckIRBB( irbb, "initial IR",
437 False/*can be non-flat*/, guest_word_type );
sewardje8e9d732004-07-16 21:03:45 +0000438
sewardjedf4d692004-08-17 13:52:58 +0000439 /* Clean it up, hopefully a lot. */
sewardj8d2291c2004-10-25 14:50:21 +0000440 irbb = do_iropt_BB ( irbb, specHelper, preciseMemExnsFn,
441 guest_bytes_addr );
sewardjb9230752004-12-29 19:25:06 +0000442 sanityCheckIRBB( irbb, "after initial iropt",
443 True/*must be flat*/, guest_word_type );
sewardjedf4d692004-08-17 13:52:58 +0000444
sewardjf48ac192004-10-29 00:41:29 +0000445 if (vex_traceflags & VEX_TRACE_OPT1) {
446 vex_printf("\n------------------------"
447 " After pre-instr IR optimisation "
448 "------------------------\n\n");
sewardjedf4d692004-08-17 13:52:58 +0000449 ppIRBB ( irbb );
450 vex_printf("\n");
451 }
452
sewardjf13a16a2004-07-05 17:10:14 +0000453 /* Get the thing instrumented. */
sewardj49651f42004-10-28 22:11:04 +0000454 if (instrument1)
sewardj918c8f32005-03-21 00:54:33 +0000455 irbb = (*instrument1)(irbb, guest_layout,
456 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000457 if (instrument2)
sewardj918c8f32005-03-21 00:54:33 +0000458 irbb = (*instrument2)(irbb, guest_layout,
459 guest_word_type, host_word_type);
sewardj49651f42004-10-28 22:11:04 +0000460
sewardjf48ac192004-10-29 00:41:29 +0000461 if (vex_traceflags & VEX_TRACE_INST) {
462 vex_printf("\n------------------------"
463 " After instrumentation "
464 "------------------------\n\n");
465 ppIRBB ( irbb );
466 vex_printf("\n");
467 }
468
sewardj49651f42004-10-28 22:11:04 +0000469 if (instrument1 || instrument2)
sewardjb9230752004-12-29 19:25:06 +0000470 sanityCheckIRBB( irbb, "after instrumentation",
471 True/*must be flat*/, guest_word_type );
sewardjf13a16a2004-07-05 17:10:14 +0000472
sewardj9578a8b2004-11-04 19:44:48 +0000473 /* Do a post-instrumentation cleanup pass. */
474 if (cleanup_after_instrumentation) {
475 do_deadcode_BB( irbb );
476 irbb = cprop_BB( irbb );
477 do_deadcode_BB( irbb );
sewardjb9230752004-12-29 19:25:06 +0000478 sanityCheckIRBB( irbb, "after post-instrumentation cleanup",
479 True/*must be flat*/, guest_word_type );
sewardj9578a8b2004-11-04 19:44:48 +0000480 }
481
482 if (vex_traceflags & VEX_TRACE_OPT2) {
483 vex_printf("\n------------------------"
484 " After post-instr IR optimisation "
485 "------------------------\n\n");
486 ppIRBB ( irbb );
487 vex_printf("\n");
488 }
489
sewardjf13a16a2004-07-05 17:10:14 +0000490 /* Turn it into virtual-registerised code. */
sewardj49651f42004-10-28 22:11:04 +0000491 do_deadcode_BB( irbb );
492 do_treebuild_BB( irbb );
sewardjf48ac192004-10-29 00:41:29 +0000493
494 if (vex_traceflags & VEX_TRACE_TREES) {
495 vex_printf("\n------------------------"
496 " After tree-building "
497 "------------------------\n\n");
498 ppIRBB ( irbb );
499 vex_printf("\n");
500 }
501
sewardje908c422005-02-04 21:18:16 +0000502 /* HACK */
cerion54560812005-02-03 13:40:49 +0000503 if (0) { *host_bytes_used = 0; return VexTransOK; }
sewardje908c422005-02-04 21:18:16 +0000504 /* end HACK */
sewardjc33671d2005-02-01 20:30:00 +0000505
sewardjf48ac192004-10-29 00:41:29 +0000506 if (vex_traceflags & VEX_TRACE_VCODE)
507 vex_printf("\n------------------------"
508 " Instruction selection "
509 "------------------------\n");
510
sewardj27e1dd62005-06-30 11:49:14 +0000511 vcode = iselBB ( irbb, archinfo_host );
sewardjf13a16a2004-07-05 17:10:14 +0000512
sewardjf48ac192004-10-29 00:41:29 +0000513 if (vex_traceflags & VEX_TRACE_VCODE)
514 vex_printf("\n");
515
sewardjf48ac192004-10-29 00:41:29 +0000516 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000517 for (i = 0; i < vcode->arr_used; i++) {
518 vex_printf("%3d ", i);
519 ppInstr(vcode->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
sewardjf13a16a2004-07-05 17:10:14 +0000525 /* Register allocate. */
526 rcode = doRegisterAllocation ( vcode, available_real_regs,
sewardj72c72812005-01-19 11:49:45 +0000527 n_available_real_regs,
528 isMove, getRegUsage, mapRegs,
529 genSpill, genReload, guest_sizeB,
530 ppInstr, ppReg );
sewardjf13a16a2004-07-05 17:10:14 +0000531
sewardjf48ac192004-10-29 00:41:29 +0000532 if (vex_traceflags & VEX_TRACE_RCODE) {
533 vex_printf("\n------------------------"
534 " Register-allocated code "
535 "------------------------\n\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000536 for (i = 0; i < rcode->arr_used; i++) {
537 vex_printf("%3d ", i);
538 ppInstr(rcode->arr[i]);
539 vex_printf("\n");
540 }
sewardjfbcaf332004-07-08 01:46:01 +0000541 vex_printf("\n");
542 }
sewardjfbcaf332004-07-08 01:46:01 +0000543
sewardje908c422005-02-04 21:18:16 +0000544 /* HACK */
545 if (0) { *host_bytes_used = 0; return VexTransOK; }
546 /* end HACK */
547
sewardj81bd5502004-07-21 18:49:27 +0000548 /* Assemble */
sewardjf48ac192004-10-29 00:41:29 +0000549 if (vex_traceflags & VEX_TRACE_ASM) {
550 vex_printf("\n------------------------"
551 " Assembly "
552 "------------------------\n\n");
553 }
554
sewardj81bd5502004-07-21 18:49:27 +0000555 out_used = 0; /* tracks along the host_bytes array */
556 for (i = 0; i < rcode->arr_used; i++) {
sewardjf48ac192004-10-29 00:41:29 +0000557 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000558 ppInstr(rcode->arr[i]);
559 vex_printf("\n");
560 }
sewardj81bd5502004-07-21 18:49:27 +0000561 j = (*emit)( insn_bytes, 32, rcode->arr[i] );
sewardjf48ac192004-10-29 00:41:29 +0000562 if (vex_traceflags & VEX_TRACE_ASM) {
sewardjbad34a92004-07-22 01:14:11 +0000563 for (k = 0; k < j; k++)
sewardj72c72812005-01-19 11:49:45 +0000564 if (insn_bytes[k] < 16)
sewardj86898e82004-07-22 17:26:12 +0000565 vex_printf("0%x ", (UInt)insn_bytes[k]);
566 else
567 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000568 vex_printf("\n\n");
569 }
sewardj81bd5502004-07-21 18:49:27 +0000570 if (out_used + j > host_bytes_size) {
sewardjd887b862005-01-17 18:34:34 +0000571 vexClearTEMP();
sewardjf48ac192004-10-29 00:41:29 +0000572 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000573 return VexTransOutputFull;
sewardj81bd5502004-07-21 18:49:27 +0000574 }
575 for (k = 0; k < j; k++) {
576 host_bytes[out_used] = insn_bytes[k];
577 out_used++;
578 }
579 vassert(out_used <= host_bytes_size);
580 }
581 *host_bytes_used = out_used;
582
sewardjd887b862005-01-17 18:34:34 +0000583 vexClearTEMP();
sewardjf13a16a2004-07-05 17:10:14 +0000584
sewardjf48ac192004-10-29 00:41:29 +0000585 vex_traceflags = 0;
sewardjd887b862005-01-17 18:34:34 +0000586 return VexTransOK;
sewardj35421a32004-07-05 13:12:34 +0000587}
588
589
sewardj893aada2004-11-29 19:57:54 +0000590/* --------- Emulation warnings. --------- */
591
592HChar* LibVEX_EmWarn_string ( VexEmWarn ew )
593{
594 switch (ew) {
595 case EmWarn_NONE:
596 return "none";
597 case EmWarn_X86_x87exns:
598 return "Unmasking x87 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000599 case EmWarn_X86_x87precision:
600 return "Selection of non-80-bit x87 FP precision";
601 case EmWarn_X86_sseExns:
sewardj5edfc262004-12-15 12:13:52 +0000602 return "Unmasking SSE FP exceptions";
603 case EmWarn_X86_fz:
604 return "Setting %mxcsr.fz (SSE flush-underflows-to-zero mode)";
605 case EmWarn_X86_daz:
606 return "Setting %mxcsr.daz (SSE treat-denormals-as-zero mode)";
cerion094d1392005-06-20 13:45:57 +0000607 case EmWarn_PPC32exns:
608 return "Unmasking PPC32 FP exceptions";
sewardj893aada2004-11-29 19:57:54 +0000609 default:
610 vpanic("LibVEX_EmWarn_string: unknown warning");
611 }
612}
sewardj35421a32004-07-05 13:12:34 +0000613
sewardj27e1dd62005-06-30 11:49:14 +0000614/* --------- Arch/Subarch stuff. --------- */
sewardjbef170b2004-12-21 01:23:00 +0000615
616const HChar* LibVEX_ppVexArch ( VexArch arch )
617{
618 switch (arch) {
619 case VexArch_INVALID: return "INVALID";
620 case VexArchX86: return "X86";
621 case VexArchAMD64: return "AMD64";
622 case VexArchARM: return "ARM";
sewardj0ec57c52005-02-01 15:24:10 +0000623 case VexArchPPC32: return "PPC32";
sewardjbef170b2004-12-21 01:23:00 +0000624 default: return "VexArch???";
625 }
626}
627
628const HChar* LibVEX_ppVexSubArch ( VexSubArch subarch )
629{
630 switch (subarch) {
sewardj0ec57c52005-02-01 15:24:10 +0000631 case VexSubArch_INVALID: return "INVALID";
632 case VexSubArch_NONE: return "NONE";
633 case VexSubArchX86_sse0: return "x86-sse0";
634 case VexSubArchX86_sse1: return "x86-sse1";
635 case VexSubArchX86_sse2: return "x86-sse2";
636 case VexSubArchARM_v4: return "arm-v4";
637 case VexSubArchPPC32_noAV: return "ppc32-noAltivec";
638 case VexSubArchPPC32_AV: return "ppc32-Altivec";
639 default: return "VexSubArch???";
sewardjbef170b2004-12-21 01:23:00 +0000640 }
641}
642
sewardj27e1dd62005-06-30 11:49:14 +0000643/* Write default settings info *vai. */
644void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
645{
646 vai->subarch = VexSubArch_INVALID;
647 vai->ppc32_cache_line_szB = 0;
648}
649
650
sewardj35421a32004-07-05 13:12:34 +0000651/*---------------------------------------------------------------*/
sewardjc0ee2ed2004-07-27 10:29:41 +0000652/*--- end main/vex_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +0000653/*---------------------------------------------------------------*/