/*---------------------------------------------------------*/
extern
-IRBB* bbToIR_ARM ( UChar* armCode,
- Addr64 eip,
- Int* guest_bytes_read,
- Bool (*byte_accessible)(Addr64),
- Bool (*resteerOkFn)(Addr64),
- Bool host_bigendian,
- VexSubArch subarch_guest );
+IRBB* bbToIR_ARM ( UChar* armCode,
+ Addr64 eip,
+ VexGuestExtents* vge,
+ Bool (*byte_accessible)(Addr64),
+ Bool (*resteerOkFn)(Addr64),
+ Bool host_bigendian,
+ VexSubArch subarch_guest );
/* Used by the optimiser to specialise calls to helpers. */
extern
dumping the IR into global irbb. Returns the size, in bytes, of
the basic block.
*/
-IRBB* bbToIR_ARM ( UChar* armCode,
- Addr64 guest_pc_start,
- Int* guest_bytes_read,
- Bool (*byte_accessible)(Addr64),
- Bool (*chase_into_ok)(Addr64),
- Bool host_bigendian,
- VexSubArch subarch_guest )
+IRBB* bbToIR_ARM ( UChar* armCode,
+ Addr64 guest_pc_start,
+ VexGuestExtents* vge,
+ Bool (*byte_accessible)(Addr64),
+ Bool (*chase_into_ok)(Addr64),
+ Bool host_bigendian,
+ VexSubArch subarch_guest )
{
UInt delta;
Int i, n_instrs, size, first_stmt_idx;
/* check sanity .. */
vassert(vex_control.guest_max_insns >= 1);
- vassert(vex_control.guest_max_insns < 1000);
+ vassert(vex_control.guest_max_insns < 500);
vassert(vex_control.guest_chase_thresh >= 0);
vassert(vex_control.guest_chase_thresh < vex_control.guest_max_insns);
vassert(subarch_guest == VexSubArchARM_v4);
+ /* Start a new, empty extent. */
+ vge->n_used = 1;
+ vge->base[0] = guest_pc_start;
+ vge->len[0] = 0;
+
/* Set up globals. */
host_is_bigendian = host_bigendian;
guest_code = armCode;
have so far gone. */
delta = 0;
n_instrs = 0;
- *guest_bytes_read = 0;
while (True) {
vassert(n_instrs < vex_control.guest_max_insns);
}
delta += size;
- *guest_bytes_read += size;
+ vge->len[vge->n_used-1] += size;
n_instrs++;
DIP("\n");
vassert(irbb->next != NULL);
return irbb;
case Dis_Resteer:
+ vpanic("bbToIR_ARM: Dis_Resteer: fixme");
+ /* need to add code here to start a new extent ... */
vassert(irbb->next == NULL);
/* figure out a new delta to continue at. */
vassert(chase_into_ok(guest_next));
/*------------------------------------------------------------*/
/*--- Helper bits and pieces for deconstructing the ---*/
-/*--- x86 insn stream. ---*/
+/*--- ARM insn stream. ---*/
/*------------------------------------------------------------*/
/* Add a statement to the list held by "irbb". */
/*---------------------------------------------------------*/
extern
-IRBB* bbToIR_X86 ( UChar* x86code,
- Addr64 eip,
- Int* guest_bytes_read,
- Bool (*byte_accessible)(Addr64),
- Bool (*resteerOkFn)(Addr64),
- Bool host_bigendian,
- VexSubArch subarch_guest );
+IRBB* bbToIR_X86 ( UChar* x86code,
+ Addr64 eip,
+ VexGuestExtents* vge,
+ Bool (*byte_accessible)(Addr64),
+ Bool (*resteerOkFn)(Addr64),
+ Bool host_bigendian,
+ VexSubArch subarch_guest );
/* Used by the optimiser to specialise calls to helpers. */
extern
/* Disassemble a complete basic block, starting at eip, and dumping
the ucode into cb. Returns the size, in bytes, of the basic
block. */
-IRBB* bbToIR_X86 ( UChar* x86code,
- Addr64 guest_eip_start,
- Int* guest_bytes_read,
- Bool (*byte_accessible)(Addr64),
- Bool (*chase_into_ok)(Addr64),
- Bool host_bigendian,
- VexSubArch subarch_guest )
+IRBB* bbToIR_X86 ( UChar* x86code,
+ Addr64 guest_eip_start,
+ VexGuestExtents* vge,
+ Bool (*byte_accessible)(Addr64),
+ Bool (*chase_into_ok)(Addr64),
+ Bool host_bigendian,
+ VexSubArch subarch_guest )
{
UInt delta;
Int i, n_instrs, size, first_stmt_idx;
/* check sanity .. */
vassert(vex_control.guest_max_insns >= 1);
- vassert(vex_control.guest_max_insns < 1000);
+ vassert(vex_control.guest_max_insns < 500);
vassert(vex_control.guest_chase_thresh >= 0);
vassert(vex_control.guest_chase_thresh < vex_control.guest_max_insns);
vassert((guest_eip_start >> 32) == 0);
+ /* Start a new, empty extent. */
+ vge->n_used = 1;
+ vge->base[0] = guest_eip_start;
+ vge->len[0] = 0;
+
/* Set up globals. */
host_is_bigendian = host_bigendian;
guest_code = x86code;
have so far gone. */
delta = 0;
n_instrs = 0;
- *guest_bytes_read = 0;
while (True) {
vassert(n_instrs < vex_control.guest_max_insns);
guest_next = 0;
- resteerOK = n_instrs < vex_control.guest_chase_thresh;
+ resteerOK
+ = n_instrs < vex_control.guest_chase_thresh
+ /* we can't afford to have a resteer once we're on the last
+ extent slot. */
+ && vge->n_used < 3;
+
first_stmt_idx = irbb->stmts_used;
if (n_instrs > 0) {
}
delta += size;
- *guest_bytes_read += size;
+ vge->len[vge->n_used-1] += size;
n_instrs++;
DIP("\n");
/* figure out a new delta to continue at. */
vassert(chase_into_ok(guest_next));
delta = (UInt)(guest_next - guest_eip_start);
+ /* we now have to start a new extent slot. */
+ vge->n_used++;
+ vassert(vge->n_used <= 3);
+ vge->base[vge->n_used-1] = guest_next;
+ vge->len[vge->n_used-1] = 0;
n_resteers++;
d_resteers++;
if (0 && (n_resteers & 0xFF) == 0)
UChar* guest_bytes,
Addr64 guest_bytes_addr,
Bool (*chase_into_ok) ( Addr64 ),
- /* OUT: the number of bytes actually read */
- Int* guest_bytes_read,
+ /* OUT: which bits of guest code actually got translated */
+ VexGuestExtents* guest_extents,
/* IN: a place to put the resulting code, and its size */
UChar* host_bytes,
Int host_bytes_size,
void (*ppInstr) ( HInstr* );
void (*ppReg) ( HReg );
HInstrArray* (*iselBB) ( IRBB*, VexSubArch );
- IRBB* (*bbToIR) ( UChar*, Addr64, Int*,
+ IRBB* (*bbToIR) ( UChar*, Addr64,
+ VexGuestExtents*,
Bool(*)(Addr64),
- Bool(*)(Addr64), Bool, VexSubArch );
+ Bool(*)(Addr64),
+ Bool, VexSubArch );
Int (*emit) ( UChar*, Int, HInstr* );
IRExpr* (*specHelper) ( Char*, IRExpr** );
Bool (*preciseMemExnsFn) ( Int, Int );
ppReg = (void(*)(HReg)) ppHRegX86;
iselBB = iselBB_X86;
emit = (Int(*)(UChar*,Int,HInstr*)) emit_X86Instr;
- host_is_bigendian = False;
+ host_is_bigendian = False;
host_word_type = Ity_I32;
vassert(subarch_host == VexSubArchX86_sse0
|| subarch_host == VexSubArchX86_sse1
"------------------------\n\n");
irbb = bbToIR ( guest_bytes,
- guest_bytes_addr,
- guest_bytes_read,
- byte_accessible,
+ guest_bytes_addr,
+ guest_extents,
+ byte_accessible,
chase_into_ok,
- host_is_bigendian,
+ host_is_bigendian,
subarch_guest );
if (irbb == NULL) {
return VexTransAccessFail;
}
+ vassert(guest_extents->n_used >= 1 && guest_extents->n_used <= 3);
+ vassert(guest_extents->base[0] == guest_bytes_addr);
+ for (i = 0; i < guest_extents->n_used; i++) {
+ vassert(guest_extents->len[i] < 10000); /* sanity */
+ }
+
/* If debugging, show the raw guest bytes for this bb. */
if (0 || (vex_traceflags & VEX_TRACE_FE)) {
- UChar* p = guest_bytes;
- vex_printf(". 0 %llx %d\n.", guest_bytes_addr, *guest_bytes_read );
- for (i = 0; i < *guest_bytes_read; i++)
+ if (guest_extents->n_used > 1) {
+ vex_printf("can't show code due to extents > 1\n");
+ } else {
+ /* HACK */
+ UChar* p = (UChar*)guest_bytes;
+ UInt guest_bytes_read = (UInt)guest_extents->len[0];
+ vex_printf(". 0 %llx %d\n.", guest_bytes_addr, guest_bytes_read );
+ for (i = 0; i < guest_bytes_read; i++)
vex_printf(" %02x", (Int)p[i] );
- vex_printf("\n\n");
+ vex_printf("\n\n");
+ }
}
/* Sanity check the initial IR. */
/* Register allocate. */
rcode = doRegisterAllocation ( vcode, available_real_regs,
- n_available_real_regs,
- isMove, getRegUsage, mapRegs,
- genSpill, genReload, guest_sizeB,
- ppInstr, ppReg );
+ n_available_real_regs,
+ isMove, getRegUsage, mapRegs,
+ genSpill, genReload, guest_sizeB,
+ ppInstr, ppReg );
if (vex_traceflags & VEX_TRACE_RCODE) {
vex_printf("\n------------------------"
j = (*emit)( insn_bytes, 32, rcode->arr[i] );
if (vex_traceflags & VEX_TRACE_ASM) {
for (k = 0; k < j; k++)
- if (insn_bytes[k] < 16)
+ if (insn_bytes[k] < 16)
vex_printf("0%x ", (UInt)insn_bytes[k]);
else
vex_printf("%x ", (UInt)insn_bytes[k]);
/*--- Make a translation ---*/
/*-------------------------------------------------------*/
+/* Describes the outcome of a translation attempt. */
typedef
enum {
VexTransOK,
}
VexTranslateResult;
+
+/* Describes precisely the pieces of guest code that a translation
+ covers. Now that Vex can chase across BB boundaries, the old
+ scheme of describing a chunk of guest code merely by its start
+ address and length is inadequate.
+
+ Hopefully this struct is only 32 bytes long. Space is important as
+ clients will have to store one of these for each translation made.
+*/
+typedef
+ struct {
+ Addr64 base[3];
+ UShort len[3];
+ UShort n_used;
+ }
+ VexGuestExtents;
+
+
extern
VexTranslateResult LibVEX_Translate (
/* The instruction sets we are translating from and to. */
UChar* guest_bytes,
Addr64 guest_bytes_addr,
Bool (*chase_into_ok) ( Addr64 ),
- /* OUT: the number of bytes actually read */
- Int* guest_bytes_read,
+ /* OUT: which bits of guest code actually got translated */
+ VexGuestExtents* guest_extents,
/* IN: a place to put the resulting code, and its size */
UChar* host_bytes,
Int host_bytes_size,
UInt u, sum;
Addr32 orig_addr;
Int bb_number, n_bbs_done = 0;
- Int orig_nbytes, trans_used, orig_used;
+ Int orig_nbytes, trans_used;
VexTranslateResult tres;
VexControl vcon;
+ VexGuestExtents vge;
if (argc != 2) {
fprintf(stderr, "usage: vex file.org\n");
VexArchX86, VexSubArchX86_sse2,
VexArchX86, VexSubArchX86_sse2,
origbuf, (Addr64)orig_addr, chase_into_not_ok,
- &orig_used,
+ &vge,
transbuf, N_TRANSBUF, &trans_used,
#if 1 /* no instrumentation */
NULL, /* instrument1 */
if (tres != VexTransOK)
printf("\ntres = %d\n", (Int)tres);
assert(tres == VexTransOK);
- assert(orig_used == orig_nbytes);
+ assert(vge.n_used == 1);
+ assert((UInt)(vge.len[0]) == orig_nbytes);
sum = 0;
for (i = 0; i < trans_used; i++)
sum += (UInt)transbuf[i];
- printf ( " %6.2f ... %d\n", (double)trans_used / (double)orig_used, sum );
+ printf ( " %6.2f ... %d\n", (double)trans_used / (double)vge.len[0], sum );
}
fclose(f);