blob: 752f20f838af0588fb6ff840d8eb29646f9ad711 [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"
sewardjf13a16a2004-07-05 17:10:14 +000010
sewardjc0ee2ed2004-07-27 10:29:41 +000011#include "main/vex_globals.h"
12#include "main/vex_util.h"
13#include "host-generic/h_generic_regs.h"
14#include "host-x86/hdefs.h"
15#include "guest-x86/gdefs.h"
sewardj35421a32004-07-05 13:12:34 +000016
17
18/* This file contains the top level interface to the library. */
19
20/* --------- Initialise the library. --------- */
21
22/* Exported to library client. */
23
sewardj887a11a2004-07-05 17:26:47 +000024void LibVEX_Init (
sewardj35421a32004-07-05 13:12:34 +000025 /* failure exit function */
sewardj2b515872004-07-05 20:50:45 +000026 __attribute__ ((noreturn))
sewardj35421a32004-07-05 13:12:34 +000027 void (*failure_exit) ( void ),
28 /* logging output function */
29 void (*log_bytes) ( Char*, Int nbytes ),
30 /* debug paranoia level */
31 Int debuglevel,
sewardj58800ff2004-07-28 01:51:10 +000032 /* initial verbosity level */
sewardj35421a32004-07-05 13:12:34 +000033 Int verbosity,
34 /* Are we supporting valgrind checking? */
35 Bool valgrind_support,
36 /* Max # guest insns per bb */
37 Int guest_insns_per_bb
38)
39{
40 vassert(!vex_initdone);
41 vassert(failure_exit);
sewardj35421a32004-07-05 13:12:34 +000042 vassert(log_bytes);
sewardj35421a32004-07-05 13:12:34 +000043 vassert(debuglevel >= 0);
sewardj35421a32004-07-05 13:12:34 +000044 vassert(verbosity >= 0);
sewardj35421a32004-07-05 13:12:34 +000045 vassert(guest_insns_per_bb >= 1 && guest_insns_per_bb <= 100);
sewardj443cd9d2004-07-18 23:06:45 +000046
47 vex_failure_exit = failure_exit;
48 vex_log_bytes = log_bytes;
49 vex_debuglevel = debuglevel;
50 vex_verbosity = verbosity;
51 vex_valgrind_support = valgrind_support;
sewardj35421a32004-07-05 13:12:34 +000052 vex_guest_insns_per_bb = guest_insns_per_bb;
sewardj443cd9d2004-07-18 23:06:45 +000053 vex_initdone = True;
54 LibVEX_SetAllocMode ( AllocModeTEMPORARY );
sewardj35421a32004-07-05 13:12:34 +000055}
56
57
58/* --------- Make a translation. --------- */
59
60/* Exported to library client. */
61
sewardj887a11a2004-07-05 17:26:47 +000062TranslateResult LibVEX_Translate (
sewardj35421a32004-07-05 13:12:34 +000063 /* The instruction sets we are translating from and to. */
64 InsnSet iset_guest,
65 InsnSet iset_host,
66 /* IN: the block to translate, and its guest address. */
sewardj81bd5502004-07-21 18:49:27 +000067 UChar* guest_bytes,
sewardj35421a32004-07-05 13:12:34 +000068 Addr64 guest_bytes_addr,
69 /* OUT: the number of bytes actually read */
70 Int* guest_bytes_read,
71 /* IN: a place to put the resulting code, and its size */
sewardj81bd5502004-07-21 18:49:27 +000072 UChar* host_bytes,
73 Int host_bytes_size,
sewardj35421a32004-07-05 13:12:34 +000074 /* OUT: how much of the output area is used. */
75 Int* host_bytes_used,
76 /* IN: optionally, an instrumentation function. */
sewardjf13a16a2004-07-05 17:10:14 +000077 IRBB* (*instrument) ( IRBB* ),
sewardj35421a32004-07-05 13:12:34 +000078 /* IN: optionally, an access check function for guest code. */
sewardj58800ff2004-07-28 01:51:10 +000079 Bool (*byte_accessible) ( Addr64 ),
80 /* IN: if > 0, use this verbosity for this bb */
81 Int bb_verbosity
sewardj35421a32004-07-05 13:12:34 +000082)
83{
sewardj81bd5502004-07-21 18:49:27 +000084 /* This the bundle of functions we need to do the back-end stuff
85 (insn selection, reg-alloc, assembly) whilst being insulated
86 from the target instruction set. */
sewardjf13a16a2004-07-05 17:10:14 +000087 HReg* available_real_regs;
88 Int n_available_real_regs;
sewardj443cd9d2004-07-18 23:06:45 +000089 Bool (*isMove) (HInstr*, HReg*, HReg*);
90 void (*getRegUsage) (HRegUsage*, HInstr*);
91 void (*mapRegs) (HRegRemap*, HInstr*);
92 HInstr* (*genSpill) ( HReg, Int );
93 HInstr* (*genReload) ( HReg, Int );
94 void (*ppInstr) ( HInstr* );
95 void (*ppReg) ( HReg );
sewardj36ca5132004-07-24 13:12:23 +000096 HInstrArray* (*iselBB) ( IRBB*, Addr64(*)(Char*) );
sewardj443cd9d2004-07-18 23:06:45 +000097 IRBB* (*bbToIR) ( UChar*, Addr64, Int*,
98 Bool(*)(Addr64), Bool );
sewardj81bd5502004-07-21 18:49:27 +000099 Int (*emit) ( UChar*, Int, HInstr* );
sewardj36ca5132004-07-24 13:12:23 +0000100 Addr64 (*findHelper) ( Char* );
sewardjf13a16a2004-07-05 17:10:14 +0000101
sewardjc9a65702004-07-07 16:32:57 +0000102 Bool host_is_bigendian = False;
sewardjf13a16a2004-07-05 17:10:14 +0000103 IRBB* irbb;
104 HInstrArray* vcode;
105 HInstrArray* rcode;
sewardj58800ff2004-07-28 01:51:10 +0000106 Int i, j, k, out_used, saved_verbosity;
sewardj2e56f9f2004-07-24 01:24:38 +0000107 UChar insn_bytes[32];
sewardjf13a16a2004-07-05 17:10:14 +0000108
sewardj36ca5132004-07-24 13:12:23 +0000109 available_real_regs = NULL;
110 n_available_real_regs = 0;
111 isMove = NULL;
112 getRegUsage = NULL;
113 mapRegs = NULL;
114 genSpill = NULL;
115 genReload = NULL;
116 ppInstr = NULL;
117 ppReg = NULL;
118 iselBB = NULL;
119 bbToIR = NULL;
120 emit = NULL;
121 findHelper = NULL;
122
sewardj58800ff2004-07-28 01:51:10 +0000123 saved_verbosity = vex_verbosity;
124 if (bb_verbosity > 0)
125 vex_verbosity = bb_verbosity;
126
sewardj35421a32004-07-05 13:12:34 +0000127 vassert(vex_initdone);
sewardj443cd9d2004-07-18 23:06:45 +0000128 LibVEX_ClearTemporary(False);
sewardjf13a16a2004-07-05 17:10:14 +0000129
130 /* First off, check that the guest and host insn sets
131 are supported. */
132 switch (iset_host) {
133 case InsnSetX86:
134 getAllocableRegs_X86 ( &n_available_real_regs,
135 &available_real_regs );
136 isMove = (Bool(*)(HInstr*,HReg*,HReg*)) isMove_X86Instr;
137 getRegUsage = (void(*)(HRegUsage*,HInstr*)) getRegUsage_X86Instr;
138 mapRegs = (void(*)(HRegRemap*,HInstr*)) mapRegs_X86Instr;
139 genSpill = (HInstr*(*)(HReg,Int)) genSpill_X86;
140 genReload = (HInstr*(*)(HReg,Int)) genReload_X86;
sewardj2b515872004-07-05 20:50:45 +0000141 ppInstr = (void(*)(HInstr*)) ppX86Instr;
142 ppReg = (void(*)(HReg)) ppHRegX86;
sewardjf13a16a2004-07-05 17:10:14 +0000143 iselBB = iselBB_X86;
sewardj81bd5502004-07-21 18:49:27 +0000144 emit = (Int(*)(UChar*,Int,HInstr*)) emit_X86Instr;
sewardjc9a65702004-07-07 16:32:57 +0000145 host_is_bigendian = False;
sewardjf13a16a2004-07-05 17:10:14 +0000146 break;
147 default:
sewardj887a11a2004-07-05 17:26:47 +0000148 vpanic("LibVEX_Translate: unsupported target insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000149 }
150
151 switch (iset_guest) {
152 case InsnSetX86:
sewardj36ca5132004-07-24 13:12:23 +0000153 bbToIR = bbToIR_X86Instr;
154 findHelper = x86guest_findhelper;
sewardjf13a16a2004-07-05 17:10:14 +0000155 break;
156 default:
sewardj887a11a2004-07-05 17:26:47 +0000157 vpanic("LibVEX_Translate: unsupported guest insn set");
sewardjf13a16a2004-07-05 17:10:14 +0000158 }
159
160 irbb = bbToIR ( guest_bytes,
161 guest_bytes_addr,
162 guest_bytes_read,
sewardjc9a65702004-07-07 16:32:57 +0000163 byte_accessible,
164 host_is_bigendian );
sewardjf13a16a2004-07-05 17:10:14 +0000165
166 if (irbb == NULL) {
167 /* Access failure. */
sewardj443cd9d2004-07-18 23:06:45 +0000168 LibVEX_ClearTemporary(False);
sewardj58800ff2004-07-28 01:51:10 +0000169 vex_verbosity = saved_verbosity;
sewardjf13a16a2004-07-05 17:10:14 +0000170 return TransAccessFail;
171 }
sewardj35439212004-07-14 22:36:10 +0000172 sanityCheckIRBB(irbb, Ity_I32);
sewardje8e9d732004-07-16 21:03:45 +0000173
sewardjf13a16a2004-07-05 17:10:14 +0000174 /* Get the thing instrumented. */
175 if (instrument)
176 irbb = (*instrument)(irbb);
177
178 /* Turn it into virtual-registerised code. */
sewardj36ca5132004-07-24 13:12:23 +0000179 vcode = iselBB ( irbb, findHelper );
sewardjf13a16a2004-07-05 17:10:14 +0000180
sewardj1f40a0a2004-07-21 12:28:07 +0000181 if (vex_verbosity > 0) {
182 vex_printf("\n-------- Virtual registerised code --------\n");
183 for (i = 0; i < vcode->arr_used; i++) {
184 vex_printf("%3d ", i);
185 ppInstr(vcode->arr[i]);
186 vex_printf("\n");
187 }
sewardjfbcaf332004-07-08 01:46:01 +0000188 vex_printf("\n");
189 }
sewardjfbcaf332004-07-08 01:46:01 +0000190
sewardjf13a16a2004-07-05 17:10:14 +0000191 /* Register allocate. */
192 rcode = doRegisterAllocation ( vcode, available_real_regs,
193 n_available_real_regs,
194 isMove, getRegUsage, mapRegs,
sewardj2b515872004-07-05 20:50:45 +0000195 genSpill, genReload,
196 ppInstr, ppReg );
sewardjf13a16a2004-07-05 17:10:14 +0000197
sewardj1f40a0a2004-07-21 12:28:07 +0000198 if (vex_verbosity > 0) {
199 vex_printf("\n-------- Post-regalloc code --------\n");
200 for (i = 0; i < rcode->arr_used; i++) {
201 vex_printf("%3d ", i);
202 ppInstr(rcode->arr[i]);
203 vex_printf("\n");
204 }
sewardjfbcaf332004-07-08 01:46:01 +0000205 vex_printf("\n");
206 }
sewardjfbcaf332004-07-08 01:46:01 +0000207
sewardj81bd5502004-07-21 18:49:27 +0000208 /* Assemble */
sewardj81bd5502004-07-21 18:49:27 +0000209 out_used = 0; /* tracks along the host_bytes array */
210 for (i = 0; i < rcode->arr_used; i++) {
sewardj14731f22004-07-25 01:24:28 +0000211 if (vex_verbosity > 1) {
sewardjbad34a92004-07-22 01:14:11 +0000212 ppInstr(rcode->arr[i]);
213 vex_printf("\n");
214 }
sewardj81bd5502004-07-21 18:49:27 +0000215 j = (*emit)( insn_bytes, 32, rcode->arr[i] );
sewardj14731f22004-07-25 01:24:28 +0000216 if (vex_verbosity > 1) {
sewardjbad34a92004-07-22 01:14:11 +0000217 for (k = 0; k < j; k++)
sewardj86898e82004-07-22 17:26:12 +0000218 if (insn_bytes[k] < 16)
219 vex_printf("0%x ", (UInt)insn_bytes[k]);
220 else
221 vex_printf("%x ", (UInt)insn_bytes[k]);
sewardjbad34a92004-07-22 01:14:11 +0000222 vex_printf("\n\n");
223 }
sewardj81bd5502004-07-21 18:49:27 +0000224 if (out_used + j > host_bytes_size) {
225 LibVEX_ClearTemporary(False);
sewardj58800ff2004-07-28 01:51:10 +0000226 vex_verbosity = saved_verbosity;
sewardj81bd5502004-07-21 18:49:27 +0000227 return TransOutputFull;
228 }
229 for (k = 0; k < j; k++) {
230 host_bytes[out_used] = insn_bytes[k];
231 out_used++;
232 }
233 vassert(out_used <= host_bytes_size);
234 }
235 *host_bytes_used = out_used;
236
sewardj1f40a0a2004-07-21 12:28:07 +0000237 // LibVEX_ClearTemporary(True);
238 LibVEX_ClearTemporary(False);
sewardjf13a16a2004-07-05 17:10:14 +0000239
sewardj58800ff2004-07-28 01:51:10 +0000240 vex_verbosity = saved_verbosity;
sewardj35421a32004-07-05 13:12:34 +0000241 return TransOK;
242}
243
244
245
246/*---------------------------------------------------------------*/
sewardjc0ee2ed2004-07-27 10:29:41 +0000247/*--- end main/vex_main.c ---*/
sewardj35421a32004-07-05 13:12:34 +0000248/*---------------------------------------------------------------*/