blob: 8f60330841fbb5552040df21e2075f62a8528629 [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
sewardj887a11a2004-07-05 17:26:47 +00009#include "libvex.h"
sewardj81ec4182004-10-25 23:15:52 +000010#include "libvex_guest_x86.h"
sewardjf13a16a2004-07-05 17:10:14 +000011
sewardjc0ee2ed2004-07-27 10:29:41 +000012#include "main/vex_globals.h"
13#include "main/vex_util.h"
14#include "host-generic/h_generic_regs.h"
15#include "host-x86/hdefs.h"
16#include "guest-x86/gdefs.h"
sewardjedf4d692004-08-17 13:52:58 +000017#include "ir/iropt.h"
sewardj35421a32004-07-05 13:12:34 +000018
19
20/* This file contains the top level interface to the library. */
21
22/* --------- Initialise the library. --------- */
23
24/* Exported to library client. */
25
sewardj08613742004-10-25 13:01:45 +000026void LibVEX_default_VexControl ( /*OUT*/ VexControl* vcon )
27{
28 vcon->iropt_verbosity = 0;
29 vcon->iropt_level = 2;
30 vcon->iropt_precise_memory_exns = False;
31 vcon->iropt_unroll_thresh = 120;
32 vcon->guest_max_insns = 50;
33 vcon->guest_chase_thresh = 10;
34}
35
36
37/* Exported to library client. */
38
sewardj887a11a2004-07-05 17:26:47 +000039void LibVEX_Init (
sewardj35421a32004-07-05 13:12:34 +000040 /* failure exit function */
sewardj2b515872004-07-05 20:50:45 +000041 __attribute__ ((noreturn))
sewardj35421a32004-07-05 13:12:34 +000042 void (*failure_exit) ( void ),
43 /* logging output function */
44 void (*log_bytes) ( Char*, Int nbytes ),
45 /* debug paranoia level */
46 Int debuglevel,
sewardj58800ff2004-07-28 01:51:10 +000047 /* initial verbosity level */
sewardj35421a32004-07-05 13:12:34 +000048 Int verbosity,
49 /* Are we supporting valgrind checking? */
50 Bool valgrind_support,
sewardj08613742004-10-25 13:01:45 +000051 /* Control ... */
52 /*READONLY*/VexControl* vcon
sewardj35421a32004-07-05 13:12:34 +000053)
54{
sewardj08613742004-10-25 13:01:45 +000055 /* First off, do enough minimal setup so that the following
56 assertions can fail in a sane fashion, if need be. */
sewardjea602bc2004-10-14 21:40:12 +000057 vex_failure_exit = failure_exit;
58 vex_log_bytes = log_bytes;
59
60 /* Now it's safe to check parameters for sanity. */
sewardj35421a32004-07-05 13:12:34 +000061 vassert(!vex_initdone);
62 vassert(failure_exit);
sewardj35421a32004-07-05 13:12:34 +000063 vassert(log_bytes);
sewardj35421a32004-07-05 13:12:34 +000064 vassert(debuglevel >= 0);
sewardj35421a32004-07-05 13:12:34 +000065 vassert(verbosity >= 0);
sewardj08613742004-10-25 13:01:45 +000066
67 vassert(vcon->iropt_verbosity >= 0);
68 vassert(vcon->iropt_level >= 0);
69 vassert(vcon->iropt_level <= 2);
70 vassert(vcon->iropt_unroll_thresh >= 0);
71 vassert(vcon->iropt_unroll_thresh <= 400);
72 vassert(vcon->guest_max_insns >= 1);
73 vassert(vcon->guest_max_insns <= 100);
74 vassert(vcon->guest_chase_thresh >= 0);
75 vassert(vcon->guest_chase_thresh < vcon->guest_max_insns);
sewardj443cd9d2004-07-18 23:06:45 +000076
sewardj81ec4182004-10-25 23:15:52 +000077 /* All the guest state structs must have an 8-aligned size. */
78 vassert(0 == sizeof(VexGuestX86State) % 8);
79
sewardjea602bc2004-10-14 21:40:12 +000080 /* Check that Vex has been built with sizes of basic types as
81 stated in priv/libvex_basictypes.h. Failure of any of these is
82 a serious configuration error and should be corrected
83 immediately. If any of these assertions fail you can fully
84 expect Vex not to work properly, if at all. */
85
86 vassert(1 == sizeof(UChar));
87 vassert(1 == sizeof(Char));
88 vassert(2 == sizeof(UShort));
89 vassert(2 == sizeof(Short));
90 vassert(4 == sizeof(UInt));
91 vassert(4 == sizeof(Int));
92 vassert(8 == sizeof(ULong));
93 vassert(8 == sizeof(Long));
94 vassert(4 == sizeof(Float));
95 vassert(8 == sizeof(Double));
96 vassert(1 == sizeof(Bool));
97 vassert(4 == sizeof(Addr32));
98 vassert(8 == sizeof(Addr64));
99
100 vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
101 vassert(sizeof(void*) == sizeof(int*));
102 vassert(sizeof(void*) == sizeof(HWord));
103
104 /* Really start up .. */
sewardj443cd9d2004-07-18 23:06:45 +0000105 vex_debuglevel = debuglevel;
106 vex_verbosity = verbosity;
107 vex_valgrind_support = valgrind_support;
sewardj08613742004-10-25 13:01:45 +0000108 vex_control = *vcon;
sewardj443cd9d2004-07-18 23:06:45 +0000109 vex_initdone = True;
110 LibVEX_SetAllocMode ( AllocModeTEMPORARY );
sewardj35421a32004-07-05 13:12:34 +0000111}
112
113
114/* --------- Make a translation. --------- */
115
116/* Exported to library client. */
117
sewardj887a11a2004-07-05 17:26:47 +0000118TranslateResult LibVEX_Translate (
sewardj35421a32004-07-05 13:12:34 +0000119 /* The instruction sets we are translating from and to. */
120 InsnSet iset_guest,
121 InsnSet iset_host,
122 /* IN: the block to translate, and its guest address. */
sewardj81bd5502004-07-21 18:49:27 +0000123 UChar* guest_bytes,
sewardj35421a32004-07-05 13:12:34 +0000124 Addr64 guest_bytes_addr,
125 /* OUT: the number of bytes actually read */
126 Int* guest_bytes_read,
127 /* IN: a place to put the resulting code, and its size */
sewardj81bd5502004-07-21 18:49:27 +0000128 UChar* host_bytes,
129 Int host_bytes_size,
sewardj35421a32004-07-05 13:12:34 +0000130 /* OUT: how much of the output area is used. */
131 Int* host_bytes_used,
132 /* IN: optionally, an instrumentation function. */
sewardjf13a16a2004-07-05 17:10:14 +0000133 IRBB* (*instrument) ( IRBB* ),
sewardj35421a32004-07-05 13:12:34 +0000134 /* IN: optionally, an access check function for guest code. */
sewardj58800ff2004-07-28 01:51:10 +0000135 Bool (*byte_accessible) ( Addr64 ),
136 /* IN: if > 0, use this verbosity for this bb */
137 Int bb_verbosity
sewardj35421a32004-07-05 13:12:34 +0000138)
139{
sewardj81bd5502004-07-21 18:49:27 +0000140 /* This the bundle of functions we need to do the back-end stuff
141 (insn selection, reg-alloc, assembly) whilst being insulated
142 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +0000143 HReg* available_real_regs;
144 Int n_available_real_regs;
sewardj443cd9d2004-07-18 23:06:45 +0000145 Bool (*isMove) (HInstr*, HReg*, HReg*);
146 void (*getRegUsage) (HRegUsage*, HInstr*);
147 void (*mapRegs) (HRegRemap*, HInstr*);
148 HInstr* (*genSpill) ( HReg, Int );
149 HInstr* (*genReload) ( HReg, Int );
150 void (*ppInstr) ( HInstr* );
151 void (*ppReg) ( HReg );
sewardj36ca5132004-07-24 13:12:23 +0000152 HInstrArray* (*iselBB) ( IRBB*, Addr64(*)(Char*) );
sewardj443cd9d2004-07-18 23:06:45 +0000153 IRBB* (*bbToIR) ( UChar*, Addr64, Int*,
154 Bool(*)(Addr64), Bool );
sewardj81bd5502004-07-21 18:49:27 +0000155 Int (*emit) ( UChar*, Int, HInstr* );
sewardj36ca5132004-07-24 13:12:23 +0000156 Addr64 (*findHelper) ( Char* );
sewardj84ff0652004-08-23 16:16:08 +0000157 IRExpr* (*specHelper) ( Char*, IRExpr** );
sewardj8d2291c2004-10-25 14:50:21 +0000158 Bool (*preciseMemExnsFn) ( Int, Int );
sewardjf13a16a2004-07-05 17:10:14 +0000159
sewardjc9a65702004-07-07 16:32:57 +0000160 Bool host_is_bigendian = False;
sewardjf13a16a2004-07-05 17:10:14 +0000161 IRBB* irbb;
162 HInstrArray* vcode;
163 HInstrArray* rcode;
sewardj81ec4182004-10-25 23:15:52 +0000164 Int i, j, k, out_used, saved_verbosity, guest_sizeB;
sewardj2e56f9f2004-07-24 01:24:38 +0000165 UChar insn_bytes[32];
sewardjf13a16a2004-07-05 17:10:14 +0000166
sewardj36ca5132004-07-24 13:12:23 +0000167 available_real_regs = NULL;
168 n_available_real_regs = 0;
169 isMove = NULL;
170 getRegUsage = NULL;
171 mapRegs = NULL;
172 genSpill = NULL;
173 genReload = NULL;
174 ppInstr = NULL;
175 ppReg = NULL;
176 iselBB = NULL;
177 bbToIR = NULL;
178 emit = NULL;
179 findHelper = NULL;
sewardj84ff0652004-08-23 16:16:08 +0000180 specHelper = NULL;
sewardj8d2291c2004-10-25 14:50:21 +0000181 preciseMemExnsFn = NULL;
sewardj36ca5132004-07-24 13:12:23 +0000182
sewardj58800ff2004-07-28 01:51:10 +0000183 saved_verbosity = vex_verbosity;
184 if (bb_verbosity > 0)
185 vex_verbosity = bb_verbosity;
186
sewardj35421a32004-07-05 13:12:34 +0000187 vassert(vex_initdone);
sewardj443cd9d2004-07-18 23:06:45 +0000188 LibVEX_ClearTemporary(False);
sewardjf13a16a2004-07-05 17:10:14 +0000189
190 /* First off, check that the guest and host insn sets
191 are supported. */
192 switch (iset_host) {
193 case InsnSetX86:
194 getAllocableRegs_X86 ( &n_available_real_regs,
195 &available_real_regs );
196 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
197 getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_X86Instr;
198 mapRegs = (void(*)(HRegRemap*,HInstr*)) mapRegs_X86Instr;
199 genSpill = (HInstr*(*)(HReg,Int)) genSpill_X86;
200 genReload = (HInstr*(*)(HReg,Int)) genReload_X86;
sewardj2b515872004-07-05 20:50:45 +0000201 ppInstr = (void(*)(HInstr*)) ppX86Instr;
202 ppReg = (void(*)(HReg)) ppHRegX86;
sewardjf13a16a2004-07-05 17:10:14 +0000203 iselBB = iselBB_X86;
sewardj81bd5502004-07-21 18:49:27 +0000204 emit = (Int(*)(UChar*,Int,HInstr*)) emit_X86Instr;
sewardjc9a65702004-07-07 16:32:57 +0000205 host_is_bigendian = False;
sewardjf13a16a2004-07-05 17:10:14 +0000206 break;
207 default:
sewardj887a11a2004-07-05 17:26:47 +0000208 vpanic("LibVEX_Translate: unsupported target insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000209 }
210
211 switch (iset_guest) {
212 case InsnSetX86:
sewardj8d2291c2004-10-25 14:50:21 +0000213 preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
214 bbToIR = bbToIR_X86Instr;
215 findHelper = x86guest_findhelper;
216 specHelper = x86guest_spechelper;
sewardj81ec4182004-10-25 23:15:52 +0000217 guest_sizeB = sizeof(VexGuestX86State);
sewardjf13a16a2004-07-05 17:10:14 +0000218 break;
219 default:
sewardj887a11a2004-07-05 17:26:47 +0000220 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000221 }
222
223 irbb = bbToIR ( guest_bytes,
224 guest_bytes_addr,
225 guest_bytes_read,
sewardjc9a65702004-07-07 16:32:57 +0000226 byte_accessible,
227 host_is_bigendian );
sewardjf13a16a2004-07-05 17:10:14 +0000228
229 if (irbb == NULL) {
230 /* Access failure. */
sewardj443cd9d2004-07-18 23:06:45 +0000231 LibVEX_ClearTemporary(False);
sewardj58800ff2004-07-28 01:51:10 +0000232 vex_verbosity = saved_verbosity;
sewardjf13a16a2004-07-05 17:10:14 +0000233 return TransAccessFail;
234 }
sewardjaa59f942004-10-09 09:34:36 +0000235
236 /* If debugging, show the raw guest bytes for this bb. */
237 if (vex_verbosity >= 2) {
238 UChar* p = guest_bytes;
239 vex_printf("\n");
240 vex_printf(". 0 %llx %d\n.", guest_bytes_addr, *guest_bytes_read );
241 for (i = 0; i < *guest_bytes_read; i++)
242 vex_printf(" %02x", (Int)p[i] );
243 vex_printf("\n");
244 }
245
246 /* Sanity check the initial IR. */
sewardj35439212004-07-14 22:36:10 +0000247 sanityCheckIRBB(irbb, Ity_I32);
sewardje8e9d732004-07-16 21:03:45 +0000248
sewardjedf4d692004-08-17 13:52:58 +0000249 /* Clean it up, hopefully a lot. */
sewardj8d2291c2004-10-25 14:50:21 +0000250 irbb = do_iropt_BB ( irbb, specHelper, preciseMemExnsFn,
251 guest_bytes_addr );
sewardjd7cb8532004-08-17 23:59:23 +0000252 sanityCheckIRBB(irbb, Ity_I32);
sewardjedf4d692004-08-17 13:52:58 +0000253
254 if (vex_verbosity > 0) {
255 vex_printf("\n-------- After IR optimisation --------\n");
256 ppIRBB ( irbb );
257 vex_printf("\n");
258 }
259
sewardjf13a16a2004-07-05 17:10:14 +0000260 /* Get the thing instrumented. */
261 if (instrument)
262 irbb = (*instrument)(irbb);
263
264 /* Turn it into virtual-registerised code. */
sewardj36ca5132004-07-24 13:12:23 +0000265 vcode = iselBB ( irbb, findHelper );
sewardjf13a16a2004-07-05 17:10:14 +0000266
sewardj1f40a0a2004-07-21 12:28:07 +0000267 if (vex_verbosity > 0) {
268 vex_printf("\n-------- Virtual registerised code --------\n");
269 for (i = 0; i < vcode->arr_used; i++) {
270 vex_printf("%3d ", i);
271 ppInstr(vcode->arr[i]);
272 vex_printf("\n");
273 }
sewardjfbcaf332004-07-08 01:46:01 +0000274 vex_printf("\n");
275 }
sewardjfbcaf332004-07-08 01:46:01 +0000276
sewardjf13a16a2004-07-05 17:10:14 +0000277 /* Register allocate. */
278 rcode = doRegisterAllocation ( vcode, available_real_regs,
279 n_available_real_regs,
280 isMove, getRegUsage, mapRegs,
sewardj81ec4182004-10-25 23:15:52 +0000281 genSpill, genReload, guest_sizeB,
sewardj2b515872004-07-05 20:50:45 +0000282 ppInstr, ppReg );
sewardjf13a16a2004-07-05 17:10:14 +0000283
sewardj1f40a0a2004-07-21 12:28:07 +0000284 if (vex_verbosity > 0) {
285 vex_printf("\n-------- Post-regalloc code --------\n");
286 for (i = 0; i < rcode->arr_used; i++) {
287 vex_printf("%3d ", i);
288 ppInstr(rcode->arr[i]);
289 vex_printf("\n");
290 }
sewardjfbcaf332004-07-08 01:46:01 +0000291 vex_printf("\n");
292 }
sewardjfbcaf332004-07-08 01:46:01 +0000293
sewardj81bd5502004-07-21 18:49:27 +0000294 /* Assemble */
sewardj81bd5502004-07-21 18:49:27 +0000295 out_used = 0; /* tracks along the host_bytes array */
296 for (i = 0; i < rcode->arr_used; i++) {
sewardj14731f22004-07-25 01:24:28 +0000297 if (vex_verbosity > 1) {
sewardjbad34a92004-07-22 01:14:11 +0000298 ppInstr(rcode->arr[i]);
299 vex_printf("\n");
300 }
sewardj81bd5502004-07-21 18:49:27 +0000301 j = (*emit)( insn_bytes, 32, rcode->arr[i] );
sewardj14731f22004-07-25 01:24:28 +0000302 if (vex_verbosity > 1) {
sewardjbad34a92004-07-22 01:14:11 +0000303 for (k = 0; k < j; k++)
sewardj86898e82004-07-22 17:26:12 +0000304 if (insn_bytes[k] < 16)
305 vex_printf("0%x ", (UInt)insn_bytes[k]);
306 else
307 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000308 vex_printf("\n\n");
309 }
sewardj81bd5502004-07-21 18:49:27 +0000310 if (out_used + j > host_bytes_size) {
311 LibVEX_ClearTemporary(False);
sewardj58800ff2004-07-28 01:51:10 +0000312 vex_verbosity = saved_verbosity;
sewardj81bd5502004-07-21 18:49:27 +0000313 return TransOutputFull;
314 }
315 for (k = 0; k < j; k++) {
316 host_bytes[out_used] = insn_bytes[k];
317 out_used++;
318 }
319 vassert(out_used <= host_bytes_size);
320 }
321 *host_bytes_used = out_used;
322
sewardj1f40a0a2004-07-21 12:28:07 +0000323 // LibVEX_ClearTemporary(True);
324 LibVEX_ClearTemporary(False);
sewardjf13a16a2004-07-05 17:10:14 +0000325
sewardj58800ff2004-07-28 01:51:10 +0000326 vex_verbosity = saved_verbosity;
sewardj35421a32004-07-05 13:12:34 +0000327 return TransOK;
328}
329
330
331
332/*---------------------------------------------------------------*/
sewardjc0ee2ed2004-07-27 10:29:41 +0000333/*--- end main/vex_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +0000334/*---------------------------------------------------------------*/